Logo Search packages:      
Sourcecode: zim version File versions  Download package

def zim::gui::pageview::TextBuffer::get_parsetree (   self,
  bounds = None,
  raw = False 
)

Returns a parse tree for the page contents.

If 'raw' is True you get a tree that is _not_ nicely cleaned up.
This raw tree should result in the exact same contents in the buffer
when reloaded so it can be used for e.g. by the undostack manager.
Also this feature allows for testability of the cleanup routines.
Raw parsetrees have an attribute to flag them as a raw tree, so on
insert we can make sure they are inserted in the same way.

Definition at line 1052 of file pageview.py.

01052                                                      :
            '''Returns a parse tree for the page contents.

            If 'raw' is True you get a tree that is _not_ nicely cleaned up.
            This raw tree should result in the exact same contents in the buffer
            when reloaded so it can be used for e.g. by the undostack manager.
            Also this feature allows for testability of the cleanup routines.
            Raw parsetrees have an attribute to flag them as a raw tree, so on
            insert we can make sure they are inserted in the same way.
            '''
            if bounds is None:
                  start, end = self.get_bounds()
            else:
                  start, end = bounds

            if raw:
                  builder = TreeBuilder()
                  builder.start('zim-tree', {'raw': True})
            else:
                  builder = ParseTreeBuilder()
                  builder.start('zim-tree')

            open_tags = []
            def set_tags(iter, tags):
                  '''This function changes the parse tree based on the TextTags in
                  effect for the next section of text.
                  '''
                  # We assume that by definition we only get one tag for each tag
                  # type and that we get tags in such an order that the one we get
                  # first should be closed first while closing later ones breaks the
                  # ones before. This is enforced using the priorities of the tags
                  # in the TagTable.
                  tags.sort(key=lambda tag: tag.get_priority(), reverse=True)

                  i = 0
                  while i < len(tags) and i < len(open_tags) \
                  and tags[i] == open_tags[i][0]:
                        i += 1

                  # so i is the breakpoint where new stack is different
                  while len(open_tags) > i:
                        builder.end(open_tags[-1][1])
                        open_tags.pop()

                  # Convert some tags on the fly
                  if tags:
                        for tag in tags[i:]:
                              t, attrib = tag.zim_tag, tag.zim_attrib
                              if t == 'indent':
                                    bullet = self._get_bullet_at_iter(iter)
                                    if bullet:
                                          t = 'li'
                                          attrib = attrib.copy() # break ref with tree
                                          attrib['bullet'] = bullet
                                          self._iter_forward_past_bullet(iter, bullet)
                                    elif not raw and not iter.starts_line():
                                          # Indent not visible if it does not start at begin of line
                                          t = '_ignore_'
                                    else:
                                          t = 'p'
                              elif t == 'pre' and not raw and not iter.starts_line():
                                    # Without indenting 'pre' looks the same as 'code'
                                    # Prevent turning into a seperate paragraph here
                                    t = 'code'
                              elif t == 'link':
                                    attrib = self.get_link_data(iter)
                                    assert attrib['href'], 'Links should have a href'
                              builder.start(t, attrib)
                              open_tags.append((tag, t))

            def break_tags(type):
                  # Forces breaking the stack of open tags on the level of 'tag'
                  # The next set_tags() will re-open any tags that are still open
                  i = 0
                  for i in range(len(open_tags)):
                        if open_tags[i][1] == type:
                              break

                  # so i is the breakpoint
                  while len(open_tags) > i:
                        builder.end(open_tags[-1][1])
                        open_tags.pop()

            # And now the actual loop going through the buffer
            iter = start.copy()
            while iter.compare(end) == -1:
                  pixbuf = iter.get_pixbuf()
                  if pixbuf:
                        if pixbuf.zim_type == 'icon':
                              # Reset all tags - and let set_tags parse the bullet
                              if open_tags:
                                    break_tags(open_tags[0][1])
                              set_tags(iter, filter(_is_indent_tag, iter.get_tags()))
                        else:
                              pass # reset all tags except indenting
                              set_tags(iter, filter(_is_indent_tag, iter.get_tags()))

                        pixbuf = iter.get_pixbuf() # iter may have moved
                        if pixbuf is None:
                              continue

                        if pixbuf.zim_type == 'icon':
                              logger.warn('BUG: Checkbox outside of indent ?')
                        elif pixbuf.zim_type == 'image':
                              attrib = pixbuf.zim_attrib.copy()
                              if 'alt' in attrib:
                                    text = attrib.pop('alt') or ''
                                    builder.start('img', attrib)
                                    builder.data(text)
                                    builder.end('img')
                              else:
                                    builder.start('img', attrib)
                                    builder.end('img')
                        else:
                              assert False, 'BUG: unknown pixbuf type'

                        iter.forward_char()
                  # FUTURE: elif embedded widget
                  else:
                        # Set tags
                        copy = iter.copy()
                        set_tags(iter, filter(_is_zim_tag, iter.get_tags()))
                        if not iter.equal(copy): # iter moved
                              continue

                        # Find biggest slice without tags being toggled
                        bound = iter.copy()
                        toggled = []
                        while not toggled:
                              if not bound.is_end() and bound.forward_to_tag_toggle(None):
                                    # For some reason the not is_end check is needed
                                    # to prevent an odd corner case infinite loop
                                    toggled = filter(_is_zim_tag,
                                          bound.get_toggled_tags(False)
                                          + bound.get_toggled_tags(True) )
                              else:
                                    bound = end.copy() # just to be sure..
                                    break

                        # But limit slice to first pixbuf
                        # FUTURE: also limit slice to any embeddded widget
                        text = iter.get_slice(bound)
                        if PIXBUF_CHR in text:
                              i = text.index(PIXBUF_CHR)
                              bound = iter.copy()
                              bound.forward_chars(i)
                              text = text[:i]

                        # And limit to end
                        if bound.compare(end) == 1:
                              bound = end.copy()
                              text = iter.get_slice(end)

                        if filter(lambda t: t[1] == 'li', open_tags) \
                        and bound.get_line() != iter.get_line():
                              # And limit bullets to a single line
                              orig = bound
                              bound = iter.copy()
                              bound.forward_line()
                              assert bound.compare(orig) < 1
                              text = iter.get_slice(bound).rstrip('\n')
                              builder.data(text)
                              break_tags('li')
                              builder.data('\n') # add to tail
                        else:
                              # Else just inser text we got
                              builder.data(text)

                        iter = bound

            # close any open tags
            set_tags(end, [])

            builder.end('zim-tree')
            tree = ParseTree(builder.close())
            tree.encode_urls()
            #~ print tree.tostring()
            return tree

      def select_line(self):


Generated by  Doxygen 1.6.0   Back to index