# Copyright 2008 by Wade Brainerd. # This file is part of Finance. # # Finance is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Finance is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Finance. If not, see . # Import standard Python modules. import logging, os, math, time, copy, json, time, datetime, locale from gettext import gettext as _ # Set up localization. locale.setlocale(locale.LC_ALL, '') # Import PyGTK. import gobject, pygtk, gtk, pango, cairo # Import Sugar UI modules. import sugar.activity.activity from sugar.graphics import * # Import activity module import finance CHART_HELP = _('The Chart view shows the proportion of your expenses that is in each category.\nYou can categorize transactions in the Register view.') class ChartScreen(gtk.HBox): def __init__(self, activity): gtk.HBox.__init__(self) self.activity = activity self.category_total = {} self.sorted_categories = [] self.area = gtk.DrawingArea() self.area.connect('expose-event', self.chart_expose_cb) label = gtk.Label() label.set_markup(''+_('Debit Categories')+'') self.catbox = gtk.VBox() box = gtk.VBox() box.pack_start(gtk.VBox(), False, False, 40) box.pack_start(label, False, False) box.pack_start(gtk.HSeparator(), False, False) box.pack_start(self.catbox, False, False, 10) box.pack_start(gtk.VBox(), True, True) self.pack_start(self.area, True, True) self.pack_start(box, False, False, 40) self.show_all() def build(self): # Build the category totals. self.category_total = {} for t in self.activity.visible_transactions: cat = t['category'] amount = t['amount'] if t['type'] == 'debit': if not self.category_total.has_key(cat): self.category_total[cat] = amount else: self.category_total[cat] += amount # Generate a list of names sorted by total. self.sorted_categories = self.category_total.keys() #self.sorted_categories.sort(lamba a, b: cmp(self.category_total[a], self.category_total[b])) # Clear and rebuild the labels box. for w in self.catbox.get_children(): self.catbox.remove(w) catgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) amountgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) for c in self.sorted_categories: hbox = gtk.HBox() catlabel = gtk.Label() catlabel.set_markup(c) catgroup.add_widget(catlabel) color = finance.get_category_color_str(c) amountlabel = gtk.Label() amountlabel.set_markup(locale.currency(self.category_total[c])) amountgroup.add_widget(amountlabel) hbox.pack_start(amountlabel, True, True, 20) hbox.pack_start(catlabel, True, True, 20) ebox = gtk.EventBox() ebox.modify_bg(gtk.STATE_NORMAL, ebox.get_colormap().alloc_color(color)) ebox.add(hbox) self.catbox.pack_end(ebox, False, False, 5) self.show_all() # Update the help text. self.activity.set_help(CHART_HELP) def chart_expose_cb(self, widget, event): context = widget.window.cairo_create() context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) context.clip() # Draw pie chart. bounds = widget.get_allocation() x = bounds.width/2 y = bounds.height/2 r = min(bounds.width, bounds.height)/2 - 10 total = 0 for c in self.sorted_categories: total += self.category_total[c] if total != 0: angle = 0.0 for c in self.sorted_categories: slice = 2*math.pi * self.category_total[c] / total color = finance.get_category_color(c) context.move_to(x, y) context.arc(x, y, r, angle, angle + slice) context.close_path() context.set_source_rgb(color[0], color[1], color[2]) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() angle += slice