# 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 math import locale # Import activity module import finance from gettext import gettext as _ from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GObject # Set up localization. locale.setlocale(locale.LC_ALL, '') 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): GObject.GObject.__init__(self) self.activity = activity self.category_total = {} self.sorted_categories = [] self.area = Gtk.DrawingArea() self.area.connect('draw', self.chart_draw_cb) self.box_area = Gtk.EventBox() self.box_area.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse('white')) self.box_area.add(self.area) label = Gtk.Label() label.set_markup('' + _('Debit Categories') + '') self.catbox = Gtk.VBox() box = Gtk.VBox() box.pack_start(Gtk.Box(orientation=Gtk.Orientation.VERTICAL), False, False, 40) box.pack_start(label, False, False, 0) box.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL), False, False, 0) box.pack_start(self.catbox, False, False, 10) box.pack_start(Gtk.Box(orientation=Gtk.Orientation.VERTICAL), True, True, 0) self.pack_start(self.box_area, True, True, 0) 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 cat not in self.category_total: 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.SizeGroupMode.HORIZONTAL) amountgroup = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL) for c in self.sorted_categories: hbox = Gtk.HBox() description = c # If there is no category, display as Unknown if c is '': description = _('Unknown') catlabel = Gtk.Label(label=description) 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() parse, color = Gdk.Color.parse(color) ebox.modify_bg(Gtk.StateType.NORMAL, color) ebox.add(hbox) self.catbox.pack_end(ebox, False, False, 5) self.show_all() def chart_draw_cb(self, widget, context): # 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