# Version 0.1
#
+_version = "StockThis 0.3 alpha1 rev1"
+
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
+#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:
settings.define_paths(runninglocally, HOME)
+logger = logging.getLogger('st')
+logging.basicConfig(filename=logfile,level=logging.ERROR, filemode='w')
+
+DEBUG = True
+
+if DEBUG:
+ #set the main logger to DEBUG
+ logger.setLevel(logging.DEBUG)
+
+ #Create a handler for console debug
+ console = logging.StreamHandler()
+ console.setLevel(logging.DEBUG)
+ # set a format which is simpler for console use
+ formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+ # tell the handler to use this format
+ console.setFormatter(formatter)
+ logging.getLogger('').addHandler(console)
+
fhsize = gtk.HILDON_SIZE_FINGER_HEIGHT
horbtn = hildon.BUTTON_ARRANGEMENT_HORIZONTAL
ui_normal = gtk.HILDON_UI_MODE_NORMAL
ui_edit = gtk.HILDON_UI_MODE_EDIT
winprogind = hildon.hildon_gtk_window_set_progress_indicator
+logger.debug("test this log")
+
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()
+ self.create_menu(self.window)
vbox = gtk.VBox()
toolbar = self.main_toolbar(False, False, None, '', '')
self.window.add(vbox)
self.window.show_all()
+ 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]
ids = ids[mindex.index(market)]
window = hildon.StackableWindow()
+ self.create_menu(window)
window.set_title("StockThis - " + inmodel[path][1])
vbox = gtk.VBox()
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()
+ self.create_menu(win)
win.set_title("StockThis - Quotes View - " + quote[1])
vbox = gtk.VBox()
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)
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])
self.show_data(quote[0], widgets, shares)
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")
+ 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")
+ self.show_info_banner(widget, "Error adding to portfolio")
def create_selector(self, data, entry):
try:
data = yt.get_all(symbol)
except:
- print 'Failed to get internet data'
+ logger.exception("Getting data from Yahoo")
data = {'price': 'N/A', 'change': 'N/A', 'volume':'N/A',
'52_week_high': 'N/A', '52_week_low': 'N/A'}
ltitle.set_markup('<b><big>Failed to get data</big></b>')
def show_graph_view(self, widget, symbol, name):
win = hildon.StackableWindow()
+ self.create_menu(win)
win.set_title("StockThis - Graph View - " + name)
vbox = gtk.VBox()
self.graph.set_from_pixbuf(pbuf)
winprogind(win, 0)
except:
+ logger.exception("Getting graph data")
winprogind(win, 0)
self.graphs_title.set_label('Failed to get data')
self.graph.destroy()
data = settings.load_portfolio(settingsdb)
win = hildon.StackableWindow()
+ self.create_menu(win)
win.set_title("StockThis - Portfolio")
vbox = gtk.VBox()
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 get_price(self, symbol):
from ystockquote import ystockquote as yt
- price = yt.get_price(symbol)
-
- return price
+ 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,
self.info_lb = gtk.Label()
self.info_lb.set_line_wrap(True)
+ self.id = False
+
hbox1 = gtk.HBox()
button = hildon.Button(fhsize, horbtn)
self.action_btn.show()
self.image.hide()
self.action_btn.set_title('I want donate')
- self.action_btn.connect("clicked", self.do_action, "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.
self.action_btn.show()
self.image.hide()
self.action_btn.set_title('Report bug')
- self.action_btn.connect("clicked", self.do_action, "report")
+ 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).
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")
+ 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()