more markets, search function, and a bunch of minor things
[stockthis] / stockthis.py
index 0fa9352..86fb395 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>
 # Version 0.1
 #
 
+_version = "StockThis 0.3 beta1 rev1"
+
 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.2", False)
-except:
-    OSSO = False
-
-from marketdata import markets, idmarket, localmarkets, localids
+import os
+import hildon
+import marketdata
+import settings
+import logging
+import sys
 
-#TODO: detect if running in Fremantle
-FREMANTLE=True
+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/'
+    runninglocally = False
 else:
-    imgdir = '/usr/share/stockthis/pixmaps/'
-
-loading_img = imgdir + 'loading.gif'
-
-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)
+    runninglocally = True
 
-        self.window.set_default_size(800, 480)
-        self.window.set_title('StockThis')
-        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_app_menu(menu)
-                about_menu = gtk.Button("About")
-                about_menu.connect("clicked", self.on_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
+HOME = os.path.expanduser("~")
 
+settingsdb, imgdir, configdir, logfile = \
+    settings.define_paths(runninglocally, HOME)
 
-        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)
+logger = logging.getLogger('st')
+logging.basicConfig(filename=logfile,level=logging.ERROR, filemode='w')
 
-        self.markets_btn = gtk.Button('Markets')
-        self.markets_btn.connect("clicked", self.create_markets_view)
-        self.markets_btn.set_property("can_focus", False)
+DEBUG = True
 
-        self.components_btn = gtk.Button('Instruments')
-        self.components_btn.connect("clicked", self.show_components_view)
-        self.components_btn.set_property("can_focus", False)
+if DEBUG:
+    #set the main logger to DEBUG
+    logger.setLevel(logging.DEBUG)
 
-        self.graph_btn = gtk.Button('Graph')
-        self.graph_btn.connect("clicked", self.create_graphs_view)
-        self.graph_btn.set_property("can_focus", False)
+    #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)
 
-        self.refresh_btn = gtk.Button('Refresh')
-        self.refresh_btn.connect("clicked", self.refresh_stock_data)
-        self.refresh_btn.set_property("can_focus", False)
+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
 
-        self.quotes_btn = gtk.Button('Quote')
-        self.quotes_btn.connect("clicked", self.show_quotes_view)
-        self.quotes_btn.set_property("can_focus", False)
+allnames = []
+allsymbols = []
 
-        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)
+gtk.gdk.threads_init()
 
-        self.mainbox = gtk.VBox()
+class StocksPy:
 
+    def __init__(self):
+        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)
 
-        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)
+        self.create_menu(self.window)
 
-        vbox.pack_start(self.swin, True, True, 0)
+        vbox = gtk.VBox()
+        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(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()
-        self.components_trv.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_HORIZONTAL)
-
-        if not FREMANTLE:
-            selection = self.components_trv.get_selection()
-            selection.connect("changed", self.changed_selection, ids)
-        else:
-            self.components_trv.connect("row-activated", self.select_component, 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 select_component(self, widget, path, column, ids):
-        self.create_quotes_view(widget,self.components_model[path][1] )
-
-    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
-
-    def _components_trv_columns(self, treeview):
-        renderer = gtk.CellRendererText()
-        renderer.set_property('scale', 1.3)
-        #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 create_menu(self, window):
+        menu = hildon.AppMenu()
+        window.set_app_menu(menu)
+        button = gtk.Button("About")
+        button.connect("clicked", About)
+        menu.append(button)
+        button = gtk.Button("Log")
+        button.connect("clicked", Log, logfile)
+        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("StockThis - " + inmodel[path][1])
 
-    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)
-        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)
+        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)
+        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)
 
-    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()
+        window.add(vbox)
+        window.show_all()
 
-        #actual_view = self.mainbox.get_children()
-        #actual_view[0].destroy()
+    def horizontal_mov(self, parea, direction, initial_x, initial_y):
+        #direction = 2 right-to-left
+        #direction = 3 lefto-to-right
 
-        try:
-            self.graphbox.destroy()
-        except:
-            pass
+        vadj = parea.get_vadjustment()
+        val = vadj.get_value()
 
-        for i in range(len(localids)):
-            if kind in localids[i]:
-                ind1, ind2 = i, localids[i].index(kind)
+        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("StockThis - Quotes View - " + quote[1])
 
-        self.quotesbox = gtk.VBox()
+        vbox = gtk.VBox()
 
-        self.titlelbl = gtk.Label('')
-        self.titlelbl.set_markup('<b><big>'+localmarkets[ind1][ind2].replace('&', '')+'</big></b>')
+        ltitle = gtk.Label('')
+        ltitle.set_markup('<b><big>' + quote[1].replace('&', '') +
+                                 '</big></b>')
         color = gtk.gdk.color_parse("#03A5FF")
-        self.titlelbl.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)
+        ltitle.modify_fg(gtk.STATE_NORMAL, color)
+
+        parea = hildon.PannableArea()
+
+        vbox1 = gtk.VBox()
+
+        hbox = gtk.HBox()
+        label = gtk.Label('')
+        label.set_markup('<b><big>Price:</big></b>')
+        lprice = gtk.Label('')
+        hbox.pack_start(label, False, False, 20)
+        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>Change:</big></b>')
+        lchange = gtk.Label('')
+        lpercent = gtk.Label('')
+        hbox.pack_start(label, False, False, 20)
+        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>Volume:</big></b>')
+        lvolume = gtk.Label('')
+        hbox.pack_start(label, False, False, 20)
+        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>52 week high:</big></b>')
+        l52whigh = gtk.Label('')
+        hbox.pack_start(label, False, False, 20)
+        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>52 week low:</big></b>')
+        l52wlow = gtk.Label('')
+        hbox.pack_start(label, False, False, 20)
+        hbox.pack_start(l52wlow, False, False, 140)
+        vbox1.pack_start(hbox, True, True, 0)
+
+        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()
+        label = gtk.Label('')
+        label.set_markup('<b><big>Shares:</big></b>')
+        lshares = gtk.Label(shares)
+        hbox1.pack_start(label, False, False, 20)
+        hbox1.pack_start(lshares, False, False, 220)
 
-        label2 = gtk.Label('')
-        label2.set_markup('<b><big>Price:</big></b>')
-        self.lprice = gtk.Label('')
+        hbox2 = gtk.HBox()
+        label = gtk.Label('')
+        label.set_markup('<b><big>Holdings Value:</big></b>')
+        holdingsvalue = gtk.Label("")
+        hbox2.pack_start(label, False, False, 20)
+        hbox2.pack_start(holdingsvalue, False, False, 105)
 
-        hbox1.pack_start(label2, False, False, 50)
-        hbox1.pack_start(self.lprice, False, False, 185)
+        hbox3 = gtk.HBox()
+        label = gtk.Label('')
+        label.set_markup("<b><big>Day's Value Change:</big></b>")
+        dayvaluechange = gtk.Label("")
+        hbox3.pack_start(label, False, False, 20)
+        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)
 
-        hbox2 = gtk.HBox()
+        parea.add_with_viewport(vbox1)
 
-        label4 = gtk.Label('')
-        label4.set_markup('<b><big>Change:</big></b>')
-        self.lchange = gtk.Label('')
-        self.lpercent = gtk.Label('')
+        widgets = [win, ltitle, lprice, lchange,  lpercent, lvolume, l52whigh,
+                    l52wlow, lshares, holdingsvalue, dayvaluechange]
 
-        hbox2.pack_start(label4, False, False, 50)
-        hbox2.pack_start(self.lchange  , False, False, 145)
-        hbox2.pack_start(self.lpercent, False, False, 0)
+        toolbar = self.main_toolbar(True, portfolio, widgets, quote[0], quote[1], False)
 
-        hbox3 = gtk.HBox()
+        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)
 
-        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)
+        win.add(vbox)
+        win.show_all()
+        self.show_data(quote[0], widgets, shares)
 
-        hbox4 = gtk.HBox()
+    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")
+            return shares
 
-        label9 = gtk.Label('')
-        label9.set_markup('<b><big>52 week high:</big></b>')
-        self.l52whigh = gtk.Label('')
+    def add_to_portfolio(self, widget, button, symbol, name):
+        shares = button.get_value()
 
-        hbox4.pack_start(label9, False, False, 50)
-        hbox4.pack_start(self.l52whigh , False, False, 55)
+        try:
+            portfolio = settings.load_portfolio(settingsdb)
+            index = "None"
+            for item in portfolio:
+                if symbol in item:
+                    index = portfolio.index(item)
 
-        hbox5 = gtk.HBox()
+            item = [symbol, name, shares, '-']
 
-        label11 = gtk.Label('')
-        label11.set_markup('<b><big>52 week low:</big></b>')
-        self.l52wlow = gtk.Label('')
+            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)
 
-        hbox5.pack_start(label11, False, False, 50)
-        hbox5.pack_start(self.l52wlow , False, False, 70)
+            self.show_info_banner(widget, "Added to portfolio")
+        except:
+            logger.exception("Adding to portfolio")
+            self.show_info_banner(widget, "Error adding to portfolio")
 
-        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(self.titlelbl, 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)
+    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])
 
-        self.mainbox.pack_start(self.quotesbox, True, True, 0)
-        self.mainbox.show_all()
-        self.compbox.hide()
-        self.databox.hide()
+        return selector
 
-    def show_data(self, kind):
+    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
+        win, ltitle, lprice, lchange,  lpercent, lvolume, l52whigh, l52wlow, lshares, holdingsvalue, dayvaluechange = widgets
+
         try:
-            data = yt.get_all(kind)
+            data = yt.get_all(symbol)
         except:
-            print 'Failed to get internet data'
+            logger.exception("Getting data from Yahoo")
             data = {'price': 'N/A', 'change': 'N/A', 'volume':'N/A',
                     '52_week_high': 'N/A', '52_week_low': 'N/A'}
-            self.titlelbl.set_markup('<b><big>Failed to get data</big></b>')
+            ltitle.set_markup('<b><big>Failed to get data</big></b>')
 
         try:
-            ch_percent = 100.0 * float(data['change'])/(float(data['price'])-float(data['change']))
+            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)
+        lpercent.modify_fg(gtk.STATE_NORMAL, color)
+        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'])
+        lvolume.set_label(data['volume'])
+        l52whigh.set_label(data['52_week_high'])
+        l52wlow.set_label(data['52_week_low'])
 
-        self.databox.show_all()
-        self.imagebox.hide()
+        try:
+            daychange = float(shares)*float(data['change'])
+        except ValueError:
+            daychange = 'N/A'
+        try:
+            holdvalue = float(shares)*float(data['price'])
+        except ValueError:
+            holdvalue = 'N/A'
 
-    def refresh_stock_data(self, widget):
-        self.show_data(self.stocks_id)
+        dayvaluechange.set_label(str(daychange))
+        holdingsvalue.set_label(str(holdvalue))
 
-    def create_graphs_view(self, widget):
-        self.graph_btn.hide()
-        self.refresh_btn.hide()
-        self.quotes_btn.show()
+        winprogind(win, 0)
 
-        self.graph = gtk.Image()
+    def refresh_stock_data(self, widget, portfolio, widgets, symbol):
+        if portfolio:
+            shares = self.get_shares_from_symbol(symbol)
+        else:
+            shares = "0"
 
-        kind = self.stocks_id
+        self.show_data(symbol, widgets, shares)
 
-        self.show_graph(None, '1d', kind)
+    def show_graph_view(self, widget, symbol, name):
+        win = hildon.StackableWindow()
+        self.create_menu(win)
+        win.set_title("StockThis - Graph View - " + name)
 
-        for i in range(len(localids)):
-            if kind in localids[i]:
-                ind1, ind2 = i, localids[i].index(kind)
+        vbox = gtk.VBox()
+        toolbar = self.main_toolbar(False, True, None, '', '', False)
 
-        #self.mainbox.destroy()
-        #self.mainbox = gtk.VBox()
-        #self.swin.add_with_viewport(self.mainbox)
+        self.graphs_title = gtk.Label(name)
+        color = gtk.gdk.color_parse("#03A5FF")
+        self.graphs_title.modify_fg(gtk.STATE_NORMAL, color)
 
-        actual_view = self.mainbox.get_children()
-        for a_widget in actual_view:
-            a_widget.destroy()
+        parea = hildon.PannableArea()
 
-        self.graphbox = gtk.VBox()
+        hbox = gtk.HBox()
+        hbox.set_homogeneous(True)
 
-        self.graphs_title = gtk.Label(localmarkets[ind1][ind2])
-        color = gtk.gdk.color_parse("#03A5FF")
-        self.graphs_title.modify_fg(gtk.STATE_NORMAL, color)
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label('1d')
+        button.connect("clicked", self.show_graph, '1d', win, symbol)
+        hbox.pack_start(button)
 
-        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(self.graphs_title, 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):
+        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)
+
+        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 = gtk.VBox()
+        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
+            url = 'http://uk.ichart.yahoo.com/b?s=%s' % symbol
         elif option == '5d':
-            url = 'http://uk.ichart.yahoo.com/w?s=%s' % kind
+            url = 'http://uk.ichart.yahoo.com/w?s=%s' % symbol
         elif option == '3m':
-            url = 'http://chart.finance.yahoo.com/c/3m/s/%s' % kind.lower()
+            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' % kind.lower()
+            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' % kind.lower()
+            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' % kind.lower()
+            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' % kind.lower()
+            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' % kind.lower()
+            url = 'http://chart.finance.yahoo.com/c/my/s/%s' % symbol.lower()
 
         try:
             myimg = urllib2.urlopen(url)
-            imgdata=myimg.read()
+            imgdata = myimg.read()
 
             pbl = gtk.gdk.PixbufLoader()
             pbl.write(imgdata)
@@ -519,41 +545,716 @@ class StocksPy:
             pbuf = pbl.get_pixbuf()
             pbl.close()
             self.graph.set_from_pixbuf(pbuf)
+            winprogind(win, 0)
         except:
-            print 'no internet data'
+            logger.exception("Getting graph data")
+            winprogind(win, 0)
             self.graphs_title.set_label('Failed to get data')
             self.graph.destroy()
 
+    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)
+
+
+        stockiconspath = "/usr/share/icons/hicolor/48x48/hildon/"
+        info_btn = hildon.Button(fhsize, horbtn)
+        img = gtk.Image()
+        img.set_from_file(stockiconspath + "general_information.png")
+        info_btn.set_image(img)
+        info_btn.connect("clicked", self.show_app_information)
+
+        search_btn = hildon.Button(fhsize, horbtn)
+        img = gtk.Image()
+        img.set_from_file(stockiconspath + "general_search.png")
+        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)
+
+        entry = hildon.Entry(fhsize)
+        dlg.vbox.pack_start(entry, False, False, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label("Search")
+        button.connect("clicked", self.do_search, entry, dlg)
+        dlg.vbox.pack_start(button, 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:
+                    if not company in allnames:
+                        allnames.append(company)
+
+            for market in marketdata.omnames:
+                for company in market:
+                    if not company in allnames:
+                        allnames.append(company)
+
+            for market in marketdata.usnames:
+                for company in market:
+                    if not company in allnames:
+                        allnames.append(company)
+
+        if allsymbols == []:
+            for market in marketdata.eusymbols:
+                for company in market:
+                    if not company in allsymbols:
+                        allsymbols.append(company)
+
+            for market in marketdata.omsymbols:
+                for company in market:
+                    if not company in allsymbols:
+                        allsymbols.append(company)
+
+            for market in marketdata.ussymbols:
+                for company in market:
+                    if not company in allsymbols:
+                        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()
+                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("StockThis - 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()
+
 
-    #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
+    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)
+
+        win = hildon.StackableWindow()
+        self.create_menu(win)
+        win.set_title("StockThis - Portfolio")
+
+        vbox = gtk.VBox()
+
+        parea = hildon.PannableArea()
+        tv = hildon.GtkTreeView(ui_normal)
+        tv.set_headers_visible(True)
+        self.portfolio_model = self._create_portfolio_model(data)
+        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)
+        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)
+
+        vbox.pack_start(parea, True, True, 0)
+        vbox.pack_start(hbox, False, False, 0)
+        win.add(vbox)
+        win.show_all()
+
+    def add_item_dlg(self, widget):
+        dlg = gtk.Dialog(title='Add to portfolio', 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("0")
+        dlg.vbox.pack_start(button1, False, False, 0)
+
+        entry1 = hildon.Entry(fhsize)
+        entry1.set_placeholder("Name")
+        dlg.vbox.pack_start(entry1, False, False, 0)
+
+        entry2 = hildon.Entry(fhsize)
+        entry2.set_placeholder("Yahoo Finance symbol")
+        dlg.vbox.pack_start(entry2, False, False, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label("Add")
+        button.connect("clicked", self.add_item, dlg, button1, entry1, entry2)
+        dlg.vbox.pack_start(button, False, False, 0)
+
+        dlg.show_all()
+        dlg.run()
+        dlg.destroy()
+
+
+    def add_item(self, widget, dlg, button, entry1, entry2):
+        symbol = entry2.get_text()
+        name = entry1.get_text()
+        shares = button.get_value()
+
+        self.add_to_portfolio(widget, button, symbol, name)
+        dlg.destroy()
+
+        niter = self.portfolio_model.append()
+        self.portfolio_model.set(niter, 0, symbol, 1, name, 2, shares, 3, "-")
+
+    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)
+        import thread
+        winprogind(win, 1)
+        thread.start_new_thread(self._do_refresh_portfolio, (data, tv, win))
+
+    def _do_refresh_portfolio(self, data, tv, win):
+        for item in data:
+            item[3] = self.get_price(item[0])
+
+        self.portfolio_model = self._create_portfolio_model(data)
+        tv.set_model(self.portfolio_model)
+        winprogind(win, 0)
+
+    def get_price(self, symbol):
+        from ystockquote import ystockquote as yt
+        try:
+            price = yt.get_price(symbol)
+            return price
+        except:
+            logger.exception("Getting price from Yahoo")
+            return "N/A"
+
+    def _create_portfolio_model(self, data):
+        lstore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING,
+                                gobject.TYPE_STRING, gobject.TYPE_STRING)
+        for item in data:
+            iter = lstore.append()
+            lstore.set(iter, 0, item[0], 1, item[1], 2, item[2], 3, item[3])
+        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)
+
+    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:
-            self.window_in_fullscreen = False
+            return True
 
-    #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 ()
-            else:
-                self.window.fullscreen ()
-
-    def on_about(self, widget):
-        dialog = gtk.AboutDialog()
-        dialog.set_name("StockThis")
-        dialog.set_version("0.2")
-        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"])
+class About:
+
+    def __init__(self, widget):
+        self.abdialog = gtk.Dialog(title='About', parent=None, flags=0)
+        self.abdialog.set_has_separator(False)
+        self.abdialog.set_size_request(-1, 400)
+
+        self.info_lb = gtk.Label()
+        self.info_lb.set_line_wrap(True)
+
+        self.id = False
+
+        hbox1 = gtk.HBox()
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title('Description')
+        button.connect("clicked", self.show_info, 'description')
+        hbox1.pack_start(button, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title('Credits')
+        button.connect("clicked", self.show_info, 'credits')
+        hbox1.pack_start(button, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title('License')
+        button.connect("clicked", self.show_info, 'license')
+        hbox1.pack_start(button, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title('Donate')
+        button.connect("clicked", self.show_info, 'donate')
+        hbox1.pack_start(button, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title('Report ')
+        button.connect("clicked", self.show_info, 'report')
+        hbox1.pack_start(button, True, True, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_title(' Rate ')
+        button.connect("clicked", self.show_info, 'vote')
+        hbox1.pack_start(button, True, True, 0)
+
+        self.action_btn = hildon.Button(fhsize, horbtn)
+        self.image = gtk.Image()
+
+        self.show_info(None, 'description')
+
+        self.abdialog.vbox.pack_start(self.action_btn, False, False, 0)
+        self.abdialog.vbox.pack_start(self.image, False, False, 5)
+        self.abdialog.vbox.pack_start(self.info_lb, True, True, 0)
+        self.abdialog.vbox.pack_start(hbox1, False, False, 0)
+
+        self.abdialog.show_all()
+        self.action_btn.hide()
+        self.image.hide()
+        self.abdialog.run()
+        self.abdialog.destroy()
+
+    def do_action(self, widget, action):
+        import dbus
+
+        self.abdialog.destroy()
+
+        bus = dbus.SystemBus()
+        proxy = bus.get_object("com.nokia.osso_browser", "/com/nokia/osso_browser/request")
+        iface = dbus.Interface(proxy, 'com.nokia.osso_browser')
+
+        if action == "donate":
+            url = "http://stockthis.garage.maemo.org/donate.html"
+        elif action == "report":
+            url = "http://stockthis.garage.maemo.org/reporting.html"
+        elif action == "vote":
+            url = "http://maemo.org/downloads/product/stockthis"
+
+        iface.load_url(url)
+
+    def show_info(self, widget, kind):
+        if kind == 'license':
+            self.action_btn.hide()
+            self.image.hide()
+            info = """<small><b>StockThis</b> is free software. It's using a GPL version 2 license or at your election any later version.
+
+Logo by Daniel Martin Yerga.
+</small>"""
+        elif kind == 'credits':
+            self.action_btn.hide()
+            self.image.hide()
+            info = """<small><b>Written by</b> Daniel Martin Yerga (dyerga@gmail.com)
+
+<b>Thanks</b> to everyone who has reported bugs, suggestions, giving spirits, critiques, writing blog articles about StockThis, and so on. Like always the list is extremely big and for not forget anybody, THANKS TO ALL!</small>"""
+        elif kind == 'description':
+            self.action_btn.hide()
+            self.image.hide()
+            info = """<b><big>StockThis 0.3</big></b>
+
+<i>StockThis is a stocks application for Maemo</i>
+
+<b>Web Page</b>:
+stockthis.garage.maemo.org"""
+
+        elif kind == 'donate':
+            self.action_btn.show()
+            self.image.hide()
+            self.action_btn.set_title('Make donation')
+            if self.id:
+                self.action_btn.disconnect(self.id)
+            self.id = self.action_btn.connect("clicked", self.do_action, "donate")
+            info = """<small><b>StockThis</b> is a free (and gratis) software application.
+Developing good software takes time and hard work.
+
+<b>StockThis's author</b> 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.</small>
+"""
+        elif kind == 'report':
+            self.action_btn.show()
+            self.image.hide()
+            self.action_btn.set_title('Report bug')
+            if self.id:
+                self.action_btn.disconnect(self.id)
+            self.id = self.action_btn.connect("clicked", self.do_action, "report")
+            info = """<small>StockThis is being improved thanks to bug reports that users have submitted. The author appreciates these reports.
+If the application is raising an error when you're using it, you have two choices to report this error:
+1) Send the log from the application menu (if there's an error in the log).
+2) Press the button and write a bug report with as much information as possible.</small>"""
+        elif kind == 'vote':
+            self.action_btn.show()
+            self.image.show()
+            self.image.set_from_file(imgdir + "maemoorg.png")
+            self.action_btn.set_title('Rate StockThis')
+            if self.id:
+                self.action_btn.disconnect(self.id)
+            self.id = self.action_btn.connect("clicked", self.do_action, "vote")
+            info = """<small>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.</small>"""
+
+        self.info_lb.set_markup(info)
+
+
+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()