From f25a8b3495a45898d55e8a25109f795e60196a82 Mon Sep 17 00:00:00 2001 From: Gonzalo Odiard Date: Fri, 18 Jul 2014 18:16:47 +0000 Subject: Initial implementation of save chart to journal --- diff --git a/chartscreen.py b/chartscreen.py index 02d67bb..d13ed12 100644 --- a/chartscreen.py +++ b/chartscreen.py @@ -18,6 +18,7 @@ import math import locale import cairo +import logging # Import activity module import colors @@ -76,13 +77,13 @@ class ChartScreen(Gtk.VBox): def build(self): if self._graph_mode == self.CHART_CREDIT: - title = _('Credit Categories') + self.title = _('Credit Categories') elif self._graph_mode == self.CHART_DEBIT: - title = _('Debit Categories') + self.title = _('Debit Categories') self._title_label.set_markup( '%s' % - title) + self.title) # Build the category totals. self.category_total = {} @@ -102,18 +103,30 @@ class ChartScreen(Gtk.VBox): # self.category_total[b])) self.area.queue_draw() + def generate_image(self, image_file, width, height): + image_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + + context = cairo.Context(image_surface) + self.create_chart(context, width, height) + image_surface.flush() + image_surface.write_to_png(image_file) + def chart_draw_cb(self, widget, context): # Draw pie chart. bounds = widget.get_allocation() - context.rectangle(0, 0, bounds.width, bounds.height) + self.create_chart(context, bounds.width, bounds.height) + + def create_chart(self, context, image_width, image_height): + 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() - # draw the labels - - margin_left = style.GRID_CELL_SIZE / 2 - margin_top = style.GRID_CELL_SIZE / 2 - padding = 20 + 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 @@ -121,7 +134,7 @@ class ChartScreen(Gtk.VBox): max_height = 0 context.select_font_face('Sans', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) - context.set_font_size(20) + context.set_font_size(20 * scale) for c in self.sorted_categories: description = c @@ -183,9 +196,9 @@ class ChartScreen(Gtk.VBox): context.restore() # draw the pie - x = (bounds.width - rectangles_width) / 2 + rectangles_width - y = bounds.height / 2 - r = min(bounds.width, bounds.height) / 2 - 10 + 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: diff --git a/finance.py b/finance.py index 9cb4e40..54049ca 100644 --- a/finance.py +++ b/finance.py @@ -23,6 +23,9 @@ import datetime import locale from gettext import gettext as _ import json +import tempfile +import StringIO +import dbus from gi.repository import Gtk from gi.repository import Pango @@ -35,7 +38,8 @@ from sugar3.graphics import style from sugar3.activity.widgets import StopButton from sugar3.activity.widgets import ActivityToolbarButton -from sugar3.activity.activity import Activity +from sugar3.activity import activity +from sugar3.datastore import datastore # Import screen classes. import registerscreen @@ -67,9 +71,9 @@ FOREVER = 4 # and options. Screens are stored in a stack, with the currently # active screen on top. -class Finance(Activity): +class Finance(activity.Activity): def __init__(self, handle): - Activity.__init__(self, handle) + activity.Activity.__init__(self, handle) self.set_title(_("Finance")) self.max_participants = 1 @@ -258,6 +262,14 @@ class Finance(Activity): headerbox.insert(self.newdebitbtn, -1) headerbox.insert(self.eraseitembtn, -1) + self.header_separator_visible = Gtk.SeparatorToolItem() + headerbox.insert(self.header_separator_visible, -1) + + self.export_image = ToolButton('save-as-image') + self.export_image.set_tooltip(_("Save as Image")) + self.export_image.connect('clicked', self.__save_image_cb) + headerbox.insert(self.export_image, -1) + self._header_separator = Gtk.SeparatorToolItem() self._header_separator.props.draw = False self._header_separator.set_expand(True) @@ -294,12 +306,20 @@ class Finance(Activity): def show_header_controls(self): for child in self.headerbox.get_children(): child.show() - if self._active_panel == self.budget: + if self._active_panel == self.register: + if child in (self.header_separator_visible, + self.export_image): + child.hide() + elif self._active_panel == self.budget: if child in (self.newcreditbtn, self.newdebitbtn, - self.eraseitembtn): + self.eraseitembtn, self.header_separator_visible, + self.export_image): child.hide() elif self._active_panel == self.chart: - if child not in (self.newcreditbtn, self.newdebitbtn): + # Use NOT here + if child not in (self.newcreditbtn, self.newdebitbtn, + self.header_separator_visible, + self.export_image): child.hide() def register_cb(self, widget): @@ -801,6 +821,7 @@ class Finance(Activity): if self.data['transactions']: self._set_internal_panel(self.register) + self.show_header_controls() self.build_transaction_map() self.build_names() @@ -816,3 +837,25 @@ class Finance(Activity): fd.write(text) finally: fd.close() + + def __save_image_cb(self, widget): + image_file = tempfile.NamedTemporaryFile(mode='w+b', suffix='.png') + journal_entry = datastore.create() + journal_entry.metadata['title'] = self.chart.title + journal_entry.metadata['keep'] = '0' + journal_entry.metadata['mime_type'] = 'image/png' + + # generate the image + self.chart.generate_image(image_file.file, 800, 600) + image_file.file.close() + journal_entry.file_path = image_file.name + + # generate the preview + preview_str = StringIO.StringIO() + self.chart.generate_image(preview_str, activity.PREVIEW_SIZE[0], + activity.PREVIEW_SIZE[1]) + journal_entry.metadata['preview'] = dbus.ByteArray( + preview_str.getvalue()) + + logging.error('Create %s image file', image_file.name) + datastore.write(journal_entry) -- cgit v0.9.1