Skip to content
Snippets Groups Projects
xmlview.py 8.47 KiB
Newer Older
  • Learn to ignore specific revisions
  • Benoit Favre's avatar
    Benoit Favre committed
    import animate, actions
    
    from gi.repository import GObject, Gtk, Pango, Gdk
    
    Benoit Favre's avatar
    Benoit Favre committed
    from xml.etree import ElementTree as ET
    
    
    Benoit Favre's avatar
    Benoit Favre committed
    class Section(Gtk.VBox):
        def __init__(self, section):
            super(Section, self).__init__()
            self.name = section.get('id')
            self.get_style_context().add_class('section-body')
            self.title = Gtk.Label()
            self.title.set_markup('Section [<a href="%s">%s</a>]' % (self.name, self.name))
            self.title.get_style_context().add_class('section-title')
            self.listeners = []
            self.title.connect('activate-link', self.link_clicked)
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.pack_start(self.title, False, False, 5)
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.sequences = []
    
            num = 1
            for sequence in section.findall('./sequence'):
    
                self.sequences.append(Sequence(sequence, section.get('id') + '.' + str(num), int(self.name) - 1))
    
    Benoit Favre's avatar
    Benoit Favre committed
                self.pack_start(self.sequences[-1], False, False, 5)
    
    Benoit Favre's avatar
    Benoit Favre committed
                num += 1
    
        def highlight(self, active=True):
            if active:
                self.get_style_context().add_class('selected-section')
                self.get_style_context().remove_class('section-body')
            else:
                self.get_style_context().remove_class('selected-section')
                self.get_style_context().add_class('section-body')
    
    Benoit Favre's avatar
    Benoit Favre committed
        def link_clicked(self, widget, uri):
            for listener in self.listeners:
                listener(self)
            return True
    
        def add_listener(self, listener):
            self.listeners.append(listener)
    
    
    class Sequence(Gtk.VBox):
    
        def __init__(self, sequence, name, section):
    
    Benoit Favre's avatar
    Benoit Favre committed
            super(Sequence, self).__init__()
            self.name = name
            self.get_style_context().add_class('sequence-body')
            self.label = Gtk.Label('Sequence %s' % name)
            self.label.get_style_context().add_class('sequence-title')
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.pack_start(self.label, False, False, 5)
    
    Benoit Favre's avatar
    Benoit Favre committed
    
            self.lines = []
    
    Benoit Favre's avatar
    Benoit Favre committed
    
            line = ''
            for c in sequence.text:
                if c == '\n':
                    line = line.strip()
                    if line != '':
                        self.lines.append(Line([Text(line)]))
                        self.pack_start(self.lines[-1], False, False, 5)
                    line = ''
                else:
                    line += c
    
    Benoit Favre's avatar
    Benoit Favre committed
            elements = []
    
    Benoit Favre's avatar
    Benoit Favre committed
            for node in sequence:
    
    Benoit Favre's avatar
    Benoit Favre committed
                line = line.strip()
                if line != '':
                    elements.append(Text(line))
                if node.tag == 'keyword':
                    text = str(node.text).strip()
                    if node.get('action').strip() != '':
    
                        elements.append(Keyword(text, node.get('action'), node.get('lang'), section))
    
    Benoit Favre's avatar
    Benoit Favre committed
                    else:
                        elements.append(Text(text))
    
    Benoit Favre's avatar
    Benoit Favre committed
                line = ''
                for c in node.tail:
                    if c == '\n':
                        line = line.strip()
                        if line != '':
                            elements.append(Text(line))
                        if len(elements) > 0:
                            self.lines.append(Line(elements))
                            self.pack_start(self.lines[-1], False, False, 5)
                            elements = []
                        line = ''
                    else:
                        line += c
            line = line.strip()
            if line != '':
                elements.append(Text(line))
    
    Benoit Favre's avatar
    Benoit Favre committed
            if len(elements) > 0:
                self.lines.append(Line(elements))
    
    Benoit Favre's avatar
    Benoit Favre committed
                self.pack_start(self.lines[-1], False, False, 5)
    
    Benoit Favre's avatar
    Benoit Favre committed
    
    class Line(Gtk.HBox):
        def __init__(self, elements):
            super(Line, self).__init__()
            self.pack_start(Gtk.Label('   '), False, False, 0)
            for element in elements:
                self.pack_start(element, False, False, 0)
            self.elements = elements
            self.get_style_context().add_class('text-line')
        
    
        #def highlight(self, active=True, scrollable=None):
        #    if active:
        #        self.label.get_style_context().add_class('highlighted')
        #    else:
        #        self.label.get_style_context().remove_class('highlighted')
        #    if scrollable != None:
        #        animate.scroll_to(scrollable, self)
    
    Benoit Favre's avatar
    Benoit Favre committed
    
    class Keyword(Gtk.Label):
    
        def __init__(self, text, action, lang, section):
    
    Benoit Favre's avatar
    Benoit Favre committed
            super(Keyword, self).__init__()
    
            self.section = section
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.action = action
            self.lang = lang
    
            self.text = '\n'.join([x.strip() for x in text.split('\n')])
            self.set_markup(self.text + ' [<a href="%s">%s</a>] ' % (action, action))
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.get_style_context().add_class('keyword')
            self.connect('activate-link', self.link_clicked)
    
            self.listeners = []
            self.num = 0
    
        def highlight(self, active=True, scrollable=None):
            if active:
                self.get_style_context().remove_class('keyword')
                self.get_style_context().add_class('keyword-highlighted')
                if scrollable != None:
                    animate.scroll_to(scrollable, self)
            else:
                self.get_style_context().add_class('keyword')
                self.get_style_context().remove_class('keyword-highlighted')
    
        def add_listener(self, listener):
            self.listeners.append(listener)
    
    Benoit Favre's avatar
    Benoit Favre committed
    
    
        def set_num(self, num):
            self.num = num
    
    Benoit Favre's avatar
    Benoit Favre committed
        def link_clicked(self, widget, uri):
    
            actions.perform_action(actions.Action(uri, keyword=widget), False)
    
            for listener in self.listeners:
                listener(self, uri, self.num)
    
    Benoit Favre's avatar
    Benoit Favre committed
            return True
    
    class Text(Gtk.Label):
        def __init__(self, text):
            super(Text, self).__init__()
            text = '\n'.join([x.strip() for x in text.split('\n')])
            self.set_text(text + ' ')
            self.get_style_context().add_class('text')
    
    Benoit Favre's avatar
    Benoit Favre committed
    
    class XmlView(Gtk.ScrolledWindow):
        def __init__(self, filename):
            super(XmlView, self).__init__()
            self.sections = []
            self.words = []
    
            self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.ALWAYS)
    
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.vbox = self.parse_xml(filename)
            self.add_with_viewport(self.vbox)
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.connect('scroll-event', lambda widget, event: animate.cancel())
    
    Benoit Favre's avatar
    Benoit Favre committed
            for section in self.sections:
                section.add_listener(self.section_clicked)
            self.set_section(0)
    
            self.keywords = []
            for section in self.sections:
                for sequence in section.sequences:
                    for line in sequence.lines:
                        for element in line.elements:
                            if hasattr(element, 'action'):
    
                                element.set_num(len(self.keywords))
    
                                self.keywords.append(element)
            self.last_highlighted = -1
    
            self.follow = True
    
    Benoit Favre's avatar
    Benoit Favre committed
        def get_view(self):
            return self
    
        def parse_xml(self, filename):
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.sections = []
    
    Benoit Favre's avatar
    Benoit Favre committed
            root = ET.parse(filename)
    
    Benoit Favre's avatar
    Benoit Favre committed
            vbox = Gtk.VBox()
            vbox.get_style_context().add_class('xmlview')
    
    Benoit Favre's avatar
    Benoit Favre committed
            for section in root.findall(".//section"):
    
    Benoit Favre's avatar
    Benoit Favre committed
                self.sections.append(Section(section))
                vbox.pack_start(self.sections[-1], True, True, 5)
            return vbox
    
    
    Benoit Favre's avatar
    Benoit Favre committed
        def num_sections(self):
            return len(self.sections)
    
    
    Benoit Favre's avatar
    Benoit Favre committed
        def get_section(self):
            return int(self.current_section.name) - 1
    
        def set_section(self, section_id, scroll=True):
            self.current_section = self.sections[section_id]
            for section in self.sections:
                section.highlight(self.current_section is section)
            if scroll:
                animate.scroll_to(self, self.current_section)
    
        def section_clicked(self, current):
            self.set_section(int(current.name) - 1)
    
            for keyword in self.keywords:
                keyword.highlight(False)
    
    Benoit Favre's avatar
    Benoit Favre committed
    
        def highlight(self, action):
    
            if hasattr(action, 'keyword'):
    
                if self.follow:
                    action.keyword.highlight(True, self)
                else:
                    action.keyword.highlight(True)
    
            elif hasattr(action, 'action_id'):
    
                #start = min([x.num for x in self.keywords if x.section == self.get_section()])
                start = 0
                action_id = action.action_id + start
                if self.follow:
                    self.keywords[action_id].highlight(True, self)
                else:
                    self.keywords[action_id].highlight(True)
    
            else:
                i = self.last_highlighted + 1
                while i < len(self.keywords):
                    if self.keywords[i].action == action.text:
    
                        if self.follow:
                            self.keywords[i].highlight(True, self)
                        else:
                            self.keywords[i].highlight(True)
    
                        self.last_highlighted = i
    
                        #print 'HIGHLIGHT:', action.text, self.last_highlighted