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 __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
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()