-#!/usr/bin/env python
+#!/usr/bin/env python2.5
# -*- coding: UTF8 -*-
# Copyright (C) 2008 by Daniel Martin Yerga
# <dyerga@gmail.com>
# Version 0.1
#
+_version = "StockThis 0.3 alpha1 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
+ runninglocally = False
else:
- running_locally = True
+ runninglocally = True
-if running_locally:
- imgdir = 'pixmaps/'
-else:
- imgdir = '/usr/share/stockthis/pixmaps/'
+HOME = os.path.expanduser("~")
-loading_img = imgdir + 'loading.gif'
+settingsdb, imgdir, configdir, logfile = \
+ settings.define_paths(runninglocally, HOME)
-gtk.gdk.threads_init()
-class StocksPy:
+logger = logging.getLogger('st')
+logging.basicConfig(filename=logfile,level=logging.ERROR, filemode='w')
- 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)
+DEBUG = 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
-
-
- vbox = gtk.VBox()
+if DEBUG:
+ #set the main logger to DEBUG
+ logger.setLevel(logging.DEBUG)
- 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)
+ #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.markets_btn = gtk.Button('Markets')
- self.markets_btn.connect("clicked", self.create_markets_view)
- self.markets_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.components_btn = gtk.Button('Instruments')
- self.components_btn.connect("clicked", self.show_components_view)
- self.components_btn.set_property("can_focus", False)
+logger.debug("test this log")
- self.graph_btn = gtk.Button('Graph')
- self.graph_btn.connect("clicked", self.create_graphs_view)
- self.graph_btn.set_property("can_focus", False)
-
- self.refresh_btn = gtk.Button('Refresh')
- self.refresh_btn.connect("clicked", self.refresh_stock_data)
- self.refresh_btn.set_property("can_focus", False)
-
- self.quotes_btn = gtk.Button('Quote')
- self.quotes_btn.connect("clicked", self.show_quotes_view)
- self.quotes_btn.set_property("can_focus", False)
-
- self.toolbar.pack_start(self.markets_btn)
- self.toolbar.pack_start(self.components_btn)
- self.toolbar.pack_start(self.graph_btn)
- self.toolbar.pack_start(self.quotes_btn)
- self.toolbar.pack_start(self.refresh_btn)
+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, '', '')
+
+ 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)
+ 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])
- 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)
+ vbox = gtk.VBox()
+ toolbar = self.main_toolbar(False, False, None, '', '')
- self.compbox.pack_start(self.components_trv, True, True, 0)
+ parea = hildon.PannableArea()
+ 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)
- self.mainbox.pack_start(self.compbox, True, True, 0)
- self.mainbox.show_all()
+ vbox.pack_start(parea, True, True, 0)
+ vbox.pack_start(gtk.HSeparator(), False, False, 5)
+ vbox.pack_start(toolbar, False, False, 0)
+
+ window.add(vbox)
+ window.show_all()
+
+ def show_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])
- def select_component(self, widget, path, column, ids):
- self.create_quotes_view(widget,self.components_model[path][1] )
+ vbox = gtk.VBox()
- 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)
+ ltitle = gtk.Label('')
+ ltitle.set_markup('<b><big>' + quote[1].replace('&', '') +
+ '</big></b>')
+ color = gtk.gdk.color_parse("#03A5FF")
+ ltitle.modify_fg(gtk.STATE_NORMAL, color)
+
+ parea = hildon.PannableArea()
+
+ 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, 110)
+ 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, 125)
+ 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)
- def __create_components_model(self):
- lstore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
- return lstore
+ 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, 215)
- 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)
+ 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, 85)
- renderer = gtk.CellRendererText()
- column = gtk.TreeViewColumn('IDS', renderer, text=1)
- column.set_visible(False)
- treeview.append_column(column)
+ 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, 10)
+
+ 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)
- 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])
+ parea.add_with_viewport(vbox1)
- 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
+ widgets = [win, ltitle, lprice, lchange, lpercent, lvolume, l52whigh,
+ l52wlow, lshares, holdingsvalue, dayvaluechange]
+
+ toolbar = self.main_toolbar(True, portfolio, widgets, quote[0], quote[1])
- def show_quotes_view(self, widget):
- kind = self.stocks_id
- self.create_quotes_view(widget, kind)
+ 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)
- def create_quotes_view(self, widget, kind):
- self.stocks_id = kind
- self.toolbar.show()
- self.components_btn.show()
- self.markets_btn.show()
- self.refresh_btn.show()
- self.graph_btn.show()
- self.quotes_btn.hide()
- #actual_view = self.mainbox.get_children()
- #actual_view[0].destroy()
+ win.add(vbox)
+ win.show_all()
+ self.show_data(quote[0], widgets, shares)
+ def get_shares_from_symbol(self, symbol):
+ shares = "0"
try:
- self.graphbox.destroy()
+ portfolio_data = settings.load_portfolio(settingsdb)
+ for item in portfolio_data :
+ if symbol in item:
+ shares = item[2]
+ return shares
except:
- pass
+ logger.exception("Getting shares from symbol")
+ return shares
- for i in range(len(localids)):
- if kind in localids[i]:
- ind1, ind2 = i, localids[i].index(kind)
+ def add_to_portfolio(self, widget, button, symbol, name):
+ shares = button.get_value()
- self.quotesbox = gtk.VBox()
+ try:
+ portfolio = settings.load_portfolio(settingsdb)
+ index = "None"
+ for item in portfolio:
+ if symbol in item:
+ index = portfolio.index(item)
- self.titlelbl = gtk.Label('')
- self.titlelbl.set_markup('<b><big>'+localmarkets[ind1][ind2].replace('&', '')+'</big></b>')
- color = gtk.gdk.color_parse("#03A5FF")
- self.titlelbl.modify_fg(gtk.STATE_NORMAL, color)
+ item = [symbol, name, shares, '-']
- self.databox = gtk.VBox()
+ if index is "None":
+ settings.insert_new_item_to_portfolio(settingsdb, item)
+ else:
+ settings.delete_item_from_portfolio(settingsdb, symbol)
+ settings.insert_new_item_to_portfolio(settingsdb, item)
- self.imagebox = gtk.VBox()
- self.dataimg = gtk.Image()
- self.imagebox.pack_start(self.dataimg)
+ self.show_info_banner(widget, "Added to portfolio")
+ except:
+ logger.exception("Adding to portfolio")
+ self.show_info_banner(widget, "Error adding to portfolio")
- self.show_data(kind)
- hbox1 = gtk.HBox()
+ def create_selector(self, data, entry):
+ if entry:
+ selector = hildon.TouchSelectorEntry(text=True)
+ else:
+ selector = hildon.hildon_touch_selector_new_text()
+ for i in range(len(data)):
+ selector.append_text(data[i])
- label2 = gtk.Label('')
- label2.set_markup('<b><big>Price:</big></b>')
- self.lprice = gtk.Label('')
+ return selector
- hbox1.pack_start(label2, False, False, 50)
- hbox1.pack_start(self.lprice, False, False, 185)
+ def show_data(self, symbol, widgets, shares):
+ import thread
+ winprogind(widgets[0], 1)
+ thread.start_new_thread(self.get_data, (symbol, widgets, shares))
- hbox2 = gtk.HBox()
+ 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
- label4 = gtk.Label('')
- label4.set_markup('<b><big>Change:</big></b>')
- self.lchange = gtk.Label('')
- self.lpercent = gtk.Label('')
+ try:
+ data = yt.get_all(symbol)
+ except:
+ 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'}
+ ltitle.set_markup('<b><big>Failed to get data</big></b>')
- hbox2.pack_start(label4, False, False, 50)
- hbox2.pack_start(self.lchange , False, False, 145)
- hbox2.pack_start(self.lpercent, False, False, 0)
+ try:
+ ch_percent = \
+ 100.0 * float(data['change'])/(float(data['price']) - \
+ float(data['change']))
+ except ValueError:
+ ch_percent = 0.0
- hbox3 = gtk.HBox()
+ lprice.set_label(data['price'])
+ lchange.set_label(data['change'])
+ lpercent.set_label('%6.2f %%' % ch_percent)
- label7 = gtk.Label('')
- label7.set_markup('<b><big>Volume:</big></b>')
- self.lvolume = gtk.Label('')
+ if '-' in data['change']:
+ color = gtk.gdk.color_parse("#FF0000")
+ else:
+ color = gtk.gdk.color_parse("#16EB78")
- hbox3.pack_start(label7, False, False, 50)
- hbox3.pack_start(self.lvolume , False, False, 145)
+ lpercent.modify_fg(gtk.STATE_NORMAL, color)
+ lchange.modify_fg(gtk.STATE_NORMAL, color)
- hbox4 = gtk.HBox()
+ lvolume.set_label(data['volume'])
+ l52whigh.set_label(data['52_week_high'])
+ l52wlow.set_label(data['52_week_low'])
- label9 = gtk.Label('')
- label9.set_markup('<b><big>52 week high:</big></b>')
- self.l52whigh = gtk.Label('')
+ try:
+ daychange = float(shares)*float(data['change'])
+ except ValueError:
+ daychange = 'N/A'
+ try:
+ holdvalue = float(shares)*float(data['price'])
+ except ValueError:
+ holdvalue = 'N/A'
- hbox4.pack_start(label9, False, False, 50)
- hbox4.pack_start(self.l52whigh , False, False, 55)
+ dayvaluechange.set_label(str(daychange))
+ holdingsvalue.set_label(str(holdvalue))
- hbox5 = gtk.HBox()
+ winprogind(win, 0)
- label11 = gtk.Label('')
- label11.set_markup('<b><big>52 week low:</big></b>')
- self.l52wlow = gtk.Label('')
+ def refresh_stock_data(self, widget, portfolio, widgets, symbol):
+ if portfolio:
+ shares = self.get_shares_from_symbol(symbol)
+ else:
+ shares = "0"
- hbox5.pack_start(label11, False, False, 50)
- hbox5.pack_start(self.l52wlow , False, False, 70)
+ self.show_data(symbol, widgets, shares)
- 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)
+ def show_graph_view(self, widget, symbol, name):
+ win = hildon.StackableWindow()
+ self.create_menu(win)
+ win.set_title("StockThis - Graph View - " + name)
- 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)
+ vbox = gtk.VBox()
+ toolbar = self.main_toolbar(False, True, None, '', '')
- self.mainbox.pack_start(self.quotesbox, True, True, 0)
- self.mainbox.show_all()
- self.compbox.hide()
- self.databox.hide()
+ self.graphs_title = gtk.Label(name)
+ color = gtk.gdk.color_parse("#03A5FF")
+ self.graphs_title.modify_fg(gtk.STATE_NORMAL, color)
- def show_data(self, kind):
- import thread
- self.dataimg.set_from_file(loading_img)
- self.imagebox.show()
- self.databox.hide()
- thread.start_new_thread(self.get_data, (kind,))
+ parea = hildon.PannableArea()
- def get_data(self, kind):
- self.graph_btn.show()
- self.refresh_btn.show()
- self.quotes_btn.hide()
+ hbox = gtk.HBox()
+ hbox.set_homogeneous(True)
- from ystockquote import ystockquote as yt
- try:
- data = yt.get_all(kind)
- except:
- print 'Failed to get internet data'
- 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>')
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('1d')
+ button.connect("clicked", self.show_graph, '1d', win, symbol)
+ hbox.pack_start(button)
- try:
- ch_percent = 100.0 * float(data['change'])/(float(data['price'])-float(data['change']))
- except ValueError:
- ch_percent = 0.0
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('5d')
+ button.connect("clicked", self.show_graph, '5d', win, symbol)
+ hbox.pack_start(button)
- self.lprice.set_label(data['price'])
- self.lchange.set_label(data['change'])
- self.lpercent.set_label('%6.2f %%' % ch_percent)
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('3m')
+ button.connect("clicked", self.show_graph, '3m', win, symbol)
+ hbox.pack_start(button)
- if '-' in data['change']:
- color = gtk.gdk.color_parse("#FF0000")
- else:
- color = gtk.gdk.color_parse("#16EB78")
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('6m')
+ button.connect("clicked", self.show_graph, '6m', win, symbol)
+ hbox.pack_start(button)
- self.lpercent.modify_fg(gtk.STATE_NORMAL, color)
- self.lchange.modify_fg(gtk.STATE_NORMAL, color)
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('1y')
+ button.connect("clicked", self.show_graph, '1y', win, symbol)
+ hbox.pack_start(button)
- self.lvolume.set_label(data['volume'])
- self.l52whigh.set_label(data['52_week_high'])
- self.l52wlow.set_label(data['52_week_low'])
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('2y')
+ button.connect("clicked", self.show_graph, '2y', win, symbol)
+ hbox.pack_start(button)
- self.databox.show_all()
- self.imagebox.hide()
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('5y')
+ button.connect("clicked", self.show_graph, '5y', win, symbol)
+ hbox.pack_start(button)
- def refresh_stock_data(self, widget):
- self.show_data(self.stocks_id)
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('Max')
+ button.connect("clicked", self.show_graph, 'max', win, symbol)
+ hbox.pack_start(button)
- def create_graphs_view(self, widget):
- self.graph_btn.hide()
- self.refresh_btn.hide()
- self.quotes_btn.show()
+ vbox1 = gtk.VBox()
+ vbox1.pack_start(hbox, False, False, 0)
self.graph = gtk.Image()
+ vbox1.pack_start(self.graph, True, True, 0)
- kind = self.stocks_id
-
- self.show_graph(None, '1d', kind)
-
- for i in range(len(localids)):
- if kind in localids[i]:
- ind1, ind2 = i, localids[i].index(kind)
-
- #self.mainbox.destroy()
- #self.mainbox = gtk.VBox()
- #self.swin.add_with_viewport(self.mainbox)
+ parea.add_with_viewport(vbox1)
- actual_view = self.mainbox.get_children()
- for a_widget in actual_view:
- a_widget.destroy()
+ 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)
- self.graphbox = gtk.VBox()
+ win.add(vbox)
+ win.show_all()
- self.graphs_title = gtk.Label(localmarkets[ind1][ind2])
- color = gtk.gdk.color_parse("#03A5FF")
- self.graphs_title.modify_fg(gtk.STATE_NORMAL, color)
+ self.show_graph(None, '1d', win, symbol)
- 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):
+ 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)
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):
+ 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)
+
+ if not portfolio:
+ toolbar.pack_start(portfolio_btn)
+ if quotesview:
+ toolbar.pack_start(graph_btn)
+ toolbar.pack_start(refresh_btn)
+
+ toolbar.show_all()
+
+ return toolbar
+
+ 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("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 remove_item(self, widget):
+ win = hildon.StackableWindow()
+ win.fullscreen()
+ toolbar = hildon.EditToolbar("Choose items to delete", "Delete")
+ win.set_edit_toolbar(toolbar)
- #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
+ 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_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):
+ dialog = gtk.Dialog(title='About', parent=None, flags=0)
+ dialog.set_has_separator(False)
+ dialog.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(' Vote ')
+ 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')
+
+ dialog.vbox.pack_start(self.action_btn, False, False, 0)
+ dialog.vbox.pack_start(self.image, False, False, 5)
+ dialog.vbox.pack_start(self.info_lb, True, True, 0)
+ dialog.vbox.pack_start(hbox1, False, False, 0)
+
+ dialog.show_all()
+ self.action_btn.hide()
+ self.image.hide()
dialog.run()
dialog.destroy()
+ def do_action(self, widget, action):
+ import webbrowser
+ 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"
+ webbrowser.open_new(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('I want donate')
+ 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 him 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 to 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. The author appreciates very much all 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) Write a bug report in the bugtracker of StockThis with as much information as possible (especially the log from the menu).</small>"""
+
+ elif kind == 'vote':
+ self.action_btn.show()
+ self.image.show()
+ self.image.set_from_file(imgdir + "maemoorg.png")
+ self.action_btn.set_title('Vote for 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):
+ 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()