5f6892e55bcd294e3ea29928196d9ed5da51ac94
[stockthis] / stockthis.py
1 #!/usr/bin/env python2.5
2 # -*- coding: UTF8 -*-
3 # Copyright (C) 2008 by Daniel Martin Yerga
4 # <dyerga@gmail.com>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 #
19 # StocksPy: Application to get stocks data from Yahoo Finance.
20 # Version 0.1
21 #
22
23 import urllib2
24 import gtk, gobject
25 import os
26 import hildon
27
28 #import osso
29 #osso_c = osso.Context("net.yerga.stockthis", "0.3", False)
30
31 import marketdata
32 import settings
33
34
35 #detect if is ran locally or not
36 import sys
37 runningpath = sys.path[0]
38
39 if '/usr/share' in runningpath:
40     runninglocally = False
41 else:
42     runninglocally = True
43
44 HOME = os.path.expanduser("~")
45
46 settingsdb, imgdir, configdir, logfile = \
47     settings.define_paths(runninglocally, HOME)
48
49
50 fhsize = gtk.HILDON_SIZE_FINGER_HEIGHT
51 horbtn = hildon.BUTTON_ARRANGEMENT_HORIZONTAL
52 ui_normal = gtk.HILDON_UI_MODE_NORMAL
53 ui_edit = gtk.HILDON_UI_MODE_EDIT
54 winprogind = hildon.hildon_gtk_window_set_progress_indicator
55
56 gtk.gdk.threads_init()
57
58 class StocksPy:
59
60     def __init__(self):
61         self.program = hildon.Program()
62         self.program.__init__()
63         gtk.set_application_name("StockThis")
64         self.window = hildon.StackableWindow()
65         self.window.set_default_size(800, 480)
66         self.program.add_window(self.window)
67         self.window.connect("destroy", gtk.main_quit)
68
69         menu = hildon.AppMenu()
70         self.window.set_app_menu(menu)
71         button = gtk.Button("About")
72         button.connect("clicked", About)
73         menu.append(button)
74         menu.show_all()
75
76         vbox = gtk.VBox()
77         toolbar = self.main_toolbar(False, False, None, '', '')
78
79         parea = hildon.PannableArea()
80         tv = hildon.GtkTreeView(ui_normal)
81         inmodel = self.__create_model(marketdata.main, marketdata.idmain)
82         tv.connect("row-activated", self.show_instrument_view, inmodel,
83                     marketdata.localmarkets, marketdata.localids,
84                     marketdata.idmain)
85         tv.set_model(inmodel)
86         self._tv_columns(tv)
87         parea.add(tv)
88
89         vbox.pack_start(parea, True, True, 0)
90         vbox.pack_start(gtk.HSeparator(), False, False, 5)
91         vbox.pack_start(toolbar, False, False, 0)
92
93         self.window.add(vbox)
94         self.window.show_all()
95
96     def show_instrument_view(self, widget, path, column, inmodel, names,
97         ids, mindex):
98         market = inmodel[path][0]
99         names = names[mindex.index(market)]
100         ids = ids[mindex.index(market)]
101
102         window = hildon.StackableWindow()
103         window.set_title("StockThis - " + inmodel[path][1])
104
105         vbox = gtk.VBox()
106         toolbar = self.main_toolbar(False, False, None, '', '')
107
108         parea = hildon.PannableArea()
109         tv = hildon.GtkTreeView(ui_normal)
110         model = self.__create_model(names, ids)
111         tv.connect("row-activated", self.show_quotes_view, model, False)
112         tv.set_model(model)
113         self._tv_columns(tv)
114         parea.add(tv)
115
116         vbox.pack_start(parea, True, True, 0)
117         vbox.pack_start(gtk.HSeparator(), False, False, 5)
118         vbox.pack_start(toolbar, False, False, 0)
119
120         window.add(vbox)
121         window.show_all()
122
123     def show_quotes_view(self, widget, path, column, model, portfolio):
124         quote = model[path][0], model[path][1]
125         print "quote:", quote[0]
126         #('EURUSD=X', 'EUR/USD')
127
128         #Currencies and ETFs should show the list now -> view = True
129         #Other items show a new list with options
130         view = False
131         for i in marketdata.localids[(len(marketdata.localids)-2):]:
132             for j in i:
133                 if quote[0] == j:
134                     print j
135                     view = True
136
137         if not view:
138             if quote[0] in marketdata.idindexes:
139                 self.show_instrument_view(widget, path, column, model,
140                                         marketdata.wnamesindexes,
141                                         marketdata.widsindexes,
142                                         marketdata.idindexes)
143                 return
144             if quote[0] in marketdata.idotmarkets:
145                 self.show_instrument_view(widget, path, column, model,
146                                         marketdata.omnames,
147                                         marketdata.omsymbols,
148                                         marketdata.idotmarkets)
149                 return
150             if quote[0] in marketdata.ideumarkets:
151                 self.show_instrument_view(widget, path, column, model,
152                                         marketdata.eunames,
153                                         marketdata.eusymbols,
154                                         marketdata.ideumarkets)
155                 return
156             if quote[0] in marketdata.idusmarkets:
157                 self.show_instrument_view(widget, path, column, model,
158                                         marketdata.usnames,
159                                         marketdata.ussymbols,
160                                         marketdata.idusmarkets)
161                 return
162
163
164         win = hildon.StackableWindow()
165         win.set_title("StockThis - Quotes View - " + quote[1])
166
167         vbox = gtk.VBox()
168
169         ltitle = gtk.Label('')
170         ltitle.set_markup('<b><big>' + quote[1].replace('&', '') +
171                                  '</big></b>')
172         color = gtk.gdk.color_parse("#03A5FF")
173         ltitle.modify_fg(gtk.STATE_NORMAL, color)
174
175         parea = hildon.PannableArea()
176
177         vbox1 = gtk.VBox()
178
179         hbox = gtk.HBox()
180         label = gtk.Label('')
181         label.set_markup('<b><big>Price:</big></b>')
182         lprice = gtk.Label('')
183         hbox.pack_start(label, False, False, 20)
184         hbox.pack_start(lprice, False, False, 245)
185         vbox1.pack_start(hbox, True, True, 0)
186
187         hbox = gtk.HBox()
188         label = gtk.Label('')
189         label.set_markup('<b><big>Change:</big></b>')
190         lchange = gtk.Label('')
191         lpercent = gtk.Label('')
192         hbox.pack_start(label, False, False, 20)
193         hbox.pack_start(lchange, False, False, 205)
194         hbox.pack_start(lpercent, False, False, 0)
195         vbox1.pack_start(hbox, True, True, 0)
196
197         hbox = gtk.HBox()
198         label = gtk.Label('')
199         label.set_markup('<b><big>Volume:</big></b>')
200         lvolume = gtk.Label('')
201         hbox.pack_start(label, False, False, 20)
202         hbox.pack_start(lvolume, False, False, 207)
203         vbox1.pack_start(hbox, True, True, 0)
204
205         hbox = gtk.HBox()
206         label = gtk.Label('')
207         label.set_markup('<b><big>52 week high:</big></b>')
208         l52whigh = gtk.Label('')
209         hbox.pack_start(label, False, False, 20)
210         hbox.pack_start(l52whigh, False, False, 110)
211         vbox1.pack_start(hbox, True, True, 0)
212
213         hbox = gtk.HBox()
214         label = gtk.Label('')
215         label.set_markup('<b><big>52 week low:</big></b>')
216         l52wlow = gtk.Label('')
217         hbox.pack_start(label, False, False, 20)
218         hbox.pack_start(l52wlow, False, False, 125)
219         vbox1.pack_start(hbox, True, True, 0)
220
221         hbox = gtk.HBox()
222         button1 = hildon.PickerButton(fhsize, horbtn)
223         data = ["50", "100", "200", "300", "400", "500", "600", "700", "800",
224                 "900", "1000"]
225         selector = self.create_selector(data, True)
226         button1.set_selector(selector)
227         button1.set_title("Your shares")
228         #FIXME: Improve as it's shown you have a component in your portfolio
229         shares = self.get_shares_from_symbol(quote[0])
230         button1.set_value(shares)
231         hbox.pack_start(button1, True, True, 0)
232
233         button = hildon.Button(fhsize, horbtn)
234         button.set_title("Add to Portfolio")
235         button.connect("clicked", self.add_to_portfolio, button1, quote[0], quote[1])
236         hbox.pack_start(button, True, True, 0)
237
238         hbox1 = gtk.HBox()
239         label = gtk.Label('')
240         label.set_markup('<b><big>Shares:</big></b>')
241         lshares = gtk.Label(shares)
242         hbox1.pack_start(label, False, False, 20)
243         hbox1.pack_start(lshares, False, False, 215)
244
245         hbox2 = gtk.HBox()
246         label = gtk.Label('')
247         label.set_markup('<b><big>Holdings Value:</big></b>')
248         holdingsvalue = gtk.Label("")
249         hbox2.pack_start(label, False, False, 20)
250         hbox2.pack_start(holdingsvalue, False, False, 85)
251
252         hbox3 = gtk.HBox()
253         label = gtk.Label('')
254         label.set_markup("<b><big>Day's Value Change:</big></b>")
255         dayvaluechange = gtk.Label("")
256         hbox3.pack_start(label, False, False, 20)
257         hbox3.pack_start(dayvaluechange, False, False, 10)
258
259         if not portfolio:
260             vbox1.pack_start(hbox, False, False, 0)
261         else:
262             vbox1.pack_start(hbox1, True, True, 0)
263             vbox1.pack_start(hbox2, True, True, 0)
264             vbox1.pack_start(hbox3, True, True, 0)
265
266         parea.add_with_viewport(vbox1)
267
268         widgets = [win, ltitle, lprice, lchange,  lpercent, lvolume, l52whigh, l52wlow, lshares, holdingsvalue, dayvaluechange]
269
270         toolbar = self.main_toolbar(True, portfolio, widgets, quote[0], quote[1])
271
272         vbox.pack_start(ltitle, False, False, 0)
273         vbox.pack_start(gtk.HSeparator(), False, False, 0)
274         vbox.pack_start(parea, True, True, 0)
275         vbox.pack_start(gtk.HSeparator(), False, False, 5)
276         vbox.pack_start(toolbar, False, False, 0)
277
278
279         win.add(vbox)
280         win.show_all()
281         self.show_data(quote[0], widgets, shares)
282
283     def get_shares_from_symbol(self, symbol):
284         portfolio_data = settings.load_portfolio(settingsdb)
285         shares = "0"
286         for item in portfolio_data :
287             if symbol in item:
288                 shares = item[2]
289         return shares
290
291     def add_to_portfolio(self, widget, button, symbol, name):
292         shares = button.get_value()
293
294         portfolio = settings.load_portfolio(settingsdb)
295         index = "None"
296         for item in portfolio:
297             if symbol in item:
298                 index = portfolio.index(item)
299
300         item = [symbol, name, shares, '-']
301
302         if index is "None":
303             settings.insert_new_item_to_portfolio(settingsdb, item)
304         else:
305             settings.delete_item_from_portfolio(settingsdb, symbol)
306             settings.insert_new_item_to_portfolio(settingsdb, item)
307
308         self.show_info_banner(widget, "Added to portfolio")
309
310
311     def create_selector(self, data, entry):
312         if entry:
313             selector = hildon.TouchSelectorEntry(text=True)
314         else:
315             selector = hildon.hildon_touch_selector_new_text()
316         for i in range(len(data)):
317             selector.append_text(data[i])
318
319         return selector
320
321     def show_data(self, symbol, widgets, shares):
322         import thread
323         winprogind(widgets[0], 1)
324         thread.start_new_thread(self.get_data, (symbol, widgets, shares))
325
326     def get_data(self, symbol, widgets, shares):
327         from ystockquote import ystockquote as yt
328         win, ltitle, lprice, lchange,  lpercent, lvolume, l52whigh, l52wlow, lshares, holdingsvalue, dayvaluechange = widgets
329
330         try:
331             data = yt.get_all(symbol)
332         except:
333             print 'Failed to get internet data'
334             data = {'price': 'N/A', 'change': 'N/A', 'volume':'N/A',
335                     '52_week_high': 'N/A', '52_week_low': 'N/A'}
336             ltitle.set_markup('<b><big>Failed to get data</big></b>')
337
338         try:
339             ch_percent = \
340                     100.0 * float(data['change'])/(float(data['price']) - \
341                     float(data['change']))
342         except ValueError:
343             ch_percent = 0.0
344
345         lprice.set_label(data['price'])
346         lchange.set_label(data['change'])
347         lpercent.set_label('%6.2f %%' % ch_percent)
348
349         if '-' in data['change']:
350             color = gtk.gdk.color_parse("#FF0000")
351         else:
352             color = gtk.gdk.color_parse("#16EB78")
353
354         lpercent.modify_fg(gtk.STATE_NORMAL, color)
355         lchange.modify_fg(gtk.STATE_NORMAL, color)
356
357         lvolume.set_label(data['volume'])
358         l52whigh.set_label(data['52_week_high'])
359         l52wlow.set_label(data['52_week_low'])
360
361         try:
362             daychange = float(shares)*float(data['change'])
363         except ValueError:
364             daychange = 'N/A'
365         try:
366             holdvalue = float(shares)*float(data['price'])
367         except ValueError:
368             holdvalue = 'N/A'
369
370         dayvaluechange.set_label(str(daychange))
371         holdingsvalue.set_label(str(holdvalue))
372
373         winprogind(win, 0)
374
375     def refresh_stock_data(self, widget, portfolio, widgets, symbol):
376         if portfolio:
377             shares = self.get_shares_from_symbol(symbol)
378         else:
379             shares = "0"
380
381         self.show_data(symbol, widgets, shares)
382
383     def show_graph_view(self, widget, symbol, name):
384         win = hildon.StackableWindow()
385         win.set_title("StockThis - Graph View - " + name)
386
387         vbox = gtk.VBox()
388         toolbar = self.main_toolbar(False, True, None, '', '')
389
390         self.graphs_title = gtk.Label(name)
391         color = gtk.gdk.color_parse("#03A5FF")
392         self.graphs_title.modify_fg(gtk.STATE_NORMAL, color)
393
394         parea = hildon.PannableArea()
395
396         hbox = gtk.HBox()
397         hbox.set_homogeneous(True)
398
399         button = hildon.Button(fhsize, horbtn)
400         button.set_label('1d')
401         button.connect("clicked", self.show_graph, '1d', win, symbol)
402         hbox.pack_start(button)
403
404         button = hildon.Button(fhsize, horbtn)
405         button.set_label('5d')
406         button.connect("clicked", self.show_graph, '5d', win, symbol)
407         hbox.pack_start(button)
408
409         button = hildon.Button(fhsize, horbtn)
410         button.set_label('3m')
411         button.connect("clicked", self.show_graph, '3m', win, symbol)
412         hbox.pack_start(button)
413
414         button = hildon.Button(fhsize, horbtn)
415         button.set_label('6m')
416         button.connect("clicked", self.show_graph, '6m', win, symbol)
417         hbox.pack_start(button)
418
419         button = hildon.Button(fhsize, horbtn)
420         button.set_label('1y')
421         button.connect("clicked", self.show_graph, '1y', win, symbol)
422         hbox.pack_start(button)
423
424         button = hildon.Button(fhsize, horbtn)
425         button.set_label('2y')
426         button.connect("clicked", self.show_graph, '2y', win, symbol)
427         hbox.pack_start(button)
428
429         button = hildon.Button(fhsize, horbtn)
430         button.set_label('5y')
431         button.connect("clicked", self.show_graph, '5y', win, symbol)
432         hbox.pack_start(button)
433
434         button = hildon.Button(fhsize, horbtn)
435         button.set_label('Max')
436         button.connect("clicked", self.show_graph, 'max', win, symbol)
437         hbox.pack_start(button)
438
439         vbox1 = gtk.VBox()
440         vbox1.pack_start(hbox, False, False, 0)
441
442         self.graph = gtk.Image()
443         vbox1.pack_start(self.graph, True, True, 0)
444
445         parea.add_with_viewport(vbox1)
446
447         vbox.pack_start(self.graphs_title, False, False, 0)
448         vbox.pack_start(gtk.HSeparator(), False, False, 0)
449         vbox.pack_start(parea, True, True, 0)
450         vbox.pack_start(gtk.HSeparator(), False, False, 5)
451         vbox.pack_start(toolbar, False, False, 0)
452
453         win.add(vbox)
454         win.show_all()
455
456         self.show_graph(None, '1d', win, symbol)
457
458     def show_graph(self, widget, option, win, symbol):
459         import thread
460         winprogind(win, 1)
461         thread.start_new_thread(self.get_graph_data, (option, win, symbol))
462
463     def get_graph_data(self, option, win, symbol):
464         if option == '1d':
465             url = 'http://uk.ichart.yahoo.com/b?s=%s' % symbol
466         elif option == '5d':
467             url = 'http://uk.ichart.yahoo.com/w?s=%s' % symbol
468         elif option == '3m':
469             url = 'http://chart.finance.yahoo.com/c/3m/s/%s' % symbol.lower()
470         elif option == '6m':
471             url = 'http://chart.finance.yahoo.com/c/6m/s/%s' % symbol.lower()
472         elif option == '1y':
473             url = 'http://chart.finance.yahoo.com/c/1y/s/%s' % symbol.lower()
474         elif option == '2y':
475             url = 'http://chart.finance.yahoo.com/c/2y/s/%s' % symbol.lower()
476         elif option == '5y':
477             url = 'http://chart.finance.yahoo.com/c/5y/s/%s' % symbol.lower()
478         elif option == 'max':
479             url = 'http://chart.finance.yahoo.com/c/my/s/%s' % symbol.lower()
480
481         try:
482             myimg = urllib2.urlopen(url)
483             imgdata = myimg.read()
484
485             pbl = gtk.gdk.PixbufLoader()
486             pbl.write(imgdata)
487
488             pbuf = pbl.get_pixbuf()
489             pbl.close()
490             self.graph.set_from_pixbuf(pbuf)
491             winprogind(win, 0)
492         except:
493             winprogind(win, 0)
494             self.graphs_title.set_label('Failed to get data')
495             self.graph.destroy()
496
497     def _tv_columns(self, treeview):
498         column = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=0)
499         column.set_visible(False)
500         treeview.append_column(column)
501
502         column = gtk.TreeViewColumn('Name', gtk.CellRendererText(), text=1)
503         treeview.append_column(column)
504
505     def __create_model(self, names, ids):
506         lstore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
507         for item in range(len(names)):
508             iter = lstore.append()
509             lstore.set(iter, 0, ids[item], 1, names[item])
510         return lstore
511
512     def main_toolbar(self, quotesview, portfolio, widgets, symbol, name):
513         toolbar = gtk.HBox()
514         toolbar.set_homogeneous(True)
515
516         portfolio_btn = hildon.Button(fhsize, horbtn)
517         portfolio_btn.set_title("Portfolio")
518         portfolio_btn.connect("clicked", self.show_portfolio_view)
519
520         graph_btn = hildon.Button(fhsize, horbtn)
521         graph_btn.set_title("Graph")
522         graph_btn.connect("clicked", self.show_graph_view, symbol, name)
523
524         refresh_btn = hildon.Button(fhsize, horbtn)
525         refresh_btn.set_title("Refresh")
526         refresh_btn.connect("clicked", self.refresh_stock_data, portfolio,
527                             widgets, symbol)
528
529         if not portfolio:
530             toolbar.pack_start(portfolio_btn)
531         if quotesview:
532             toolbar.pack_start(graph_btn)
533             toolbar.pack_start(refresh_btn)
534
535         toolbar.show_all()
536
537         return toolbar
538
539     def show_portfolio_view(self, widget):
540         data = settings.load_portfolio(settingsdb)
541
542         win = hildon.StackableWindow()
543         win.set_title("StockThis - Portfolio")
544
545         vbox = gtk.VBox()
546
547         parea = hildon.PannableArea()
548         tv = hildon.GtkTreeView(ui_normal)
549         tv.set_headers_visible(True)
550         self.portfolio_model = self._create_portfolio_model(data)
551         tv.connect("row-activated", self.show_quotes_view, self.portfolio_model, True)
552         tv.set_model(self.portfolio_model)
553         self._tv_portfolio_columns(tv)
554         parea.add(tv)
555
556         hbox = gtk.HBox()
557         button = hildon.Button(fhsize, horbtn)
558         button.set_title("Refresh All")
559         button.connect("clicked", self.refresh_portfolio, tv, win)
560         hbox.pack_start(button, True, True, 0)
561
562         button = hildon.Button(fhsize, horbtn)
563         button.set_title("Remove")
564         button.connect("clicked", self.remove_item)
565         hbox.pack_start(button, True, True, 0)
566
567         vbox.pack_start(parea, True, True, 0)
568         vbox.pack_start(hbox, False, False, 0)
569         win.add(vbox)
570         win.show_all()
571
572     def remove_item(self, widget):
573         win = hildon.StackableWindow()
574         win.fullscreen()
575         toolbar = hildon.EditToolbar("Choose items to delete", "Delete")
576         win.set_edit_toolbar(toolbar)
577
578         vbox = gtk.VBox()
579         parea = hildon.PannableArea()
580         tv = hildon.GtkTreeView(ui_edit)
581         selection = tv.get_selection()
582         selection.set_mode(gtk.SELECTION_MULTIPLE)
583         tv.set_model(self.portfolio_model)
584         self._tv_remove_portfolio_columns(tv)
585         parea.add(tv)
586
587         toolbar.connect("button-clicked", self.delete_from_portfolio, win, tv,
588                         selection)
589         toolbar.connect_object("arrow-clicked", gtk.Window.destroy, win)
590
591         vbox.pack_start(parea, True, True, 0)
592         win.add(vbox)
593         win.show_all()
594
595     def delete_from_portfolio(self, widget, win, tv, selection):
596         if not self.is_treeview_selected(tv):
597             return
598
599         conf = self.show_confirmation(win, "Delete items?")
600
601         if conf:
602             selmodel, selected = selection.get_selected_rows()
603             iters = [selmodel.get_iter(path) for path in selected]
604             for i in iters:
605                 symbol = selmodel.get_value(i, 0)
606                 settings.delete_item_from_portfolio(settingsdb, symbol)
607                 selmodel.remove(i)
608
609     def _tv_remove_portfolio_columns(self, treeview):
610         column = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=0)
611         column.set_visible(False)
612         treeview.append_column(column)
613
614         column = gtk.TreeViewColumn('Name', gtk.CellRendererText(), text=1)
615         column.set_property("expand", True)
616         treeview.append_column(column)
617
618         column = gtk.TreeViewColumn('Shares', gtk.CellRendererText(), text=2)
619         column.set_visible(False)
620         treeview.append_column(column)
621
622         column = gtk.TreeViewColumn('Price', gtk.CellRendererText(), text=3)
623         column.set_visible(False)
624         treeview.append_column(column)
625
626     def refresh_portfolio(self, widget, tv, win):
627         data = settings.load_portfolio(settingsdb)
628         import thread
629         winprogind(win, 1)
630         thread.start_new_thread(self._do_refresh_portfolio, (data, tv, win))
631
632     def _do_refresh_portfolio(self, data, tv, win):
633         for item in data:
634             item[3] = self.get_price(item[0])
635
636         self.portfolio_model = self._create_portfolio_model(data)
637         tv.set_model(self.portfolio_model)
638         winprogind(win, 0)
639
640     def get_price(self, symbol):
641         from ystockquote import ystockquote as yt
642         price = yt.get_price(symbol)
643
644         return price
645
646     def _create_portfolio_model(self, data):
647         lstore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING,
648                                 gobject.TYPE_STRING, gobject.TYPE_STRING)
649         for item in data:
650             iter = lstore.append()
651             lstore.set(iter, 0, item[0], 1, item[1], 2, item[2], 3, item[3])
652         return lstore
653
654     def _tv_portfolio_columns(self, treeview):
655         column = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=0)
656         column.set_visible(False)
657         treeview.append_column(column)
658
659         column = gtk.TreeViewColumn('Name', gtk.CellRendererText(), text=1)
660         column.set_property("expand", True)
661         treeview.append_column(column)
662
663         column = gtk.TreeViewColumn('Shares', gtk.CellRendererText(), text=2)
664         treeview.append_column(column)
665
666         column = gtk.TreeViewColumn('Price', gtk.CellRendererText(), text=3)
667         treeview.append_column(column)
668
669     def show_confirmation(self, window, msg):
670         dialog = hildon.hildon_note_new_confirmation(window, msg)
671         dialog.show_all()
672         result = dialog.run()
673         if result == gtk.RESPONSE_OK:
674             dialog.destroy()
675             return True
676
677         dialog.destroy()
678         return False
679
680     def show_info_banner(self, widget, msg):
681         hildon.hildon_banner_show_information(widget, 'qgn_note_infoprint', msg)
682
683     def is_treeview_selected(self, treeview):
684         selection = treeview.get_selection()
685         if selection.count_selected_rows() == 0:
686             self.show_info_banner(treeview, 'No selected item')
687             return False
688         else:
689             return True
690
691 class About:
692
693     def __init__(self, widget):
694         dialog = gtk.Dialog(title='About', parent=None, flags=0)
695         dialog.set_has_separator(False)
696         dialog.set_size_request(-1, 400)
697
698         self.info_lb = gtk.Label()
699         self.info_lb.set_line_wrap(True)
700
701         hbox1 = gtk.HBox()
702
703         button = hildon.Button(fhsize, horbtn)
704         button.set_title('Description')
705         button.connect("clicked", self.show_info, 'description')
706         hbox1.pack_start(button, True, True, 0)
707
708         button = hildon.Button(fhsize, horbtn)
709         button.set_title('Credits')
710         button.connect("clicked", self.show_info, 'credits')
711         hbox1.pack_start(button, True, True, 0)
712
713         button = hildon.Button(fhsize, horbtn)
714         button.set_title('License')
715         button.connect("clicked", self.show_info, 'license')
716         hbox1.pack_start(button, True, True, 0)
717
718         button = hildon.Button(fhsize, horbtn)
719         button.set_title('Donate')
720         button.connect("clicked", self.show_info, 'donate')
721         hbox1.pack_start(button, True, True, 0)
722
723         button = hildon.Button(fhsize, horbtn)
724         button.set_title('Report ')
725         button.connect("clicked", self.show_info, 'report')
726         hbox1.pack_start(button, True, True, 0)
727
728         button = hildon.Button(fhsize, horbtn)
729         button.set_title(' Vote ')
730         button.connect("clicked", self.show_info, 'vote')
731         hbox1.pack_start(button, True, True, 0)
732
733         self.action_btn = hildon.Button(fhsize, horbtn)
734         self.image = gtk.Image()
735
736         self.show_info(None, 'description')
737
738         dialog.vbox.pack_start(self.action_btn, False, False, 0)
739         dialog.vbox.pack_start(self.image, False, False, 5)
740         dialog.vbox.pack_start(self.info_lb, True, True, 0)
741         dialog.vbox.pack_start(hbox1, False, False, 0)
742
743         dialog.show_all()
744         self.action_btn.hide()
745         self.image.hide()
746         dialog.run()
747         dialog.destroy()
748
749     def do_action(self, widget, action):
750         import webbrowser
751         if action == "donate":
752             url = "http://stockthis.garage.maemo.org/donate.html"
753         elif action == "report":
754             url = "http://stockthis.garage.maemo.org/reporting.html"
755         elif action == "vote":
756             url = "http://maemo.org/downloads/product/stockthis"
757         webbrowser.open_new(url)
758
759     def show_info(self, widget, kind):
760         if kind == 'license':
761             self.action_btn.hide()
762             self.image.hide()
763             info = """<small><b>StockThis</b> is free software. It's using a GPL version 2 license or at your election any later version.
764
765 Logo by Daniel Martin Yerga.
766 </small>"""
767         elif kind == 'credits':
768             self.action_btn.hide()
769             self.image.hide()
770             info = """<small><b>Written by</b> Daniel Martin Yerga (dyerga@gmail.com)
771
772 <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>"""
773         elif kind == 'description':
774             self.action_btn.hide()
775             self.image.hide()
776             info = """<b><big>StockThis 0.3</big></b>
777
778 <i>StockThis is a stocks application for Maemo</i>
779
780 <b>Web Page</b>:
781 stockthis.garage.maemo.org"""
782
783         elif kind == 'donate':
784             self.action_btn.show()
785             self.image.hide()
786             self.action_btn.set_title('I want donate')
787             self.action_btn.connect("clicked", self.do_action, "donate")
788             info = """<small><b>StockThis</b> is a free (and gratis) software application.
789 Developing good software takes time and hard work.
790
791 <b>StockThis's author</b> develops the program in him spare time.
792 If you like the program and it's helpful, consider donating a small amount of money.
793 Donations are a great incentive and help to feel that the hard work is appreciated.</small>
794 """
795
796         elif kind == 'report':
797             self.action_btn.show()
798             self.image.hide()
799             self.action_btn.set_title('Report bug')
800             self.action_btn.connect("clicked", self.do_action, "report")
801             info = """<small>StockThis is being improved thanks to bug reports. The author appreciates very much all these reports.
802 If the application is raising an error when you're using it, you have two choices to report this error:
803 1) Send the log from the application menu (if there's an error in the log).
804 2) Write a bug report in the bugtracker of StockThis with as much information as possible (especially the log from the menu).</small>"""
805
806         elif kind == 'vote':
807             self.action_btn.show()
808             self.image.show()
809             self.image.set_from_file(imgdir + "maemoorg.png")
810             self.action_btn.set_title('Vote for StockThis')
811             self.action_btn.connect("clicked", self.do_action, "vote")
812             info = """<small>The downloads section in maemo.org has a nice system where you can rate applications.
813 If you consider StockThis a good application (or a bad one too), you could rate it in maemo.org site.</small>"""
814
815         self.info_lb.set_markup(info)
816
817
818 if __name__ == "__main__":
819     stockspy = StocksPy()
820     gtk.gdk.threads_enter()
821     gtk.main()
822     gtk.gdk.threads_leave()