Exemple #1
0
    def __init__(self, element_id, report_data_set_chart_id, report_data_set_instance_id, data, settings, jfile):
        self.annotations_map = []
        self.config = ConfigReader()
        self.file_man = JChartFile()
        self.element_id = element_id
        self.report_data_set_chart_id = report_data_set_chart_id
        self.report_data_set_instance_id = report_data_set_instance_id
        self.chart_data = data['chart_data']
        self.layout_data = data['layout_data']
        self.data = data
        self.settings = settings
        self._jfile = jfile

        #self.create_chart()

        self.datasets = {}
Exemple #2
0
class BasePieChart:
    annotations_map = list()

    def __init__(self, element_id, report_data_set_chart_id, report_data_set_instance_id, data, settings, jfile):
        self.annotations_map = list()
        self.config = ConfigReader()
        self.file_man = JChartFile()
        self.element_id = element_id
        self.report_data_set_chart_id = report_data_set_chart_id
        self.report_data_set_instance_id = report_data_set_instance_id
        self.chart_data = data['chart_data']
        self.layout_data = data['layout_data']
        self.data = data
        self.settings = settings
        self._jfile = jfile

        self.create_chart()
        if self.settings['type'] == 'large':
            self.create_map_file()
        self.datasets = dict()

    def create_chart(self):
        c = PieChart(self.layout_data['chart_object_size_x'],
                     self.layout_data['chart_object_size_y'],
                     FontManager.get_db_color(self.layout_data['background_color']),
                     FontManager.get_db_color(self.layout_data['border_color']),
                     0)

        # make pretty fonts
        c.setAntiAlias(True, AntiAlias)

        labels = self.chart_data['formatted_header']

        try:
            c.setData(self.chart_data['data'], labels)
        except TypeError:
            raise Exception("Chart %s misconfigured. Sector Values must contain numeric values." % self.report_data_set_chart_id)

        # colors for sectors for the pie chart
        if self.chart_data['colors']:
            c.setColors2(DataColor, self.chart_data['colors'])

        # set chart title
        if self.layout_data['include_title_ind'] == 'Y':
            c.addTitle(self.layout_data['name'],
                        FontManager.get_db_font(self.layout_data['title_font']),
                        self.layout_data['title_font_size'],
                        self.layout_data['title_font_color'])
        # define center coordinates
        if not self.layout_data['pie_chart_center_x_coord']:
            self.layout_data['pie_chart_center_x_coord'] = self.layout_data['chart_object_size_x'] // 2

        if not self.layout_data['pie_chart_center_y_coord']:
            self.layout_data['pie_chart_center_y_coord'] = self.layout_data['chart_object_size_y'] // 2

        # define radius
        if not self.layout_data['pie_chart_radius']:
            if self.layout_data['chart_object_size_y'] > self.layout_data['chart_object_size_x']:
                smallest_side = self.layout_data['chart_object_size_x']
            else:
                smallest_side = self.layout_data['chart_object_size_y']
            self.layout_data['pie_chart_radius'] = int(smallest_side // 2 * 0.7)
            # reduce radius for preview chart
            if self.settings['type'] == 'preview':
                #self.layout_data['pie_chart_radius'] = self.layout_data['pie_chart_radius'] * 0.9
                self.layout_data['pie_chart_radius'] *= 0.9

        # set pie position and radius
        c.setPieSize(self.layout_data['pie_chart_center_x_coord'], self.layout_data['pie_chart_center_y_coord'], self.layout_data['pie_chart_radius'])

        # 3D chart settings
        if self.layout_data['pie_chart_type'] == '3D':
            # if depth not specified use default
            if not self.layout_data['pie_chart_depth']:
                self.layout_data['pie_chart_depth'] = -1
            # if start angle not specified use default
            if not self.layout_data['pie_chart_display_angle']:
                self.layout_data['pie_chart_display_angle'] = -1
            c.set3D(self.layout_data['pie_chart_depth'], self.layout_data['pie_chart_display_angle'])

        # start angle
        if not self.layout_data['pie_chart_start_angle']:
            self.layout_data['pie_chart_start_angle'] = 0
        c.setStartAngle(self.layout_data['pie_chart_start_angle'])

        # set labels position formats
        if self.settings['type'] == 'preview':
            label_pos = 5
        else:
            label_pos = 15
        c.setLabelLayout(SideLayout, label_pos)

        # label font color
        if self.settings['type'] == 'thumbnail':
            self.layout_data['pie_chart_sector_label_font_color'] = Transparent
        else:
            if self.layout_data['pie_chart_sector_label_font_color']:
                # use specified color
                self.layout_data['pie_chart_sector_label_font_color'] = FontManager.get_db_color(self.layout_data['pie_chart_sector_label_font_color'])
            else:
                # same as sector color
                self.layout_data['pie_chart_sector_label_font_color'] = SameAsMainColor

        t = c.setLabelStyle(FontManager.get_db_font(self.layout_data['pie_chart_sector_label_font']),
                            self.layout_data['pie_chart_sector_label_font_size'],
                            self.layout_data['pie_chart_sector_label_font_color'])
        if self.settings['type'] == 'preview' or self.settings['type'] == 'large':
            max_label_width = (self.layout_data['chart_object_size_x'] - self.layout_data['pie_chart_radius'] * 2 - label_pos * 2) / 2
            t.setMaxWidth(max_label_width)

        if self.settings['type'] == 'thumbnail':
            fill_label_color = Transparent
            sector_label_border_color = Transparent
        else:
            if self.layout_data['use_sector_color_for_Label_fill_ind'] == 'Y':
                # same as sector color
                fill_label_color = SameAsMainColor
            else:
                # no background
                fill_label_color = Transparent
            if self.layout_data['sector_label_border_color']:
                # use specified color
                sector_label_border_color = FontManager.get_db_color(self.layout_data['sector_label_border_color'])
            else:
                # no border
                sector_label_border_color = Transparent
        # set label background and border color
        t.setBackground(fill_label_color, sector_label_border_color)

        # rounded corners of labels
        if self.layout_data['sector_label_corner_style'] == 'Rounded':
            t.setRoundedCorners()

        # join line format
        if self.settings['type'] == 'thumbnail':
            # do not draw line
            join_line_color = Transparent
        else:
            if self.layout_data['sector_label_join_line_color']:
                # use specified color
                join_line_color = FontManager.get_db_color(self.layout_data['sector_label_join_line_color'])
            else:
                # use sector color
                join_line_color = SameAsMainColor

        c.setJoinLine(join_line_color)

        # shading format
        if self.layout_data['pie_chart_shading'] == 'Rounded Edge':
            shading = RoundedEdgeShading
        elif self.layout_data['pie_chart_shading'] == 'Flat Gradient' and self.layout_data['pie_chart_type'] == '3D':
            shading = FlatShading
        else:
            shading = DefaultShading

        # explode sectors
        if self.layout_data['explode_all_pie_sectors'] == 'all' or \
             (self.layout_data['explode_all_pie_sectors'] == '2D' and self.layout_data['pie_chart_type'] == '2D') or \
              (self.layout_data['explode_all_pie_sectors'] == '3D' and self.layout_data['pie_chart_type'] == '3D'):
            if not self.layout_data['pie_sectors_explode_width']:
                self.layout_data['pie_sectors_explode_width'] = 0
            # reduce border width for small images
            if self.settings['type'] != 'large':
                #self.layout_data['pie_sectors_explode_width'] = self.layout_data['pie_sectors_explode_width'] / 2
                self.layout_data['pie_sectors_explode_width'] /= 2

            c.setExplode(-1, self.layout_data['pie_sectors_explode_width'])
            self.layout_data['pie_chart_sector_border_width'] = 0
            self.layout_data['sector_edge_line_color'] = ''

        # sector border(edge) color
        if self.layout_data['sector_edge_line_color']:
            # use specified color
            edge_line_color = FontManager.get_db_color(self.layout_data['sector_edge_line_color'])
        else:
            # use sector color
            edge_line_color = SameAsMainColor

        # sector border(edge) width
        if not self.layout_data['pie_chart_sector_border_width']:
            self.layout_data['pie_chart_sector_border_width'] = 0

        # reduce border with for small images
        if self.settings['type'] != 'large':
            #self.layout_data['pie_chart_sector_border_width'] = self.layout_data['pie_chart_sector_border_width'] / 2
            self.layout_data['pie_chart_sector_border_width'] /= 2

        c.setSectorStyle(shading, edge_line_color, self.layout_data['pie_chart_sector_border_width'])

        # number of digits after point for % value
        if not self.layout_data['sector_value_pct_precision_digits']:
            self.layout_data['sector_value_pct_precision_digits'] = 0

        # label color
        if self.layout_data['pie_chart_sector_value_font_color']:
            self.layout_data['pie_chart_sector_value_font_color'] = FontManager.get_db_color(self.layout_data['pie_chart_sector_value_font_color'])
        else:
            self.layout_data['pie_chart_sector_value_font_color'] = None

        # label format
        if self.layout_data['show_sector_value_ind'] == 'Y':
            # show label, percentage and value in label
            c.addExtraField(self.chart_data['formatted_data'])
            label_format = "<*block*><*font=%s,size=%s,color=%s*>{label}<*br*>{field0} ({percent|%s}%%)<*/*>"
        else:
            # show label and percentage in label
            label_format = "<*block*><*font=%s,size=%s,color=%s*>{label}<*br*>({percent|%s}%%)<*/*>"

        # sector value font size
        if not self.layout_data['pie_chart_sector_value_font_size'] or self.layout_data['pie_chart_sector_value_font_size'] < 3:
            self.layout_data['pie_chart_sector_value_font_size'] = 8

        #reduce label font size for preview images
        if self.settings['type'] == 'preview':
            self.layout_data['pie_chart_sector_value_font_size'] = 8

        if self.layout_data['pie_chart_sector_value_font_color'] is not None:
            # if label color is specified, use it for all labels
            c.setLabelFormat(label_format % (
                                    FontManager.get_db_font(self.layout_data['pie_chart_sector_value_font']),
                                    self.layout_data['pie_chart_sector_value_font_size'],
                                    self.layout_data['pie_chart_sector_value_font_color'],
                                    self.layout_data['sector_value_pct_precision_digits']))
        else:
            # if label color is not specified, use color of sector
            for i, color in enumerate(self.chart_data['colors']):
                c.sector(i).setLabelFormat(label_format % (
                                    FontManager.get_db_font(self.layout_data['pie_chart_sector_value_font']),
                                    self.layout_data['pie_chart_sector_value_font_size'],
                                    hex(color),
                                    self.layout_data['sector_value_pct_precision_digits']))

        # draw annotations
        if self.settings['type'] == 'large':
            c.layout()
            index = 1
            for i, header in enumerate(self.chart_data['formatted_header']):
                if self.chart_data['annotations'][header]:
                    sector = c.getSector(i)
                    coord_string = sector.getLabelCoor()

                    content = urllib.unquote(coord_string)

                    res = re.findall(r'shape="rect" coords="(.+?),(.+?),(.+?),(.+?)"', content)
                    coords = res[0]

                    x_coord = (int(coords[2]) + int(coords[0])) / 2
                    y_coord = int(coords[1]) + 25

                    annot_marker = "<*img=%s*>" % self.config.resource_file('annotation.png')
                    c.addText(x_coord, y_coord, annot_marker, "", 0, 0x0, BottomCenter)
                    c.addText(x_coord, y_coord - 32, str(index), FontManager.get_default_bold_font(), 10, 0xffffff, BottomCenter)
                    for annot in self.chart_data['annotations'][header]:
                        annot['index'] = index
                        annot['shape'] = 'rect'
                        annot['chart_by_column_value'] = header
                        annot['chart_element_identifier'] = ''
                        annot['value'] = self.chart_data['formatted_data'][self.chart_data['header'].index(header)]
                        marker_coors = [x_coord - 9, y_coord - 47, x_coord + 10, y_coord - 29]
                        annot['coords'] = ','.join(map(str, marker_coors))
                        annot['annotation_interval'] = 'point'
                        annot['start_time'] = ''
                        annot['finish_time'] = ''
                        annot['raw_start_time'] = ''
                        annot['raw_finish_time'] = ''
                        self.annotations_map.append(annot)
                    index += 1

        filename = ''
        if self.settings['type'] == 'large':
            filename = self._jfile.get_chart_file_name(self.report_data_set_chart_id, self.report_data_set_instance_id)
        elif self.settings['type'] == 'thumbnail':
            filename = self._jfile.get_thumbnail_file_name()
        elif self.settings['type'] == 'preview':
            filename = self._jfile.get_preview_file_name()

        if not c.makeChart(filename):
            raise Exception("ChartDirector cannot create image file %s for chart %s." % (filename, self.report_data_set_chart_id))
        self.file_man.change_perm(filename)

        self.chart_object = c

    def create_map_file(self):
        map = self.get_parsed_map()
        data = list()
        for v in map:
            data.append({'shape': v['shape'],
                        'coords': v['coords'],
                        'name': v['name'],
                        'meas_index': v['meas_index'],
                        'raw_meas_index': '',
                        'value': v['value']})

        self._jfile.make_chart_file(data, self.annotations_map, self.report_data_set_chart_id, self.report_data_set_instance_id, 'pie', 'non date')

    def get_parsed_map(self):
        content = self.chart_object.getHTMLImageMap('url', 'sector={sector}&label={label}&percent={percent}')
        content = urllib.unquote(content)
        res = re.findall(r'(<area shape="poly" coords="(.+?)" href="url\?sector=(.+?)&label=(.+?)&percent=(.+?)">)', content)
        result = list({'shape': "poly",
                       'coords': v[1],
                       'name': self.chart_data['formatted_header'][int(v[2])],
                       'meas_index': self.chart_data['formatted_data'][int(v[2])],
                       'value': v[4] + '%'} for v in res)
        return result