def category_render_cb(self, column, cell_renderer, model, iter, data):
     id = model.get_value(iter, 0)
     t = self.activity.transaction_map[id]
     category = t['category']
     cell_renderer.set_property('text', category)
     if category:
         category_color = colors.get_category_color_str(category)
         cell_renderer.set_property('background', category_color)
         if not colors.is_too_light(category_color):
             cell_renderer.set_property('foreground', '#FFFFFF')
     else:
         cell_renderer.set_property('background', None)
 def category_render_cb(self, column, cell_renderer, model, iter, data):
     id = model.get_value(iter, 0)
     t = self.activity.transaction_map[id]
     category = t['category']
     cell_renderer.set_property('text', category)
     if category:
         category_color = colors.get_category_color_str(category)
         cell_renderer.set_property('background', category_color)
         if not colors.is_too_light(category_color):
             cell_renderer.set_property('foreground', '#FFFFFF')
     else:
         cell_renderer.set_property('background', None)
    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 = list(self.category_total.keys())
        self.sorted_categories.sort()

        # Clear all widgets.
        for w in self.budgetbox.get_children():
            self.budgetbox.remove(w)

        # Build header.
        catlabel = Gtk.Label()
        catlabel.set_markup(
            '<span size="x-large" foreground="white"><b>%s</b></span>' %
            _('Category'))
        spentlabel = Gtk.Label()
        spentlabel.set_markup(
            '<span size="x-large" foreground="white"><b>%s</b></span>' %
            _('Spent'))
        budgetlabel = Gtk.Label()
        budgetlabel.set_markup(
            '<span size="x-large" foreground="white"><b>%s</b></span>' %
            _('Budget'))

        header = Gtk.EventBox()
        header.modify_bg(Gtk.StateType.NORMAL,
                         style.Color('#666666').get_gdk_color())
        header.set_size_request(-1, style.GRID_CELL_SIZE)

        headerbox = Gtk.HBox()
        headerbox.pack_start(catlabel, False, True, 20)
        headerbox.pack_start(spentlabel, True, True, 10)
        headerbox.pack_start(budgetlabel, False, True, 20)

        header.add(headerbox)
        self.budgetbox.pack_start(header, False, False, 0)

        catgroup = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)
        catgroup.add_widget(catlabel)

        spentgroup = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)
        spentgroup.add_widget(spentlabel)

        budgetgroup = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)
        budgetgroup.add_widget(budgetlabel)

        # Build categories.
        for c in self.sorted_categories:
            description = c
            # If there is no category, display as Unknown
            if c is '':
                description = _('Unknown')

            color = colors.get_category_color_str(c)
            if colors.is_too_light(color):
                font_color = '#000000'
            else:
                font_color = '#FFFFFF'

            catbox = Gtk.Label()
            catbox.set_markup('<span color="%s">%s</span>' %
                              (font_color, description))

            catbox.set_padding(10, 0)

            ebox = Gtk.EventBox()
            parse, color = Gdk.Color.parse(color)
            ebox.modify_bg(Gtk.StateType.NORMAL, color)
            ebox.add(catbox)

            catgroup.add_widget(ebox)

            bar = Gtk.DrawingArea()
            bar.connect('draw', self.bar_draw_cb, c)
            spentgroup.add_widget(bar)

            budgetentry = Gtk.Entry()
            budgetentry.connect('changed', self.budget_changed_cb, c)
            budgetentry.set_width_chars(10)
            if c in self.activity.data['budgets']:
                b = self.activity.data['budgets'][c]
                budgetentry.set_text(locale.currency(b['amount'], False))
            budgetgroup.add_widget(budgetentry)

            # freqcombo = Gtk.ComboBoxText()
            # freqcombo.append_text(_('Daily'))
            # freqcombo.append_text(_('Weekly'))
            # freqcombo.append_text(_('Monthly'))
            # freqcombo.append_text(_('Annually'))
            # freqcombo.set_active(2)

            hbox = Gtk.HBox()
            hbox.pack_start(ebox, False, False, 20)
            hbox.pack_start(bar, True, True, 10)
            hbox.pack_start(budgetentry, False, False, 20)
            # hbox.pack_start(freqcombo, True, True, 0)

            self.budgetbox.pack_start(hbox, False, False, 5)

        self.show_all()
    def _create_pie_chart(self, context, image_width, image_height):

        _set_screen_dpi()

        scale = image_width / 1600.
        context.rectangle(0, 0, image_width, image_height)
        logging.debug('canvas size %s x %s - scale %s', image_width,
                      image_height, scale)
        context.set_source_rgb(1, 1, 1)
        context.fill()

        margin_left = (style.GRID_CELL_SIZE / 2) * scale
        margin_top = (style.GRID_CELL_SIZE / 2) * scale
        padding = 20 * scale

        title_font_size = self._calculate_title_font_size(scale)

        title_width, title_height = self._measure_text(self._title,
                                                       title_font_size,
                                                       max_width=image_width -
                                                       margin_left * 2)
        logging.error('measure text pie %s %s', title_width, title_height)

        rectangles_width = 0
        if self._show_labels:
            # measure the descriptions
            max_width_desc = 0
            max_width_amount = 0
            max_height = 0
            label_font_size = 14 * scale
            for data in self._data:
                description = data['label']
                # If there is no category, display as Unknown
                if description is '':
                    description = _('Unknown')
                if len(description) > 30:
                    description = description[:30] + '...'

                # need measure the description width to align the amounts
                width, height = self._measure_text(description,
                                                   label_font_size)

                max_width_desc = max(max_width_desc, width)
                max_height = max(max_height, height)

                width, height = self._measure_text(str(data['value']),
                                                   label_font_size)

                max_height = max(max_height, height)
                max_width_amount = max(max_width_amount, width)

            # draw the labels
            labels_height = (max_height * 2.5) * len(self._data)
            y = (image_height - labels_height) / 2
            context.save()
            context.translate(margin_left, 0)
            rectangles_width = max_width_desc + max_width_amount + padding * 3
            for data in self._data:
                description = data['label']
                if description is '':
                    description = _('Unknown')
                if len(description) > 30:
                    description = description[:30] + '...'

                context.save()
                context.translate(0, y)
                draw_round_rect(context, 0, 0, rectangles_width,
                                max_height * 2, 10)

                color = style.Color(data['color'])
                context.set_source_rgba(*color.get_rgba())
                context.fill()

                if colors.is_too_light(data['color']):
                    context.set_source_rgb(0, 0, 0)
                else:
                    context.set_source_rgb(1, 1, 1)

                width, height = self._measure_text(description,
                                                   label_font_size)

                self._print_text(context, padding, height * .5, description,
                                 label_font_size)

                text = str(data['value'])
                width, height = self._measure_text(text, label_font_size)

                self._print_text(context, rectangles_width - width - padding,
                                 height * .5, text, label_font_size)

                y += max_height * 2.5
                context.restore()

            context.restore()

        self._print_text(context,
                         0,
                         margin_top,
                         self._title,
                         title_font_size,
                         max_width=image_width - margin_left * 2,
                         alignment=Pango.Alignment.CENTER,
                         color=self._title_color)
        margin_top += title_height + margin_top * 2

        # draw the pie
        r = min(image_width - rectangles_width - margin_left * 3,
                image_height - margin_top - margin_left) / 2
        y = max(r + margin_top, image_height / 2)
        if rectangles_width == 0:
            x = image_width / 2
        else:
            x = image_width - margin_left - r

        total = 0
        for data in self._data:
            total += data['value']

        if total != 0:
            angle = 0.0

            for data in self._data:
                value = data['value']
                slice = 2 * math.pi * value / total
                color = style.Color(data['color'])

                context.move_to(x, y)
                context.arc(x, y, r, angle, angle + slice)
                context.close_path()

                context.set_source_rgba(*color.get_rgba())
                context.fill()

                angle += slice
示例#5
0
    def create_chart(self, context, image_width, image_height):

        _set_screen_dpi()

        scale = image_width / 1600.
        context.rectangle(0, 0, image_width, image_height)
        logging.debug('canvas size %s x %s - scale %s', image_width,
                      image_height, scale)
        context.set_source_rgb(1, 1, 1)
        context.fill()

        margin_left = (style.GRID_CELL_SIZE / 2) * scale
        margin_top = (style.GRID_CELL_SIZE / 2) * scale
        padding = 20 * scale

        # measure the descriptions
        max_width_desc = 0
        max_width_amount = 0
        max_height = 0
        context.select_font_face('Sans', cairo.FONT_SLANT_NORMAL,
                                 cairo.FONT_WEIGHT_NORMAL)
        context.set_font_size(26 * scale)

        for c in self.sorted_categories:
            description = c
            # If there is no category, display as Unknown
            if c is '':
                description = _('Unknown')

            # need measure the description width to align the amounts
            x_bearing, y_bearing, width, height, x_advance, y_advance = \
                context.text_extents(description)
            max_width_desc = max(max_width_desc, width)
            max_height = max(max_height, height)

            x_bearing, y_bearing, width, height, x_advance, y_advance = \
                context.text_extents(locale.currency(self.category_total[c]))
            max_height = max(max_height, height)
            max_width_amount = max(max_width_amount, width)

        # draw the labels
        y = margin_top
        context.save()
        context.translate(margin_left, 0)
        rectangles_width = max_width_desc + max_width_amount + padding * 3
        for c in self.sorted_categories:
            description = c
            if c is '':
                description = _('Unknown')
            context.save()
            context.translate(0, y)
            context.rectangle(0, 0, rectangles_width, max_height + padding)

            color = colors.get_category_color(c)
            context.set_source_rgb(color[0], color[1], color[2])
            context.fill()

            if colors.is_too_light(colors.get_category_color_str(c)):
                context.set_source_rgb(0, 0, 0)
            else:
                context.set_source_rgb(1, 1, 1)

            context.save()
            x_bearing, y_bearing, width, height, x_advance, y_advance = \
                context.text_extents(description)
            context.move_to(padding, padding * 2.5 + y_bearing)
            context.show_text(description)
            context.restore()

            context.save()
            text = locale.currency(self.category_total[c])
            x_bearing, y_bearing, width, height, x_advance, y_advance = \
                context.text_extents(text)
            context.move_to(rectangles_width - x_advance - padding,
                            padding * 2.5 + y_bearing)
            context.show_text(text)
            context.restore()

            y += max_height + padding * 2
            context.restore()

        context.restore()

        # draw the pie
        x = (image_width - rectangles_width) / 2 + rectangles_width
        y = image_height / 2
        r = min(image_width, image_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 = colors.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()

                angle += slice
    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()

        # Clear all widgets.
        for w in self.budgetbox.get_children():
            self.budgetbox.remove(w)

        # Build header.
        catlabel = Gtk.Label()
        catlabel.set_markup(
            '<span size="x-large" foreground="white"><b>%s</b></span>' %
            _('Category'))
        spentlabel = Gtk.Label()
        spentlabel.set_markup(
            '<span size="x-large" foreground="white"><b>%s</b></span>' %
            _('Spent'))
        budgetlabel = Gtk.Label()
        budgetlabel.set_markup(
            '<span size="x-large" foreground="white"><b>%s</b></span>' %
            _('Budget'))

        header = Gtk.EventBox()
        header.modify_bg(Gtk.StateType.NORMAL,
                         style.Color('#666666').get_gdk_color())
        header.set_size_request(-1, style.GRID_CELL_SIZE)

        headerbox = Gtk.HBox()
        headerbox.pack_start(catlabel, False, True, 20)
        headerbox.pack_start(spentlabel, True, True, 10)
        headerbox.pack_start(budgetlabel, False, True, 20)

        header.add(headerbox)
        self.budgetbox.pack_start(header, False, False, 0)

        catgroup = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)
        catgroup.add_widget(catlabel)

        spentgroup = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)
        spentgroup.add_widget(spentlabel)

        budgetgroup = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)
        budgetgroup.add_widget(budgetlabel)

        # Build categories.
        for c in self.sorted_categories:
            description = c
            # If there is no category, display as Unknown
            if c is '':
                description = _('Unknown')

            color = colors.get_category_color_str(c)
            if colors.is_too_light(color):
                font_color = '#000000'
            else:
                font_color = '#FFFFFF'

            catbox = Gtk.Label()
            catbox.set_markup(
                '<span color="%s">%s</span>' % (font_color, description))

            catbox.set_padding(10, 0)

            ebox = Gtk.EventBox()
            parse, color = Gdk.Color.parse(color)
            ebox.modify_bg(Gtk.StateType.NORMAL, color)
            ebox.add(catbox)

            catgroup.add_widget(ebox)

            bar = Gtk.DrawingArea()
            bar.connect('draw', self.bar_draw_cb, c)
            spentgroup.add_widget(bar)

            budgetentry = Gtk.Entry()
            budgetentry.connect('changed', self.budget_changed_cb, c)
            budgetentry.set_width_chars(10)
            if c in self.activity.data['budgets']:
                b = self.activity.data['budgets'][c]
                budgetentry.set_text(locale.currency(b['amount'], False))
            budgetgroup.add_widget(budgetentry)

            # freqcombo = Gtk.ComboBoxText()
            # freqcombo.append_text(_('Daily'))
            # freqcombo.append_text(_('Weekly'))
            # freqcombo.append_text(_('Monthly'))
            # freqcombo.append_text(_('Annually'))
            # freqcombo.set_active(2)

            hbox = Gtk.HBox()
            hbox.pack_start(ebox, False, False, 20)
            hbox.pack_start(bar, True, True, 10)
            hbox.pack_start(budgetentry, False, False, 20)
            # hbox.pack_start(freqcombo, True, True, 0)

            self.budgetbox.pack_start(hbox, False, False, 5)

        self.show_all()
示例#7
0
    def _create_pie_chart(self, context, image_width, image_height):

        _set_screen_dpi()

        scale = image_width / 1600.
        context.rectangle(0, 0, image_width, image_height)
        context.set_source_rgb(1, 1, 1)
        context.fill()

        margin_left = (style.GRID_CELL_SIZE / 2) * scale
        margin_top = (style.GRID_CELL_SIZE / 2) * scale
        padding = 20 * scale

        title_font_size = self._calculate_title_font_size(scale)

        title_width, title_height = self._measure_text(
            self._title, title_font_size,
            max_width=image_width - margin_left * 2)

        rectangles_width = 0
        if self._show_labels:
            # measure the descriptions
            max_width_desc = 0
            max_width_amount = 0
            max_height = 0
            label_font_size = 14 * scale
            for data in self._data:
                description = data['label']
                # If there is no category, display as Unknown
                if description is '':
                    description = _('Unknown')
                if len(description) > 30:
                    description = description[:30] + '...'

                # need measure the description width to align the amounts
                width, height = self._measure_text(description,
                                                   label_font_size)

                max_width_desc = max(max_width_desc, width)
                max_height = max(max_height, height)

                width, height = self._measure_text(str(data['value']),
                                                   label_font_size)

                max_height = max(max_height, height)
                max_width_amount = max(max_width_amount, width)

            # draw the labels
            labels_height = (max_height * 2.5) * len(self._data)
            y = (image_height - labels_height) / 2
            context.save()
            context.translate(margin_left, 0)
            rectangles_width = max_width_desc + max_width_amount + padding * 3
            for data in self._data:
                description = data['label']
                if description is '':
                    description = _('Unknown')
                if len(description) > 30:
                    description = description[:30] + '...'

                context.save()
                context.translate(0, y)
                draw_round_rect(context, 0, 0,
                                rectangles_width, max_height * 2, 10)

                color = style.Color(data['color'])
                context.set_source_rgba(*color.get_rgba())
                context.fill()

                if colors.is_too_light(data['color']):
                    context.set_source_rgb(0, 0, 0)
                else:
                    context.set_source_rgb(1, 1, 1)

                width, height = self._measure_text(description,
                                                   label_font_size)

                self._print_text(context, padding, height * .5, description,
                                 label_font_size)

                text = str(data['value'])
                width, height = self._measure_text(text, label_font_size)

                self._print_text(context, rectangles_width - width - padding,
                                 height * .5, text, label_font_size)

                y += max_height * 2.5
                context.restore()

            context.restore()

        self._print_text(
            context,
            0, margin_top,
            self._title, title_font_size,
            max_width=image_width - margin_left * 2,
            alignment=Pango.Alignment.CENTER, color=self._title_color)
        margin_top += title_height + margin_top * 2

        # draw the pie
        r = min(image_width - rectangles_width - margin_left * 3,
                image_height - margin_top - margin_left) / 2
        y = max(r + margin_top,
                image_height / 2)
        if rectangles_width == 0:
            x = image_width / 2
        else:
            x = image_width - margin_left - r

        total = 0
        for data in self._data:
            total += data['value']

        if total != 0:
            angle = 0.0

            for data in self._data:
                value = data['value']
                slice = 2 * math.pi * value / total
                color = style.Color(data['color'])

                context.move_to(x, y)
                context.arc(x, y, r, angle, angle + slice)
                context.close_path()

                context.set_source_rgba(*color.get_rgba())
                context.fill()

                angle += slice