diff options
author | monsta <[email protected]> | 2018-01-13 13:54:33 +0300 |
---|---|---|
committer | raveit65 <[email protected]> | 2018-01-14 16:19:48 +0100 |
commit | 41f7b7a2a38ca9f3929fcbd88d228b3815034876 (patch) | |
tree | 4da95992b542ba378b7ccc82b8d55a3dd86302d3 /invest-applet/invest | |
parent | 55fbad37580a11d2ac539b382f463af2f12e114c (diff) | |
download | mate-applets-41f7b7a2a38ca9f3929fcbd88d228b3815034876.tar.bz2 mate-applets-41f7b7a2a38ca9f3929fcbd88d228b3815034876.tar.xz |
drop broken invest-applet and all Python dependencies
closes https://github.com/mate-desktop/mate-applets/issues/297
Diffstat (limited to 'invest-applet/invest')
-rw-r--r-- | invest-applet/invest/Makefile.am | 41 | ||||
-rw-r--r-- | invest-applet/invest/__init__.py | 204 | ||||
-rw-r--r-- | invest-applet/invest/about.py | 40 | ||||
-rw-r--r-- | invest-applet/invest/applet.py | 199 | ||||
-rw-r--r-- | invest-applet/invest/chart.py | 267 | ||||
-rw-r--r-- | invest-applet/invest/currencies.py | 145 | ||||
-rw-r--r-- | invest-applet/invest/defs.py.in | 9 | ||||
-rw-r--r-- | invest-applet/invest/help.py | 12 | ||||
-rwxr-xr-x | invest-applet/invest/invest-applet.py | 101 | ||||
-rwxr-xr-x | invest-applet/invest/mate-invest-chart | 19 | ||||
-rw-r--r-- | invest-applet/invest/networkmanager.py | 26 | ||||
-rw-r--r-- | invest-applet/invest/preferences.py | 290 | ||||
-rw-r--r-- | invest-applet/invest/quotes.py | 475 | ||||
-rwxr-xr-x | invest-applet/invest/test.py | 30 | ||||
-rw-r--r-- | invest-applet/invest/widgets.py | 263 |
15 files changed, 0 insertions, 2121 deletions
diff --git a/invest-applet/invest/Makefile.am b/invest-applet/invest/Makefile.am deleted file mode 100644 index 7ab75594..00000000 --- a/invest-applet/invest/Makefile.am +++ /dev/null @@ -1,41 +0,0 @@ -invest-applet: invest-applet.py - sed -e "s|\@PYTHONDIR\@|$(pythondir)/|" $< > $@ - -bin_SCRIPTS = mate-invest-chart - -libexec_SCRIPTS = invest-applet - -investdir = $(pythondir)/mate_invest -invest_PYTHON = \ - __init__.py \ - about.py \ - help.py \ - applet.py \ - chart.py \ - currencies.py \ - widgets.py \ - quotes.py \ - networkmanager.py \ - preferences.py -nodist_invest_PYTHON = \ - defs.py - -BUILT_SOURCES = \ - invest-applet - -CLEANFILES = \ - $(BUILT_SOURCES) - -DISTCLEANFILES = \ - defs.py \ - $(CLEANFILES) - -EXTRA_DIST = \ - defs.py.in \ - invest-applet.py \ - mate-invest-chart \ - test.py - -#TESTS = test.py - --include $(top_srcdir)/git.mk diff --git a/invest-applet/invest/__init__.py b/invest-applet/invest/__init__.py deleted file mode 100644 index 0bc70f94..00000000 --- a/invest-applet/invest/__init__.py +++ /dev/null @@ -1,204 +0,0 @@ -import os, sys -from os.path import join, exists, isdir, isfile, dirname, abspath -from types import ListType -import datetime - -# Autotools set the actual data_dir in defs.py -from defs import * - -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GObject -from gi.repository import Gio -from gi.repository import GLib - -import cPickle - -import networkmanager - - - -DEBUGGING = False - -# central debugging and error method -def debug(msg): - if DEBUGGING: - print "%s: %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"), msg) - -def error(msg): - print "%s: ERROR: %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"), msg) - - -# Allow to use uninstalled invest --------------------------------------------- -UNINSTALLED_INVEST = False -def _check(path): - return exists(path) and isdir(path) and isfile(path+"/Makefile.am") - -name = join(dirname(__file__), '..') -if _check(name): - UNINSTALLED_INVEST = True - -# Sets SHARED_DATA_DIR to local copy, or the system location -# Shared data dir is most the time /usr/share/invest-applet -if UNINSTALLED_INVEST: - SHARED_DATA_DIR = abspath(join(dirname(__file__), '..', 'data')) - BUILDER_DATA_DIR = SHARED_DATA_DIR - ART_DATA_DIR = join(SHARED_DATA_DIR, 'art') -else: - SHARED_DATA_DIR = join(DATA_DIR, "mate-applets", "invest-applet") - BUILDER_DATA_DIR = BUILDERDIR - ART_DATA_DIR = SHARED_DATA_DIR - -USER_INVEST_DIR = join(GLib.get_user_config_dir(), "mate/invest-applet") -if not exists(USER_INVEST_DIR): - try: - os.makedirs(USER_INVEST_DIR, 0744) - except Exception , msg: - error('Could not create user dir (%s): %s' % (USER_INVEST_DIR, msg)) -# ------------------------------------------------------------------------------ - -# Set the cwd to the home directory so spawned processes behave correctly -# when presenting save/open dialogs -os.chdir(GLib.get_home_dir()) - -# tests whether the given stocks are in the old labelless format -def labelless_stock_format(stocks): - if len(stocks) == 0: - return False - - # take the first element of the dict and check if its value is a list - if type(stocks[stocks.keys()[0]]) is ListType: - return True - - # there is no list, so it is already the new stock file format - return False - -# converts the given stocks from the labelless format into the one with labels -def update_to_labeled_stock_format(stocks): - new = {} - - for k, l in stocks.items(): - d = {'label':"", 'purchases':l} - new[k] = d - - return new - -# tests whether the given stocks are in the format without exchange information -def exchangeless_stock_format(stocks): - if len(stocks) == 0: - return False - - # take the first element of the dict and check if its value is a list - for symbol, data in stocks.items(): - purchases = stocks[symbol]["purchases"] - if len(purchases) > 0: - purchase = purchases[0] - if not purchase.has_key("exchange"): - return True - - return False - -# converts the given stocks into format with exchange information -def update_to_exchange_stock_format(stocks): - for symbol, data in stocks.items(): - purchases = data["purchases"] - for purchase in purchases: - purchase["exchange"] = 0 - - return stocks - -STOCKS_FILE = join(USER_INVEST_DIR, "stocks.pickle") - -try: - STOCKS = cPickle.load(file(STOCKS_FILE)) - - # if the stocks file is in the stocks format without labels, - # then we need to convert it into the new labeled format - if labelless_stock_format(STOCKS): - STOCKS = update_to_labeled_stock_format(STOCKS); - - # if the stocks file does not contain exchange rates, add them - if exchangeless_stock_format(STOCKS): - STOCKS = update_to_exchange_stock_format(STOCKS); -except Exception, msg: - error("Could not load the stocks from %s: %s" % (STOCKS_FILE, msg) ) - STOCKS = {} - -#STOCKS = { -# "AAPL": { -# "amount": 12, -# "bought": 74.94, -# "comission": 31, -# }, -# "INTC": { -# "amount": 30, -# "bought": 25.85, -# "comission": 31, -# }, -# "GOOG": { -# "amount": 1, -# "bought": 441.4, -# "comission": 31, -# }, -#} - -CONFIG_FILE = join(USER_INVEST_DIR, "config.pickle") -try: - CONFIG = cPickle.load(file(CONFIG_FILE)) -except Exception, msg: - CONFIG = {} # default configuration - -CURRENCIES_FILE = join(USER_INVEST_DIR, "currencies.csv") -QUOTES_FILE = join(USER_INVEST_DIR, "quotes.csv") - - -# set default proxy config -PROXY = None - -# borrowed from Ross Burton -# http://burtonini.com/blog/computers/postr -# extended by exception handling and retry scheduling -def get_gnome_proxy(): - - # sanity check if we still need to look for proxy configuration - global PROXY - if PROXY != None: - return - - # try to get config from gsettings - try: - proxy_settings = Gio.Settings.new("org.gnome.system.proxy") - proxy_http_settings = Gio.Settings.new("org.gnome.system.proxy.http") - - proxy_mode = proxy_settings.get_enum("mode") - - if proxy_mode == 1: - host = proxy_http_settings.get_string("host") - port = proxy_http_settings.get_int("port") - if host is None or host == "" or port == 0: - # system proxy is not valid, stop here - return - - if proxy_http_settings.get_boolean("use-authentication"): - user = proxy_http_settings.get_string("authentication-user") - password = proxy_http_settings.get_string("authentication-password") - if user and user != "": - url = "http://%s:%s@%s:%d" % (user, password, host, port) - else: - url = "http://%s:%d" % (host, port) - else: - url = "http://%s:%d" % (host, port) - - # proxy config found, memorize - PROXY = {'http': url} - - except Exception, msg: - error("Failed to get proxy configuration from GSettings:\n%s" % msg) - -get_gnome_proxy() - - -# connect to Network Manager to identify current network connectivity -nm = networkmanager.NetworkManager() diff --git a/invest-applet/invest/about.py b/invest-applet/invest/about.py deleted file mode 100644 index 5a32cdb9..00000000 --- a/invest-applet/invest/about.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -from os.path import join -from gettext import gettext as _ -from mate_invest.defs import VERSION -import mate_invest - -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GdkPixbuf - -invest_logo = None -try: - invest_logo = GdkPixbuf.Pixbuf.new_from_file_at_size(join(mate_invest.ART_DATA_DIR, "invest_neutral.svg"), 96, 96) -except Exception, msg: - pass - -def show_about(): - about = Gtk.AboutDialog() - infos = { - "program-name" : _("Invest"), - "logo" : invest_logo, - "version" : VERSION, - "comments" : _("Track your invested money."), - "copyright" : "Copyright © 2004-2005 Raphael Slinckx\nCopyright © 2009-2010 Enrico Minack\nCopyright © 2012-2018 MATE developers" - } - -# about.set_authors("Raphael Slinckx <[email protected]>\nEnrico Minack <[email protected]>") -# about.set_artists([]) -# about.set_documenters([]) - - #translators: These appear in the About dialog, usual format applies. - about.set_translator_credits( _("translator-credits") ) - - for prop, val in infos.items(): - about.set_property(prop, val) - - about.connect ("response", lambda self, *args: self.destroy ()) - about.show_all() diff --git a/invest-applet/invest/applet.py b/invest-applet/invest/applet.py deleted file mode 100644 index 82001ed3..00000000 --- a/invest-applet/invest/applet.py +++ /dev/null @@ -1,199 +0,0 @@ -import os, time -from os.path import * -import mate_invest.defs - -import gi -gi.require_version("Gtk", "3.0") - -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GdkPixbuf -from gi.repository import GObject -from gi.repository import MatePanelApplet - -GObject.threads_init() -from gettext import gettext as _ - -import mate_invest, mate_invest.about, mate_invest.chart, mate_invest.preferences -from mate_invest.quotes import QuoteUpdater -from mate_invest.widgets import * - -Gtk.Window.set_default_icon_from_file(join(mate_invest.ART_DATA_DIR, "invest_neutral.svg")) - -class InvestApplet(MatePanelApplet.Applet): - def __init__(self, applet): - self.applet = applet - - # name, stock_id, label, accellerator, tooltip, callback - menu_actions = [("About", Gtk.STOCK_ABOUT, _("About"), None, None, self.on_about), - ("Help", Gtk.STOCK_HELP, _("Help"), None, None, self.on_help), - ("Prefs", Gtk.STOCK_PREFERENCES, _("Preferences"), None, None, self.on_preferences), - ("Refresh", Gtk.STOCK_REFRESH, _("Refresh"), None, None, self.on_refresh) - ] - actiongroup = Gtk.ActionGroup.new("InvestAppletActions") - actiongroup.set_translation_domain(mate_invest.defs.GETTEXT_PACKAGE) - actiongroup.add_actions(menu_actions, None) - self.applet.setup_menu_from_file (join(mate_invest.defs.PKGDATADIR, "Invest_Applet.xml"), actiongroup) - - evbox = Gtk.HBox() - self.applet_icon = Gtk.Image() - self.set_applet_icon(0) - self.applet_icon.show() - evbox.add(self.applet_icon) - self.applet.add(evbox) - self.applet.connect("button-press-event", self.button_clicked) - self.applet.show_all() - self.new_ilw() - - def new_ilw(self): - self.quotes_updater = QuoteUpdater(self.set_applet_icon, - self.set_applet_tooltip) - self.investwidget = InvestWidget(self.quotes_updater) - self.ilw = InvestmentsListWindow(self.applet, self.investwidget) - - def reload_ilw(self): - self.ilw.destroy() - self.new_ilw() - - def button_clicked(self, widget,event): - if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 1: - # Three cases... - if len (mate_invest.STOCKS) == 0: - # a) We aren't configured yet - mate_invest.preferences.show_preferences(self, _("<b>You have not entered any stock information yet</b>")) - self.reload_ilw() - elif not self.quotes_updater.quotes_valid: - # b) We can't get the data (e.g. offline) - alert = Gtk.MessageDialog(buttons=Gtk.ButtonsType.CLOSE) - alert.set_markup(_("<b>No stock quotes are currently available</b>")) - alert.format_secondary_text(_("The server could not be contacted. The computer is either offline or the servers are down. Try again later.")) - alert.run() - alert.destroy() - else: - # c) Everything is normal: pop-up the window - self.ilw.toggle_show() - - def on_about(self, action): - mate_invest.about.show_about() - - def on_help(self, action): - mate_invest.help.show_help() - - def on_preferences(self, action): - mate_invest.preferences.show_preferences(self) - self.reload_ilw() - - def on_refresh(self, action): - self.quotes_updater.refresh() - - def set_applet_icon(self, change): - if change == 1: - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(join(mate_invest.ART_DATA_DIR, "invest-22_up.png"), -1,-1) - elif change == 0: - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(join(mate_invest.ART_DATA_DIR, "invest-22_neutral.png"), -1,-1) - else: - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(join(mate_invest.ART_DATA_DIR, "invest-22_down.png"), -1,-1) - self.applet_icon.set_from_pixbuf(pixbuf) - - def set_applet_tooltip(self, text): - self.applet_icon.set_tooltip_text(text) - -class InvestmentsListWindow(Gtk.Window): - def __init__(self, applet, list): - Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL) - self.set_type_hint(Gdk.WindowTypeHint.DOCK) - self.stick() - self.set_resizable(False) - self.set_border_width(6) - - self.applet = applet # this is the widget we want to align with - self.alignment = self.applet.get_orient () - - self.add(list) - list.show() - - # boolean variable that identifies if the window is visible - # show/hide is triggered by left-clicking on the applet - self.hidden = True - - def toggle_show(self): - if self.hidden == True: - self.update_position() - self.show_all() - self.hidden = False - elif self.hidden == False: - self.hide() - self.hidden = True - - def update_position (self): - """ - Calculates the position and moves the window to it. - """ - self.realize() - - # Get our own dimensions & position - #(wx, wy) = self.get_origin() - - window = self.applet.get_window() - screen = window.get_screen() - monitor = screen.get_monitor_geometry (screen.get_monitor_at_window (window)) - (ret, ax, ay) = window.get_origin() - (ignored, ignored, aw, ah) = window.get_geometry() - - (ww, wh) = self.get_size() - - if self.alignment == MatePanelApplet.AppletOrient.LEFT: - x = ax - ww - y = ay - - if (y + wh > monitor.y + monitor.height): - y = monitor.y + monitor.height - wh - - if (y < 0): - y = 0 - - if (y + wh > monitor.height / 2): - gravity = Gdk.Gravity.SOUTH_WEST - else: - gravity = Gdk.Gravity.NORTH_WEST - - elif self.alignment == MatePanelApplet.AppletOrient.RIGHT: - x = ax + aw - y = ay - - if (y + wh > monitor.y + monitor.height): - y = monitor.y + monitor.height - wh - - if (y < 0): - y = 0 - - if (y + wh > monitor.height / 2): - gravity = Gdk.Gravity.SOUTH_EAST - else: - gravity = Gdk.Gravity.NORTH_EAST - - elif self.alignment == MatePanelApplet.AppletOrient.DOWN: - x = ax - y = ay + ah - - if (x + ww > monitor.x + monitor.width): - x = monitor.x + monitor.width - ww - - if (x < 0): - x = 0 - - gravity = Gdk.Gravity.NORTH_WEST - elif self.alignment == MatePanelApplet.AppletOrient.UP: - x = ax - y = ay - wh - - if (x + ww > monitor.x + monitor.width): - x = monitor.x + monitor.width - ww - - if (x < 0): - x = 0 - - gravity = Gdk.Gravity.SOUTH_WEST - - self.move(x, y) - self.set_gravity(gravity) diff --git a/invest-applet/invest/chart.py b/invest-applet/invest/chart.py deleted file mode 100644 index eb5322cb..00000000 --- a/invest-applet/invest/chart.py +++ /dev/null @@ -1,267 +0,0 @@ -#!/usr/bin/env python - -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GdkPixbuf -from gi.repository import GObject -import os -import mate_invest -from gettext import gettext as _ -from mate_invest import * -import sys -from os.path import join -import urllib -from threading import Thread -import time - -AUTOREFRESH_TIMEOUT = 20*60*1000 # 15 minutes - -# based on http://www.johnstowers.co.nz/blog/index.php/2007/03/12/threading-and-pygtk/ -class _IdleObject(GObject.GObject): - """ - Override GObject.GObject to always emit signals in the main thread - by emmitting on an idle handler - """ - def __init__(self): - GObject.GObject.__init__(self) - - def emit(self, *args): - GObject.idle_add(GObject.GObject.emit,self,*args) - -class ImageRetriever(Thread, _IdleObject): - """ - Thread which uses gobject signals to return information - to the GUI. - """ - __gsignals__ = { - "completed": ( - GObject.SignalFlags.RUN_LAST, None, []), - # FIXME: should we be making use of this? - #"progress": ( - # GObject.SignalFlags.RUN_LAST, None, [ - # GObject.TYPE_FLOAT]) #percent complete - } - - def __init__(self, image_url): - Thread.__init__(self) - _IdleObject.__init__(self) - self.image_url = image_url - self.retrieved = False - - def run(self): - self.image = Gtk.Image() - try: sock = urllib.urlopen(self.image_url, proxies = mate_invest.PROXY) - except Exception, msg: - mate_invest.debug("Error while opening %s: %s" % (self.image_url, msg)) - else: - loader = GdkPixbuf.PixbufLoader() - loader.connect("closed", lambda loader: self.image.set_from_pixbuf(loader.get_pixbuf())) - loader.write(sock.read()) - sock.close() - loader.close() - self.retrieved = True - self.emit("completed") - -# p: -# eX = Exponential Moving Average -# mX = Moving Average -# b = Bollinger Bands Overlay -# v = Volume Overlay -# p = Parabolic SAR overlay -# s = Splits Overlay -# q: -# l = Line -# c = Candles -# b = Bars -# l: -# on = Logarithmic -# off = Linear -# z: -# l = Large -# m = Medium -# t: -# Xd = X Days -# Xm = X Months -# Xy = X Years -# a: -# fX = MFI X days -# ss = Slow Stochastic -# fs = Fast Stochastic -# wX = W%R X Days -# mX-Y-Z = MACD X Days, Y Days, Signal -# pX = ROC X Days -# rX = RSI X Days -# v = Volume -# vm = Volume +MA -# c: -# X = compare with X -# - -class FinancialChart: - def __init__(self, ui): - self.ui = ui - - #Time ranges of the plot (parameter / combo-box t) - self.time_ranges = ["1d", "5d", "3m", "6m", "1y", "5y", "my"] - - #plot types (parameter / combo-box q) - self.plot_types = ["l", "b", "c"] - - #plot scales (parameter / combo-box l) - self.plot_scales = ["off", "on"] - - # Window Properties - win = ui.get_object("window") - win.set_title(_("Financial Chart")) - - try: - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(join(mate_invest.ART_DATA_DIR, "invest_neutral.svg"), 96,96) - self.ui.get_object("plot").set_from_pixbuf(pixbuf) - except Exception, msg: - mate_invest.debug("Could not load 'invest-neutral.svg' file: %s" % msg) - pass - - # Defaut comboboxes values - for widget in ["t", "q", "l"]: - ui.get_object(widget).set_active(0) - - # Connect every option widget to its corresponding change signal - symbolentry = ui.get_object("s") - refresh_chart_callback = lambda w: self.on_refresh_chart() - - for widgets, signal in [ - (("pm5","pm10","pm20","pm50","pm100","pm200", - "pe5","pe10", "pe20","pe50","pe100","pe200", - "pb","pp","ps","pv", - "ar","af","ap","aw","am","ass","afs","av","avm"), "toggled"), - (("t", "q", "l"), "changed"), - (("s",), "activate"), - ]: - for widget in widgets: - ui.get_object(widget).connect(signal, refresh_chart_callback) - - ui.get_object("progress").hide() - - # Connect auto-refresh widget - self.autorefresh_id = 0 - ui.get_object("autorefresh").connect("toggled", self.on_autorefresh_toggled) - - def on_refresh_chart(self, from_timer=False): - tickers = self.ui.get_object("s").get_text() - - if tickers.strip() == "": - return True - - # FIXME: We don't just do US stocks, so we can't be this - # simplistic about it, but it is a good idea. - #if from_timer and not ustime.hour_between(9, 16): - # return True - - tickers = [ticker.strip().upper() for ticker in tickers.split(' ') if ticker != ""] - - # Update Window Title ------------------------------------------------------ - win = self.ui.get_object("window") - title = _("Financial Chart - %s") - titletail = "" - for ticker in tickers: - titletail += "%s / " % ticker - title = title % titletail - - win.set_title(title[:-3]) - - # Detect Comparison or simple chart ---------------------------------------- - opt = "" - for ticker in tickers[1:]: - opt += "&c=%s" % ticker - - # Create the overlay string ------------------------------------------------ - p = "" - for name, param in [ - ("pm5", 5), - ("pm10", 10), - ("pm20", 20), - ("pm50", 50), - ("pm100", 100), - ("pm200", 200), - ("pe5", 5), - ("pe10", 10), - ("pe20", 20), - ("pe50", 50), - ("pe100", 100), - ("pe200", 200), - ("pb", ""), - ("pp", ""), - ("ps", ""), - ("pv", ""), - ]: - if self.ui.get_object(name).get_active(): - p += "%s%s," % (name[1], param) - - # Create the indicators string --------------------------------------------- - a = "" - for name, param in [ - ("ar", 14), - ("af", 14), - ("ap", 12), - ("aw", 14), - ("am", "26-12-9"), - ("ass", ""), - ("afs", ""), - ("av", ""), - ("avm", ""), - ]: - if self.ui.get_object(name).get_active(): - a += "%s%s," % (name[1:], param) - - # Create the image URL ----------------------------------------------------- - chart_base_url = "http://chart.finance.yahoo.com/z?s=%(s)s&t=%(t)s&q=%(q)s&l=%(l)s&z=%(z)s&p=%(p)s&a=%(a)s%(opt)s" - url = chart_base_url % { - "s": tickers[0], - "t": self.time_ranges[self.ui.get_object("t").get_active()], - "q": self.plot_types[self.ui.get_object("q").get_active()], - "l": self.plot_scales[self.ui.get_object("l").get_active()], - "z": "l", - "p": p, - "a": a, - "opt": opt, - } - - # Download and display the image ------------------------------------------- - progress = self.ui.get_object("progress") - progress.set_text(_("Opening Chart")) - progress.show() - - image_retriever = ImageRetriever(url) - image_retriever.connect("completed", self.on_retriever_completed) - image_retriever.start() - - # Update timer if needed - self.on_autorefresh_toggled(self.ui.get_object("autorefresh")) - return True - - def on_retriever_completed(self, retriever): - self.ui.get_object("plot").set_from_pixbuf(retriever.image.get_pixbuf()) - progress = self.ui.get_object("progress") - if retriever.retrieved == True: - progress.set_text(_("Chart downloaded")) - else: - progress.set_text(_("Chart could not be downloaded")) - - def on_autorefresh_toggled(self, autorefresh): - if self.autorefresh_id != 0: - GObject.source_remove(self.autorefresh_id) - self.autorefresh_id = 0 - - if autorefresh.get_active(): - self.autorefresh_id = GObject.timeout_add(AUTOREFRESH_TIMEOUT, self.on_refresh_chart, True) - -def show_chart(tickers): - ui = Gtk.Builder(); - ui.add_from_file(os.path.join(mate_invest.BUILDER_DATA_DIR, "financialchart.ui")) - chart = FinancialChart(ui) - ui.get_object("s").set_text(' '.join(tickers)) - chart.on_refresh_chart() - return ui.get_object("window") - diff --git a/invest-applet/invest/currencies.py b/invest-applet/invest/currencies.py deleted file mode 100644 index 0eaa075c..00000000 --- a/invest-applet/invest/currencies.py +++ /dev/null @@ -1,145 +0,0 @@ -class Currencies: - currencies = { - "BZD" : "Belize Dollar", - "NLG" : "Dutch Guilder", - "SLL" : "Sierra Leone Leone", - "FRF" : "French Franc", - "NGN" : "Nigerian Naira", - "CRC" : "Costa Rican Colon", - "LAK" : "Laos Kip", - "CLP" : "Chilean Peso", - "DZD" : "Algerian Dinar", - "SZL" : "Swaziland Lilangeni", - "MUR" : "Mauritius Rupee", - "WST" : "Western Samoa Tala", - "MMK" : "Myanmar Kyat", - "IDR" : "Indonesian Rupiah", - "GTQ" : "Guatemala Quetzal", - "CAD" : "Canadian Dollar", - "AWG" : "Aruban Florin", - "TTD" : "Trinidad Dollar", - "PKR" : "Pakistani Rupee", - "XCD" : "East Caribbean Dollar", - "VUV" : "Vanuatu Vatu", - "XOF" : "CFA Franc (BCEAO)", - "ROL" : "Romanian Leu", - "KMF" : "Comoros Franc", - "SIT" : "Slovenian Tolar", - "VEB" : "Venezuelan Bolivar", - "ANG" : "Netherlands Antilles Guilder", - "MNT" : "Mongolian Tugrik", - "LBP" : "Lebanese Pound", - "KES" : "Kenyan Shilling", - "BTN" : "Bhutan Ngultrum", - "GBP" : "British Pound", - "SEK" : "Swedish Krona", - "ZMK" : "Zambia Kwacha", - "SKK" : "Slovak Koruna", - "DKK" : "Danish Krone", - "AFA" : "Afganistan Afghani", - "CYP" : "Cypriot Pound", - "SCR" : "Seychelles Rupee", - "FJD" : "Fiji Dollar", - "SRG" : "Surinam Guilder", - "SHP" : "St. Helena Pound", - "ALL" : "Albanian Lek", - "TOP" : "Tonga Isl Pa'anga", - "UGX" : "Ugandan Shilling", - "OMR" : "Oman Rial", - "DJF" : "Djibouti Franc", - "BND" : "Brunei Dollar", - "TND" : "Tunisian Dinar", - "PTE" : "Portuguese Escudo", - "IEP" : "Irish Punt", - "SBD" : "Salomon Islands Dollar", - "GNF" : "Guinea Franc", - "BOB" : "Bolivian Boliviano", - "CVE" : "Cape Verde Escudo", - "ARS" : "Argentinian Peso", - "GMD" : "Gambia Dalasi", - "ZWD" : "Zimbabwean Dollar", - "MWK" : "Malawi Kwacha", - "BDT" : "Bangladesh Taka", - "GRD" : "Greek Drachma", - "KWD" : "Kuwaiti Dinar", - "EUR" : "Euro", - "TRL" : "Turkish Lira", - "CHF" : "Swiss Franc", - "DOP" : "Dominican Peso", - "PEN" : "Peruvian Sol", - "SVC" : "El Salvador Colon", - "SGD" : "Singapore Dollar", - "TWD" : "Taiwan New Dollar", - "USD" : "US Dollar", - "BGN" : "Bulgarian Lev", - "MAD" : "Moroccan Dirham", - "SAR" : "Saudi Arabian Riyal", - "AUD" : "Australian Dollar", - "KYD" : "Cayman Islands Dollar", - "GHC" : "Ghanaian Cedi", - "KRW" : "South Korean Won", - "GIP" : "Gibraltar Pound", - "NAD" : "Namibian Dollar", - "CZK" : "Czech Koruna", - "JMD" : "Jamaican Dollar", - "MXN" : "Mexican Peso", - "BWP" : "Botswana Pula", - "GYD" : "Guyana Dollar", - "EGP" : "Egyptian Pound", - "THB" : "Thai Baht", - "AED" : "United Arab Emirates Dirham", - "JPY" : "Japanese Yen", - "JOD" : "Jordanian Dinar", - "HRK" : "Croatian Kuna", - "ZAR" : "South African Rand", - "CUP" : "Cuban Peso", - "BBD" : "Barbados Dollar", - "PGK" : "Papua New Guinea Kina", - "LKR" : "Sri Lanka Rupee", - "BEF" : "Belgian Franc", - "PLN" : "Polish Zloty", - "MYR" : "Malaysian Ringgit", - "FIM" : "Finnish Markka", - "CNY" : "Renmimbi Yuan", - "SDD" : "Sudanese Dinar", - "LVL" : "Latvian Lats", - "ITL" : "Italian Lira", - "INR" : "Indian Rupee", - "NIO" : "Nicaraguan Cordoba", - "PHP" : "Philippines Peso", - "HNL" : "Honduras Lempira", - "HKD" : "Hong Kong Dollar", - "NZD" : "New Zealand Dollar", - "BRL" : "Brazilian Real", - "MTL" : "Maltese Pound", - "ATS" : "Austrian Schilling", - "EEK" : "Estonian Kroon", - "NOK" : "Norwegian Krone", - "ISK" : "Iceland Krona", - "ILS" : "Israeli Shekel", - "LSL" : "Lesotho Loti", - "HUF" : "Hungarian Forint", - "ESP" : "Spanish Peseta", - "UAH" : "Ukraine Hryvnia", - "RUB" : "Russian Ruble", - "BMD" : "Bermuda Dollar", - "MVR" : "Maldives Rufiyan", - "QAR" : "Qatari Rial", - "VND" : "Vietnam Dong", - "MRO" : "Mauritania Ouguiya", - "MZM" : "Mozambique Metical", - "NPR" : "Nepal Rupee", - "COP" : "Colombian Peso", - "TZS" : "Tanzanian Shilling", - "MGF" : "Malagasy Franc", - "KHR" : "Cambodian Riel", - "SYP" : "Syria Pound", - "HTG" : "Haitian Gourde", - "DEM" : "German Mark", - "BHD" : "Bahraini Dinar", - "XAF" : "CFA Franc(BEAC)", - "STD" : "Sao Tome & Principe Dobra", - "LTL" : "Lithuanian Litas", - "ETB" : "Ethiopian Birr", - "XPF" : "CFP Franc", -} diff --git a/invest-applet/invest/defs.py.in b/invest-applet/invest/defs.py.in deleted file mode 100644 index 9a39484f..00000000 --- a/invest-applet/invest/defs.py.in +++ /dev/null @@ -1,9 +0,0 @@ -DATA_DIR = "@DATADIR@" -LIB_DIR = "@LIBDIR@" -VERSION = "@VERSION@" -PACKAGE = "@PACKAGE@" -PYTHONDIR = "@PYTHONDIR@" -GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@" -MATELOCALEDIR = "@MATELOCALEDIR@" -BUILDERDIR = "@BUILDERDIR@" -PKGDATADIR = "@PKGDATADIR@" diff --git a/invest-applet/invest/help.py b/invest-applet/invest/help.py deleted file mode 100644 index ec0a6dbe..00000000 --- a/invest-applet/invest/help.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- - -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk -from gi.repository import Gdk - -def show_help(): - Gtk.show_uri(None, "help:mate-invest-applet", Gdk.CURRENT_TIME) - -def show_help_section(id): - Gtk.show_uri(None, "help:mate-invest-applet/%s" % id, Gdk.CURRENT_TIME) diff --git a/invest-applet/invest/invest-applet.py b/invest-applet/invest/invest-applet.py deleted file mode 100755 index b1e10578..00000000 --- a/invest-applet/invest/invest-applet.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python -import mate_invest.defs - -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk -from gi.repository import GObject -from gi.repository import MatePanelApplet - -import getopt, sys -from os.path import * - -# Allow to use uninstalled -def _check(path): - return exists(path) and isdir(path) and isfile(path+"/Makefile.am") - -name = join(dirname(__file__), '..') -if _check(name): - print 'Running uninstalled invest, modifying PYTHONPATH' - sys.path.insert(0, abspath(name)) -else: - sys.path.insert(0, abspath("@PYTHONDIR@")) - -# Now the path is set, import our applet -import mate_invest, mate_invest.applet, mate_invest.help - -# Prepare i18n -import gettext, locale -gettext.bindtextdomain(mate_invest.defs.GETTEXT_PACKAGE, mate_invest.defs.MATELOCALEDIR) -gettext.textdomain(mate_invest.defs.GETTEXT_PACKAGE) -locale.bindtextdomain(mate_invest.defs.GETTEXT_PACKAGE, mate_invest.defs.MATELOCALEDIR) -locale.textdomain(mate_invest.defs.GETTEXT_PACKAGE) - -from gettext import gettext as _ - -def applet_factory(applet, iid, data): - mate_invest.debug('Starting invest instance: %s %s'% ( applet, iid )) - mate_invest.applet.InvestApplet(applet) - return True - -# Return a standalone window that holds the applet -def build_window(): - app = Gtk.Window(Gtk.WindowType.TOPLEVEL) - app.set_title(_("Invest Applet")) - app.connect("destroy", Gtk.main_quit) - app.set_property('resizable', False) - - applet = MatePanelApplet.Applet() - applet_factory(applet, None, None) - applet.reparent(app) - - app.show_all() - - return app - - -def usage(): - print """=== Invest applet: Usage -$ invest-applet [OPTIONS] - -OPTIONS: - -h, --help Print this help notice. - -d, --debug Enable debug output (default=off). - -w, --window Launch the applet in a standalone window for test purposes (default=no). - """ - sys.exit() - -if __name__ == "__main__": - standalone = False - - try: - opts, args = getopt.getopt(sys.argv[1:], "hdw", ["help", "debug", "window"]) - except getopt.GetoptError: - # Unknown args were passed, we fallback to behave as if - # no options were passed - opts = [] - args = sys.argv[1:] - - for o, a in opts: - if o in ("-h", "--help"): - usage() - elif o in ("-d", "--debug"): - mate_invest.DEBUGGING = True - mate_invest.debug("Debugging enabled") - # these messages cannot be turned by mate_invest.DEBUGGING at their originating location, - # because that variable was set here to be True - mate_invest.debug("Data Dir: %s" % mate_invest.SHARED_DATA_DIR) - mate_invest.debug("Detected PROXY: %s" % mate_invest.PROXY) - elif o in ("-w", "--window"): - standalone = True - - if standalone: - build_window() - Gtk.main() - else: - MatePanelApplet.Applet.factory_main( - "InvestAppletFactory", - True, - MatePanelApplet.Applet.__gtype__, - applet_factory, - None) diff --git a/invest-applet/invest/mate-invest-chart b/invest-applet/invest/mate-invest-chart deleted file mode 100755 index 6c3ed184..00000000 --- a/invest-applet/invest/mate-invest-chart +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python - -import sys, mate_invest.chart - -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk - -# Prepare i18n -import gettext, locale -gettext.bindtextdomain(mate_invest.defs.GETTEXT_PACKAGE, mate_invest.defs.MATELOCALEDIR) -gettext.textdomain(mate_invest.defs.GETTEXT_PACKAGE) -locale.bindtextdomain(mate_invest.defs.GETTEXT_PACKAGE, mate_invest.defs.MATELOCALEDIR) -locale.textdomain(mate_invest.defs.GETTEXT_PACKAGE) - -if __name__ == "__main__": - win = mate_invest.chart.show_chart(sys.argv[1:]) - win.connect("destroy", lambda x: Gtk.main_quit()) - Gtk.main() diff --git a/invest-applet/invest/networkmanager.py b/invest-applet/invest/networkmanager.py deleted file mode 100644 index 446e0429..00000000 --- a/invest-applet/invest/networkmanager.py +++ /dev/null @@ -1,26 +0,0 @@ -import mate_invest -from gi.repository import Gio - -class NetworkManager: - def __init__(self): - self.network_available = True - self.statechange_callback = None - - self.monitor = Gio.NetworkMonitor.get_default() - self.monitor.connect('network-changed', self.on_network_changed) - - def online(self): - return self.network_available - - def offline(self): - return not self.online() - - # the signal handler for signals from the network manager - def on_network_changed(self, monitor, available): - self.network_available = available - # notify about state change - if self.statechange_callback != None: - self.statechange_callback() - - def set_statechange_callback(self,handler): - self.statechange_callback = handler diff --git a/invest-applet/invest/preferences.py b/invest-applet/invest/preferences.py deleted file mode 100644 index 40cd72f3..00000000 --- a/invest-applet/invest/preferences.py +++ /dev/null @@ -1,290 +0,0 @@ -from gettext import gettext as _ -import locale -from os.path import join - -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk -from gi.repository import GObject -import mate_invest -import currencies -import cPickle - -class PrefsDialog: - def __init__(self, applet): - self.ui = Gtk.Builder() - self.ui.add_from_file(join(mate_invest.BUILDER_DATA_DIR, "prefs-dialog.ui")) - - self.dialog = self.ui.get_object("preferences") - self.treeview = self.ui.get_object("stocks") - self.currency = self.ui.get_object("currency") - self.currency_code = None - self.currencies = currencies.Currencies.currencies - - self.ui.get_object("add").connect('clicked', self.on_add_stock) - self.ui.get_object("add").connect('activate', self.on_add_stock) - self.ui.get_object("remove").connect('clicked', self.on_remove_stock) - self.ui.get_object("remove").connect('activate', self.on_remove_stock) - self.ui.get_object("help").connect('clicked', self.on_help) - self.treeview.connect('key-press-event', self.on_tree_keypress) - self.currency.connect('key-press-event', self.on_entry_keypress) - self.currency.connect('activate', self.on_activate_entry) - self.currency.connect('focus-out-event', self.on_focus_out_entry) - - self.typs = (str, str, float, float, float, float) - self.names = (_("Symbol"), _("Label"), _("Amount"), _("Price"), _("Commission"), _("Currency Rate")) - store = Gtk.ListStore(*self.typs) - store.set_sort_column_id(0, Gtk.SortType.ASCENDING) - self.treeview.set_model(store) - self.model = store - - completion = Gtk.EntryCompletion() - self.currency.set_completion(completion) - liststore = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) - completion.set_model(liststore) - completion.set_text_column(0) - for code, label in self.currencies.items(): - liststore.append([self.format_currency(label, code), code]) - completion.set_match_func(self.match_func, 0) - completion.connect("match-selected", self.on_completion_selection, 1) - - if mate_invest.CONFIG.has_key("currency"): - code = mate_invest.CONFIG["currency"]; - if self.currencies.has_key(code): - self.currency_code = code; - currency = self.format_currency(self.currencies[self.currency_code], self.currency_code) - self.currency.set_text(currency) - - for n in xrange (0, 5): - self.create_cell (self.treeview, n, self.names[n], self.typs[n]) - if self.currency_code != None: - self.add_exchange_column() - - stock_items = mate_invest.STOCKS.items () - stock_items.sort () - for key, data in stock_items: - label = data["label"] - purchases = data["purchases"] - for purchase in purchases: - if purchase.has_key("exchange"): - exchange = purchase["exchange"] - else: - exchange = 0.0 - store.append([key, label, float(purchase["amount"]), float(purchase["bought"]), float(purchase["comission"]), float(exchange)]) - - self.sync_ui() - - def on_cell_edited(self, cell, path, new_text, col, typ): - try: - if col == 0: # stock symbols must be uppercase - new_text = str.upper(new_text) - if col < 2: - self.model[path][col] = new_text - else: - value = locale.atof(new_text) - self.model[path][col] = value - except Exception, msg: - mate_invest.error('Exception while processing cell change: %s' % msg) - pass - - def format(self, fmt, value): - return locale.format(fmt, value, True) - - def get_cell_data(self, column, cell, model, iter, data): - typ, col = data - val = model[iter][col] - if typ == int: - cell.set_property('text', "%d" % typ(val)) - elif typ == float: - # provide float numbers with at least 2 fractional digits - digits = self.fraction_digits(val) - fmt = "%%.%df" % max(digits, 2) - cell.set_property('text', self.format(fmt, val)) - else: - cell.set_property('text', typ(val)) - - # determine the number of non zero digits in the fraction of the value - def fraction_digits(self, value): - text = "%g" % value # do not use locale here, so that %g always is rendered to a number with . as decimal separator - if text.find(".") < 0: - return 0 - return len(text) - text.find(".") - 1 - - def create_cell (self, view, column, name, typ): - cell_description = Gtk.CellRendererText () - if typ == float: - cell_description.set_property("xalign", 1.0) - cell_description.set_property("editable", True) - cell_description.connect("edited", self.on_cell_edited, column, typ) - column_description = Gtk.TreeViewColumn (name, cell_description) - if typ == str: - #column_description.add_attribute (cell_description, column, 0) - column_description.set_sort_column_id(column) - column_description.set_cell_data_func(cell_description, self.get_cell_data, (typ, column)) - view.append_column(column_description) - - def add_exchange_column(self): - self.create_cell (self.treeview, 5, self.names[5], self.typs[5]) - - def remove_exchange_column(self): - column = self.treeview.get_column(5) - self.treeview.remove_column(column) - - def show_run_hide(self, explanation = ""): - expl = self.ui.get_object("explanation") - expl.set_markup(explanation) - self.dialog.show_all() - if explanation == "": - expl.hide() - # returns 1 if help is clicked - while self.dialog.run() == 1: - pass - self.dialog.destroy() - - mate_invest.STOCKS = {} - - def save_symbol(model, path, iter, data): - #if int(model[iter][1]) == 0 or float(model[iter][2]) < 0.0001: - # return - - if not model[iter][0] in mate_invest.STOCKS: - mate_invest.STOCKS[model[iter][0]] = { 'label': model[iter][1], 'purchases': [] } - - mate_invest.STOCKS[model[iter][0]]["purchases"].append({ - "amount": float(model[iter][2]), - "bought": float(model[iter][3]), - "comission": float(model[iter][4]), - "exchange": float(model[iter][5]) - }) - self.model.foreach(save_symbol, None) - try: - cPickle.dump(mate_invest.STOCKS, file(mate_invest.STOCKS_FILE, 'w')) - mate_invest.debug('Stocks written to file') - except Exception, msg: - mate_invest.error('Could not save stocks file: %s' % msg) - - mate_invest.CONFIG = {} - if self.currency_code != None and len(self.currency_code) == 3: - mate_invest.CONFIG['currency'] = self.currency_code - try: - cPickle.dump(mate_invest.CONFIG, file(mate_invest.CONFIG_FILE, 'w')) - mate_invest.debug('Configuration written to file') - except Exception, msg: - mate_invest.debug('Could not save configuration file: %s' % msg) - - def sync_ui(self): - pass - - def on_add_stock(self, w): - iter = self.model.append(["GOOG", "Google Inc.", 0.0, 0.0, 0.0, 0.0]) - path = self.model.get_path(iter) - self.treeview.set_cursor(path, self.treeview.get_column(0), True) - - def on_remove_stock(self, w): - model, paths = self.treeview.get_selection().get_selected_rows() - for path in paths: - model.remove(model.get_iter(path)) - - def on_help(self, w): - mate_invest.help.show_help_section("invest-applet-usage") - - def on_tree_keypress(self, w, event): - if event.keyval == 65535: - self.on_remove_stock(w) - - return False - - def format_currency(self, label, code): - if code == None: - return label - return label + " (" + code + ")" - - def on_entry_keypress(self, w, event): - # enter key was pressed - if event.keyval == 65293: - self.match_currency() - return False - - # entry was activated (Enter) - def on_activate_entry(self, entry): - self.match_currency() - - # entry left focus - def on_focus_out_entry(self, w, event): - self.match_currency() - return False - - # tries to find a currency for the text in the currency entry - def match_currency(self): - # get the text - text = self.currency.get_text().upper() - - # if there is none, finish - if len(text) == 0: - self.currency_code = None - self.pick_currency(None) - return - - # if it is a currency code, take that one - if len(text) == 3: - # try to find the string as code - if self.currencies.has_key(text): - self.pick_currency(text) - return - else: - # try to find the code for the string - for code, label in self.currencies.items(): - # if the entry equals to the full label, - # or the entry equals to the label+code concat - if label.upper() == text or self.format_currency(label.upper(), code) == text: - # then we take that code - self.pick_currency(code) - return - - # the entry is not valid, reuse the old one - self.pick_currency(self.currency_code) - - # pick this currency, stores it and sets the entry text - def pick_currency(self, code): - if code == None: - label = "" - if len(self.treeview.get_columns()) == 6: - self.remove_exchange_column() - else: - label = self.currencies[code] - if len(self.treeview.get_columns()) == 5: - self.add_exchange_column() - self.currency.set_text(self.format_currency(label, code)) - self.currency_code = code - - # finds matches by testing candidate strings to have tokens starting with the entered text's tokens - def match_func(self, completion, key, iter, column): - keys = key.split() - model = completion.get_model() - text = model.get_value(iter, column).lower() - tokens = text.split() - - # each key must have a match - for key in keys: - found_key = False - # check any token of the completions start with the key - for token in tokens: - # remove the ( from the currency code - if token.startswith("("): - token = token[1:] - if token.startswith(key): - found_key = True - break - # this key does not have a match, this is not a completion - if not found_key: - return False - # all keys matched, this is a completion - return True - - # stores the selected currency code - def on_completion_selection(self, completion, model, iter, column): - self.pick_currency(model.get_value(iter, column)) - - -def show_preferences(applet, explanation = ""): - PrefsDialog(applet).show_run_hide(explanation) diff --git a/invest-applet/invest/quotes.py b/invest-applet/invest/quotes.py deleted file mode 100644 index 5331e007..00000000 --- a/invest-applet/invest/quotes.py +++ /dev/null @@ -1,475 +0,0 @@ -from os.path import join, getmtime - -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GdkPixbuf -from gi.repository import GObject -from gettext import gettext as _ -import csv -import locale -from urllib import urlopen -import datetime -from threading import Thread - -import mate_invest, mate_invest.about, mate_invest.chart -import currencies - -CHUNK_SIZE = 512*1024 # 512 kB -AUTOREFRESH_TIMEOUT = 15*60*1000 # 15 minutes - -QUOTES_URL="http://finance.yahoo.com/d/quotes.csv?s=%(s)s&f=snc4l1d1t1c1ohgv&e=.csv" - -# Sample (09/2/2010): "UCG.MI","UNICREDIT","EUR","UCG.MI",1.9410,"2/9/2010","6:10am",+0.0210,1.9080,1.9810,1.8920,166691232 -QUOTES_CSV_FIELDS=["ticker", "label", "currency", ("trade", float), "date", "time", ("variation", float), ("open", float), ("high", float), ("low", float), ("volume", int)] - -# based on http://www.johnstowers.co.nz/blog/index.php/2007/03/12/threading-and-pygtk/ -class _IdleObject(GObject.GObject): - """ - Override GObject.GObject to always emit signals in the main thread - by emmitting on an idle handler - """ - def __init__(self): - GObject.GObject.__init__(self) - - def emit(self, *args): - GObject.idle_add(GObject.GObject.emit,self,*args) - -class QuotesRetriever(Thread, _IdleObject): - """ - Thread which uses gobject signals to return information - to the GUI. - """ - __gsignals__ = { - "completed": ( - GObject.SignalFlags.RUN_LAST, None, []), - # FIXME: We don't monitor progress, yet ... - #"progress": ( - # GObject.SignalFlags.RUN_LAST, None, [ - # GObject.TYPE_FLOAT]) #percent complete - } - - def __init__(self, tickers): - Thread.__init__(self) - _IdleObject.__init__(self) - self.tickers = tickers - self.retrieved = False - self.data = [] - self.currencies = [] - mate_invest.debug("QuotesRetriever created"); - - def run(self): - mate_invest.debug("QuotesRetriever started"); - quotes_url = QUOTES_URL % {"s": self.tickers} - try: - quotes_file = urlopen(quotes_url, proxies = mate_invest.PROXY) - self.data = quotes_file.read () - quotes_file.close () - except Exception, msg: - mate_invest.debug("Error while retrieving quotes data (url = %s): %s" % (quotes_url, msg)) - else: - self.retrieved = True - self.emit("completed") - - -class QuoteUpdater(Gtk.ListStore): - updated = False - last_updated = None - quotes_valid = False - timeout_id = None - SYMBOL, LABEL, CURRENCY, TICKER_ONLY, BALANCE, BALANCE_PCT, VALUE, VARIATION_PCT, PB = range(9) - def __init__ (self, change_icon_callback, set_tooltip_callback): - Gtk.ListStore.__init__ (self, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, bool, float, float, float, float, GdkPixbuf.Pixbuf) - self.set_update_interval(AUTOREFRESH_TIMEOUT) - self.change_icon_callback = change_icon_callback - self.set_tooltip_callback = set_tooltip_callback - self.set_sort_column_id(1, Gtk.SortType.ASCENDING) - self.load_quotes() # read the last cached quotes file - self.refresh() # download a new quotes file, this may fail if disconnected - - # tell the network manager to notify me when network status changes - mate_invest.nm.set_statechange_callback(self.nm_state_changed) - - # loads the cached csv file and its last-modification-time as self.last_updated - def load_quotes(self): - mate_invest.debug("Loading quotes"); - try: - f = open(mate_invest.QUOTES_FILE, 'r') - data = f.readlines() - f.close() - - self.populate(self.parse_yahoo_csv(csv.reader(data))) - self.updated = True - self.last_updated = datetime.datetime.fromtimestamp(getmtime(mate_invest.QUOTES_FILE)) - self.update_tooltip() - except Exception, msg: - mate_invest.error("Could not load the cached quotes file %s: %s" % (mate_invest.QUOTES_FILE, msg) ) - - # stores the csv content on disk so it can be used on next start up - def save_quotes(self, data): - mate_invest.debug("Storing quotes") - try: - f = open(mate_invest.QUOTES_FILE, 'w') - f.write(data) - f.close() - except Exception, msg: - mate_invest.error("Could not save the retrieved quotes file to %s: %s" % (mate_invest.QUOTES_FILE, msg) ) - - def set_update_interval(self, interval): - if self.timeout_id != None: - mate_invest.debug("Canceling refresh timer") - GObject.source_remove(self.timeout_id) - self.timeout_id = None - if interval > 0: - mate_invest.debug("Setting refresh timer to %s:%02d.%03d" % ( interval / 60000, interval % 60000 / 1000, interval % 1000) ) - self.timeout_id = GObject.timeout_add(interval, self.refresh) - - def nm_state_changed(self): - # when nm is online but we do not have an update timer, create it and refresh - if mate_invest.nm.online(): - if self.timeout_id == None: - self.set_update_interval(AUTOREFRESH_TIMEOUT) - self.refresh() - - def refresh(self): - mate_invest.debug("Refreshing") - - # when nm tells me I am offline, stop the update interval - if mate_invest.nm.offline(): - mate_invest.debug("We are offline, stopping update timer") - self.set_update_interval(0) - return False - - if len(mate_invest.STOCKS) == 0: - mate_invest.debug("No stocks configured") - return True - - tickers = '+'.join(mate_invest.STOCKS.keys()) - mate_invest.debug("creating QuotesRetriever") - quotes_retriever = QuotesRetriever(tickers) - quotes_retriever.connect("completed", self.on_retriever_completed) - mate_invest.debug("starting QuotesRetriever") - quotes_retriever.start() - mate_invest.debug("started QuotesRetriever") - - return True - - - # locale-aware formatting of the percent float (decimal point, thousand grouping point) with 2 decimal digits - def format_percent(self, value): - return locale.format("%+.2f", value, True) + "%" - - # locale-aware formatting of the float value (decimal point, thousand grouping point) with sign and 2 decimal digits - def format_difference(self, value): - return locale.format("%+.2f", value, True, True) - - def on_retriever_completed(self, retriever): - if retriever.retrieved == False: - mate_invest.debug("QuotesRetriever failed"); - self.update_tooltip(_('Invest could not connect to Yahoo! Finance')) - - else: - mate_invest.debug("QuotesRetriever completed"); - # cache the retrieved csv file - self.save_quotes(retriever.data) - # load the cache and parse it - self.load_quotes() - - def on_currency_retriever_completed(self, retriever): - if retriever.retrieved == False: - mate_invest.error("Failed to retrieve currency rates!") - else: - mate_invest.debug("CurrencyRetriever completed") - self.save_currencies(retriever.data) - self.load_currencies() - self.update_tooltip() - - def save_currencies(self, data): - mate_invest.debug("Storing currencies to %s" % mate_invest.CURRENCIES_FILE) - try: - f = open(mate_invest.CURRENCIES_FILE, 'w') - f.write(data) - f.close() - except Exception as msg: - mate_invest.error("Could not save the retrieved currencies to %s: %s" % (mate_invest.CURRENCIES_FILE, msg) ) - - def load_currencies(self): - mate_invest.debug("Loading currencies from %s" % mate_invest.CURRENCIES_FILE) - try: - f = open(mate_invest.CURRENCIES_FILE, 'r') - data = f.readlines() - f.close() - - self.convert_currencies(self.parse_yahoo_csv(csv.reader(data))) - except Exception as msg: - mate_invest.error("Could not load the currencies from %s: %s" % (mate_invest.CURRENCIES_FILE, msg) ) - - def update_tooltip(self, msg = None): - tooltip = [] - if self.quotes_count > 0: - # Translators: This is share-market jargon. It is the average percentage change of all stock prices. The %s gets replaced with the string value of the change (localized), including the percent sign. - tooltip.append(_('Average change: %s') % self.format_percent(self.avg_quotes_change)) - for currency, stats in self.statistics.items(): - # get the statsitics - balance = stats["balance"] - paid = stats["paid"] - change = self.format_percent(balance / paid * 100) - balance = self.format_difference(balance) - - # Translators: This is share-market jargon. It refers to the total difference between the current price and purchase price for all the shares put together for a particular currency. i.e. How much money would be earned if they were sold right now. The first string is the change value, the second the currency, and the third value is the percentage of the change, formatted using user's locale. - tooltip.append(_('Positions balance: %s %s (%s)') % (balance, currency, change)) - if self.last_updated != None: - tooltip.append(_('Updated at %s') % self.last_updated.strftime("%H:%M")) - if msg != None: - tooltip.append(msg) - self.set_tooltip_callback('\n'.join(tooltip)) - - - def parse_yahoo_csv(self, csvreader): - result = {} - for fields in csvreader: - if len(fields) == 0: - continue - - result[fields[0]] = {} - for i, field in enumerate(QUOTES_CSV_FIELDS): - if type(field) == tuple: - try: - result[fields[0]][field[0]] = field[1](fields[i]) - except: - result[fields[0]][field[0]] = 0 - else: - result[fields[0]][field] = fields[i] - # calculated fields - try: - result[fields[0]]['variation_pct'] = result[fields[0]]['variation'] / float(result[fields[0]]['trade'] - result[fields[0]]['variation']) * 100 - except ZeroDivisionError: - result[fields[0]]['variation_pct'] = 0 - return result - - # Computes the balance of the given purchases using a certain current value - # and optionally a current exchange rate. - def balance(self, purchases, value, currentrate=None): - current = 0 - paid = 0 - - for purchase in purchases: - if purchase["amount"] != 0: - buyrate = purchase["exchange"] - # if the buy rate is invalid, use 1.0 - if buyrate <= 0: - buyrate = 1.0 - - # if no current rate is given, ignore buy rate - if currentrate == None: - buyrate = 1.0 - rate = 1.0 - else: - # otherwise, take use buy rate and current rate to compute the balance - rate = currentrate - - # current value is the current rate * amount * value - current += rate * purchase["amount"] * value - # paid is buy rate * ( amount * price + commission ) - paid += buyrate * (purchase["amount"] * purchase["bought"] + purchase["comission"]) - - balance = current - paid - if paid != 0: - change = 100*balance/paid - else: - change = 100 # Not technically correct, but it will look more intuitive than the real result of infinity. - - return (balance, change) - - def populate(self, quotes): - if (len(quotes) == 0): - return - - self.clear() - self.currencies = [] - - try: - quote_items = quotes.items () - quote_items.sort () - - quotes_change = 0 - self.quotes_count = 0 - self.statistics = {} - - for ticker, val in quote_items: - pb = None - - # ignore unknown stocks - if ticker not in mate_invest.STOCKS.keys(): - mate_invest.debug("Observed unknown stock: %s" % ticker) - continue - - # get the label of this stock for later reuse - label = mate_invest.STOCKS[ticker]["label"] - if len(label) == 0: - if len(val["label"]) != 0: - label = val["label"] - else: - label = ticker - - # make sure the currency field is upper case - val["currency"] = val["currency"].upper(); - - # the currency of currency conversion rates like EURUSD=X is wrong in csv - # this can be fixed easily by reusing the latter currency in the symbol - if len(ticker) == 8 and ticker.endswith("=X"): - val["currency"] = ticker[3:6] - - # indices should not have a currency, though yahoo says so - if ticker.startswith("^"): - val["currency"] = "" - - # sometimes, funny currencies are returned (special characters), only consider known currencies - if len(val["currency"]) > 0 and val["currency"] not in currencies.Currencies.currencies: - mate_invest.debug("Currency '%s' is not known, dropping" % val["currency"]) - val["currency"] = "" - - # if this is a currency not yet seen and different from the target currency, memorize it - if val["currency"] not in self.currencies and len(val["currency"]) > 0: - self.currencies.append(val["currency"]) - - # Check whether the symbol is a simple quote, or a portfolio value - is_simple_quote = True - for purchase in mate_invest.STOCKS[ticker]["purchases"]: - if purchase["amount"] != 0: - is_simple_quote = False - break - - if is_simple_quote: - row = self.insert(0, [ticker, label, val["currency"], True, 0.0, 0.0, val["trade"], val["variation_pct"], pb]) - else: - (balance, change) = self.balance(mate_invest.STOCKS[ticker]["purchases"], val["trade"]) - row = self.insert(0, [ticker, label, val["currency"], False, float(balance), float(change), val["trade"], val["variation_pct"], pb]) - self.add_balance_change(balance, change, val["currency"]) - - if len(ticker.split('.')) == 2: - url = 'http://chart.finance.yahoo.com/h?s=%s' % ticker - else: - url = 'http://ichart.yahoo.com/h?s=%s' % ticker - - image_retriever = mate_invest.chart.ImageRetriever(url) - image_retriever.connect("completed", self.set_pb_callback, row) - image_retriever.start() - - quotes_change += val['variation_pct'] - self.quotes_count += 1 - - # we can only compute an avg quote if there are quotes - if self.quotes_count > 0: - self.avg_quotes_change = quotes_change / float(self.quotes_count) - - # change icon - quotes_change_sign = 0 - if self.avg_quotes_change != 0: - quotes_change_sign = self.avg_quotes_change / abs(self.avg_quotes_change) - self.change_icon_callback(quotes_change_sign) - else: - self.avg_quotes_change = 0 - - # mark quotes to finally be valid - self.quotes_valid = True - - except Exception, msg: - mate_invest.debug("Failed to populate quotes: %s" % msg) - mate_invest.debug(quotes) - self.quotes_valid = False - - # start retrieving currency conversion rates - if mate_invest.CONFIG.has_key("currency"): - target_currency = mate_invest.CONFIG["currency"] - symbols = [] - - mate_invest.debug("These currencies occur: %s" % self.currencies) - for currency in self.currencies: - if currency == target_currency: - continue - - mate_invest.debug("%s will be converted to %s" % ( currency, target_currency )) - symbol = currency + target_currency + "=X" - symbols.append(symbol) - - if len(symbols) > 0: - tickers = '+'.join(symbols) - quotes_retriever = QuotesRetriever(tickers) - quotes_retriever.connect("completed", self.on_currency_retriever_completed) - quotes_retriever.start() - - def convert_currencies(self, quotes): - # if there is no target currency, this method should never have been called - if not mate_invest.CONFIG.has_key("currency"): - return - - # reset the overall balance - self.statistics = {} - - # collect the rates for the currencies - rates = {} - for symbol, data in quotes.items(): - currency = symbol[0:3] - rate = data["trade"] - rates[currency] = rate - - # convert all non target currencies - target_currency = mate_invest.CONFIG["currency"] - iter = self.get_iter_first() - while iter != None: - currency = self.get_value(iter, self.CURRENCY) - symbol = self.get_value(iter, self.SYMBOL) - # ignore stocks that are currency conversions - # and only convert stocks that are not in the target currency - # and if we have a conversion rate - if not ( len(symbol) == 8 and symbol[6:8] == "=X" ) and \ - currency != target_currency and rates.has_key(currency): - # first convert the balance, it needs the original value - if not self.get_value(iter, self.TICKER_ONLY): - ticker = self.get_value(iter, self.SYMBOL) - value = self.get_value(iter, self.VALUE) - (balance, change) = self.balance(mate_invest.STOCKS[ticker]["purchases"], value, rates[currency]) - self.set_value(iter, self.BALANCE, balance) - self.set_value(iter, self.BALANCE_PCT, change) - self.add_balance_change(balance, change, target_currency) - - # now, convert the value - value = self.get_value(iter, self.VALUE) - value *= rates[currency] - self.set_value(iter, self.VALUE, value) - self.set_value(iter, self.CURRENCY, target_currency) - - else: - # consider non-converted stocks here - balance = self.get_value(iter, self.BALANCE) - change = self.get_value(iter, self.BALANCE_PCT) - self.add_balance_change(balance, change, currency) - - iter = self.iter_next(iter) - - def add_balance_change(self, balance, change, currency): - if balance == 0 and change == 0: - return - - if self.statistics.has_key(currency): - self.statistics[currency]["balance"] += balance - self.statistics[currency]["paid"] += balance/change*100 - else: - self.statistics[currency] = { "balance" : balance, "paid" : balance/change*100 } - - def set_pb_callback(self, retriever, row): - self.set_value(row, self.PB, retriever.image.get_pixbuf()) - - # check if we have only simple quotes - def simple_quotes_only(self): - res = True - for entry, data in mate_invest.STOCKS.iteritems(): - purchases = data["purchases"] - for purchase in purchases: - if purchase["amount"] != 0: - res = False - break - return res - diff --git a/invest-applet/invest/test.py b/invest-applet/invest/test.py deleted file mode 100755 index 046881bb..00000000 --- a/invest-applet/invest/test.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python - -import unittest -from os.path import * -import sys - -# Make sure we run the local version -sys.path.insert(0, abspath(dirname(__file__) + "/..")) -print sys.path - -import quotes -import mate_invest - -def null_function (*args): - pass - -class TestQuotes (unittest.TestCase): - def testQuoteUpdater_populate (self): - qu = quotes.QuoteUpdater (null_function, null_function) - mate_invest.STOCKS = {'GOGO': {'label': "Google Inc.", 'purchases': [{'amount' : 1, 'comission' : 0.0, 'bought': 0.0}]}, 'JAVA': {'label':"Sun Microsystems Inc.", 'purchases': [{'amount' : 1, 'comission' : 0.0, 'bought': 0.0}]}} - quote = { 'GOGO': { "ticker": 'GOGO', "trade": 386.91, "time": "10/3/2008", "date": "4.00pm", "variation": -3.58, "open": 397.14, "variation_pct": 10 }} - qu.populate (quote) - self.assertEqual (qu.quotes_valid, True) - # In response to bug 554425, try a stock that isn't in our database - quote = { "clearlyFake": { "ticker": "clearlyFake", "trade": 386.91, "time": "10/3/2008", "date": "4.00pm", "variation": -3.58, "open": 397.14, "variation_pct": 10 }} - qu.populate (quote) - self.assertEqual (qu.quotes_valid, False) - -if __name__ == '__main__': - unittest.main () diff --git a/invest-applet/invest/widgets.py b/invest-applet/invest/widgets.py deleted file mode 100644 index 8d15a5ed..00000000 --- a/invest-applet/invest/widgets.py +++ /dev/null @@ -1,263 +0,0 @@ -import os, time -from os.path import * - -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GObject -from gi.repository import Pango - -from gettext import gettext as _ -import locale -import csv -import mate_invest, mate_invest.about, mate_invest.chart - -COLORSCALE_POSITIVE = [ - "white", - "#ad7fa8", - "#75507b", - "#5c3566", - "#729fcf", - "#3465a4", - "#204a87", - "#8ae234", - "#73d216", - "#4e9a06", -] -COLORSCALE_NEGATIVE = [ - "white", - "#fce94f", - "#e9b96e", - "#fcaf3e", - "#c17d11", - "#f57900", - "#ce5c00", - "#ef2929", - "#cc0000", - "#a40000", -] -LIGHT = -3 -MEDIUM = -1 - -TICKER_TIMEOUT = 10000#3*60*1000# - -class InvestWidget(Gtk.TreeView): - def __init__(self, quotes_updater): - Gtk.TreeView.__init__(self) - self.set_property("rules-hint", True) -# self.set_property("reorderable", True) - self.set_property("hover-selection", True) - - simple_quotes_only = quotes_updater.simple_quotes_only() - - # model: SYMBOL, LABEL, TICKER_ONLY, BALANCE, BALANCE_PCT, VALUE, VARIATION_PCT, PB - # Translators: these words all refer to a stock. Last is short - # for "last price". Gain is referring to the gain since the - # stock was purchased. - col_names = [_('Ticker'), _('Last'), _('Change %'), _('Chart'), _('Gain'), _('Gain %')] - col_cellgetdata_functions = [self._getcelldata_label, self._getcelldata_value, - self._getcelldata_variation, None, self._getcelldata_balance, - self._getcelldata_balancepct] - for i, col_name in enumerate(col_names): - if i < 3: - cell = Gtk.CellRendererText() - if i > 0: - cell.set_property("xalign", 1.0) - column = Gtk.TreeViewColumn (col_name, cell) - if i == 0: - column.set_sort_column_id(quotes_updater.LABEL) - elif i == 2: - column.set_sort_column_id(quotes_updater.VARIATION_PCT) - column.set_cell_data_func(cell, col_cellgetdata_functions[i]) - self.append_column(column) - elif i == 3: - cell_pb = Gtk.CellRendererPixbuf() - column = Gtk.TreeViewColumn (col_name, cell_pb, pixbuf=quotes_updater.PB) - self.append_column(column) - else: - # add the last two column only if we have any positions - if simple_quotes_only == False: - cell = Gtk.CellRendererText() - cell.set_property("xalign", 1.0) - column = Gtk.TreeViewColumn (col_name, cell) - if i == 4: - column.set_sort_column_id(quotes_updater.BALANCE) - elif i == 5: - column.set_sort_column_id(quotes_updater.BALANCE_PCT) - column.set_cell_data_func(cell, col_cellgetdata_functions[i]) - self.append_column(column) - - if simple_quotes_only == True: - self.set_property('headers-visible', False) - - self.connect('row-activated', self.on_row_activated) - self.set_model(quotes_updater) - - - # locale-aware formatting of the value as monetary, without currency symbol, using 2 decimal digits - def format_currency(self, value, currency): - return locale.format("%.2f", value, True, True) + " " + currency - - # locale-aware formatting of the percent float (decimal point, thousand grouping point) with 2 decimal digits - def format_percent(self, value): - return locale.format("%+.2f", value, True) + "%" - - # locale-aware formatting of the float value (decimal point, thousand grouping point) with sign and 2 decimal digits - def format_difference(self, value, currency): - return locale.format("%+.2f", value, True, True) + " " + currency - - - def _getcelldata_label(self, column, cell, model, iter, userdata): - label = model[iter][model.LABEL] - cell.set_property('text', label) - - def _getcelldata_value(self, column, cell, model, iter, userdata): - value = model[iter][model.VALUE]; - currency = model[iter][model.CURRENCY]; - if value == None or currency == None: - cell.set_property('text', "") - else: - cell.set_property('text', self.format_currency(value, currency)) - - def is_selected(self, model, iter): - m, it = self.get_selection().get_selected() - return it != None and model.get_path(iter) == m.get_path(it) - - def get_color(self, model, iter, field): - palette = COLORSCALE_POSITIVE - intensity = MEDIUM - if model[iter][field] < 0: - palette = COLORSCALE_NEGATIVE - if self.is_selected(model, iter): - intensity = LIGHT - return palette[intensity] - - def _getcelldata_variation(self, column, cell, model, iter, userdata): - color = self.get_color(model, iter, model.VARIATION_PCT) - change_pct = self.format_percent(model[iter][model.VARIATION_PCT]) - cell.set_property('markup', - "<span foreground='%s'>%s</span>" % - (color, change_pct)) - - def _getcelldata_balance(self, column, cell, model, iter, userdata): - is_ticker_only = model[iter][model.TICKER_ONLY] - color = self.get_color(model, iter, model.BALANCE) - if is_ticker_only: - cell.set_property('text', '') - else: - balance = self.format_difference(model[iter][model.BALANCE], model[iter][model.CURRENCY]) - cell.set_property('markup', - "<span foreground='%s'>%s</span>" % - (color, balance)) - - def _getcelldata_balancepct(self, column, cell, model, iter, userdata): - is_ticker_only = model[iter][model.TICKER_ONLY] - color = self.get_color(model, iter, model.BALANCE_PCT) - if is_ticker_only: - cell.set_property('text', '') - else: - balance_pct = self.format_percent(model[iter][model.BALANCE_PCT]) - cell.set_property('markup', - "<span foreground='%s'>%s</span>" % - (color, balance_pct)) - - def on_row_activated(self, treeview, path, view_column): - ticker = self.get_model()[self.get_model().get_iter(path)][0] - if ticker == None: - return - - mate_invest.chart.show_chart([ticker]) - -#class InvestTicker(Gtk.Label): -# def __init__(self): -# Gtk.Label.__init__(self, _("Waiting...")) -# -# self.quotes = [] -# GObject.timeout_add(TICKER_TIMEOUT, self.scroll_quotes) -# -# get_quotes_updater().connect('quotes-updated', self.on_quotes_update) -# -# def on_quotes_update(self, updater): -# self.quotes = [] -# updater.foreach(self.update_quote, None) -# -# def update_quote(self, model, path, iter, user_data): -# color = GREEN -# if model[iter][model.BALANCE] < 0: -# color = RED -# -# self.quotes.append( -# "%s: <span foreground='%s'>%+.2f (%+.2f%%)</span> %.2f" % -# (model[iter][model.SYMBOL], color, model[iter][model.BALANCE], model[iter][model.BALANCE_PCT], model[iter][model.VALUE])) -# -# def scroll_quotes(self): -# if len(self.quotes) == 0: -# return True -# -# q = self.quotes.pop() -# self.set_markup("<span face='Monospace'>%s</span>" % q) -# self.quotes.insert(0, q) -# -# return True -# -#GObject.type_register(InvestTicker) - -class InvestTrend(Gtk.Image): - def __init__(self): - Gtk.Image.__init__(self) - self.pixbuf = None - self.previous_allocation = (0,0) - self.connect('size-allocate', self.on_size_allocate) - get_quotes_updater().connect('quotes-updated', self.on_quotes_update) - - def on_size_allocate(self, widget, allocation): - if self.previous_allocation == (allocation.width, allocation.height): - return - - self.pixbuf = GdkPixbuf.Pixbuf(GdkPixbuf.Colorspace.RGB, True, 8, allocation.height, allocation.height) - self.set_color("grey") - self.previous_allocation = (allocation.width, allocation.height) - - def set_color(self, color, opacity=0xFF): - if self.pixbuf != None: - try: - color = Pango.Color(color) - factor = float(0xFF)/0xFFFF - self.pixbuf.fill( - int(color.red*factor)<<24|int(color.green*factor)<<16|int(color.blue*factor)<<8|opacity) - self.set_from_pixbuf(self.pixbuf) - except Exception, msg: - mate_invest.error("Could not set color: %s" % msg) - - def on_quotes_update(self, updater): - start_total = 0 - now_total = 0 - for row in updater: - # Don't count the ticker only symbols in the color-trend - if row[updater.TICKER_ONLY]: - continue - - var = row[updater.VARIATION]/100 - now = row[updater.VALUE] - - start = now / (1 + var) - - portfolio_number = sum([purchase["amount"] for purchase in mate_invest.STOCKS[row[updater.SYMBOL]]["purchases"]]) - start_total += start * portfolio_number - now_total += now * portfolio_number - - day_var = 0 - if start_total != 0: - day_var = (now_total - start_total) / start_total * 100 - - color = int(2*day_var) - opacity = min(0xFF, int(abs(127.5*day_var))) - if day_var < 0: - color = COLORSCALE_NEGATIVE[min(len(COLORSCALE_NEGATIVE)-1, abs(color))] - else: - color = COLORSCALE_POSITIVE[min(len(COLORSCALE_POSITIVE)-1, abs(color))] - - self.set_color(color, opacity) - -GObject.type_register(InvestTrend) |