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()
Beispiel #4
0
    def __init__(self,
                 poll,
                 current_vote,
                 view_answer,
                 chart_type=CHART_TYPE_PIE):

        Gtk.EventBox.__init__(self)
        self.modify_bg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color())

        self._current_vote = current_vote
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        box.props.margin_left = style.GRID_CELL_SIZE * 2
        box.props.margin_right = style.GRID_CELL_SIZE * 2

        self.add(box)

        self._poll = poll

        self._grid = Gtk.Grid()
        box.pack_start(self._grid, True, True, 0)
        row = 0

        if not poll.active:
            self.title = Gtk.Label()
            self.title.set_markup('<span size="xx-large">%s</span>' %
                                  GObject.markup_escape_text(poll.title))
            self.title.props.margin_top = style.GRID_CELL_SIZE / 2
            self.title.props.margin_bottom = style.GRID_CELL_SIZE / 2
            self.title.set_halign(Gtk.Align.START)
            self.title.set_max_width_chars(70)
            self.title.set_ellipsize(Pango.EllipsizeMode.END)
            self._grid.attach(self.title, 0, row, 2, 1)
            row += 1

        self.question = Gtk.Label()
        self.question.set_markup(
            '<span size="xx-large" color="%s"><b>%s</b></span>' %
            (darker_color_str, GObject.markup_escape_text(poll.question)))
        self.question.props.margin_top = style.GRID_CELL_SIZE / 2
        self.question.props.margin_bottom = style.GRID_CELL_SIZE / 2
        self.question.set_halign(Gtk.Align.CENTER)
        self.question.set_max_width_chars(70)
        self.question.set_ellipsize(Pango.EllipsizeMode.END)
        self._grid.attach(self.question, 0, row, 2, 1)
        row += 1

        self.tabla = Gtk.Table(rows=6, columns=6)

        scroll = Gtk.ScrolledWindow()

        scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)

        scroll.add_with_viewport(self.tabla)
        scroll.set_hexpand(True)
        scroll.set_vexpand(True)

        group = Gtk.RadioButton()

        row = 0
        data = []
        self._button_labels = []
        for choice in range(poll.number_of_options):
            # data is used by the chart
            color_str = colors.get_category_color_str(poll.options[choice])
            # verify if the color is unique
            unique = False
            counter = 1
            while not unique:
                unique = True
                for element in data:
                    if element['color'] == color_str:
                        unique = False
                if not unique:
                    color_str = colors.get_category_color_str(
                        poll.options[choice] + str(counter))
                    counter += 1

            data.append({
                'label': poll.options[choice],
                'value': poll.data[choice],
                'color': color_str
            })

            if poll.active:
                box = Gtk.VBox()
                text = poll.options[choice]
                color = style.Color(color_str)
                roundbox = RoundBox()
                roundbox.background_color = color
                roundbox.border_color = color
                button = Gtk.RadioButton.new_from_widget(group)
                label = Gtk.Label(text)
                label.set_max_width_chars(28)
                label.set_ellipsize(Pango.EllipsizeMode.END)
                self._button_labels.append(label)
                button.add(label)
                button.props.margin = style.GRID_CELL_SIZE / 4
                button.set_halign(Gtk.Align.START)
                roundbox.add(button)
                roundbox.set_valign(Gtk.Align.CENTER)
                roundbox.set_hexpand(False)
                box.pack_start(roundbox, False, False, 0)
                box.set_valign(Gtk.Align.CENTER)
                button.connect('toggled', self.__vote_radio_button_cb, choice)

                self.tabla.attach(box, 0, 1, row, row + 1)

                if choice == current_vote:
                    button.set_active(True)

                if poll.images[int(choice)]:
                    image = Gtk.Image()
                    image.set_from_pixbuf(poll.images[choice])
                    image.set_halign(Gtk.Align.START)
                    self.tabla.attach(image, 1, 2, row, row + 1)

            row += 1

        logging.error('poll options %s data %s', poll.options, poll.data)

        self.chart = Chart(data,
                           chart_type,
                           show_labels=not poll.active,
                           title=poll.question,
                           title_color=darker_color_str)
        self.chart.set_hexpand(True)
        self.chart.set_vexpand(True)

        # Button area
        if poll.active:
            self._grid.attach(scroll, 0, row, 1, 1)
            self._grid.attach(self.chart, 1, row, 1, 1)
            row += 1

            button = Gtk.Button(_("Vote"))
            button.set_image(
                Icon(icon_name='dialog-ok', pixel_size=style.MEDIUM_ICON_SIZE))
            theme = 'GtkButton {background-color: %s;' \
                'font-size:%s;' \
                'padding: 5px 35px 5px 35px;}' % \
                ('#ff0000', style.FONT_SIZE * 2)
            css_provider = Gtk.CssProvider()
            css_provider.load_from_data(theme)
            style_context = button.get_style_context()
            style_context.add_provider(css_provider,
                                       Gtk.STYLE_PROVIDER_PRIORITY_USER)

            button.connect('clicked', self.__button_vote_cb)
            button.set_hexpand(False)
            button.set_halign(Gtk.Align.CENTER)

            self._grid.attach(button, 0, row, 2, 1)
            row += 1

        else:
            logging.error('poll not active')
            self._grid.attach(self.chart, 0, row, 2, 1)
            row += 1

        counter_label = Gtk.Label()
        if poll.active:
            text = '%s from %s votes collected' % (poll.vote_count,
                                                   poll.maxvoters)
        else:
            text = '%s votes collected' % poll.maxvoters
        counter_label.set_markup('<span size="large">%s</span>' %
                                 GObject.markup_escape_text(text))

        counter_label.props.margin_top = style.GRID_CELL_SIZE / 2
        counter_label.props.margin_bottom = style.GRID_CELL_SIZE / 2
        counter_label.set_halign(Gtk.Align.CENTER)
        self._grid.attach(counter_label, 0, row, 2, 1)

        self.show_all()
        # hide or show the results if needed
        self.set_view_answer(view_answer or not poll.active)
    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
Beispiel #6
0
    def __init__(self, poll, current_vote, view_answer,
                 chart_type=CHART_TYPE_PIE):

        Gtk.EventBox.__init__(self)
        self.modify_bg(Gtk.StateType.NORMAL,
                       style.COLOR_WHITE.get_gdk_color())

        self._current_vote = current_vote
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        box.props.margin_left = style.GRID_CELL_SIZE * 2
        box.props.margin_right = style.GRID_CELL_SIZE * 2

        self.add(box)

        self._poll = poll

        self._grid = Gtk.Grid()
        box.pack_start(self._grid, True, True, 0)
        row = 0

        if not poll.active:
            self.title = Gtk.Label()
            self.title.set_markup('<span size="xx-large">%s</span>' %
                                  GObject.markup_escape_text(poll.title))
            self.title.props.margin_top = style.GRID_CELL_SIZE / 2
            self.title.props.margin_bottom = style.GRID_CELL_SIZE / 2
            self.title.set_halign(Gtk.Align.START)
            self.title.set_max_width_chars(70)
            self.title.set_ellipsize(Pango.EllipsizeMode.END)
            self._grid.attach(self.title, 0, row, 2, 1)
            row += 1

        self.question = Gtk.Label()
        self.question.set_markup(
            '<span size="xx-large" color="%s"><b>%s</b></span>' %
            (darker_color_str, GObject.markup_escape_text(poll.question)))
        self.question.props.margin_top = style.GRID_CELL_SIZE / 2
        self.question.props.margin_bottom = style.GRID_CELL_SIZE / 2
        self.question.set_halign(Gtk.Align.CENTER)
        self.question.set_max_width_chars(70)
        self.question.set_ellipsize(Pango.EllipsizeMode.END)
        self._grid.attach(self.question, 0, row, 2, 1)
        row += 1

        self.tabla = Gtk.Table(rows=6, columns=6)

        scroll = Gtk.ScrolledWindow()

        scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)

        scroll.add_with_viewport(self.tabla)
        scroll.set_hexpand(True)
        scroll.set_vexpand(True)

        group = Gtk.RadioButton()

        row = 0
        data = []
        self._button_labels = []
        for choice in range(poll.number_of_options):
            # data is used by the chart
            color_str = colors.get_category_color_str(poll.options[choice])
            # verify if the color is unique
            unique = False
            counter = 1
            while not unique:
                unique = True
                for element in data:
                    if element['color'] == color_str:
                        unique = False
                if not unique:
                    color_str = colors.get_category_color_str(
                        poll.options[choice] + str(counter))
                    counter += 1

            data.append({'label': poll.options[choice],
                         'value': poll.data[choice],
                         'color': color_str})

            if poll.active:
                box = Gtk.VBox()
                text = poll.options[choice]
                color = style.Color(color_str)
                roundbox = RoundBox()
                roundbox.background_color = color
                roundbox.border_color = color
                button = Gtk.RadioButton.new_from_widget(group)
                label = Gtk.Label(text)
                label.set_max_width_chars(28)
                label.set_ellipsize(Pango.EllipsizeMode.END)
                self._button_labels.append(label)
                button.add(label)
                button.props.margin = style.GRID_CELL_SIZE / 4
                button.set_halign(Gtk.Align.START)
                roundbox.add(button)
                roundbox.set_valign(Gtk.Align.CENTER)
                roundbox.set_hexpand(False)
                box.pack_start(roundbox, False, False, 0)
                box.set_valign(Gtk.Align.CENTER)
                button.connect('toggled', self.__vote_radio_button_cb, choice)

                self.tabla.attach(box, 0, 1, row, row + 1)

                if choice == current_vote:
                    button.set_active(True)

                if poll.images[int(choice)]:
                    image = Gtk.Image()
                    image.set_from_pixbuf(poll.images[choice])
                    image.set_halign(Gtk.Align.START)
                    self.tabla.attach(image, 1, 2, row, row + 1)

            row += 1

        logging.debug('poll options %s data %s', poll.options, poll.data)

        self.chart = Chart(data, chart_type, show_labels=not poll.active,
                           title=poll.question,
                           title_color=darker_color_str)
        self.chart.set_hexpand(True)
        self.chart.set_vexpand(True)

        # Button area
        if poll.active:
            self._grid.attach(scroll, 0, row, 1, 1)
            self._grid.attach(self.chart, 1, row, 1, 1)
            row += 1

            button = Gtk.Button(_("Vote"))
            button.set_image(Icon(icon_name='dialog-ok',
                                  pixel_size=style.MEDIUM_ICON_SIZE))
            theme = 'GtkButton {background-color: %s;' \
                'font-size:%s;' \
                'padding: 5px 35px 5px 35px;}' % \
                ('#ff0000', style.FONT_SIZE * 2)
            css_provider = Gtk.CssProvider()
            css_provider.load_from_data(theme)
            style_context = button.get_style_context()
            style_context.add_provider(css_provider,
                                       Gtk.STYLE_PROVIDER_PRIORITY_USER)

            button.connect('clicked', self.__button_vote_cb)
            button.set_hexpand(False)
            button.set_halign(Gtk.Align.CENTER)

            self._grid.attach(button, 0, row, 2, 1)
            row += 1

        else:
            logging.debug('poll not active')
            self._grid.attach(self.chart, 0, row, 2, 1)
            row += 1

        counter_label = Gtk.Label()
        if poll.active:
            text = '%s from %s votes collected' % (poll.vote_count,
                                                   poll.maxvoters)
        else:
            text = '%s votes collected' % poll.maxvoters
        counter_label.set_markup('<span size="large">%s</span>' %
                                 GObject.markup_escape_text(text))

        counter_label.props.margin_top = style.GRID_CELL_SIZE / 2
        counter_label.props.margin_bottom = style.GRID_CELL_SIZE / 2
        counter_label.set_halign(Gtk.Align.CENTER)
        self._grid.attach(counter_label, 0, row, 2, 1)

        self.show_all()
        # hide or show the results if needed
        self.set_view_answer(view_answer or not poll.active)
    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()