summaryrefslogtreecommitdiff
path: root/invest-applet/invest/preferences.py
diff options
context:
space:
mode:
Diffstat (limited to 'invest-applet/invest/preferences.py')
-rw-r--r--invest-applet/invest/preferences.py287
1 files changed, 287 insertions, 0 deletions
diff --git a/invest-applet/invest/preferences.py b/invest-applet/invest/preferences.py
new file mode 100644
index 00000000..3c48ee42
--- /dev/null
+++ b/invest-applet/invest/preferences.py
@@ -0,0 +1,287 @@
+from gettext import gettext as _
+import locale
+from os.path import join
+import gtk, gobject, mateconf
+import invest
+import currencies
+import cPickle
+
+class PrefsDialog:
+ def __init__(self, applet):
+ self.ui = gtk.Builder()
+ self.ui.add_from_file(join(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.SORT_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 invest.CONFIG.has_key("currency"):
+ code = 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 = 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, purchase["amount"], purchase["bought"], purchase["comission"], 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:
+ 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
+ if typ == int:
+ cell.set_property('text', "%d" % typ(model[iter][col]))
+ elif typ == float:
+ # provide float numbers with at least 2 fractional digits
+ val = model[iter][col]
+ digits = self.fraction_digits(val)
+ fmt = "%%.%df" % max(digits, 2)
+ cell.set_property('text', self.format(fmt, val))
+ else:
+ cell.set_property('text', typ(model[iter][col]))
+
+ # 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.set_attributes (cell_description, text=column)
+ column_description.set_sort_column_id(column)
+ if typ == float:
+ column_description.set_cell_data_func(cell_description, self.get_cell_data, (float, 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()
+
+ invest.STOCKS = {}
+
+ def save_symbol(model, path, iter):
+ #if int(model[iter][1]) == 0 or float(model[iter][2]) < 0.0001:
+ # return
+
+ if not model[iter][0] in invest.STOCKS:
+ invest.STOCKS[model[iter][0]] = { 'label': model[iter][1], 'purchases': [] }
+
+ 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)
+ try:
+ cPickle.dump(invest.STOCKS, file(invest.STOCKS_FILE, 'w'))
+ invest.debug('Stocks written to file')
+ except Exception, msg:
+ invest.error('Could not save stocks file: %s' % msg)
+
+ invest.CONFIG = {}
+ if self.currency_code != None and len(self.currency_code) == 3:
+ invest.CONFIG['currency'] = self.currency_code
+ try:
+ cPickle.dump(invest.CONFIG, file(invest.CONFIG_FILE, 'w'))
+ invest.debug('Configuration written to file')
+ except Exception, msg:
+ 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])
+ 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):
+ 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)