Implement serialization/deserialization
This commit is contained in:
parent
490c146da9
commit
401dca032c
103
chat/richtext.py
103
chat/richtext.py
@ -4,6 +4,7 @@ import pygtk
|
|||||||
pygtk.require('2.0')
|
pygtk.require('2.0')
|
||||||
import gtk
|
import gtk
|
||||||
import pango
|
import pango
|
||||||
|
import xml.sax
|
||||||
|
|
||||||
class RichTextBuffer(gtk.TextBuffer):
|
class RichTextBuffer(gtk.TextBuffer):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -33,12 +34,6 @@ class RichTextBuffer(gtk.TextBuffer):
|
|||||||
pos_end.backward_chars(length)
|
pos_end.backward_chars(length)
|
||||||
self.apply_tag_by_name(tag, pos, pos_end)
|
self.apply_tag_by_name(tag, pos, pos_end)
|
||||||
|
|
||||||
def to_xml():
|
|
||||||
next_iter = buffer.get_start_iter()
|
|
||||||
while not next_iter.is_end():
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RichTextToolbar(gtk.Toolbar):
|
class RichTextToolbar(gtk.Toolbar):
|
||||||
def __init__(self, buf):
|
def __init__(self, buf):
|
||||||
gtk.Toolbar.__init__(self)
|
gtk.Toolbar.__init__(self)
|
||||||
@ -61,8 +56,99 @@ class RichTextToolbar(gtk.Toolbar):
|
|||||||
else:
|
else:
|
||||||
self.buf.unapply_tag(tag_name)
|
self.buf.unapply_tag(tag_name)
|
||||||
|
|
||||||
|
class RichTextHandler(xml.sax.handler.ContentHandler):
|
||||||
|
def __init__(self, buf):
|
||||||
|
self.buf = buf
|
||||||
|
self.tags = []
|
||||||
|
|
||||||
|
def _deserialize_element(self, el_name):
|
||||||
|
if el_name == "bold":
|
||||||
|
return "bold"
|
||||||
|
elif el_name == "italic":
|
||||||
|
return "italic"
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def startElement(self, name, attributes):
|
||||||
|
tag = self._deserialize_element(name)
|
||||||
|
if tag:
|
||||||
|
self.tags.append(tag)
|
||||||
|
|
||||||
|
def characters(self, data):
|
||||||
|
start_it = it = self.buf.get_end_iter()
|
||||||
|
mark = self.buf.create_mark(None, start_it, True)
|
||||||
|
self.buf.insert(it, data)
|
||||||
|
start_it = self.buf.get_iter_at_mark(mark)
|
||||||
|
|
||||||
|
for tag in self.tags:
|
||||||
|
self.buf.apply_tag_by_name(tag, start_it, it)
|
||||||
|
|
||||||
|
def endElement(self, name):
|
||||||
|
tag = self._deserialize_element(name)
|
||||||
|
if tag:
|
||||||
|
self.tags.remove(tag)
|
||||||
|
|
||||||
|
class RichTextSerializer:
|
||||||
|
def __init__(self):
|
||||||
|
self._open_xml_tags = []
|
||||||
|
|
||||||
|
def _get_xml_tag(self, tag):
|
||||||
|
if tag.get_property("name") == "bold":
|
||||||
|
return "bold"
|
||||||
|
elif tag.get_property("name") == "italic":
|
||||||
|
return "italic"
|
||||||
|
else:
|
||||||
|
return "unknown_tag"
|
||||||
|
|
||||||
|
def serialize(self, buf):
|
||||||
|
xml = "<richtext>"
|
||||||
|
|
||||||
|
next_it = buf.get_start_iter()
|
||||||
|
while not next_it.is_end():
|
||||||
|
it = next_it.copy()
|
||||||
|
if not next_it.forward_to_tag_toggle(None):
|
||||||
|
next_it = buf.get_end_iter()
|
||||||
|
|
||||||
|
reopen_xml_tags = []
|
||||||
|
for tag in it.get_toggled_tags(False):
|
||||||
|
xml_tag = self._get_xml_tag(tag)
|
||||||
|
while 1:
|
||||||
|
open_xml_tag = self._open_xml_tags.pop()
|
||||||
|
if open_xml_tag != xml_tag:
|
||||||
|
xml += "</" + open_xml_tag + ">"
|
||||||
|
reopen_xml_tags.append(open_xml_tag)
|
||||||
|
else:
|
||||||
|
xml += "</" + xml_tag + ">"
|
||||||
|
break
|
||||||
|
|
||||||
|
for xml_tag in reopen_xml_tags:
|
||||||
|
self._open_xml_tags.append(xml_tag)
|
||||||
|
xml += "<" + xml_tag + ">"
|
||||||
|
|
||||||
|
for tag in it.get_toggled_tags(True):
|
||||||
|
xml_tag = self._get_xml_tag(tag)
|
||||||
|
self._open_xml_tags.append(xml_tag)
|
||||||
|
xml += "<" + xml_tag + ">"
|
||||||
|
|
||||||
|
xml += buf.get_text(it, next_it)
|
||||||
|
|
||||||
|
if next_it.is_end():
|
||||||
|
for xml_tag in self._open_xml_tags:
|
||||||
|
xml += "</" + xml_tag + ">"
|
||||||
|
|
||||||
|
xml += "</richtext>"
|
||||||
|
|
||||||
|
return xml
|
||||||
|
|
||||||
|
def deserialize(self, xml_string, buf):
|
||||||
|
parser = xml.sax.make_parser()
|
||||||
|
handler = RichTextHandler(buf)
|
||||||
|
parser.setContentHandler(handler)
|
||||||
|
parser.feed(xml_string)
|
||||||
|
parser.close()
|
||||||
|
|
||||||
def test_quit(window, rich_buf):
|
def test_quit(window, rich_buf):
|
||||||
print rich_buf.to_xml()
|
print RichTextSerializer().serialize(rich_buf)
|
||||||
gtk.main_quit()
|
gtk.main_quit()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@ -73,6 +159,9 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
rich_buf = RichTextBuffer()
|
rich_buf = RichTextBuffer()
|
||||||
|
|
||||||
|
xml_string = "<richtext><bold><italic>Hello</italic>World</bold></richtext>"
|
||||||
|
RichTextSerializer().deserialize(xml_string, rich_buf)
|
||||||
|
|
||||||
view = gtk.TextView(rich_buf)
|
view = gtk.TextView(rich_buf)
|
||||||
vbox.pack_start(view)
|
vbox.pack_start(view)
|
||||||
view.show()
|
view.show()
|
||||||
|
Loading…
Reference in New Issue
Block a user