import animate, actions 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') 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) self.pack_start(self.title, False, False, 5) self.sequences = [] num = 1 for sequence in section.findall('./sequence'): self.sequences.append(Sequence(sequence, section.get('id') + '.' + str(num), int(self.name) - 1)) self.pack_start(self.sequences[-1], False, False, 5) 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') 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): 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, False, False, 5) self.lines = [] 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 elements = [] for node in sequence: 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)) else: elements.append(Text(text)) 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)) if len(elements) > 0: self.lines.append(Line(elements)) self.pack_start(self.lines[-1], False, False, 5) 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) class Keyword(Gtk.Label): def __init__(self, text, action, lang, section): super(Keyword, self).__init__() self.section = section 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)) 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) def set_num(self, num): self.num = num 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) 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') 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) self.vbox = self.parse_xml(filename) self.add_with_viewport(self.vbox) self.connect('scroll-event', lambda widget, event: animate.cancel()) 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 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 def num_sections(self): return len(self.sections) 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) 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 break i += 1