new portfolio features, metal graphs, preparing for 0.4 release
[stockthis] / stockthis.py
index 40aef5c..7ca72b4 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.5
+#!/usr/bin/env python
 # -*- coding: UTF8 -*-
 # Copyright (C) 2008 by Daniel Martin Yerga
 # <dyerga@gmail.com>
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #
-# StocksPy: Application to get stocks data from Yahoo Finance.
-# Version 0.1
+# StocksThis: Application to get stocks data from Yahoo Finance.
 #
 
+_version = "StockThis 0.4 rev1"
+VERSION = "0.4"
+
 import urllib2
 import gtk, gobject
-try:
-    import hildon
-    HILDON = True
-except:
-    HILDON = False
-    
-try:
-    import osso
-    OSSO = True
-    osso_c = osso.Context("net.yerga.stockthis", "0.1", False)
-except:
-    OSSO = False    
-
-from marketdata import markets, idmarket, localmarkets, localids
-
-#TODO: detect if running in Fremantle
-FREMANTLE=True
+import os
+import hildon
+import marketdata
+import settings
+import logging
+import sys
+
+from portrait import FremantleRotation
+
+import osso
+osso_c = osso.Context("net.yerga.stockthis", "0.3", False)
 
 #detect if is ran locally or not
-import sys
 runningpath = sys.path[0]
 
-if '/usr/share' in runningpath:
-    running_locally = False
-else:
-    running_locally = True
-    
-if running_locally:
-    imgdir = 'pixmaps/'
+if '/opt/' in runningpath:
+    runninglocally = False
 else:
-    imgdir = '/usr/share/stockthis/pixmaps/'
+    runninglocally = True
+
+HOME = os.path.expanduser("~")
+
+settingsdb, imgdir, configdir, logfile = \
+    settings.define_paths(runninglocally, HOME)
+
+logger = logging.getLogger('st')
+logging.basicConfig(filename=logfile,level=logging.ERROR, filemode='w')
+
+DEBUG = True
+
+if DEBUG:
+    #set the main logger to DEBUG
+    logger.setLevel(logging.DEBUG)
+
+    #Create a handler for console debug
+    console = logging.StreamHandler()
+    console.setLevel(logging.DEBUG)
+    # set a format which is simpler for console use
+    formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+    # tell the handler to use this format
+    console.setFormatter(formatter)
+    logging.getLogger('').addHandler(console)
+
+fhsize = gtk.HILDON_SIZE_FINGER_HEIGHT
+horbtn = hildon.BUTTON_ARRANGEMENT_HORIZONTAL
+ui_normal = gtk.HILDON_UI_MODE_NORMAL
+ui_edit = gtk.HILDON_UI_MODE_EDIT
+winprogind = hildon.hildon_gtk_window_set_progress_indicator
 
-loading_img = imgdir + 'loading.gif'
+allnames = []
+allsymbols = []
 
 gtk.gdk.threads_init()
 
 class StocksPy:
 
     def __init__(self):
-        if HILDON:
-            self.program = hildon.Program()
-            self.program.__init__()
-            gtk.set_application_name('')
-            if FREMANTLE:
-                self.window = hildon.StackableWindow()
-            else:
-                self.window = hildon.Window()                
-            self.program.add_window(self.window) 
-        else:
-            self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
-
-        self.window.set_default_size(800, 480)  
-        self.window.set_title('StocksPy')
+        self.program = hildon.Program()
+        self.program.__init__()
+        gtk.set_application_name("StockThis")
+        self.window = hildon.StackableWindow()
+        self.window.set_default_size(800, 480)
+        self.program.add_window(self.window)
         self.window.connect("destroy", gtk.main_quit)
-        self.window.connect("key-press-event", self.on_key_press)
-        self.window.connect("window-state-event", self.on_window_state_change)
-        self.window_in_fullscreen = False
-        
-        if HILDON:
-            if FREMANTLE:
-                menu = hildon.AppMenu()
-                self.window.set_main_menu(menu)
-                about_menu = gtk.Button("About")
-            else:
-                menu = gtk.Menu()
-                self.window.set_menu(menu)
-                about_menu = gtk.MenuItem("About")
-                about_menu.set_size_request(-1, 55)
-            
-            about_menu.connect("activate", self.on_about)
-            menu.append(about_menu)            
-            menu.show_all()
-        else:
-            #TODO: create a gtk.menubar
-            pass
-        
-        
+
+        FremantleRotation('StockThis', None, "0.3", 0)
+
+        self.create_menu(self.window)
+
         vbox = gtk.VBox()
-        
-        self.toolbar = gtk.HBox()
-        self.toolbar.set_property("no-show-all", True)
-        self.toolbar.hide()
-        self.toolbar.set_homogeneous(True)
-        self.toolbar.set_size_request(-1, 55)
-        
-        self.markets_btn = gtk.Button('Markets')
-        self.markets_btn.connect("clicked", self.create_markets_view)
-        self.markets_btn.set_property("can_focus", False)
-        
-        self.components_btn = gtk.Button('Components')
-        self.components_btn.connect("clicked", self.show_components_view)
-        self.components_btn.set_property("can_focus", False)          
-        
-        self.graph_btn = gtk.Button('Graphs')
-        self.graph_btn.connect("clicked", self.create_graphs_view)
-        self.graph_btn.set_property("can_focus", False)
-        
-        self.refresh_btn = gtk.Button('Refresh')
-        self.refresh_btn.connect("clicked", self.refresh_stock_data)
-        self.refresh_btn.set_property("can_focus", False)
-        
-        self.quotes_btn = gtk.Button('Quotes')
-        self.quotes_btn.connect("clicked", self.show_quotes_view)
-        self.quotes_btn.set_property("can_focus", False)        
-        
-        self.toolbar.pack_start(self.markets_btn)        
-        self.toolbar.pack_start(self.components_btn)
-        self.toolbar.pack_start(self.graph_btn)
-        self.toolbar.pack_start(self.quotes_btn) 
-        self.toolbar.pack_start(self.refresh_btn)        
-        
-        self.mainbox = gtk.VBox()
-
-
-        if FREMANTLE:
-            self.swin = hildon.PannableArea()
-        else:
-            self.swin = gtk.ScrolledWindow()
-            if HILDON:
-                hildon.hildon_helper_set_thumb_scrollbar(self.swin, True)
-            self.swin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
-        self.swin.add_with_viewport(self.mainbox)
+        toolbar = self.main_toolbar(False, False, None, '', '', True)
+
+        parea = hildon.PannableArea()
+        tv = hildon.GtkTreeView(ui_normal)
+        inmodel = self.__create_model(marketdata.main, marketdata.idmain)
+        tv.connect("row-activated", self.show_instrument_view, inmodel,
+                    marketdata.localmarkets, marketdata.localids,
+                    marketdata.idmain)
+        tv.set_model(inmodel)
+        self._tv_columns(tv)
+        parea.add(tv)
 
-        vbox.pack_start(self.swin, True, True, 0)
+        vbox.pack_start(parea, True, True, 0)
         vbox.pack_start(gtk.HSeparator(), False, False, 5)
-        vbox.pack_start(self.toolbar, False, False, 0)
+        vbox.pack_start(toolbar, False, False, 0)
 
-        self.create_markets_view(self.mainbox)
         self.window.add(vbox)
-
         self.window.show_all()
 
-    def create_markets_view(self, widget): 
-        names = markets
-        ids = idmarket
-        self.toolbar.hide()
-        
-        actual_view = self.mainbox.get_children()
-        if len(actual_view) > 0:
-            for a_widget in actual_view:
-                a_widget.destroy()
-
-        self.marketsbox = gtk.VBox()        
-        lnames = len(names)
-        
-        for i in range(lnames):
-            button = gtk.Button(names[i])
-            button.connect("clicked", self.create_components_view, ids[i])
-            button.set_size_request(-1, 65)
-            button.set_property("can_focus", False)
-            self.marketsbox.pack_start(button, True, True, 2)
-        
-        self.mainbox.pack_start(self.marketsbox, True, True, 2)
-        self.mainbox.show_all()
-
-    def show_components_view(self, widget):
-        kind = self.market_id
-        self.create_components_view(widget, kind)
-
-    def create_components_view(self, widget, kind):    
-        actual_view = self.mainbox.get_children()
-        for i in actual_view:
-            i.destroy()
-    
-        self.market_id = kind
-        self.toolbar.show()
-        self.components_btn.hide()
-        self.markets_btn.show()
-        self.refresh_btn.hide()
-        self.graph_btn.hide()
-        self.quotes_btn.hide()
-        
-        names = localmarkets[idmarket.index(kind)]
-        ids = localids[idmarket.index(kind)]
-        
-        self.compbox = gtk.VBox()
-        
-        self.components_trv = gtk.TreeView()
-        selection = self.components_trv.get_selection()
-        selection.connect("changed", self.changed_selection, ids)
-        self.components_trv.set_rubber_banding(True)
-        self.components_trv.set_headers_visible(False)        
-        self.components_model = self.__create_components_model()
-        self.components_trv.set_model(self.components_model)
-        self._components_trv_columns(self.components_trv)   
-        self.add_initial_components(names, ids)
-        
-        self.compbox.pack_start(self.components_trv, True, True, 0) 
-
-        self.mainbox.pack_start(self.compbox, True, True, 0)
-        self.mainbox.show_all()
-    
-    def changed_selection(self, widget, ids):
-        n, i, m = self.get_selected_from_treeview(self.components_trv, self.components_model, 1)
-        if n is not None:
-            self.create_quotes_view(widget, n)
-            
-    def __create_components_model(self):
-        lstore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
-        return lstore
+        self.show_info_banner(self.window,
+            ("StockThis uses your network connection to get data.\n"
+            "Be aware of the high costs that your network provider may apply."))
 
-    def _components_trv_columns(self, treeview): 
-        renderer = gtk.CellRendererText()
-        renderer.set_property('scale', 1.6)
-        #renderer.set_property("background", 'lightgray')
-        renderer.set_property("xpad", 15)
-        column = gtk.TreeViewColumn('Name', renderer, text=0)
-        column.set_expand(True)
-        treeview.append_column(column) 
-        
-        renderer = gtk.CellRendererText()
-        column = gtk.TreeViewColumn('IDS', renderer, text=1)
-        column.set_visible(False)
-        treeview.append_column(column)         
-        
-    def add_initial_components(self, kind, ids):
-        for i in range(len(kind)):
-            niter = self.components_model.append() 
-            self.components_model.set(niter, 0, kind[i], 1, ids[i])    
-
-    def get_selected_from_treeview(self, treeview, model, setting):
-        selection = treeview.get_selection()
-        selected_model, selected_iter = selection.get_selected()
-        if selected_iter:
-            selected_name = model.get_value(selected_iter, setting)
+    def create_menu(self, window):
+        menu = hildon.AppMenu()
+        window.set_app_menu(menu)
+        button = gtk.Button("About")
+        button.connect("clicked", About)
+        menu.append(button)
+        menu.show_all()
+
+    def show_instrument_view(self, widget, path, column, inmodel, names,
+        ids, mindex):
+        market = inmodel[path][0]
+        names = names[mindex.index(market)]
+        ids = ids[mindex.index(market)]
+
+        window = hildon.StackableWindow()
+        self.create_menu(window)
+        window.set_title(inmodel[path][1])
+
+        vbox = gtk.VBox()
+        toolbar = self.main_toolbar(False, False, None, '', '', False)
+
+        parea = hildon.PannableArea()
+        parea.connect("horizontal-movement", self.horizontal_mov)
+        tv = hildon.GtkTreeView(ui_normal)
+        model = self.__create_model(names, ids)
+
+        if market == 'metals':
+            tv.connect("row-activated", self.show_metal_graphs, model)
         else:
-            selected_name = None
-        return selected_name, selected_iter, selected_model
-
-    def show_quotes_view(self, widget):
-        kind = self.stocks_id
-        self.create_quotes_view(widget, kind)
-
-    def create_quotes_view(self, widget, kind):
-        self.stocks_id = kind
-        self.toolbar.show()
-        self.components_btn.show()
-        self.markets_btn.show()
-        self.refresh_btn.show()
-        self.graph_btn.show() 
-        self.quotes_btn.hide() 
-    
-        #actual_view = self.mainbox.get_children()
-        #actual_view[0].destroy()
-        
-        try:
-            self.graphbox.destroy()
-        except:
-            pass
-        
-        for i in range(len(localids)):
-            if kind in localids[i]:
-                ind1, ind2 = i, localids[i].index(kind)  
-
-        self.quotesbox = gtk.VBox()
-
-        label1 = gtk.Label('')
-        label1.set_markup('<b><big>'+localmarkets[ind1][ind2]+'</big></b>')
-        color = gtk.gdk.color_parse("#03A5FF")          
-        label1.modify_fg(gtk.STATE_NORMAL, color)
-
-        self.databox = gtk.VBox()
-        
-        self.imagebox = gtk.VBox()
-        self.dataimg = gtk.Image()        
-        self.imagebox.pack_start(self.dataimg)
-        
-        self.show_data(kind)        
-        
+            tv.connect("row-activated", self.show_quotes_view, model, False)
+
+        tv.set_model(model)
+        self._tv_columns(tv)
+        parea.add(tv)
+
+        vbox.pack_start(parea, True, True, 0)
+        vbox.pack_start(gtk.HSeparator(), False, False, 5)
+        vbox.pack_start(toolbar, False, False, 0)
+
+        window.add(vbox)
+        window.show_all()
+
+    def horizontal_mov(self, parea, direction, initial_x, initial_y):
+        #direction = 2 right-to-left
+        #direction = 3 lefto-to-right
+
+        vadj = parea.get_vadjustment()
+        val = vadj.get_value()
+
+        if direction == 2:
+            if int(val)-2500 < 0:
+                 parea.scroll_to(-1, 0)
+            else:
+                parea.scroll_to(-1, int(val)-2500)
+        elif direction == 3:
+            parea.scroll_to(-1, int(val)+3500)
+
+        #print val
+
+    def show_quotes_view(self, widget, path, column, model, portfolio):
+        quote = model[path][0], model[path][1]
+        #print "quote:", quote[0]
+        #('EURUSD=X', 'EUR/USD')
+
+        #Currencies and ETFs should show the list now -> view = True
+        #Other items show a new list with options
+        view = False
+        for i in marketdata.localids[(len(marketdata.localids)-2):]:
+            for j in i:
+                if quote[0] == j:
+                    #print j
+                    view = True
+
+        if not view:
+            if quote[0] in marketdata.idindexes:
+                self.show_instrument_view(widget, path, column, model,
+                                        marketdata.wnamesindexes,
+                                        marketdata.widsindexes,
+                                        marketdata.idindexes)
+                return
+            if quote[0] in marketdata.idotmarkets:
+                self.show_instrument_view(widget, path, column, model,
+                                        marketdata.omnames,
+                                        marketdata.omsymbols,
+                                        marketdata.idotmarkets)
+                return
+            if quote[0] in marketdata.ideumarkets:
+                self.show_instrument_view(widget, path, column, model,
+                                        marketdata.eunames,
+                                        marketdata.eusymbols,
+                                        marketdata.ideumarkets)
+                return
+            if quote[0] in marketdata.idusmarkets:
+                self.show_instrument_view(widget, path, column, model,
+                                        marketdata.usnames,
+                                        marketdata.ussymbols,
+                                        marketdata.idusmarkets)
+                return
+
+
+        win = hildon.StackableWindow()
+        self.create_menu(win)
+        win.set_title(quote[1])
+
+        vbox = gtk.VBox()
+
+        ltitle = gtk.Label('')
+        ltitle.set_markup('<b><big>' + quote[1].replace('&', '') +
+                                 '</big></b>')
+        color = gtk.gdk.color_parse("#03A5FF")
+        ltitle.modify_fg(gtk.STATE_NORMAL, color)
+
+        parea = hildon.PannableArea()
+        parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
+
+        vbox1 = gtk.VBox()
+
+        hbox = gtk.HBox()
+        label = gtk.Label('')
+        label.set_markup('<b><big>%39s:</big></b>' % '<u>Price</u>')
+        lprice = gtk.Label('')
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(lprice, False, False, 25)
+        #else:
+        #    hbox.pack_start(lprice, False, False, 245)
+
+        vbox1.pack_start(hbox, True, True, 0)
+
+        hbox = gtk.HBox()
+        label = gtk.Label('')
+        label.set_markup('<b><big>%35s:</big></b>' % '<u>Change</u>')
+        lchange = gtk.Label('')
+        lpercent = gtk.Label('')
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(lchange, False, False, 25)
+        hbox.pack_start(lpercent, False, False, 0)
+        #else:
+        #    hbox.pack_start(lchange, False, False, 205)
+        #    hbox.pack_start(lpercent, False, False, 0)
+
+        vbox1.pack_start(hbox, True, True, 0)
+
+        hbox = gtk.HBox()
+        label = gtk.Label('')
+        label.set_markup('<b><big>%35s:</big></b>' % '<u>Volume</u>')
+        lvolume = gtk.Label('')
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(lvolume, False, False, 25)
+        #else:
+        #    hbox.pack_start(lvolume, False, False, 207)
+
+        vbox1.pack_start(hbox, True, True, 0)
+
+        hbox = gtk.HBox()
+        label = gtk.Label('')
+        label.set_markup('<b><big>%30s:</big></b>' % '<u>52 week high</u>')
+        l52whigh = gtk.Label('')
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(l52whigh, False, False, 25)
+        #else:
+        #    hbox.pack_start(l52whigh, False, False, 125)
+
+        vbox1.pack_start(hbox, True, True, 0)
+
+        hbox = gtk.HBox()
+        label = gtk.Label('')
+        label.set_markup('<b><big>%30s:</big></b>' % '<u>52 week low</u>')
+        l52wlow = gtk.Label('')
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(l52wlow, False, False, 26)
+        #else:
+        #    hbox.pack_start(l52wlow, False, False, 140)
+        vbox1.pack_start(hbox, True, True, 0)
+
+        #if self.is_portrait():
+        #    hbox = gtk.VBox()
+        #else:
+        hbox = gtk.HBox()
+        button1 = hildon.PickerButton(fhsize, horbtn)
+        data = ["50", "100", "200", "300", "400", "500", "600", "700", "800",
+                "900", "1000"]
+        selector = self.create_selector(data, True)
+        button1.set_selector(selector)
+        button1.set_title("Your shares")
+        shares = self.get_shares_from_symbol(quote[0])
+        button1.set_value(shares)
+        hbox.pack_start(button1, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title("Add to Portfolio")
+        button.connect("clicked", self.add_to_portfolio, button1, quote[0], quote[1])
+        hbox.pack_start(button, True, True, 0)
+
         hbox1 = gtk.HBox()
-        
-        label2 = gtk.Label('')
-        label2.set_markup('<b><big>Price:</big></b>')
-        self.lprice = gtk.Label('')
-        
-        hbox1.pack_start(label2, False, False, 50)
-        hbox1.pack_start(self.lprice, False, False, 185)
-        
+        label = gtk.Label('')
+        label.set_markup('<b><big>%37s:</big></b>' % '<u>Shares</u>')
+        lshares = gtk.Label(shares)
+        hbox1.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox1.pack_start(lshares, False, False, 25)
+        #else:
+        #    hbox1.pack_start(lshares, False, False, 220)
+
         hbox2 = gtk.HBox()
+        label = gtk.Label('')
+        label.set_markup('<b><big>%29s:</big></b>' % '<u>Holdings Value</u>')
+        holdingsvalue = gtk.Label("")
+        hbox2.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox2.pack_start(holdingsvalue, False, False, 25)
+        #else:
+        #    hbox2.pack_start(holdingsvalue, False, False, 105)
 
-        label4 = gtk.Label('')
-        label4.set_markup('<b><big>Change:</big></b>')
-        self.lchange = gtk.Label('')
-        self.lpercent = gtk.Label('')
-        
-        hbox2.pack_start(label4, False, False, 50)
-        hbox2.pack_start(self.lchange  , False, False, 145)             
-        hbox2.pack_start(self.lpercent, False, False, 0)
-                
         hbox3 = gtk.HBox()
-        
-        label7 = gtk.Label('')
-        label7.set_markup('<b><big>Volume:</big></b>')
-        self.lvolume = gtk.Label('')
-        
-        hbox3.pack_start(label7, False, False, 50)
-        hbox3.pack_start(self.lvolume  , False, False, 145)    
-        
-        hbox4 = gtk.HBox()
-        
-        label9 = gtk.Label('')
-        label9.set_markup('<b><big>52 week high:</big></b>')
-        self.l52whigh = gtk.Label('')
-        
-        hbox4.pack_start(label9, False, False, 50)
-        hbox4.pack_start(self.l52whigh , False, False, 55)             
-        
-        hbox5 = gtk.HBox()
-        
-        label11 = gtk.Label('')
-        label11.set_markup('<b><big>52 week low:</big></b>')
-        self.l52wlow = gtk.Label('')
-        
-        hbox5.pack_start(label11, False, False, 50)
-        hbox5.pack_start(self.l52wlow , False, False, 70)
-    
-        self.databox.pack_start(hbox1, True, True, 0)
-        self.databox.pack_start(hbox2, True, True, 0)
-        self.databox.pack_start(hbox3, True, True, 0)
-        self.databox.pack_start(hbox4, True, True, 0)
-        self.databox.pack_start(hbox5, True, True, 0)
-               
-        self.quotesbox.pack_start(label1, False, False, 0)
-        self.quotesbox.pack_start(gtk.HSeparator(), False, False, 0)     
-        self.quotesbox.pack_start(self.databox, True, True, 0)     
-        self.quotesbox.pack_start(self.imagebox, True, True, 0)    
-
-        self.mainbox.pack_start(self.quotesbox, True, True, 0)
-        self.mainbox.show_all()
-        self.compbox.hide()
-        self.databox.hide()
-
-    def show_data(self, kind):
+        label = gtk.Label('')
+        label.set_markup("<b><big>%25s:</big></b>" % "<u>Day's Value Change</u>")
+        dayvaluechange = gtk.Label("")
+        hbox3.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox3.pack_start(dayvaluechange, False, False, 25)
+        #else:
+        #    hbox3.pack_start(dayvaluechange, False, False, 45)
+
+        if not portfolio:
+            vbox1.pack_start(hbox, False, False, 0)
+        else:
+            vbox1.pack_start(hbox1, True, True, 0)
+            vbox1.pack_start(hbox2, True, True, 0)
+            vbox1.pack_start(hbox3, True, True, 0)
+
+        parea.add_with_viewport(vbox1)
+
+        widgets = [win, ltitle, lprice, lchange,  lpercent, lvolume, l52whigh,
+                    l52wlow, lshares, holdingsvalue, dayvaluechange]
+
+        toolbar = self.main_toolbar(True, portfolio, widgets, quote[0], quote[1], False)
+
+        vbox.pack_start(ltitle, False, False, 0)
+        vbox.pack_start(gtk.HSeparator(), False, False, 0)
+        vbox.pack_start(parea, True, True, 0)
+        vbox.pack_start(gtk.HSeparator(), False, False, 5)
+        vbox.pack_start(toolbar, False, False, 0)
+
+
+        win.add(vbox)
+        win.show_all()
+        self.show_data(quote[0], widgets, shares)
+
+    def is_portrait(self):
+        width = gtk.gdk.screen_width()
+        height = gtk.gdk.screen_height()
+        if width > height:
+            return False
+        else:
+            return True
+
+    def get_shares_from_symbol(self, symbol):
+        shares = "0"
+        try:
+            portfolio_data = settings.load_portfolio(settingsdb)
+            for item in portfolio_data :
+                if symbol in item:
+                    shares = item[2]
+            return shares
+        except:
+            logger.exception("Getting shares from symbol: %s" % symbol)
+            return shares
+
+    def add_to_portfolio(self, widget, button, symbol, name):
+        shares = button.get_value()
+
+        try:
+            portfolio = settings.load_portfolio(settingsdb)
+            index = "None"
+            for item in portfolio:
+                if symbol in item:
+                    index = portfolio.index(item)
+
+            item = [symbol, name, shares, '-']
+
+            if index is "None":
+                settings.insert_new_item_to_portfolio(settingsdb, item)
+            else:
+                settings.delete_item_from_portfolio(settingsdb, symbol)
+                settings.insert_new_item_to_portfolio(settingsdb, item)
+
+            self.show_info_banner(widget, "Added to portfolio")
+        except:
+            logger.exception("Adding to portfolio: %s, %s" % (symbol, name))
+            self.show_info_banner(widget, "Error adding to portfolio")
+
+
+    def create_selector(self, data, entry):
+        if entry:
+            selector = hildon.TouchSelectorEntry(text=True)
+        else:
+            selector = hildon.TouchSelector(text=True)
+        for i in range(len(data)):
+            selector.append_text(data[i])
+
+        return selector
+
+    def show_data(self, symbol, widgets, shares):
         import thread
-        self.dataimg.set_from_file(loading_img)
-        self.imagebox.show()
-        self.databox.hide()
-        thread.start_new_thread(self.get_data, (kind,))
-
-    def get_data(self, kind):    
-        self.graph_btn.show()
-        self.refresh_btn.show()
-        self.quotes_btn.hide() 
-        
+        winprogind(widgets[0], 1)
+        thread.start_new_thread(self.get_data, (symbol, widgets, shares))
+
+    def get_data(self, symbol, widgets, shares):
         from ystockquote import ystockquote as yt
-        data = yt.get_all(kind)
-        
+        win, ltitle, lprice, lchange,  lpercent, lvolume, l52whigh, l52wlow, lshares, holdingsvalue, dayvaluechange = widgets
+
+        try:
+            data = yt.get_all(symbol)
+        except:
+            logger.exception("Getting data from Yahoo: %s" % symbol)
+            data = {'price': 'N/A', 'change': 'N/A', 'volume':'N/A',
+                    '52_week_high': 'N/A', '52_week_low': 'N/A'}
+            ltitle.set_markup('<b><big>Failed to get data</big></b>')
+
         try:
-            ch_percent = 100.0 * float(data['change'])/float(data['price'])
+            ch_percent = \
+                    100.0 * float(data['change'])/(float(data['price']) - \
+                    float(data['change']))
         except ValueError:
             ch_percent = 0.0
 
-        self.lprice.set_label(data['price'])
-        self.lchange.set_label(data['change'])
-        self.lpercent.set_label('%6.2f %%' % ch_percent)
-        
+        lprice.set_label(data['price'])
+        lchange.set_label(data['change'])
+        lpercent.set_label('%6.2f %%' % ch_percent)
+
         if '-' in data['change']:
             color = gtk.gdk.color_parse("#FF0000")
         else:
-            color = gtk.gdk.color_parse("#16EB78")   
-                     
-        self.lpercent.modify_fg(gtk.STATE_NORMAL, color)
-        self.lchange.modify_fg(gtk.STATE_NORMAL, color) 
-                   
-        self.lvolume.set_label(data['volume'])
-        self.l52whigh.set_label(data['52_week_high'])
-        self.l52wlow.set_label(data['52_week_low'])
-               
-        self.databox.show_all()  
-        self.imagebox.hide()  
-
-    def refresh_stock_data(self, widget):
-        self.show_data(self.stocks_id)
-
-    def create_graphs_view(self, widget):        
-        self.graph_btn.hide()
-        self.refresh_btn.hide()
-        self.quotes_btn.show()
-        
-        self.graph = gtk.Image()
-        
-        kind = self.stocks_id
-        
-        self.show_graph(None, '1d', kind)
-        
-        for i in range(len(localids)):
-            if kind in localids[i]:
-                ind1, ind2 = i, localids[i].index(kind)
-
-        #self.mainbox.destroy()  
-        #self.mainbox = gtk.VBox()
-        #self.swin.add_with_viewport(self.mainbox) 
-        
-        actual_view = self.mainbox.get_children()
-        for a_widget in actual_view:
-            a_widget.destroy() 
-
-        self.graphbox = gtk.VBox()
-
-        label1 = gtk.Label(localmarkets[ind1][ind2])
+            color = gtk.gdk.color_parse("#16EB78")
+
+        lpercent.modify_fg(gtk.STATE_NORMAL, color)
+        lchange.modify_fg(gtk.STATE_NORMAL, color)
+
+        lvolume.set_label(data['volume'])
+        l52whigh.set_label(data['52_week_high'])
+        l52wlow.set_label(data['52_week_low'])
+
+        try:
+            daychange = float(shares)*float(data['change'])
+        except ValueError:
+            daychange = 'N/A'
+        try:
+            holdvalue = float(shares)*float(data['price'])
+        except ValueError:
+            holdvalue = 'N/A'
+
+        dayvaluechange.set_label(str(daychange))
+        holdingsvalue.set_label(str(holdvalue))
+
+        winprogind(win, 0)
+
+    def refresh_stock_data(self, widget, portfolio, widgets, symbol):
+        if portfolio:
+            shares = self.get_shares_from_symbol(symbol)
+        else:
+            shares = "0"
+
+        self.show_data(symbol, widgets, shares)
+
+    def show_graph_view(self, widget, symbol, name):
+        win = hildon.StackableWindow()
+        self.create_menu(win)
+        win.set_title(name)
+
+        vbox = gtk.VBox()
+        toolbar = self.main_toolbar(False, True, None, '', '', False)
+
+        self.graphs_title = gtk.Label(name)
         color = gtk.gdk.color_parse("#03A5FF")
-        label1.modify_fg(gtk.STATE_NORMAL, color)
-        
-        hbox1 = gtk.HBox()
-        hbox1.set_size_request(-1, 55)
-        hbox1.set_homogeneous(True)
-        
-        self.btn1d = gtk.Button('1d')
-        self.btn1d.set_property("can_focus", False)
-        self.btn1d.connect("clicked", self.show_graph, '1d', kind)
-        self.btn5d = gtk.Button('5d')
-        self.btn5d.set_property("can_focus", False)
-        self.btn5d.connect("clicked", self.show_graph, '5d', kind)
-        self.btn3m = gtk.Button('3m')
-        self.btn3m.set_property("can_focus", False)
-        self.btn3m.connect("clicked", self.show_graph, '3m', kind)
-        self.btn6m = gtk.Button('6m')
-        self.btn6m.set_property("can_focus", False)
-        self.btn6m.connect("clicked", self.show_graph, '6m', kind)
-        self.btn1y = gtk.Button('1y')
-        self.btn1y.set_property("can_focus", False)
-        self.btn1y.connect("clicked", self.show_graph, '1y', kind)
-        self.btn2y = gtk.Button('2y')
-        self.btn2y.set_property("can_focus", False)
-        self.btn2y.connect("clicked", self.show_graph, '2y', kind)
-        self.btn5y = gtk.Button('5y')
-        self.btn5y.set_property("can_focus", False)
-        self.btn5y.connect("clicked", self.show_graph, '5y', kind)
-        self.btnmax = gtk.Button('max')
-        self.btnmax.set_property("can_focus", False)
-        self.btnmax.connect("clicked", self.show_graph, 'max', kind)
-        
-        hbox1.pack_start(self.btn1d)
-        hbox1.pack_start(self.btn5d)        
-        hbox1.pack_start(self.btn3m)        
-        hbox1.pack_start(self.btn6m)        
-        hbox1.pack_start(self.btn1y) 
-        hbox1.pack_start(self.btn2y)        
-        hbox1.pack_start(self.btn5y)        
-        hbox1.pack_start(self.btnmax)      
-           
-        self.graphbox.pack_start(label1, False, False, 2)
-        self.graphbox.pack_start(hbox1, False, False, 0)     
-        self.graphbox.pack_start(self.graph, True, True, 5)
-        
-        self.mainbox.pack_start(self.graphbox, False, False, 2)
-        self.mainbox.show_all()   
-
-    def show_graph(self, widget, option, kind):
+        self.graphs_title.modify_fg(gtk.STATE_NORMAL, color)
+
+        parea = hildon.PannableArea()
+        parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
+
+        vbox1 = gtk.VBox()
+
+        hbox = gtk.HBox()
+        hbox.set_homogeneous(True)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('1d')
+        button.connect("clicked", self.show_graph, '1d', win, symbol)
+        hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('5d')
+        button.connect("clicked", self.show_graph, '5d', win, symbol)
+        hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('3m')
+        button.connect("clicked", self.show_graph, '3m', win, symbol)
+        hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('6m')
+        button.connect("clicked", self.show_graph, '6m', win, symbol)
+        hbox.pack_start(button)
+
+        vbox1.pack_start(hbox, False, False, 0)
+        hbox = gtk.HBox()
+        hbox.set_homogeneous(True)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('1y')
+        button.connect("clicked", self.show_graph, '1y', win, symbol)
+        hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('2y')
+        button.connect("clicked", self.show_graph, '2y', win, symbol)
+        hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('5y')
+        button.connect("clicked", self.show_graph, '5y', win, symbol)
+        hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('Max')
+        button.connect("clicked", self.show_graph, 'max', win, symbol)
+        hbox.pack_start(button)
+
+        vbox1.pack_start(hbox, False, False, 0)
+
+        self.graph = gtk.Image()
+        vbox1.pack_start(self.graph, True, True, 0)
+
+        parea.add_with_viewport(vbox1)
+
+        vbox.pack_start(self.graphs_title, False, False, 0)
+        vbox.pack_start(gtk.HSeparator(), False, False, 0)
+        vbox.pack_start(parea, True, True, 0)
+        vbox.pack_start(gtk.HSeparator(), False, False, 5)
+        vbox.pack_start(toolbar, False, False, 0)
+
+        win.add(vbox)
+        win.show_all()
+
+        self.show_graph(None, '1d', win, symbol)
+
+    def show_graph(self, widget, option, win, symbol):
         import thread
-        self.graph.set_from_file(loading_img)
-        thread.start_new_thread(self.get_graph_data, (option, kind))
+        winprogind(win, 1)
+        thread.start_new_thread(self.get_graph_data, (option, win, symbol))
 
-    def get_graph_data(self, option, kind):
+    def get_graph_data(self, option, win, symbol):
         if option == '1d':
-            url = 'http://uk.ichart.yahoo.com/b?s=%s' % kind
-        elif option == '5d':  
-            url = 'http://uk.ichart.yahoo.com/w?s=%s' % kind
-        elif option == '3m':  
-            url = 'http://chart.finance.yahoo.com/c/3m/s/%s' % kind.lower()
-        elif option == '6m':  
-            url = 'http://chart.finance.yahoo.com/c/6m/s/%s' % kind.lower()
-        elif option == '1y':  
-            url = 'http://chart.finance.yahoo.com/c/1y/s/%s' % kind.lower()
-        elif option == '2y':  
-            url = 'http://chart.finance.yahoo.com/c/2y/s/%s' % kind.lower()
-        elif option == '5y':  
-            url = 'http://chart.finance.yahoo.com/c/5y/s/%s' % kind.lower()
-        elif option == 'max':  
-            url = 'http://chart.finance.yahoo.com/c/my/s/%s' % kind.lower()
-                
-        myimg = urllib2.urlopen(url)
-        imgdata=myimg.read()
-
-        pbl = gtk.gdk.PixbufLoader()
-        pbl.write(imgdata)
-
-        pbuf = pbl.get_pixbuf()
-        pbl.close()
-        
-        self.graph.set_from_pixbuf(pbuf)
-
-    #Functions for fullscreen
-    def on_window_state_change(self, widget, event, *args):           
-        if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
-            self.window_in_fullscreen = True
+            url = 'http://uk.ichart.yahoo.com/b?s=%s' % symbol
+        elif option == '5d':
+            url = 'http://uk.ichart.yahoo.com/w?s=%s' % symbol
+        elif option == '3m':
+            url = 'http://chart.finance.yahoo.com/c/3m/s/%s' % symbol.lower()
+        elif option == '6m':
+            url = 'http://chart.finance.yahoo.com/c/6m/s/%s' % symbol.lower()
+        elif option == '1y':
+            url = 'http://chart.finance.yahoo.com/c/1y/s/%s' % symbol.lower()
+        elif option == '2y':
+            url = 'http://chart.finance.yahoo.com/c/2y/s/%s' % symbol.lower()
+        elif option == '5y':
+            url = 'http://chart.finance.yahoo.com/c/5y/s/%s' % symbol.lower()
+        elif option == 'max':
+            url = 'http://chart.finance.yahoo.com/c/my/s/%s' % symbol.lower()
+
+        try:
+            myimg = urllib2.urlopen(url)
+            imgdata = myimg.read()
+
+            pbl = gtk.gdk.PixbufLoader()
+            pbl.write(imgdata)
+
+            pbuf = pbl.get_pixbuf()
+            pbuf = pbuf.scale_simple(475, 235, gtk.gdk.INTERP_TILES)
+            pbl.close()
+            self.graph.set_from_pixbuf(pbuf)
+            winprogind(win, 0)
+        except:
+            logger.exception("Getting graph data: %s" % url)
+            winprogind(win, 0)
+            self.graphs_title.set_label('Failed to get data')
+            self.graph.destroy()
+
+    def show_metal_graphs(self, widget, path, column, model):
+        metal = model[path][1]
+        metal_urls = self.get_metal_graphs_urls(metal)
+        options =  []
+        for i in metal_urls:
+            options.append(i[0])
+
+        win = hildon.StackableWindow()
+        #self.create_menu(win)
+        win.set_title(metal)
+
+        vbox = gtk.VBox()
+        #toolbar = self.main_toolbar(False, True, None, '', '', False)
+
+        self.metalgraph_title = gtk.Label(metal)
+        color = gtk.gdk.color_parse("#03A5FF")
+        self.metalgraph_title.modify_fg(gtk.STATE_NORMAL, color)
+
+        parea = hildon.PannableArea()
+        parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
+
+        vbox1 = gtk.VBox()
+
+        hbox = gtk.HBox()
+        hbox.set_homogeneous(True)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('live')
+        button.connect("clicked", self.show_metalgraph, 'live', win, metal_urls)
+        if 'live' in options:
+            hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('30d')
+        button.connect("clicked", self.show_metalgraph, '30d', win, metal_urls)
+        if '30d' in options:
+            hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('60d')
+        button.connect("clicked", self.show_metalgraph, '60d', win, metal_urls)
+        if '60d' in options:
+            hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('6m')
+        button.connect("clicked", self.show_metalgraph, '6m', win, metal_urls)
+        if '6m' in options:
+            hbox.pack_start(button)
+
+        vbox1.pack_start(hbox, False, False, 0)
+        hbox = gtk.HBox()
+        hbox.set_homogeneous(True)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('1y')
+        button.connect("clicked", self.show_metalgraph, '1y', win, metal_urls)
+        if '1y' in options:
+            hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('5y')
+        button.connect("clicked", self.show_metalgraph, '5y', win, metal_urls)
+        if '5y' in options:
+            hbox.pack_start(button)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('10y')
+        button.connect("clicked", self.show_metalgraph, '10y', win, metal_urls)
+        if '10y' in options:
+            hbox.pack_start(button)
+
+        vbox1.pack_start(hbox, False, False, 0)
+
+        self.metalgraph = gtk.Image()
+        vbox1.pack_start(self.metalgraph, True, True, 0)
+
+        parea.add_with_viewport(vbox1)
+
+        vbox.pack_start(self.metalgraph_title, False, False, 0)
+        vbox.pack_start(gtk.HSeparator(), False, False, 0)
+        vbox.pack_start(parea, True, True, 0)
+        vbox.pack_start(gtk.HSeparator(), False, False, 5)
+        #vbox.pack_start(toolbar, False, False, 0)
+
+        win.add(vbox)
+        win.show_all()
+
+        self.show_metalgraph(None, options[0], win, metal_urls)
+
+    def show_metalgraph(self, widget, option, win, metal_urls):
+        import thread
+        winprogind(win, 1)
+        thread.start_new_thread(self.get_metalgraph_data, (option, win, metal_urls))
+
+    def get_metalgraph_data(self, option, win, metal_urls):
+        for i in metal_urls:
+            if i[0] == option:
+                print i[1]
+                url = i[1]
+
+        try:
+            myimg = urllib2.urlopen(url)
+            imgdata = myimg.read()
+
+            pbl = gtk.gdk.PixbufLoader()
+            pbl.write(imgdata)
+
+
+            pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, 475, 235)
+            pixbuf.fill(0xffffffff)
+
+
+            pbuf = pbl.get_pixbuf()
+            pbuf = pbuf.scale_simple(475, 235, gtk.gdk.INTERP_TILES)
+
+            pixbuf.composite(pbuf, 0, 0, pixbuf.props.width, pixbuf.props.height, 0, 0, 1.0, 1.0, gtk.gdk.INTERP_HYPER, 55)
+
+
+            pbl.close()
+            self.metalgraph.set_from_pixbuf(pbuf)
+            winprogind(win, 0)
+        except:
+            logger.exception("Getting graph data: %s" % url)
+            winprogind(win, 0)
+            self.metalgraph_title.set_label('Failed to get data')
+            self.metalgraph.destroy()
+
+    def get_metal_graphs_urls(self, metal):
+        metal_urls = []
+        liveurl = 'http://www.kitco.com/images/live/%s'
+        graphurl = 'http://www.kitco.com/LFgif/%s'
+        t24url = 'http://www.kitconet.com/charts/metals/base/%s'
+        if metal == 'Gold':
+            metal_urls.append(['live', liveurl % 'gold.gif'])
+            metal_urls.append(['30d', graphurl % 'au0030lnb.gif'])
+            metal_urls.append(['60d', graphurl % 'au0060lnb.gif'])
+            metal_urls.append(['6m', graphurl % 'au0182nyb.gif'])
+            metal_urls.append(['1y', graphurl % 'au0365nyb.gif'])
+            metal_urls.append(['5y', graphurl % 'au1825nyb.gif'])
+            metal_urls.append(['10y', graphurl % 'au3650nyb.gif'])
+        elif metal == 'Silver':
+            metal_urls.append(['live', liveurl % 'silver.gif'])
+            metal_urls.append(['30d', graphurl % 'ag0030lnb.gif'])
+            metal_urls.append(['60d', graphurl % 'ag0060lnb.gif'])
+            metal_urls.append(['6m', graphurl % 'ag0182nyb.gif'])
+            metal_urls.append(['1y', graphurl % 'ag0365nyb.gif'])
+            metal_urls.append(['5y', graphurl % 'ag1825nyb.gif'])
+            metal_urls.append(['10y', graphurl % 'ag3650nyb.gif'])
+        elif metal == 'Platinum':
+            metal_urls.append(['live', liveurl % 'plati.gif'])
+            metal_urls.append(['30d', graphurl % 'pt0030lnb.gif'])
+            metal_urls.append(['60d', graphurl % 'pt0060lnb.gif'])
+            metal_urls.append(['6m', graphurl % 'pt0182nyb.gif'])
+            metal_urls.append(['1y', graphurl % 'pt0365nyb.gif'])
+            metal_urls.append(['5y', graphurl % 'pt1825nyb.gif'])
+        elif metal == 'Palladium':
+            metal_urls.append(['live', liveurl % 'plad.gif'])
+            metal_urls.append(['30d', graphurl % 'pd0030lnb.gif'])
+            metal_urls.append(['60d', graphurl % 'pd0060lnb.gif'])
+            metal_urls.append(['6m', graphurl % 'pd0182nyb.gif'])
+            metal_urls.append(['1y', graphurl % 'pd0365nyb.gif'])
+            metal_urls.append(['5y', graphurl % 'pd1825nyb.gif'])
+        elif metal == 'Rhodium':
+            metal_urls.append(['30d', graphurl % 'rh0030lnb.gif'])
+            metal_urls.append(['60d', graphurl % 'rh0060lnb.gif'])
+            metal_urls.append(['6m', graphurl % 'rh0182lnb.gif'])
+            metal_urls.append(['1y', graphurl % 'rh0365lnb.gif'])
+            metal_urls.append(['5y', graphurl % 'rh1825lnb.gif'])
+        elif metal == 'Copper':
+            metal_urls.append(['live', t24url % 't24_cp450x275.gif'])
+        elif metal == 'Nickel':
+            metal_urls.append(['live', t24url % 't24_nk450x275.gif'])
+        elif metal == 'Aluminium':
+            metal_urls.append(['live', t24url % 't24_al450x275.gif'])
+        elif metal == 'Zinc':
+            metal_urls.append(['live', t24url % 't24_zc450x275.gif'])
+        elif metal == 'Lead':
+            metal_urls.append(['live', t24url % 't24_ld450x275.gif'])
+
+        return metal_urls
+
+    def _tv_columns(self, treeview):
+        column = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=0)
+        column.set_visible(False)
+        treeview.append_column(column)
+
+        column = gtk.TreeViewColumn('Name', gtk.CellRendererText(), text=1)
+        treeview.append_column(column)
+
+    def __create_model(self, names, ids):
+        lstore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+        for item in range(len(names)):
+            iter = lstore.append()
+            lstore.set(iter, 0, ids[item], 1, names[item])
+        return lstore
+
+    def main_toolbar(self, quotesview, portfolio, widgets, symbol, name, initial):
+        toolbar = gtk.HBox()
+        #toolbar.set_homogeneous(True)
+
+        portfolio_btn = hildon.Button(fhsize, horbtn)
+        portfolio_btn.set_title("Portfolio")
+        portfolio_btn.connect("clicked", self.show_portfolio_view)
+
+        graph_btn = hildon.Button(fhsize, horbtn)
+        graph_btn.set_title("Graph")
+        graph_btn.connect("clicked", self.show_graph_view, symbol, name)
+
+        refresh_btn = hildon.Button(fhsize, horbtn)
+        refresh_btn.set_title("Refresh")
+        refresh_btn.connect("clicked", self.refresh_stock_data, portfolio,
+                            widgets, symbol)
+
+
+        info_btn = hildon.Button(fhsize, horbtn)
+        img = gtk.image_new_from_icon_name("general_information", gtk.ICON_SIZE_SMALL_TOOLBAR)
+        info_btn.set_image(img)
+        info_btn.connect("clicked", self.show_app_information)
+
+        search_btn = hildon.Button(fhsize, horbtn)
+        img = gtk.image_new_from_icon_name("general_search", gtk.ICON_SIZE_SMALL_TOOLBAR)
+        search_btn.set_image(img)
+        search_btn.connect("clicked", self.show_search_dialog)
+
+        if not portfolio:
+            toolbar.pack_start(portfolio_btn)
+            if not quotesview:
+                toolbar.pack_start(info_btn, False, False, 0)
+        if quotesview:
+            toolbar.pack_start(graph_btn)
+            toolbar.pack_start(refresh_btn)
+
+        if initial:
+            toolbar.pack_start(search_btn, False, False, 0)
+
+        toolbar.show_all()
+
+        return toolbar
+
+    def show_search_dialog(self, widget):
+        dlg = gtk.Dialog(title='Search company', parent=None, flags=0)
+        dlg.set_has_separator(False)
+
+        hbox = gtk.HBox()
+
+        entry = hildon.Entry(fhsize)
+        entry.connect("activate", self.do_search, entry, dlg)
+        hbox.pack_start(entry, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        img = gtk.image_new_from_icon_name("general_search", gtk.ICON_SIZE_SMALL_TOOLBAR)
+        button.set_image(img)
+        button.connect("clicked", self.do_search, entry, dlg)
+        hbox.pack_start(button, False, False, 0)
+
+        dlg.vbox.pack_start(hbox, False, False, 0)
+
+        dlg.show_all()
+        dlg.run()
+        dlg.destroy()
+
+
+    def do_search(self, widget, entry, dlg):
+        import thread
+        text = entry.get_text()
+        dlg.destroy()
+
+        winprogind(self.window, 1)
+        thread.start_new_thread(self._really_do_search, (text,))
+
+    def _really_do_search(self, text):
+
+        if allnames == []:
+            for market in marketdata.eunames:
+                for company in market:
+                    allnames.append(company)
+
+            for market in marketdata.omnames:
+                for company in market:
+                    allnames.append(company)
+
+            for market in marketdata.usnames:
+                for company in market:
+                    allnames.append(company)
+
+        if allsymbols == []:
+            for market in marketdata.eusymbols:
+                for company in market:
+                    allsymbols.append(company)
+
+            for market in marketdata.omsymbols:
+                for company in market:
+                    allsymbols.append(company)
+
+            for market in marketdata.ussymbols:
+                for company in market:
+                    allsymbols.append(company)
+
+        new_model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+        for i in range(len(allnames)):
+            if text.lower() in allnames[i].lower():
+                niter = new_model.append()
+                #print allsymbols[i], allnames[i]
+                #FIXME: repeated companies in the results list
+                #print if allnames[i]
+                #for j in new_model:
+                #    if j[1] == allnames[i]:
+                new_model.set(niter, 0, allsymbols[i], 1, allnames[i])
+
+        if len(new_model) == 0:
+            winprogind(self.window, 0)
+            gtk.gdk.threads_enter()
+            self.show_info_banner(self.window, "No items found for this search")
+            gtk.gdk.threads_leave()
+            return
+
+        gtk.gdk.threads_enter()
+        self.show_search_screen(new_model, text)
+        gtk.gdk.threads_leave()
+        winprogind(self.window, 0)
+
+
+    def show_search_screen(self, model, text):
+        window = hildon.StackableWindow()
+        self.create_menu(window)
+        window.set_title("Search for " + text)
+
+        vbox = gtk.VBox()
+        toolbar = self.main_toolbar(False, False, None, '', '', False)
+
+        parea = hildon.PannableArea()
+        parea.connect("horizontal-movement", self.horizontal_mov)
+        tv = hildon.GtkTreeView(ui_normal)
+        tv.connect("row-activated", self.show_quotes_view, model, False)
+        tv.set_model(model)
+        self._tv_columns(tv)
+        parea.add(tv)
+
+        vbox.pack_start(parea, True, True, 0)
+        vbox.pack_start(gtk.HSeparator(), False, False, 5)
+        vbox.pack_start(toolbar, False, False, 0)
+
+        window.add(vbox)
+        window.show_all()
+
+    def show_app_information(self, widget):
+        self.show_information_note(self.window, (
+        "The data is got from Yahoo! Finance.\n"
+        "It could be delayed or even wrong.\n"
+        "The author doesn't validate in any way this data and therefore he is not responsible for any damage that may occur.\n\n"
+        "You can scroll large list with gestures:\n"
+        "Left-to-right gesture: scroll down.\n"
+        "Right-to-left gesture: scroll up."))
+
+    def show_portfolio_view(self, widget):
+        data = settings.load_portfolio(settingsdb)
+        for item in data:
+            item.append('-')
+            item.append('-')
+
+        win = hildon.StackableWindow()
+        self.create_menu(win)
+        win.set_title("Portfolio")
+
+        vbox = gtk.VBox()
+
+        parea = hildon.PannableArea()
+        parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
+        tv = hildon.GtkTreeView(ui_normal)
+        tv.set_headers_visible(True)
+        self.portfolio_model = self._create_portfolio_model(data)
+        self.quotes_id = tv.connect("row-activated", self.show_quotes_view,
+                                    self.portfolio_model, True)
+        tv.set_model(self.portfolio_model)
+        self._tv_portfolio_columns(tv)
+        parea.add(tv)
+
+        hbox = gtk.HBox()
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title("Refresh All")
+        button.connect("clicked", self.refresh_portfolio, tv, win)
+        hbox.pack_start(button, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title("Add manually")
+        button.connect("clicked", self.add_item_dlg, None, None)
+        hbox.pack_start(button, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title("Remove")
+        button.connect("clicked", self.remove_item)
+        hbox.pack_start(button, True, True, 0)
+
+        button = hildon.CheckButton(fhsize)
+        button.set_label("Edit")
+
+        button.connect("toggled", self.edit_toggled, tv)
+        hbox.pack_start(button, True, True, 0)
+
+
+        vbox.pack_start(parea, True, True, 0)
+        vbox.pack_start(hbox, False, False, 0)
+        win.add(vbox)
+        win.show_all()
+
+    def edit_toggled(self, widget, tv):
+        if widget.get_active():
+            tv.disconnect(self.quotes_id)
+            self.edit_id = tv.connect("row-activated",
+                            self.edit_portfolio_item, self.portfolio_model)
+        else:
+            tv.disconnect(self.edit_id)
+            self.quotes_id = tv.connect("row-activated",
+                            self.show_quotes_view, self.portfolio_model, True)
+
+    def edit_portfolio_item(self, widget, path, column, model):
+        seliter = model.get_iter(path)
+
+        symbol = model[path][0]
+        name = model[path][1]
+        shares = model[path][2]
+
+        data = [shares, symbol, name]
+        self.add_item_dlg(widget, data, seliter)
+
+    def add_item_dlg(self, widget, data, seliter):
+        if data:
+            shares = data[0]
+            symbol = data[1]
+            name = data[2]
+            title = "Edit item from portfolio"
+            btntext = "Edit"
+            edit = True
         else:
-            self.window_in_fullscreen = False
+            shares = "0"
+            symbol = ""
+            name = ""
+            title = "Add to portfolio"
+            btntext = "Add"
+            edit = False
+
+        dlg = gtk.Dialog(title=title, parent=None, flags=0)
+        dlg.set_has_separator(False)
+
+        button1 = hildon.PickerButton(fhsize, horbtn)
+        data = ["50", "100", "200", "300", "400", "500", "600", "700", "800",
+                "900", "1000"]
+        selector = self.create_selector(data, True)
+        button1.set_selector(selector)
+        button1.set_title("Your shares")
+        button1.set_value(shares)
+        dlg.vbox.pack_start(button1, False, False, 0)
+
+        entry1 = hildon.Entry(fhsize)
+        entry1.set_text(name)
+        entry2 = hildon.Entry(fhsize)
+        entry2.set_text(symbol)
+
+        entry1.set_placeholder("Name")
+        entry1.connect("activate", self.add_item, dlg, button1, entry1,
+                        entry2, edit, seliter)
+        dlg.vbox.pack_start(entry1, False, False, 0)
+
+        entry2.connect("activate", self.add_item, dlg, button1, entry1,
+                        entry2, edit, seliter)
+        entry2.set_placeholder("Yahoo Finance symbol")
+        dlg.vbox.pack_start(entry2, False, False, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label(btntext)
+        button.connect("clicked", self.add_item, dlg, button1, entry1,
+                        entry2, edit, seliter)
+        dlg.vbox.pack_start(button, False, False, 0)
 
-    #F6 fullscreen, F7 bigger font, F8 smaller font
-    def on_key_press(self, widget, event, *args):  
-        if event.keyval == gtk.keysyms.F6:
-            if self.window_in_fullscreen:
-                self.window.unfullscreen ()
+        dlg.show_all()
+        dlg.run()
+        dlg.destroy()
+
+    def add_item(self, widget, dlg, button, entry1, entry2, edit, seliter):
+        symbol = entry2.get_text()
+        name = entry1.get_text()
+        shares = button.get_value()
+
+        if name == '' or symbol == '':
+            self.show_info_banner(widget, "Must add the name and symbol")
+            return
+
+        self.add_to_portfolio(widget, button, symbol, name)
+        dlg.destroy()
+
+        if edit:
+            self.portfolio_model.set(seliter, 0, symbol, 1, name, 2, shares,
+                                       3, "-", 4, "-", 5, "-", 6, "green")
+        else:
+            niter = self.portfolio_model.append()
+            self.portfolio_model.set(niter, 0, symbol, 1, name, 2, shares,
+                                    3, "-", 4, "-", 5, "-", 6, "green")
+
+    def remove_item(self, widget):
+        win = hildon.StackableWindow()
+        win.fullscreen()
+        toolbar = hildon.EditToolbar("Choose items to delete", "Delete")
+        win.set_edit_toolbar(toolbar)
+
+        vbox = gtk.VBox()
+        parea = hildon.PannableArea()
+        tv = hildon.GtkTreeView(ui_edit)
+        selection = tv.get_selection()
+        selection.set_mode(gtk.SELECTION_MULTIPLE)
+        tv.set_model(self.portfolio_model)
+        self._tv_remove_portfolio_columns(tv)
+        parea.add(tv)
+
+        toolbar.connect("button-clicked", self.delete_from_portfolio, win, tv,
+                        selection)
+        toolbar.connect_object("arrow-clicked", gtk.Window.destroy, win)
+
+        vbox.pack_start(parea, True, True, 0)
+        win.add(vbox)
+        win.show_all()
+
+    def delete_from_portfolio(self, widget, win, tv, selection):
+        if not self.is_treeview_selected(tv):
+            return
+
+        conf = self.show_confirmation(win, "Delete items?")
+
+        if conf:
+            try:
+                selmodel, selected = selection.get_selected_rows()
+                iters = [selmodel.get_iter(path) for path in selected]
+                for i in iters:
+                    symbol = selmodel.get_value(i, 0)
+                    settings.delete_item_from_portfolio(settingsdb, symbol)
+                    selmodel.remove(i)
+            except:
+                logger.exception("Deleting item from portfolio")
+                self.info_banner(widget, "Error deleting item")
+
+    def _tv_remove_portfolio_columns(self, treeview):
+        column = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=0)
+        column.set_visible(False)
+        treeview.append_column(column)
+
+        column = gtk.TreeViewColumn('Name', gtk.CellRendererText(), text=1)
+        column.set_property("expand", True)
+        treeview.append_column(column)
+
+        column = gtk.TreeViewColumn('Shares', gtk.CellRendererText(), text=2)
+        column.set_visible(False)
+        treeview.append_column(column)
+
+        column = gtk.TreeViewColumn('Price', gtk.CellRendererText(), text=3)
+        column.set_visible(False)
+        treeview.append_column(column)
+
+    def refresh_portfolio(self, widget, tv, win):
+        data = settings.load_portfolio(settingsdb)
+        for item in data:
+            item.append('-')
+            item.append('-')
+        import thread
+        winprogind(win, 1)
+        thread.start_new_thread(self._do_refresh_portfolio, (data, tv, win))
+
+    def _do_refresh_portfolio(self, data, tv, win):
+        print data
+        for item in data:
+            item[3], item[4] = self.get_portfolio_data(item[0])
+            try:
+                ch_percent = \
+                        100.0 * float(item[4])/(float(item[3]) - \
+                        float(item[4]))
+            except ValueError:
+                ch_percent = 0.0
+
+            item[5] = '%6.2f %%' % ch_percent
+
+
+        print data
+        self.portfolio_model = self._create_portfolio_model(data)
+        tv.set_model(self.portfolio_model)
+        winprogind(win, 0)
+
+    def get_portfolio_data(self, symbol):
+        from ystockquote import ystockquote as yt
+        try:
+            data = yt.get_all(symbol)
+            return data['price'], data['change']
+        except:
+            logger.exception("Getting price from Yahoo: %s" % symbol)
+            return "-", "-"
+
+    def _create_portfolio_model(self, data):
+        lstore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING,
+                                gobject.TYPE_STRING, gobject.TYPE_STRING,
+                                gobject.TYPE_STRING, gobject.TYPE_STRING,
+                                gobject.TYPE_STRING)
+        for item in data:
+            iter = lstore.append()
+            if '+' in item[4]:
+                color = 'green'
             else:
-                self.window.fullscreen () 
-
-    def on_about(self, widget):
-        dialog = gtk.AboutDialog()
-        dialog.set_name("StockThis")
-        dialog.set_version("0.1")
-        dialog.set_copyright("Copyright © 2009")
-        dialog.set_website("http://stockthis.garage.maemo.org")
-        dialog.set_authors(["Daniel Martin Yerga <dyerga@gmail.com>"])
-        logo = gtk.gdk.pixbuf_new_from_file(imgdir + "stockthis.png")
-        dialog.set_logo(logo)
-        dialog.set_license("This program is released under the GNU\nGeneral Public License. Please visit \nhttp://www.gnu.org/copyleft/gpl.html\nfor details.")
-        dialog.set_artists(["Logo by Daniel Martin Yerga"])
+                color = 'red'
+            lstore.set(iter, 0, item[0], 1, item[1], 2, item[2], 3, item[3],
+                        4, item[4], 5, item[5], 6, color)
+        return lstore
+
+    def _tv_portfolio_columns(self, treeview):
+        column = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=0)
+        column.set_visible(False)
+        treeview.append_column(column)
+
+        column = gtk.TreeViewColumn('Name', gtk.CellRendererText(), text=1)
+        column.set_property("expand", True)
+        treeview.append_column(column)
+
+        column = gtk.TreeViewColumn('Shares', gtk.CellRendererText(), text=2)
+        treeview.append_column(column)
+
+        column = gtk.TreeViewColumn('Price', gtk.CellRendererText(), text=3)
+        treeview.append_column(column)
+
+        column = gtk.TreeViewColumn('Change', gtk.CellRendererText(), text=4)
+        treeview.append_column(column)
+
+
+        renderer = gtk.CellRendererText()
+        renderer.set_property("foreground-set", True)
+        column = gtk.TreeViewColumn('%', renderer, text=5, foreground=6)
+        treeview.append_column(column)
+
+    def show_confirmation(self, window, msg):
+        dialog = hildon.hildon_note_new_confirmation(window, msg)
+        dialog.show_all()
+        result = dialog.run()
+        if result == gtk.RESPONSE_OK:
+            dialog.destroy()
+            return True
+
+        dialog.destroy()
+        return False
+
+    def show_information_note(self, window, msg):
+        dialog = hildon.hildon_note_new_information(window, msg)
+        dialog.show_all()
+        result = dialog.run()
+        dialog.destroy()
+
+    def show_info_banner(self, widget, msg):
+        hildon.hildon_banner_show_information(widget, 'qgn_note_infoprint', msg)
+
+    def is_treeview_selected(self, treeview):
+        selection = treeview.get_selection()
+        if selection.count_selected_rows() == 0:
+            self.show_info_banner(treeview, 'No selected item')
+            return False
+        else:
+            return True
+
+class About:
+
+    def __init__(self, widget):
+        self.abdialog = gtk.Dialog()
+        self.abdialog.set_title("About StockThis")
+
+        notebook = gtk.Notebook()
+        notebook.set_show_tabs(False)
+        notebook.set_scrollable(False)
+        notebook.set_show_border(False)
+
+        # Description page #
+        vbox = gtk.VBox()
+
+        label = gtk.Label()
+        label.set_markup("<b><big>StockThis %s</big></b>" % VERSION)
+        vbox.pack_start(label, True, True, 0)
+
+        label = gtk.Label("Stocks application with big database")
+        vbox.pack_start(label, True, True, 0)
+
+        label = gtk.Label("GNU General Public License")
+        vbox.pack_start(label, True, True, 0)
+
+        url = "http://stockthis.garage.maemo.org"
+        webbtn = gtk.LinkButton(url, "Web")
+        vbox.pack_start(webbtn, True, True, 0)
+        gtk.link_button_set_uri_hook(self.launch_browser)
+
+        notebook.append_page(vbox, gtk.Label())
+
+        # Credits page #
+        vbox = gtk.VBox()
+        textview = hildon.TextView()
+        textview.set_cursor_visible(False)
+        textview.set_wrap_mode(gtk.WRAP_WORD)
+        text = "Written by Daniel Martin Yerga (dyerga@gmail.com)"
+        textview.get_buffer().set_text(text)
+
+        parea = hildon.PannableArea()
+        parea.add(textview)
+
+        vbox.pack_start(parea, True, True, 0)
+        notebook.append_page(vbox, gtk.Label())
+
+
+        # Donate page #
+        vbox = gtk.VBox()
+
+        textview = hildon.TextView()
+        textview.set_cursor_visible(False)
+        textview.set_wrap_mode(gtk.WRAP_WORD)
+        text = """StockThis is a free software application.
+Developing good software takes time and hard work.
+StockThis's author develops the program in his spare time.
+If you like the program and it's helpful, consider donating a small amount of money.
+Donations are a great incentive and help the developer feel that the hard work is appreciated.
+"""
+        textview.get_buffer().set_text(text)
+
+        parea = hildon.PannableArea()
+        parea.add(textview)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title("Make donation")
+        url = "http://stockthis.garage.maemo.org/donate.html"
+        button.connect("clicked", self.launch_browser, url)
+        vbox.pack_start(button, False, False, 0)
+        vbox.pack_start(parea, True, True, 0)
+
+        notebook.append_page(vbox, gtk.Label())
+
+        # Report page #
+        vbox = gtk.VBox()
+
+        textview = hildon.TextView()
+        textview.set_cursor_visible(False)
+        textview.set_wrap_mode(gtk.WRAP_WORD)
+        text = """StockThis is being improved thanks to bug reports that users have submitted. The author appreciates these reports.
+If the application is having an error when you're using it, you have two choices to report this error:
+1) Send the log from the button above (if there's an error in the log).
+2) Press the button and read how to report a bug."""
+        textview.get_buffer().set_text(text)
+
+        parea = hildon.PannableArea()
+        parea.add(textview)
+
+        hbox = gtk.HBox()
+        hbox.set_homogeneous(True)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title("Report error")
+        url = "http://stockthis.garage.maemo.org/reporting.html"
+        button.connect("clicked", self.launch_browser, url)
+        hbox.pack_start(button, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title("Log")
+        button.connect("clicked", self.on_show_log)
+        hbox.pack_start(button, True, True, 0)
+
+        vbox.pack_start(hbox, False, False, 0)
+        vbox.pack_start(parea, True, True, 0)
+
+        notebook.append_page(vbox, gtk.Label())
+
+        # Rate page #
+        vbox = gtk.VBox()
+
+        textview = hildon.TextView()
+        textview.set_cursor_visible(False)
+        textview.set_wrap_mode(gtk.WRAP_WORD)
+        text = """The downloads section in maemo.org has a nice system where you can rate applications.
+If you consider StockThis a good application (or a bad one too), you could rate it in maemo.org site."""
+        textview.get_buffer().set_text(text)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title("Rate StockThis")
+        url = "http://maemo.org/downloads/product/Maemo5/stockthis"
+        button.connect("clicked", self.launch_browser, url)
+        image = gtk.Image()
+        image.set_from_file(imgdir + "maemoorg.png")
+        vbox.pack_start(button, False, False, 0)
+        vbox.pack_start(image, False, False, 5)
+        vbox.pack_start(textview, True, True, 0)
+
+        notebook.append_page(vbox, gtk.Label())
+
+        # Buttons #
+        self.abdialog.vbox.pack_start(notebook, True, True, 0)
+
+        hbox = gtk.HBox()
+
+        descbutton = hildon.GtkRadioButton(fhsize)
+        descbutton.set_mode(False)
+        descbutton.set_active(True)
+        descbutton.set_label('Description')
+        descbutton.connect("toggled", self.change_tab, notebook, 0)
+        hbox.pack_start(descbutton, True, True, 0)
+
+        button = hildon.GtkRadioButton(fhsize)
+        button.set_mode(False)
+        button.set_active(True)
+        button.set_label('Credits')
+        button.set_group(descbutton)
+        button.connect("toggled", self.change_tab, notebook, 1)
+        hbox.pack_start(button, True, True, 0)
+
+        button = hildon.GtkRadioButton(fhsize)
+        button.set_mode(False)
+        button.set_label('Donate')
+        button.set_group(descbutton)
+        button.connect("clicked", self.change_tab, notebook, 2)
+        hbox.pack_start(button, True, True, 0)
+
+        button = hildon.GtkRadioButton(fhsize)
+        button.set_mode(False)
+        button.set_label('Report')
+        button.set_group(descbutton)
+        button.connect("clicked", self.change_tab, notebook, 3)
+        hbox.pack_start(button, True, True, 0)
+
+        button = hildon.GtkRadioButton(fhsize)
+        button.set_mode(False)
+        button.set_label('Rate')
+        button.set_group(descbutton)
+        button.connect("clicked", self.change_tab, notebook, 4)
+        hbox.pack_start(button, True, True, 0)
+
+        self.abdialog.vbox.pack_start(hbox, False, False, 0)
+
+        self.abdialog.show_all()
+        self.abdialog.run()
+        self.abdialog.destroy()
+
+    def change_tab(self, widget, notebook, number):
+        notebook.set_current_page(number)
+
+    def launch_browser(self, widget, url):
+        import dbus
+        bus = dbus.SystemBus()
+        proxy = bus.get_object("com.nokia.osso_browser", "/com/nokia/osso_browser/request")
+        iface = dbus.Interface(proxy, 'com.nokia.osso_browser')
+
+        self.abdialog.destroy()
+
+        iface.open_new_window(url)
+
+    def on_show_log(self, widget):
+        Log(widget, logfile)
+
+
+class Log:
+
+    def __init__(self, widget, logfile):
+        #Log dialog UI
+        dialog = gtk.Dialog(title='Log', parent=None)
+
+        dialog.set_size_request(600, 350)
+
+        parea = hildon.PannableArea()
+        parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
+
+        textview = hildon.TextView()
+        textview.set_property("editable", False)
+        textview.set_property("wrap-mode", gtk.WRAP_WORD)
+
+        log = open(logfile, 'r')
+        logtext = log.read()
+        log.close()
+
+        textview.get_buffer().set_text(logtext)
+        parea.add(textview)
+
+        dialog.vbox.pack_start(parea, True, True, 0)
+
+        hbox = gtk.HBox()
+
+        save_btn = hildon.Button(fhsize, horbtn)
+        save_btn.set_title("Save")
+        save_btn.connect('clicked', self.save, logfile, dialog)
+
+        clear_btn = hildon.Button(fhsize, horbtn)
+        clear_btn.set_title("Clear")
+        clear_btn.connect('clicked', self.clear, textview, logfile)
+
+        send_btn = hildon.Button(fhsize, horbtn)
+        send_btn.set_title('Send')
+        send_btn.connect('clicked', self.send, dialog, logfile)
+
+        hbox.pack_start(save_btn, True, True, 0)
+        hbox.pack_start(clear_btn, True, True, 0)
+        hbox.pack_start(send_btn, True, True, 0)
+
+        dialog.vbox.pack_start(hbox, False, False, 0)
+
+        dialog.show_all()
         dialog.run()
         dialog.destroy()
-          
+
+    def show_filechooser(self, window, title, name, EXT):
+        action = gtk.FILE_CHOOSER_ACTION_SAVE
+
+        m = hildon.FileSystemModel()
+        file_dialog = hildon.FileChooserDialog(window, action, m)
+        file_dialog.set_title(title)
+
+        file_dialog.set_current_name(name)
+        HOME = os.path.expanduser("~")
+
+        if os.path.exists(HOME + '/MyDocs/.documents'):
+            file_dialog.set_current_folder(HOME + '/MyDocs/.documents')
+        else:
+            file_dialog.set_current_folder(HOME)
+
+        file_dialog.set_default_response(gtk.RESPONSE_CANCEL)
+
+        result = file_dialog.run()
+        if result == gtk.RESPONSE_OK:
+            namefile = file_dialog.get_filename()
+            namefile, extension = os.path.splitext(namefile)
+            namefile = namefile + "." + EXT
+        else:
+            namefile = None
+        file_dialog.destroy()
+
+        return namefile
+
+
+    def clear(self, widget, textview, logfile):
+        textview.get_buffer().set_text('')
+        f = open(logfile, 'w')
+        f.close()
+
+    def save(self, widget, logfile, dlg):
+        import shutil
+        filename = self.show_filechooser(dlg, "Save log file",
+                    "stockthis-log", "txt")
+
+        if not filename:
+            return
+
+        try:
+            shutil.copyfile(logfile, filename)
+            stockspy.show_info_banner(widget, 'Log file saved')
+        except:
+            logger.exception("Saving log file")
+            stockspy.show_info_banner(widget, 'Error saving the log file')
+
+    def send(self, widget, dlg, logfile):
+        sendtxt = ("You are going to send the log to the developers.\n"
+        "This helps the developers to track problems with the application.\n"
+        "It doesn't send any personal information (like passwords or similar).")
+
+        dialog = hildon.hildon_note_new_confirmation(dlg, sendtxt)
+        dialog.set_button_texts("Send", "Cancel")
+        dialog.show_all()
+        response = dialog.run()
+        if response == gtk.RESPONSE_OK:
+            self.do_pre_send(dlg, logfile)
+
+        dialog.destroy()
+
+    def do_pre_send(self, dlg, logfile):
+        import thread
+        hildon.hildon_gtk_window_set_progress_indicator(dlg, 1)
+        thread.start_new_thread(self._do_send, (dlg, logfile))
+
+    def _do_send(self, dlg, logfile):
+        import pycurl, shutil, random, commands
+        try:
+            rname = ''
+            for i in random.sample('abcdefghijkl123456789', 18):
+                rname += i
+
+            rnamepath = HOME + "/.stockthis/" + rname
+            shutil.copyfile(logfile, rnamepath)
+
+            gtkversion = "%s.%s.%s" % gtk.ver
+            if os.path.exists("/etc/maemo_version"):
+                mfile = open("/etc/maemo_version", 'r')
+                maemoversion = mfile.read()
+                mfile.close()
+            else:
+                maemoversion = ''
+
+            opsystem = ' '.join(os.uname())
+            pyversion = os.sys.version
+            pid = os.getpid()
+            comm = ("awk '/Private_Dirty/{sum+=$2}END{print sum \"kB\"}'"
+            " /proc/%s/smaps") % pid
+            status, dirtymem = commands.getstatusoutput(comm)
+
+            lfile = open(rnamepath, 'r')
+            log = lfile.read()
+            lfile.close()
+
+
+            log = ("%s\nPython version: %s\nGtk version: %s\n"
+            "Maemo version: %sOperating system: %s\n"
+            "Dirty Memory: %s\nLog:\n%s") % (_version, pyversion, gtkversion,
+            maemoversion, opsystem, dirtymem, log)
+
+            lfile = open(rnamepath, 'w')
+            lfile.write(log)
+            lfile.close()
+
+            url = "http://yerga.net/logs/uploader.php"
+            data = [('uploadedfile', (pycurl.FORM_FILE, rnamepath)),]
+            mycurl = pycurl.Curl()
+            mycurl.setopt(pycurl.URL, url)
+            mycurl.setopt(pycurl.HTTPPOST, data)
+
+            mycurl.perform()
+            mycurl.close()
+            os.remove(rnamepath)
+
+            gtk.gdk.threads_enter()
+            stockspy.show_info_banner(dlg, 'Log sent')
+            gtk.gdk.threads_leave()
+            hildon.hildon_gtk_window_set_progress_indicator(dlg, 0)
+        except:
+            logger.exception("Sending log file")
+            gtk.gdk.threads_enter()
+            stockspy.show_info_banner(dlg, 'Error sending the log file')
+            gtk.gdk.threads_leave()
+            hildon.hildon_gtk_window_set_progress_indicator(dlg, 0)
+
+
 if __name__ == "__main__":
     stockspy = StocksPy()
     gtk.gdk.threads_enter()
     gtk.main()
     gtk.gdk.threads_leave()
-