Changeset 97:a6d5014aea9c

Show
Ignore:
Timestamp:
01/22/09 04:39:36 (14 months ago)
Author:
Ga?tan de Menten <ged@…>
Branch:
default
Message:

- moved rowspanned column loops handling to a separate method
- prefixed variables added to the context for column looping by "relatorio"
- comments updated
- misc cleanup

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • relatorio/templates/opendocument.py

    r96 r97  
    274274        table_row_tag = '{%s}table-row' % table_namespace 
    275275        table_cell_tag = '{%s}table-cell' % table_namespace 
    276         table_cov_cell_tag = '{%s}covered-table-cell' % table_namespace 
    277276        table_num_col_attr = '{%s}number-columns-repeated' % table_namespace 
    278277        table_name_attr = '{%s}name' % table_namespace 
    279         table_rowspan_attr = '{%s}number-rows-spanned' % table_namespace 
    280278 
    281279        office_name = '{%s}value' % self.namespaces['office'] 
     
    284282        py_namespace = self.namespaces['py'] 
    285283        py_attrs_attr = '{%s}attrs' % py_namespace 
    286         genshi_replace = '{%s}replace' % py_namespace 
     284        py_replace = '{%s}replace' % py_namespace 
    287285 
    288286        repeat_tag = '{%s}repeat' % self.namespaces['relatorio'] 
     
    321319                outermost_c_ancestor = c_ancestors[-1] 
    322320 
    323                 # handle horizontal repetition (over columns) 
     321                # handle horizontal repetitions (over columns) 
    324322                if directive == "for" and ancestor.tag == table_row_tag: 
    325323                    self.has_col_loop = True 
     
    337335                    # operations, but a unique id within the table is required 
    338336                    # to support nested column repetition 
    339                     attr_value = "__reset_col_count(%d)" % loop_id 
    340                     ancestor.attrib[py_attrs_attr] = attr_value 
     337                    ancestor.attrib[py_attrs_attr] = \ 
     338                        "__relatorio_reset_col_count(%d)" % loop_id 
    341339 
    342340                    # 2) add increment code (through a py:attrs attribute) on 
     
    345343                    enclosed_cell = outermost_o_ancestor.getnext() 
    346344                    assert enclosed_cell.tag == table_cell_tag 
    347                     attr_value = "__inc_col_count(%d)" % loop_id 
    348                     enclosed_cell.attrib[py_attrs_attr] = attr_value 
     345                    enclosed_cell.attrib[py_attrs_attr] = \ 
     346                        "__relatorio_inc_col_count(%d)" % loop_id 
    349347 
    350348                    # 3) add "store count" code as a py:replace node, as the 
    351349                    #    last child of the row 
    352                     attr_value = "__store_col_count(%d, %r)" % (loop_id, 
    353                                                                table_name) 
    354                     replace_node = EtreeElement('{%s}replace' % py_namespace, 
     350                    attr_value = "__relatorio_store_col_count(%d, %r)" \ 
     351                                 % (loop_id, table_name) 
     352                    replace_node = EtreeElement(py_replace, 
    355353                                                attrib={'value': attr_value}, 
    356354                                                nsmap=self.namespaces) 
     
    369367 
    370368                    # check whether or not the opening tag spans several rows 
    371                     o_node_attrs = outermost_o_ancestor.attrib 
    372                     if table_rowspan_attr in o_node_attrs: 
    373                         rows_spanned = int(o_node_attrs[table_rowspan_attr]) 
    374  
    375                         # a_val == "target in iterable" 
    376                         target, iterable = a_val.split(' in ', 1) 
    377                         temp_var = "temp%d" % id(outermost_o_ancestor) 
    378                         # I need to get "temp_iterable = list(iterable)" 
    379                         vars = "%s = list(%s)" % (temp_var, iterable.strip()) 
    380                         # transform a_val to "target in temp_iterable" 
    381                         a_val = "%s in %s" % (target, temp_var) 
    382  
    383                         with_node = EtreeElement('{%s}with' % py_namespace, 
    384                                                  attrib={"vars": vars}, 
    385                                                  nsmap=self.namespaces) 
    386  
    387                         # if so, we need to replace the corresponding cell on 
    388                         # the next line (a covered-table-cell) by a duplicate 
    389                         # py:for node, delete the covered-table-cell 
    390                         # corresponding to the /for, and move all cells between 
    391                         # them into the py:for node 
    392                         row_node = outermost_o_ancestor.getparent() 
    393                         row_node.addprevious(with_node) 
    394                         rows_to_wrap = [row_node] 
    395  
    396                         assert row_node.tag == table_row_tag 
    397                         next_rows = row_node.itersiblings(table_row_tag) 
    398                         for row_idx in range(rows_spanned-1): 
    399                             next_row_node = next_rows.next() 
    400                             rows_to_wrap.append(next_row_node) 
    401                             first = next_row_node[opening_pos] 
    402                             last = next_row_node[closing_pos] 
    403                             assert first.tag == table_cov_cell_tag 
    404                             assert last.tag == table_cov_cell_tag 
    405  
    406                             # execute moves (add a <py:for> node around 
    407                             # the column definitions nodes) 
    408                             tag = '{%s}%s' % (py_namespace, directive) 
    409                             for_node = EtreeElement(tag, 
    410                                                     attrib={attr: a_val}, 
    411                                                     nsmap=self.namespaces) 
    412                             wrap_nodes_between(first, last, for_node) 
    413  
    414                         for node in rows_to_wrap: 
    415                             with_node.append(node) 
     369                    a_val = self._handle_row_spanned_column_loops(parsed, 
     370                                outermost_o_ancestor, opening_pos, closing_pos) 
    416371 
    417372                    # check if this table's headers were already processed 
     
    427382                                'same columns across all lines.') 
    428383                    else: 
    429                         # compute splits: we need to split any column header 
    430                         # which is repeated so many times that it encompass 
    431                         # any of the column headers that we need to repeat 
     384                        # compute splits: oo collapses the headers of adjacent 
     385                        # columns which use the same style. We need to split 
     386                        # any column header which is repeated so many times 
     387                        # that it encompasses any of the column headers that 
     388                        # we need to repeat 
    432389                        to_split = [] 
    433390                        idx = 0 
     
    450407                            table_node[tag_pos:tag_pos+1] = new_tags 
    451408 
    452                         # compute moves and deletes: the column headers 
    453                         # corresponding to the opening and closing tags 
    454                         # need to be deleted. The column headers between them 
    455                         # need to be moved to inside the "repeat" tag (which 
    456                         # is to be created later). 
     409                        # recompute the list of column headers as it could 
     410                        # have changed. 
    457411                        coldefs = list(table_node.iterchildren(table_col_tag)) 
     412 
     413                        # compute the column header nodes corresponding to 
     414                        # the opening and closing tags. 
    458415                        first = table_node[opening_pos] 
    459416                        last = table_node[closing_pos] 
    460417 
    461                         # execute moves (add a <relatorio:repeat> node around 
    462                         # the column definitions nodes) 
     418                        # add a <relatorio:repeat> node around the column 
     419                        # definitions nodes 
    463420                        attribs = { 
    464421                           "opening": str(opening_pos), 
     
    485442            else: 
    486443                # It's not a genshi statement it's a python expression 
    487                 r_node.attrib[genshi_replace] = expr 
     444                r_node.attrib[py_replace] = expr 
    488445                parent = r_node.getparent().getparent() 
    489446                if parent is None or parent.tag != table_cell_tag: 
     
    497454                parent.attrib.pop(office_valuetype, None) 
    498455                parent.attrib.pop(office_name, None) 
     456 
     457    def _handle_row_spanned_column_loops(self, parsed, outer_o_node, 
     458                                         opening_pos, closing_pos): 
     459        _, directive, attr, a_val = parsed 
     460        table_rowspan_attr = '{%s}number-rows-spanned' \ 
     461                             % self.namespaces['table'] 
     462        rows_spanned = int(outer_o_node.attrib.get(table_rowspan_attr, 1)) 
     463 
     464        # checks wether there is a (meaningful) rowspan 
     465        if rows_spanned == 1: 
     466            return a_val 
     467 
     468        py_namespace = self.namespaces['py'] 
     469        table_namespace = self.namespaces['table'] 
     470        table_row_tag = '{%s}table-row' % table_namespace 
     471        table_cov_cell_tag = '{%s}covered-table-cell' % table_namespace 
     472 
     473        # if so, we need to: 
     474 
     475        # 1) create a with node to define a temporary variable 
     476        temp_var = "__relatorio_temp%d" % id(outer_o_node) 
     477        # a_val == "target in iterable" 
     478        target, iterable = a_val.split(' in ', 1) 
     479        vars = "%s = list(%s)" % (temp_var, iterable.strip()) 
     480        with_node = EtreeElement('{%s}with' % py_namespace, 
     481                                 attrib={"vars": vars}, 
     482                                 nsmap=self.namespaces) 
     483 
     484        # 2) transform a_val to use that temporary variable 
     485        a_val = "%s in %s" % (target, temp_var) 
     486 
     487        # 3) wrap the corresponding cells on the next row(s) 
     488        #    (those should be covered-table-cell) inside a 
     489        #    duplicate py:for node (looping on the temporary 
     490        #    variable). 
     491        row_node = outer_o_node.getparent() 
     492        row_node.addprevious(with_node) 
     493        rows_to_wrap = [row_node] 
     494        assert row_node.tag == table_row_tag 
     495        next_rows = row_node.itersiblings(table_row_tag) 
     496        for row_idx in range(rows_spanned-1): 
     497            next_row_node = next_rows.next() 
     498            rows_to_wrap.append(next_row_node) 
     499            # compute the start and end nodes 
     500            first = next_row_node[opening_pos] 
     501            last = next_row_node[closing_pos] 
     502            assert first.tag == table_cov_cell_tag 
     503            assert last.tag == table_cov_cell_tag 
     504            # wrap them 
     505            tag = '{%s}%s' % (py_namespace, directive) 
     506            for_node = EtreeElement(tag, 
     507                                    attrib={attr: a_val}, 
     508                                    nsmap=self.namespaces) 
     509            wrap_nodes_between(first, last, for_node) 
     510 
     511        # 4) wrap all the corresponding rows indide the "with" 
     512        #    node 
     513        for node in rows_to_wrap: 
     514            with_node.append(node) 
     515        return a_val 
    499516 
    500517    def _handle_images(self, tree): 
     
    527544 
    528545        counter = ColumnCounter() 
    529         kwargs['__reset_col_count'] = counter.reset 
    530         kwargs['__inc_col_count'] = counter.inc 
    531         kwargs['__store_col_count'] = counter.store 
     546        kwargs['__relatorio_reset_col_count'] = counter.reset 
     547        kwargs['__relatorio_inc_col_count'] = counter.inc 
     548        kwargs['__relatorio_store_col_count'] = counter.store 
    532549 
    533550        stream = super(Template, self).generate(*args, **kwargs)