-#!/usr/bin/env python2.5
+#!/usr/bin/env python
# -*- coding: UTF8 -*-
# Copyright (C) 2008 by Daniel Martin Yerga
# <dyerga@gmail.com>
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
-# StocksPy: Application to get stocks data from Yahoo Finance.
-# Version 0.1
+# StocksThis: Application to get stocks data from Yahoo Finance.
#
+_version = "StockThis 0.4 rev1"
+VERSION = "0.4"
+
import urllib2
import gtk, gobject
import os
import hildon
-
-#import osso
-#osso_c = osso.Context("net.yerga.stockthis", "0.3", False)
-
import marketdata
import settings
+import logging
+import sys
+
+from portrait import FremantleRotation
+import osso
+osso_c = osso.Context("net.yerga.stockthis", "0.3", False)
#detect if is ran locally or not
-import sys
runningpath = sys.path[0]
-if '/usr/share' in runningpath:
+if '/opt/' in runningpath:
runninglocally = False
else:
runninglocally = True
settingsdb, imgdir, configdir, logfile = \
settings.define_paths(runninglocally, HOME)
+logger = logging.getLogger('st')
+logging.basicConfig(filename=logfile,level=logging.ERROR, filemode='w')
+
+DEBUG = True
+
+if DEBUG:
+ #set the main logger to DEBUG
+ logger.setLevel(logging.DEBUG)
+
+ #Create a handler for console debug
+ console = logging.StreamHandler()
+ console.setLevel(logging.DEBUG)
+ # set a format which is simpler for console use
+ formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+ # tell the handler to use this format
+ console.setFormatter(formatter)
+ logging.getLogger('').addHandler(console)
fhsize = gtk.HILDON_SIZE_FINGER_HEIGHT
horbtn = hildon.BUTTON_ARRANGEMENT_HORIZONTAL
ui_edit = gtk.HILDON_UI_MODE_EDIT
winprogind = hildon.hildon_gtk_window_set_progress_indicator
+allnames = []
+allsymbols = []
+
gtk.gdk.threads_init()
class StocksPy:
self.program.add_window(self.window)
self.window.connect("destroy", gtk.main_quit)
- menu = hildon.AppMenu()
- self.window.set_app_menu(menu)
- button = gtk.Button("About")
- button.connect("clicked", About)
- menu.append(button)
- menu.show_all()
+ FremantleRotation('StockThis', None, "0.3", 0)
+
+ self.create_menu(self.window)
vbox = gtk.VBox()
- toolbar = self.main_toolbar(False, False, None, '', '')
+ toolbar = self.main_toolbar(False, False, None, '', '', True)
parea = hildon.PannableArea()
tv = hildon.GtkTreeView(ui_normal)
self.window.add(vbox)
self.window.show_all()
+ self.show_info_banner(self.window,
+ ("StockThis uses your network connection to get data.\n"
+ "Be aware of the high costs that your network provider may apply."))
+
+ def create_menu(self, window):
+ menu = hildon.AppMenu()
+ window.set_app_menu(menu)
+ button = gtk.Button("About")
+ button.connect("clicked", About)
+ menu.append(button)
+ menu.show_all()
+
def show_instrument_view(self, widget, path, column, inmodel, names,
ids, mindex):
market = inmodel[path][0]
ids = ids[mindex.index(market)]
window = hildon.StackableWindow()
- window.set_title("StockThis - " + inmodel[path][1])
+ self.create_menu(window)
+ window.set_title(inmodel[path][1])
vbox = gtk.VBox()
- toolbar = self.main_toolbar(False, False, None, '', '')
+ 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)
+
+ if market == 'metals':
+ tv.connect("row-activated", self.show_metal_graphs, model)
+ else:
+ tv.connect("row-activated", self.show_quotes_view, model, False)
+
tv.set_model(model)
self._tv_columns(tv)
parea.add(tv)
window.add(vbox)
window.show_all()
+ def horizontal_mov(self, parea, direction, initial_x, initial_y):
+ #direction = 2 right-to-left
+ #direction = 3 lefto-to-right
+
+ vadj = parea.get_vadjustment()
+ val = vadj.get_value()
+
+ if direction == 2:
+ if int(val)-2500 < 0:
+ parea.scroll_to(-1, 0)
+ else:
+ parea.scroll_to(-1, int(val)-2500)
+ elif direction == 3:
+ parea.scroll_to(-1, int(val)+3500)
+
+ #print val
+
def show_quotes_view(self, widget, path, column, model, portfolio):
quote = model[path][0], model[path][1]
- print "quote:", quote[0]
+ #print "quote:", quote[0]
#('EURUSD=X', 'EUR/USD')
#Currencies and ETFs should show the list now -> view = True
for i in marketdata.localids[(len(marketdata.localids)-2):]:
for j in i:
if quote[0] == j:
- print j
+ #print j
view = True
if not view:
win = hildon.StackableWindow()
- win.set_title("StockThis - Quotes View - " + quote[1])
+ self.create_menu(win)
+ win.set_title(quote[1])
vbox = gtk.VBox()
ltitle.modify_fg(gtk.STATE_NORMAL, color)
parea = hildon.PannableArea()
+ parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
vbox1 = gtk.VBox()
hbox = gtk.HBox()
label = gtk.Label('')
- label.set_markup('<b><big>Price:</big></b>')
+ label.set_markup('<b><big>%39s:</big></b>' % '<u>Price</u>')
lprice = gtk.Label('')
- hbox.pack_start(label, False, False, 20)
- hbox.pack_start(lprice, False, False, 245)
+ hbox.pack_start(label, False, False, 0)
+ #if self.is_portrait():
+ hbox.pack_start(lprice, False, False, 25)
+ #else:
+ # hbox.pack_start(lprice, False, False, 245)
+
vbox1.pack_start(hbox, True, True, 0)
hbox = gtk.HBox()
label = gtk.Label('')
- label.set_markup('<b><big>Change:</big></b>')
+ label.set_markup('<b><big>%35s:</big></b>' % '<u>Change</u>')
lchange = gtk.Label('')
lpercent = gtk.Label('')
- hbox.pack_start(label, False, False, 20)
- hbox.pack_start(lchange, False, False, 205)
+ hbox.pack_start(label, False, False, 0)
+ #if self.is_portrait():
+ hbox.pack_start(lchange, False, False, 25)
hbox.pack_start(lpercent, False, False, 0)
+ #else:
+ # hbox.pack_start(lchange, False, False, 205)
+ # hbox.pack_start(lpercent, False, False, 0)
+
vbox1.pack_start(hbox, True, True, 0)
hbox = gtk.HBox()
label = gtk.Label('')
- label.set_markup('<b><big>Volume:</big></b>')
+ label.set_markup('<b><big>%35s:</big></b>' % '<u>Volume</u>')
lvolume = gtk.Label('')
- hbox.pack_start(label, False, False, 20)
- hbox.pack_start(lvolume, False, False, 207)
+ hbox.pack_start(label, False, False, 0)
+ #if self.is_portrait():
+ hbox.pack_start(lvolume, False, False, 25)
+ #else:
+ # hbox.pack_start(lvolume, False, False, 207)
+
vbox1.pack_start(hbox, True, True, 0)
hbox = gtk.HBox()
label = gtk.Label('')
- label.set_markup('<b><big>52 week high:</big></b>')
+ label.set_markup('<b><big>%30s:</big></b>' % '<u>52 week high</u>')
l52whigh = gtk.Label('')
- hbox.pack_start(label, False, False, 20)
- hbox.pack_start(l52whigh, False, False, 110)
+ hbox.pack_start(label, False, False, 0)
+ #if self.is_portrait():
+ hbox.pack_start(l52whigh, False, False, 25)
+ #else:
+ # hbox.pack_start(l52whigh, False, False, 125)
+
vbox1.pack_start(hbox, True, True, 0)
hbox = gtk.HBox()
label = gtk.Label('')
- label.set_markup('<b><big>52 week low:</big></b>')
+ label.set_markup('<b><big>%30s:</big></b>' % '<u>52 week low</u>')
l52wlow = gtk.Label('')
- hbox.pack_start(label, False, False, 20)
- hbox.pack_start(l52wlow, False, False, 125)
+ hbox.pack_start(label, False, False, 0)
+ #if self.is_portrait():
+ hbox.pack_start(l52wlow, False, False, 26)
+ #else:
+ # hbox.pack_start(l52wlow, False, False, 140)
vbox1.pack_start(hbox, True, True, 0)
+ #if self.is_portrait():
+ # hbox = gtk.VBox()
+ #else:
hbox = gtk.HBox()
button1 = hildon.PickerButton(fhsize, horbtn)
data = ["50", "100", "200", "300", "400", "500", "600", "700", "800",
selector = self.create_selector(data, True)
button1.set_selector(selector)
button1.set_title("Your shares")
- #FIXME: Improve as it's shown you have a component in your portfolio
shares = self.get_shares_from_symbol(quote[0])
button1.set_value(shares)
hbox.pack_start(button1, True, True, 0)
hbox1 = gtk.HBox()
label = gtk.Label('')
- label.set_markup('<b><big>Shares:</big></b>')
+ label.set_markup('<b><big>%37s:</big></b>' % '<u>Shares</u>')
lshares = gtk.Label(shares)
- hbox1.pack_start(label, False, False, 20)
- hbox1.pack_start(lshares, False, False, 215)
+ hbox1.pack_start(label, False, False, 0)
+ #if self.is_portrait():
+ hbox1.pack_start(lshares, False, False, 25)
+ #else:
+ # hbox1.pack_start(lshares, False, False, 220)
hbox2 = gtk.HBox()
label = gtk.Label('')
- label.set_markup('<b><big>Holdings Value:</big></b>')
+ label.set_markup('<b><big>%29s:</big></b>' % '<u>Holdings Value</u>')
holdingsvalue = gtk.Label("")
- hbox2.pack_start(label, False, False, 20)
- hbox2.pack_start(holdingsvalue, False, False, 85)
+ hbox2.pack_start(label, False, False, 0)
+ #if self.is_portrait():
+ hbox2.pack_start(holdingsvalue, False, False, 25)
+ #else:
+ # hbox2.pack_start(holdingsvalue, False, False, 105)
hbox3 = gtk.HBox()
label = gtk.Label('')
- label.set_markup("<b><big>Day's Value Change:</big></b>")
+ label.set_markup("<b><big>%25s:</big></b>" % "<u>Day's Value Change</u>")
dayvaluechange = gtk.Label("")
- hbox3.pack_start(label, False, False, 20)
- hbox3.pack_start(dayvaluechange, False, False, 10)
+ hbox3.pack_start(label, False, False, 0)
+ #if self.is_portrait():
+ hbox3.pack_start(dayvaluechange, False, False, 25)
+ #else:
+ # hbox3.pack_start(dayvaluechange, False, False, 45)
if not portfolio:
vbox1.pack_start(hbox, False, False, 0)
parea.add_with_viewport(vbox1)
- widgets = [win, ltitle, lprice, lchange, lpercent, lvolume, l52whigh, l52wlow, lshares, holdingsvalue, dayvaluechange]
+ widgets = [win, ltitle, lprice, lchange, lpercent, lvolume, l52whigh,
+ l52wlow, lshares, holdingsvalue, dayvaluechange]
- toolbar = self.main_toolbar(True, portfolio, widgets, quote[0], quote[1])
+ toolbar = self.main_toolbar(True, portfolio, widgets, quote[0], quote[1], False)
vbox.pack_start(ltitle, False, False, 0)
vbox.pack_start(gtk.HSeparator(), False, False, 0)
win.show_all()
self.show_data(quote[0], widgets, shares)
+ def is_portrait(self):
+ width = gtk.gdk.screen_width()
+ height = gtk.gdk.screen_height()
+ if width > height:
+ return False
+ else:
+ return True
+
def get_shares_from_symbol(self, symbol):
- portfolio_data = settings.load_portfolio(settingsdb)
shares = "0"
- for item in portfolio_data :
- if symbol in item:
- shares = item[2]
- return shares
+ try:
+ portfolio_data = settings.load_portfolio(settingsdb)
+ for item in portfolio_data :
+ if symbol in item:
+ shares = item[2]
+ return shares
+ except:
+ logger.exception("Getting shares from symbol: %s" % symbol)
+ return shares
def add_to_portfolio(self, widget, button, symbol, name):
shares = button.get_value()
- portfolio = settings.load_portfolio(settingsdb)
- index = "None"
- for item in portfolio:
- if symbol in item:
- index = portfolio.index(item)
+ try:
+ portfolio = settings.load_portfolio(settingsdb)
+ index = "None"
+ for item in portfolio:
+ if symbol in item:
+ index = portfolio.index(item)
- item = [symbol, name, shares, '-']
+ item = [symbol, name, shares, '-']
- if index is "None":
- settings.insert_new_item_to_portfolio(settingsdb, item)
- else:
- settings.delete_item_from_portfolio(settingsdb, symbol)
- settings.insert_new_item_to_portfolio(settingsdb, item)
+ if index is "None":
+ settings.insert_new_item_to_portfolio(settingsdb, item)
+ else:
+ settings.delete_item_from_portfolio(settingsdb, symbol)
+ settings.insert_new_item_to_portfolio(settingsdb, item)
- self.show_info_banner(widget, "Added to portfolio")
+ self.show_info_banner(widget, "Added to portfolio")
+ except:
+ logger.exception("Adding to portfolio: %s, %s" % (symbol, name))
+ self.show_info_banner(widget, "Error adding to portfolio")
def create_selector(self, data, entry):
if entry:
selector = hildon.TouchSelectorEntry(text=True)
else:
- selector = hildon.hildon_touch_selector_new_text()
+ selector = hildon.TouchSelector(text=True)
for i in range(len(data)):
selector.append_text(data[i])
try:
data = yt.get_all(symbol)
except:
- print 'Failed to get internet data'
+ logger.exception("Getting data from Yahoo: %s" % symbol)
data = {'price': 'N/A', 'change': 'N/A', 'volume':'N/A',
'52_week_high': 'N/A', '52_week_low': 'N/A'}
ltitle.set_markup('<b><big>Failed to get data</big></b>')
def show_graph_view(self, widget, symbol, name):
win = hildon.StackableWindow()
- win.set_title("StockThis - Graph View - " + name)
+ self.create_menu(win)
+ win.set_title(name)
vbox = gtk.VBox()
- toolbar = self.main_toolbar(False, True, None, '', '')
+ toolbar = self.main_toolbar(False, True, None, '', '', False)
self.graphs_title = gtk.Label(name)
color = gtk.gdk.color_parse("#03A5FF")
self.graphs_title.modify_fg(gtk.STATE_NORMAL, color)
parea = hildon.PannableArea()
+ parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
+
+ vbox1 = gtk.VBox()
hbox = gtk.HBox()
hbox.set_homogeneous(True)
button.connect("clicked", self.show_graph, '6m', win, symbol)
hbox.pack_start(button)
+ vbox1.pack_start(hbox, False, False, 0)
+ hbox = gtk.HBox()
+ hbox.set_homogeneous(True)
+
button = hildon.Button(fhsize, horbtn)
button.set_label('1y')
button.connect("clicked", self.show_graph, '1y', win, symbol)
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()
pbl.write(imgdata)
pbuf = pbl.get_pixbuf()
+ pbuf = pbuf.scale_simple(475, 235, gtk.gdk.INTERP_TILES)
pbl.close()
self.graph.set_from_pixbuf(pbuf)
winprogind(win, 0)
except:
+ logger.exception("Getting graph data: %s" % url)
winprogind(win, 0)
self.graphs_title.set_label('Failed to get data')
self.graph.destroy()
+ def show_metal_graphs(self, widget, path, column, model):
+ metal = model[path][1]
+ metal_urls = self.get_metal_graphs_urls(metal)
+ options = []
+ for i in metal_urls:
+ options.append(i[0])
+
+ win = hildon.StackableWindow()
+ #self.create_menu(win)
+ win.set_title(metal)
+
+ vbox = gtk.VBox()
+ #toolbar = self.main_toolbar(False, True, None, '', '', False)
+
+ self.metalgraph_title = gtk.Label(metal)
+ color = gtk.gdk.color_parse("#03A5FF")
+ self.metalgraph_title.modify_fg(gtk.STATE_NORMAL, color)
+
+ parea = hildon.PannableArea()
+ parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
+
+ vbox1 = gtk.VBox()
+
+ hbox = gtk.HBox()
+ hbox.set_homogeneous(True)
+
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('live')
+ button.connect("clicked", self.show_metalgraph, 'live', win, metal_urls)
+ if 'live' in options:
+ hbox.pack_start(button)
+
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('30d')
+ button.connect("clicked", self.show_metalgraph, '30d', win, metal_urls)
+ if '30d' in options:
+ hbox.pack_start(button)
+
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('60d')
+ button.connect("clicked", self.show_metalgraph, '60d', win, metal_urls)
+ if '60d' in options:
+ hbox.pack_start(button)
+
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('6m')
+ button.connect("clicked", self.show_metalgraph, '6m', win, metal_urls)
+ if '6m' in options:
+ hbox.pack_start(button)
+
+ vbox1.pack_start(hbox, False, False, 0)
+ hbox = gtk.HBox()
+ hbox.set_homogeneous(True)
+
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('1y')
+ button.connect("clicked", self.show_metalgraph, '1y', win, metal_urls)
+ if '1y' in options:
+ hbox.pack_start(button)
+
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('5y')
+ button.connect("clicked", self.show_metalgraph, '5y', win, metal_urls)
+ if '5y' in options:
+ hbox.pack_start(button)
+
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label('10y')
+ button.connect("clicked", self.show_metalgraph, '10y', win, metal_urls)
+ if '10y' in options:
+ hbox.pack_start(button)
+
+ vbox1.pack_start(hbox, False, False, 0)
+
+ self.metalgraph = gtk.Image()
+ vbox1.pack_start(self.metalgraph, True, True, 0)
+
+ parea.add_with_viewport(vbox1)
+
+ vbox.pack_start(self.metalgraph_title, False, False, 0)
+ vbox.pack_start(gtk.HSeparator(), False, False, 0)
+ vbox.pack_start(parea, True, True, 0)
+ vbox.pack_start(gtk.HSeparator(), False, False, 5)
+ #vbox.pack_start(toolbar, False, False, 0)
+
+ win.add(vbox)
+ win.show_all()
+
+ self.show_metalgraph(None, options[0], win, metal_urls)
+
+ def show_metalgraph(self, widget, option, win, metal_urls):
+ import thread
+ winprogind(win, 1)
+ thread.start_new_thread(self.get_metalgraph_data, (option, win, metal_urls))
+
+ def get_metalgraph_data(self, option, win, metal_urls):
+ for i in metal_urls:
+ if i[0] == option:
+ print i[1]
+ url = i[1]
+
+ try:
+ myimg = urllib2.urlopen(url)
+ imgdata = myimg.read()
+
+ pbl = gtk.gdk.PixbufLoader()
+ pbl.write(imgdata)
+
+
+ pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, 475, 235)
+ pixbuf.fill(0xffffffff)
+
+
+ pbuf = pbl.get_pixbuf()
+ pbuf = pbuf.scale_simple(475, 235, gtk.gdk.INTERP_TILES)
+
+ pixbuf.composite(pbuf, 0, 0, pixbuf.props.width, pixbuf.props.height, 0, 0, 1.0, 1.0, gtk.gdk.INTERP_HYPER, 55)
+
+
+ pbl.close()
+ self.metalgraph.set_from_pixbuf(pbuf)
+ winprogind(win, 0)
+ except:
+ logger.exception("Getting graph data: %s" % url)
+ winprogind(win, 0)
+ self.metalgraph_title.set_label('Failed to get data')
+ self.metalgraph.destroy()
+
+ def get_metal_graphs_urls(self, metal):
+ metal_urls = []
+ liveurl = 'http://www.kitco.com/images/live/%s'
+ graphurl = 'http://www.kitco.com/LFgif/%s'
+ t24url = 'http://www.kitconet.com/charts/metals/base/%s'
+ if metal == 'Gold':
+ metal_urls.append(['live', liveurl % 'gold.gif'])
+ metal_urls.append(['30d', graphurl % 'au0030lnb.gif'])
+ metal_urls.append(['60d', graphurl % 'au0060lnb.gif'])
+ metal_urls.append(['6m', graphurl % 'au0182nyb.gif'])
+ metal_urls.append(['1y', graphurl % 'au0365nyb.gif'])
+ metal_urls.append(['5y', graphurl % 'au1825nyb.gif'])
+ metal_urls.append(['10y', graphurl % 'au3650nyb.gif'])
+ elif metal == 'Silver':
+ metal_urls.append(['live', liveurl % 'silver.gif'])
+ metal_urls.append(['30d', graphurl % 'ag0030lnb.gif'])
+ metal_urls.append(['60d', graphurl % 'ag0060lnb.gif'])
+ metal_urls.append(['6m', graphurl % 'ag0182nyb.gif'])
+ metal_urls.append(['1y', graphurl % 'ag0365nyb.gif'])
+ metal_urls.append(['5y', graphurl % 'ag1825nyb.gif'])
+ metal_urls.append(['10y', graphurl % 'ag3650nyb.gif'])
+ elif metal == 'Platinum':
+ metal_urls.append(['live', liveurl % 'plati.gif'])
+ metal_urls.append(['30d', graphurl % 'pt0030lnb.gif'])
+ metal_urls.append(['60d', graphurl % 'pt0060lnb.gif'])
+ metal_urls.append(['6m', graphurl % 'pt0182nyb.gif'])
+ metal_urls.append(['1y', graphurl % 'pt0365nyb.gif'])
+ metal_urls.append(['5y', graphurl % 'pt1825nyb.gif'])
+ elif metal == 'Palladium':
+ metal_urls.append(['live', liveurl % 'plad.gif'])
+ metal_urls.append(['30d', graphurl % 'pd0030lnb.gif'])
+ metal_urls.append(['60d', graphurl % 'pd0060lnb.gif'])
+ metal_urls.append(['6m', graphurl % 'pd0182nyb.gif'])
+ metal_urls.append(['1y', graphurl % 'pd0365nyb.gif'])
+ metal_urls.append(['5y', graphurl % 'pd1825nyb.gif'])
+ elif metal == 'Rhodium':
+ metal_urls.append(['30d', graphurl % 'rh0030lnb.gif'])
+ metal_urls.append(['60d', graphurl % 'rh0060lnb.gif'])
+ metal_urls.append(['6m', graphurl % 'rh0182lnb.gif'])
+ metal_urls.append(['1y', graphurl % 'rh0365lnb.gif'])
+ metal_urls.append(['5y', graphurl % 'rh1825lnb.gif'])
+ elif metal == 'Copper':
+ metal_urls.append(['live', t24url % 't24_cp450x275.gif'])
+ elif metal == 'Nickel':
+ metal_urls.append(['live', t24url % 't24_nk450x275.gif'])
+ elif metal == 'Aluminium':
+ metal_urls.append(['live', t24url % 't24_al450x275.gif'])
+ elif metal == 'Zinc':
+ metal_urls.append(['live', t24url % 't24_zc450x275.gif'])
+ elif metal == 'Lead':
+ metal_urls.append(['live', t24url % 't24_ld450x275.gif'])
+
+ return metal_urls
+
def _tv_columns(self, treeview):
column = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=0)
column.set_visible(False)
lstore.set(iter, 0, ids[item], 1, names[item])
return lstore
- def main_toolbar(self, quotesview, portfolio, widgets, symbol, name):
+ def main_toolbar(self, quotesview, portfolio, widgets, symbol, name, initial):
toolbar = gtk.HBox()
- toolbar.set_homogeneous(True)
+ #toolbar.set_homogeneous(True)
portfolio_btn = hildon.Button(fhsize, horbtn)
portfolio_btn.set_title("Portfolio")
refresh_btn.connect("clicked", self.refresh_stock_data, portfolio,
widgets, symbol)
+
+ info_btn = hildon.Button(fhsize, horbtn)
+ img = gtk.image_new_from_icon_name("general_information", gtk.ICON_SIZE_SMALL_TOOLBAR)
+ info_btn.set_image(img)
+ info_btn.connect("clicked", self.show_app_information)
+
+ search_btn = hildon.Button(fhsize, horbtn)
+ img = gtk.image_new_from_icon_name("general_search", gtk.ICON_SIZE_SMALL_TOOLBAR)
+ search_btn.set_image(img)
+ search_btn.connect("clicked", self.show_search_dialog)
+
if not portfolio:
toolbar.pack_start(portfolio_btn)
+ if not quotesview:
+ toolbar.pack_start(info_btn, False, False, 0)
if quotesview:
toolbar.pack_start(graph_btn)
toolbar.pack_start(refresh_btn)
+ if initial:
+ toolbar.pack_start(search_btn, False, False, 0)
+
toolbar.show_all()
return toolbar
+ def show_search_dialog(self, widget):
+ dlg = gtk.Dialog(title='Search company', parent=None, flags=0)
+ dlg.set_has_separator(False)
+
+ hbox = gtk.HBox()
+
+ entry = hildon.Entry(fhsize)
+ entry.connect("activate", self.do_search, entry, dlg)
+ hbox.pack_start(entry, True, True, 0)
+
+ button = hildon.Button(fhsize, horbtn)
+ img = gtk.image_new_from_icon_name("general_search", gtk.ICON_SIZE_SMALL_TOOLBAR)
+ button.set_image(img)
+ button.connect("clicked", self.do_search, entry, dlg)
+ hbox.pack_start(button, False, False, 0)
+
+ dlg.vbox.pack_start(hbox, False, False, 0)
+
+ dlg.show_all()
+ dlg.run()
+ dlg.destroy()
+
+
+ def do_search(self, widget, entry, dlg):
+ import thread
+ text = entry.get_text()
+ dlg.destroy()
+
+ winprogind(self.window, 1)
+ thread.start_new_thread(self._really_do_search, (text,))
+
+ def _really_do_search(self, text):
+
+ if allnames == []:
+ for market in marketdata.eunames:
+ for company in market:
+ allnames.append(company)
+
+ for market in marketdata.omnames:
+ for company in market:
+ allnames.append(company)
+
+ for market in marketdata.usnames:
+ for company in market:
+ allnames.append(company)
+
+ if allsymbols == []:
+ for market in marketdata.eusymbols:
+ for company in market:
+ allsymbols.append(company)
+
+ for market in marketdata.omsymbols:
+ for company in market:
+ allsymbols.append(company)
+
+ for market in marketdata.ussymbols:
+ for company in market:
+ allsymbols.append(company)
+
+ new_model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+ for i in range(len(allnames)):
+ if text.lower() in allnames[i].lower():
+ niter = new_model.append()
+ #print allsymbols[i], allnames[i]
+ #FIXME: repeated companies in the results list
+ #print if allnames[i]
+ #for j in new_model:
+ # if j[1] == allnames[i]:
+ new_model.set(niter, 0, allsymbols[i], 1, allnames[i])
+
+ if len(new_model) == 0:
+ winprogind(self.window, 0)
+ gtk.gdk.threads_enter()
+ self.show_info_banner(self.window, "No items found for this search")
+ gtk.gdk.threads_leave()
+ return
+
+ gtk.gdk.threads_enter()
+ self.show_search_screen(new_model, text)
+ gtk.gdk.threads_leave()
+ winprogind(self.window, 0)
+
+
+ def show_search_screen(self, model, text):
+ window = hildon.StackableWindow()
+ self.create_menu(window)
+ window.set_title("Search for " + text)
+
+ vbox = gtk.VBox()
+ toolbar = self.main_toolbar(False, False, None, '', '', False)
+
+ parea = hildon.PannableArea()
+ parea.connect("horizontal-movement", self.horizontal_mov)
+ tv = hildon.GtkTreeView(ui_normal)
+ tv.connect("row-activated", self.show_quotes_view, model, False)
+ tv.set_model(model)
+ self._tv_columns(tv)
+ parea.add(tv)
+
+ vbox.pack_start(parea, True, True, 0)
+ vbox.pack_start(gtk.HSeparator(), False, False, 5)
+ vbox.pack_start(toolbar, False, False, 0)
+
+ window.add(vbox)
+ window.show_all()
+
+ def show_app_information(self, widget):
+ self.show_information_note(self.window, (
+ "The data is got from Yahoo! Finance.\n"
+ "It could be delayed or even wrong.\n"
+ "The author doesn't validate in any way this data and therefore he is not responsible for any damage that may occur.\n\n"
+ "You can scroll large list with gestures:\n"
+ "Left-to-right gesture: scroll down.\n"
+ "Right-to-left gesture: scroll up."))
+
def show_portfolio_view(self, widget):
data = settings.load_portfolio(settingsdb)
+ for item in data:
+ item.append('-')
+ item.append('-')
win = hildon.StackableWindow()
- win.set_title("StockThis - Portfolio")
+ self.create_menu(win)
+ win.set_title("Portfolio")
vbox = gtk.VBox()
parea = hildon.PannableArea()
+ parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
tv = hildon.GtkTreeView(ui_normal)
tv.set_headers_visible(True)
self.portfolio_model = self._create_portfolio_model(data)
- tv.connect("row-activated", self.show_quotes_view, self.portfolio_model, True)
+ self.quotes_id = tv.connect("row-activated", self.show_quotes_view,
+ self.portfolio_model, True)
tv.set_model(self.portfolio_model)
self._tv_portfolio_columns(tv)
parea.add(tv)
hbox.pack_start(button, True, True, 0)
button = hildon.Button(fhsize, horbtn)
+ button.set_title("Add manually")
+ button.connect("clicked", self.add_item_dlg, None, None)
+ hbox.pack_start(button, True, True, 0)
+
+ button = hildon.Button(fhsize, horbtn)
button.set_title("Remove")
button.connect("clicked", self.remove_item)
hbox.pack_start(button, True, True, 0)
+ button = hildon.CheckButton(fhsize)
+ button.set_label("Edit")
+
+ button.connect("toggled", self.edit_toggled, tv)
+ hbox.pack_start(button, True, True, 0)
+
+
vbox.pack_start(parea, True, True, 0)
vbox.pack_start(hbox, False, False, 0)
win.add(vbox)
win.show_all()
+ def edit_toggled(self, widget, tv):
+ if widget.get_active():
+ tv.disconnect(self.quotes_id)
+ self.edit_id = tv.connect("row-activated",
+ self.edit_portfolio_item, self.portfolio_model)
+ else:
+ tv.disconnect(self.edit_id)
+ self.quotes_id = tv.connect("row-activated",
+ self.show_quotes_view, self.portfolio_model, True)
+
+ def edit_portfolio_item(self, widget, path, column, model):
+ seliter = model.get_iter(path)
+
+ symbol = model[path][0]
+ name = model[path][1]
+ shares = model[path][2]
+
+ data = [shares, symbol, name]
+ self.add_item_dlg(widget, data, seliter)
+
+ def add_item_dlg(self, widget, data, seliter):
+ if data:
+ shares = data[0]
+ symbol = data[1]
+ name = data[2]
+ title = "Edit item from portfolio"
+ btntext = "Edit"
+ edit = True
+ else:
+ shares = "0"
+ symbol = ""
+ name = ""
+ title = "Add to portfolio"
+ btntext = "Add"
+ edit = False
+
+ dlg = gtk.Dialog(title=title, parent=None, flags=0)
+ dlg.set_has_separator(False)
+
+ button1 = hildon.PickerButton(fhsize, horbtn)
+ data = ["50", "100", "200", "300", "400", "500", "600", "700", "800",
+ "900", "1000"]
+ selector = self.create_selector(data, True)
+ button1.set_selector(selector)
+ button1.set_title("Your shares")
+ button1.set_value(shares)
+ dlg.vbox.pack_start(button1, False, False, 0)
+
+ entry1 = hildon.Entry(fhsize)
+ entry1.set_text(name)
+ entry2 = hildon.Entry(fhsize)
+ entry2.set_text(symbol)
+
+ entry1.set_placeholder("Name")
+ entry1.connect("activate", self.add_item, dlg, button1, entry1,
+ entry2, edit, seliter)
+ dlg.vbox.pack_start(entry1, False, False, 0)
+
+ entry2.connect("activate", self.add_item, dlg, button1, entry1,
+ entry2, edit, seliter)
+ entry2.set_placeholder("Yahoo Finance symbol")
+ dlg.vbox.pack_start(entry2, False, False, 0)
+
+ button = hildon.Button(fhsize, horbtn)
+ button.set_label(btntext)
+ button.connect("clicked", self.add_item, dlg, button1, entry1,
+ entry2, edit, seliter)
+ dlg.vbox.pack_start(button, False, False, 0)
+
+ dlg.show_all()
+ dlg.run()
+ dlg.destroy()
+
+ def add_item(self, widget, dlg, button, entry1, entry2, edit, seliter):
+ symbol = entry2.get_text()
+ name = entry1.get_text()
+ shares = button.get_value()
+
+ if name == '' or symbol == '':
+ self.show_info_banner(widget, "Must add the name and symbol")
+ return
+
+ self.add_to_portfolio(widget, button, symbol, name)
+ dlg.destroy()
+
+ if edit:
+ self.portfolio_model.set(seliter, 0, symbol, 1, name, 2, shares,
+ 3, "-", 4, "-", 5, "-", 6, "green")
+ else:
+ niter = self.portfolio_model.append()
+ self.portfolio_model.set(niter, 0, symbol, 1, name, 2, shares,
+ 3, "-", 4, "-", 5, "-", 6, "green")
+
def remove_item(self, widget):
win = hildon.StackableWindow()
win.fullscreen()
conf = self.show_confirmation(win, "Delete items?")
if conf:
- 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)
+ 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)
def refresh_portfolio(self, widget, tv, win):
data = settings.load_portfolio(settingsdb)
+ for item in data:
+ item.append('-')
+ item.append('-')
import thread
winprogind(win, 1)
thread.start_new_thread(self._do_refresh_portfolio, (data, tv, win))
def _do_refresh_portfolio(self, data, tv, win):
+ print data
for item in data:
- item[3] = self.get_price(item[0])
+ item[3], item[4] = self.get_portfolio_data(item[0])
+ try:
+ ch_percent = \
+ 100.0 * float(item[4])/(float(item[3]) - \
+ float(item[4]))
+ except ValueError:
+ ch_percent = 0.0
+
+ item[5] = '%6.2f %%' % ch_percent
+
+ print data
self.portfolio_model = self._create_portfolio_model(data)
tv.set_model(self.portfolio_model)
winprogind(win, 0)
- def get_price(self, symbol):
+ def get_portfolio_data(self, symbol):
from ystockquote import ystockquote as yt
- price = yt.get_price(symbol)
-
- return price
+ try:
+ data = yt.get_all(symbol)
+ return data['price'], data['change']
+ except:
+ logger.exception("Getting price from Yahoo: %s" % symbol)
+ return "-", "-"
def _create_portfolio_model(self, data):
lstore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING,
- gobject.TYPE_STRING, gobject.TYPE_STRING)
+ gobject.TYPE_STRING, gobject.TYPE_STRING,
+ gobject.TYPE_STRING, 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])
+ if '+' in item[4]:
+ color = 'green'
+ else:
+ color = 'red'
+ lstore.set(iter, 0, item[0], 1, item[1], 2, item[2], 3, item[3],
+ 4, item[4], 5, item[5], 6, color)
return lstore
def _tv_portfolio_columns(self, treeview):
column = gtk.TreeViewColumn('Price', gtk.CellRendererText(), text=3)
treeview.append_column(column)
+ column = gtk.TreeViewColumn('Change', gtk.CellRendererText(), text=4)
+ treeview.append_column(column)
+
+
+ renderer = gtk.CellRendererText()
+ renderer.set_property("foreground-set", True)
+ column = gtk.TreeViewColumn('%', renderer, text=5, foreground=6)
+ treeview.append_column(column)
+
def show_confirmation(self, window, msg):
dialog = hildon.hildon_note_new_confirmation(window, msg)
dialog.show_all()
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)
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.abdialog = gtk.Dialog()
+ self.abdialog.set_title("About StockThis")
- self.info_lb = gtk.Label()
- self.info_lb.set_line_wrap(True)
+ notebook = gtk.Notebook()
+ notebook.set_show_tabs(False)
+ notebook.set_scrollable(False)
+ notebook.set_show_border(False)
- hbox1 = gtk.HBox()
+ # Description page #
+ vbox = gtk.VBox()
- button = hildon.Button(fhsize, horbtn)
- button.set_title('Description')
- button.connect("clicked", self.show_info, 'description')
- hbox1.pack_start(button, True, True, 0)
+ label = gtk.Label()
+ label.set_markup("<b><big>StockThis %s</big></b>" % VERSION)
+ vbox.pack_start(label, 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)
+ label = gtk.Label("Stocks application with big database")
+ vbox.pack_start(label, True, True, 0)
+
+ label = gtk.Label("GNU General Public License")
+ vbox.pack_start(label, True, True, 0)
+
+ url = "http://stockthis.garage.maemo.org"
+ webbtn = gtk.LinkButton(url, "Web")
+ vbox.pack_start(webbtn, True, True, 0)
+ gtk.link_button_set_uri_hook(self.launch_browser)
+
+ notebook.append_page(vbox, gtk.Label())
+
+ # Credits page #
+ vbox = gtk.VBox()
+ textview = hildon.TextView()
+ textview.set_cursor_visible(False)
+ textview.set_wrap_mode(gtk.WRAP_WORD)
+ text = "Written by Daniel Martin Yerga (dyerga@gmail.com)"
+ textview.get_buffer().set_text(text)
+
+ parea = hildon.PannableArea()
+ parea.add(textview)
+
+ vbox.pack_start(parea, True, True, 0)
+ notebook.append_page(vbox, gtk.Label())
+
+
+ # Donate page #
+ vbox = gtk.VBox()
+
+ textview = hildon.TextView()
+ textview.set_cursor_visible(False)
+ textview.set_wrap_mode(gtk.WRAP_WORD)
+ text = """StockThis is a free software application.
+Developing good software takes time and hard work.
+StockThis's author develops the program in his spare time.
+If you like the program and it's helpful, consider donating a small amount of money.
+Donations are a great incentive and help the developer feel that the hard work is appreciated.
+"""
+ textview.get_buffer().set_text(text)
+
+ parea = hildon.PannableArea()
+ parea.add(textview)
button = hildon.Button(fhsize, horbtn)
- button.set_title('License')
- button.connect("clicked", self.show_info, 'license')
- hbox1.pack_start(button, True, True, 0)
+ button.set_title("Make donation")
+ url = "http://stockthis.garage.maemo.org/donate.html"
+ button.connect("clicked", self.launch_browser, url)
+ vbox.pack_start(button, False, False, 0)
+ vbox.pack_start(parea, True, True, 0)
+
+ notebook.append_page(vbox, gtk.Label())
+
+ # Report page #
+ vbox = gtk.VBox()
+
+ textview = hildon.TextView()
+ textview.set_cursor_visible(False)
+ textview.set_wrap_mode(gtk.WRAP_WORD)
+ text = """StockThis is being improved thanks to bug reports that users have submitted. The author appreciates these reports.
+If the application is having an error when you're using it, you have two choices to report this error:
+1) Send the log from the button above (if there's an error in the log).
+2) Press the button and read how to report a bug."""
+ textview.get_buffer().set_text(text)
+
+ parea = hildon.PannableArea()
+ parea.add(textview)
+
+ hbox = gtk.HBox()
+ hbox.set_homogeneous(True)
button = hildon.Button(fhsize, horbtn)
- button.set_title('Donate')
- button.connect("clicked", self.show_info, 'donate')
- hbox1.pack_start(button, True, True, 0)
+ button.set_title("Report error")
+ url = "http://stockthis.garage.maemo.org/reporting.html"
+ button.connect("clicked", self.launch_browser, url)
+ hbox.pack_start(button, True, True, 0)
button = hildon.Button(fhsize, horbtn)
- button.set_title('Report ')
- button.connect("clicked", self.show_info, 'report')
- hbox1.pack_start(button, True, True, 0)
+ button.set_title("Log")
+ button.connect("clicked", self.on_show_log)
+ hbox.pack_start(button, True, True, 0)
+
+ vbox.pack_start(hbox, False, False, 0)
+ vbox.pack_start(parea, True, True, 0)
+
+ notebook.append_page(vbox, gtk.Label())
+
+ # Rate page #
+ vbox = gtk.VBox()
+
+ textview = hildon.TextView()
+ textview.set_cursor_visible(False)
+ textview.set_wrap_mode(gtk.WRAP_WORD)
+ text = """The downloads section in maemo.org has a nice system where you can rate applications.
+If you consider StockThis a good application (or a bad one too), you could rate it in maemo.org site."""
+ textview.get_buffer().set_text(text)
button = hildon.Button(fhsize, horbtn)
- button.set_title(' Vote ')
- button.connect("clicked", self.show_info, 'vote')
- hbox1.pack_start(button, True, True, 0)
+ button.set_title("Rate StockThis")
+ url = "http://maemo.org/downloads/product/Maemo5/stockthis"
+ button.connect("clicked", self.launch_browser, url)
+ image = gtk.Image()
+ image.set_from_file(imgdir + "maemoorg.png")
+ vbox.pack_start(button, False, False, 0)
+ vbox.pack_start(image, False, False, 5)
+ vbox.pack_start(textview, True, True, 0)
+
+ notebook.append_page(vbox, gtk.Label())
- self.action_btn = hildon.Button(fhsize, horbtn)
- self.image = gtk.Image()
+ # Buttons #
+ self.abdialog.vbox.pack_start(notebook, True, True, 0)
- self.show_info(None, 'description')
+ hbox = gtk.HBox()
+
+ descbutton = hildon.GtkRadioButton(fhsize)
+ descbutton.set_mode(False)
+ descbutton.set_active(True)
+ descbutton.set_label('Description')
+ descbutton.connect("toggled", self.change_tab, notebook, 0)
+ hbox.pack_start(descbutton, True, True, 0)
+
+ button = hildon.GtkRadioButton(fhsize)
+ button.set_mode(False)
+ button.set_active(True)
+ button.set_label('Credits')
+ button.set_group(descbutton)
+ button.connect("toggled", self.change_tab, notebook, 1)
+ hbox.pack_start(button, True, True, 0)
+
+ button = hildon.GtkRadioButton(fhsize)
+ button.set_mode(False)
+ button.set_label('Donate')
+ button.set_group(descbutton)
+ button.connect("clicked", self.change_tab, notebook, 2)
+ hbox.pack_start(button, True, True, 0)
+
+ button = hildon.GtkRadioButton(fhsize)
+ button.set_mode(False)
+ button.set_label('Report')
+ button.set_group(descbutton)
+ button.connect("clicked", self.change_tab, notebook, 3)
+ hbox.pack_start(button, True, True, 0)
+
+ button = hildon.GtkRadioButton(fhsize)
+ button.set_mode(False)
+ button.set_label('Rate')
+ button.set_group(descbutton)
+ button.connect("clicked", self.change_tab, notebook, 4)
+ hbox.pack_start(button, True, True, 0)
+
+ self.abdialog.vbox.pack_start(hbox, False, False, 0)
+
+ self.abdialog.show_all()
+ self.abdialog.run()
+ self.abdialog.destroy()
+
+ def change_tab(self, widget, notebook, number):
+ notebook.set_current_page(number)
+
+ def launch_browser(self, widget, url):
+ import dbus
+ bus = dbus.SystemBus()
+ proxy = bus.get_object("com.nokia.osso_browser", "/com/nokia/osso_browser/request")
+ iface = dbus.Interface(proxy, 'com.nokia.osso_browser')
+
+ self.abdialog.destroy()
+
+ iface.open_new_window(url)
+
+ def on_show_log(self, widget):
+ Log(widget, logfile)
+
+
+class Log:
+
+ def __init__(self, widget, logfile):
+ #Log dialog UI
+ dialog = gtk.Dialog(title='Log', parent=None)
+
+ dialog.set_size_request(600, 350)
+
+ parea = hildon.PannableArea()
+ parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
- 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)
+ 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()
- 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')
- 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.
+ def show_filechooser(self, window, title, name, EXT):
+ action = gtk.FILE_CHOOSER_ACTION_SAVE
-<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>
-"""
+ 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')
- elif kind == 'report':
- self.action_btn.show()
- self.image.hide()
- self.action_btn.set_title('Report bug')
- 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')
- 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)
+ 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__":