Skip to content
Snippets Groups Projects
xmlview_widgets.py 6.34 KiB
Newer Older
  • Learn to ignore specific revisions
  • Benoit Favre's avatar
    Benoit Favre committed
    import animate
    
    
    Benoit Favre's avatar
    Benoit Favre committed
    from gi.repository import GObject, Gtk, Pango, Gdk
    from xml.etree import ElementTree as ET
    
    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')
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.title = Gtk.EventBox()
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.label = Gtk.Label('Section %s' % self.name)
            self.label.get_style_context().add_class('section-title')
    
    Benoit Favre's avatar
    Benoit Favre committed
            self.title.add(self.label)
            self.title.connect('button-press-event', self.clicked)
            self.handler = None
            #cursor = Gdk.Cursor(Gdk.CursorType.HAND1)
            #self.label.get_window().set_cursor(cursor)
            self.pack_start(self.title, True, True, 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)))
                self.pack_start(self.sequences[-1], True, True, 5)
                num += 1
    
    
    Benoit Favre's avatar
    Benoit Favre committed
        def highlight(self, active=True):
            if active:
                self.label.get_style_context().remove_class('section-title')
                self.label.get_style_context().add_class('selected-section-title')
                self.get_style_context().add_class('selected-section-body')
                self.get_style_context().remove_class('section-body')
            else:
                self.label.get_style_context().remove_class('selected-section-title')
                self.label.get_style_context().add_class('section-title')
                self.get_style_context().remove_class('selected-section-body')
                self.get_style_context().add_class('section-body')
    
        def clicked(self, widget, event):
            if self.handler:
                self.handler(int(self.name) - 1)
    
        def set_handler(self, handler):
            self.handler = handler
    
    
    
    Benoit Favre's avatar
    Benoit Favre committed
    class Sequence(Gtk.VBox):
        def __init__(self, sequence, name):
            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')
            self.pack_start(self.label, True, True, 5)
    
            self.lines = []
    
    Benoit Favre's avatar
    Benoit Favre committed
            elements = []
            for line in sequence.text.split('\n'):
    
    Benoit Favre's avatar
    Benoit Favre committed
                line = line.strip()
                if line != '':
    
    Benoit Favre's avatar
    Benoit Favre committed
                    elements.append(Text(line))
                if len(elements) > 0:
                    self.lines.append(Line(elements))
    
    Benoit Favre's avatar
    Benoit Favre committed
                    self.pack_start(self.lines[-1], True, True, 5)
    
    Benoit Favre's avatar
    Benoit Favre committed
                elements = []
            for node in sequence:
                if node.tag == 'keyword':
                    text = str(node.text).strip()
                    if node.get('action').strip() != '':
                        elements.append(Keyword(text, node.get('action'), node.get('lang')))
                    else:
                        elements.append(Text(text))
                for line in node.tail.split('\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], True, True, 5)
                    elements = []
            if len(elements) > 0:
                self.lines.append(Line(elements))
                self.pack_start(self.lines[-1], True, True, 5)
    
    class Line(Gtk.HBox):
        def __init__(self, elements):
    
    Benoit Favre's avatar
    Benoit Favre committed
            super(Line, self).__init__()
    
    Benoit Favre's avatar
    Benoit Favre committed
            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')
    
    Benoit Favre's avatar
    Benoit Favre committed
        def set_handler(self, handler):
            for element in self.elements:
                if hasattr(element, 'set_handler'):
                    element.set_handler(handler)
    
    Benoit Favre's avatar
    Benoit Favre committed
        def highlight(self, active=True):
            if active:
    
                self.label.get_style_context().add_class('highlighted')
    
                self.label.get_style_context().remove_class('highlighted')
    
    Benoit Favre's avatar
    Benoit Favre committed
    class Keyword(Gtk.Label):
        def __init__(self, text, action, lang):
            super(Keyword, self).__init__()
            self.action = action
            self.lang = lang
            text = '\n'.join([x.strip() for x in text.split('\n')])
            self.set_markup(text + ' [<a href="%s">%s</a>] ' % (action, action))
            self.get_style_context().add_class('keyword')
            self.connect('activate-link', self.link_clicked)
            self.handler = None
    
        def set_handler(self, handler):
            self.handler = handler
    
        def link_clicked(self, widget, uri):
            if self.handler:
                self.handler(uri)
            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.last_section = None
    
            self.connect('scroll-event', lambda widget, event: animate.cancel())
    
    Benoit Favre's avatar
    Benoit Favre committed
    
        def get_view(self):
            return self
    
        def parse_xml(self, filename):
            self.sections = []
            root = ET.parse(filename)
            vbox = Gtk.VBox()
            vbox.get_style_context().add_class('xmlview')
            for section in root.findall(".//section"):
                self.sections.append(Section(section))
                vbox.pack_start(self.sections[-1], True, True, 5)
            return vbox
    
    
    Benoit Favre's avatar
    Benoit Favre committed
        def set_action_clicked_handler(self, handler):
            for line in self.get_line_iterator():
                line.set_handler(handler)
    
    
        def get_line_iterator(self):
            for section in self.sections:
                for sequence in section.sequences:
                    for line in sequence.lines:
                        yield line
    
    Benoit Favre's avatar
    Benoit Favre committed
        def highlight_section(self, section):
            if section < 1 or section > len(self.sections):
                print "invalid section", section
            else:
                for current in range(len(self.sections)):
                    self.sections[current].highlight(current == section - 1)
                animate.scroll_to(self, self.sections[section - 1])