diff --git a/src/GrampsDbUtils/_GrampsDbWriteXML.py b/src/GrampsDbUtils/_GrampsDbWriteXML.py
index 427d4083f..ebbab01bb 100644
--- a/src/GrampsDbUtils/_GrampsDbWriteXML.py
+++ b/src/GrampsDbUtils/_GrampsDbWriteXML.py
@@ -295,7 +295,7 @@ class GrampsDbXmlWriter(UpdateCallback):
self.g.write(" \n")
for key in self.db.get_note_handles():
note = self.db.get_note_from_handle(key)
- self.write_note(note,2)
+ self.write_note(note, 2)
self.update()
self.g.write(" \n")
@@ -392,29 +392,53 @@ class GrampsDbXmlWriter(UpdateCallback):
for handle in note_list:
self.write_ref("noteref", handle,indent)
- def write_note(self, note,index=1):
+ def write_note(self, note, index=2):
if not note:
return
- self.write_primary_tag("note", note,2,close=False)
+ self.write_primary_tag('note', note, index, close=False)
ntype = escxml(note.get_type().xml_str())
format = note.get_format()
- text = note.get()
+ text = note.get_styledtext()
+ tags = text.get_tags()
+ text = str(text)
self.g.write(' type="%s"' % ntype)
if format != note.FLOWED:
self.g.write(' format="%d"' % format)
- self.g.write('>')
+ self.g.write('>\n')
+
+ self.write_text('text', text, index + 1)
- self.g.write(self.fix(text.rstrip()))
- self.g.write("\n")
+ if tags:
+ self.write_texttags(tags, index + 1)
- def write_text(self,val,text,indent=0):
+ self.g.write(' ' * index + '\n')
+
+
+ def write_texttags(self, tags, index=3):
+ for tag in tags:
+ name = tag.name.xml_str()
+ value = tag.value
+
+ self.g.write(' ' * index + '\n')
+
+ for (start, end) in tag.ranges:
+ self.g.write((' ' * (index + 1)) +
+ '\n' % (start, end))
+
+ self.g.write(' ' * index + '\n')
+
+ def write_text(self, val, text, indent=0):
if not text:
return
- if indent != 0:
- self.g.write(" " * indent)
+
+ if indent:
+ self.g.write(' ' * indent)
self.g.write('<%s>' % val)
self.g.write(self.fix(text.rstrip()))
diff --git a/src/GrampsDbUtils/_ReadXML.py b/src/GrampsDbUtils/_ReadXML.py
index 832c83cff..2bfba345c 100644
--- a/src/GrampsDbUtils/_ReadXML.py
+++ b/src/GrampsDbUtils/_ReadXML.py
@@ -374,6 +374,8 @@ class GrampsParser(UpdateCallback):
self.in_note = 0
self.in_stext = 0
self.in_scomments = 0
+ self.note_text = None
+ self.note_tags = []
self.in_witness = False
self.db = database
self.photo = None
@@ -432,108 +434,111 @@ class GrampsParser(UpdateCallback):
self.eidswap = {}
self.func_map = {
- "address" : (self.start_address, self.stop_address),
- "addresses" : (None, None),
- "childlist" : (None, None),
- "aka" : (self.start_name, self.stop_aka),
- "attribute" : (self.start_attribute, self.stop_attribute),
- "attr_type" : (None, self.stop_attr_type),
- "attr_value" : (None, self.stop_attr_value),
- "bookmark" : (self.start_bmark, None),
- "bookmarks" : (None, None),
- "format" : (self.start_format, None),
- "name-formats" : (None, None),
- "child" : (self.start_child, None),
- "childof" : (self.start_childof, None),
- "childref" : (self.start_childref, self.stop_childref),
- "personref" : (self.start_personref, self.stop_personref),
- "city" : (None, self.stop_city),
- "county" : (None, self.stop_county),
- "country" : (None, self.stop_country),
- "comment" : (None, self.stop_comment),
- "created" : (self.start_created, None),
- "ref" : (None, self.stop_ref),
- "database" : (self.start_database, self.stop_database),
- "phone" : (None, self.stop_phone),
- "date" : (None, self.stop_date),
- "cause" : (None, self.stop_cause),
+ "address": (self.start_address, self.stop_address),
+ "addresses": (None, None),
+ "childlist": (None, None),
+ "aka": (self.start_name, self.stop_aka),
+ "attribute": (self.start_attribute, self.stop_attribute),
+ "attr_type": (None, self.stop_attr_type),
+ "attr_value": (None, self.stop_attr_value),
+ "bookmark": (self.start_bmark, None),
+ "bookmarks": (None, None),
+ "format": (self.start_format, None),
+ "name-formats": (None, None),
+ "child": (self.start_child, None),
+ "childof": (self.start_childof, None),
+ "childref": (self.start_childref, self.stop_childref),
+ "personref": (self.start_personref, self.stop_personref),
+ "city": (None, self.stop_city),
+ "county": (None, self.stop_county),
+ "country": (None, self.stop_country),
+ "comment": (None, self.stop_comment),
+ "created": (self.start_created, None),
+ "ref": (None, self.stop_ref),
+ "database": (self.start_database, self.stop_database),
+ "phone": (None, self.stop_phone),
+ "date": (None, self.stop_date),
+ "cause": (None, self.stop_cause),
"description": (None, self.stop_description),
- "event" : (self.start_event, self.stop_event),
- "type" : (None, self.stop_type),
- "witness" : (self.start_witness, self.stop_witness),
- "eventref" : (self.start_eventref, self.stop_eventref),
- "data_item" : (self.start_data_item, None),
- "families" : (None, self.stop_families),
- "family" : (self.start_family, self.stop_family),
- "rel" : (self.start_rel, None),
- "region" : (self.start_region, None),
- "father" : (self.start_father, None),
- "first" : (None, self.stop_first),
- "call" : (None, self.stop_call),
- "gender" : (None, self.stop_gender),
- "header" : (None, None),
- "last" : (self.start_last, self.stop_last),
- "map" : (self.start_namemap, None),
- "mediapath" : (None, self.stop_mediapath),
- "mother" : (self.start_mother, None),
- "name" : (self.start_name, self.stop_name),
- "namemaps" : (None, None),
- "nick" : (None, self.stop_nick),
- "note" : (self.start_note, self.stop_note),
- "noteref" : (self.start_noteref, None),
- "p" : (None, self.stop_ptag),
- "parentin" : (self.start_parentin, None),
- "people" : (self.start_people, self.stop_people),
- "person" : (self.start_person, self.stop_person),
- "img" : (self.start_photo, self.stop_photo),
- "objref" : (self.start_objref, self.stop_objref),
- "object" : (self.start_object, self.stop_object),
- "file" : (self.start_file, None),
- "place" : (self.start_place, self.stop_place),
- "dateval" : (self.start_dateval, None),
- "daterange" : (self.start_daterange, None),
- "datespan" : (self.start_datespan, None),
- "datestr" : (self.start_datestr, None),
- "places" : (None, self.stop_places),
- "placeobj" : (self.start_placeobj, self.stop_placeobj),
- "ptitle" : (None, self.stop_ptitle),
- "location" : (self.start_location, None),
- "lds_ord" : (self.start_lds_ord, self.stop_lds_ord),
- "temple" : (self.start_temple, None),
- "status" : (self.start_status, None),
- "sealed_to" : (self.start_sealed_to, None),
- "coord" : (self.start_coord, None),
- "patronymic" : (None, self.stop_patronymic),
- "pos" : (self.start_pos, None),
- "postal" : (None, self.stop_postal),
- "researcher" : (None, self.stop_research),
- "resname" : (None, self.stop_resname ),
- "resaddr" : (None, self.stop_resaddr ),
- "rescity" : (None, self.stop_rescity ),
- "resstate" : (None, self.stop_resstate ),
- "rescountry" : (None, self.stop_rescountry),
- "respostal" : (None, self.stop_respostal),
- "resphone" : (None, self.stop_resphone),
- "resemail" : (None, self.stop_resemail),
- "sauthor" : (None, self.stop_sauthor),
- "sabbrev" : (None, self.stop_sabbrev),
- "scomments" : (None, self.stop_scomments),
- "source" : (self.start_source, self.stop_source),
- "sourceref" : (self.start_sourceref, self.stop_sourceref),
- "sources" : (None, None),
- "spage" : (None, self.stop_spage),
- "spubinfo" : (None, self.stop_spubinfo),
- "state" : (None, self.stop_state),
- "stext" : (None, self.stop_stext),
- "stitle" : (None, self.stop_stitle),
- "street" : (None, self.stop_street),
- "suffix" : (None, self.stop_suffix),
- "title" : (None, self.stop_title),
- "url" : (self.start_url, None),
- "repository" : (self.start_repo, self.stop_repo),
- "reporef" : (self.start_reporef, self.stop_reporef),
- "rname" : (None, self.stop_rname),
- }
+ "event": (self.start_event, self.stop_event),
+ "type": (None, self.stop_type),
+ "witness": (self.start_witness, self.stop_witness),
+ "eventref": (self.start_eventref, self.stop_eventref),
+ "data_item": (self.start_data_item, None),
+ "families": (None, self.stop_families),
+ "family": (self.start_family, self.stop_family),
+ "rel": (self.start_rel, None),
+ "region": (self.start_region, None),
+ "father": (self.start_father, None),
+ "first": (None, self.stop_first),
+ "call": (None, self.stop_call),
+ "gender": (None, self.stop_gender),
+ "header": (None, None),
+ "last": (self.start_last, self.stop_last),
+ "map": (self.start_namemap, None),
+ "mediapath": (None, self.stop_mediapath),
+ "mother": (self.start_mother, None),
+ "name": (self.start_name, self.stop_name),
+ "namemaps": (None, None),
+ "nick": (None, self.stop_nick),
+ "note": (self.start_note, self.stop_note),
+ "noteref": (self.start_noteref, None),
+ "p": (None, self.stop_ptag),
+ "parentin": (self.start_parentin, None),
+ "people": (self.start_people, self.stop_people),
+ "person": (self.start_person, self.stop_person),
+ "img": (self.start_photo, self.stop_photo),
+ "objref": (self.start_objref, self.stop_objref),
+ "object": (self.start_object, self.stop_object),
+ "file": (self.start_file, None),
+ "place": (self.start_place, self.stop_place),
+ "dateval": (self.start_dateval, None),
+ "daterange": (self.start_daterange, None),
+ "datespan": (self.start_datespan, None),
+ "datestr": (self.start_datestr, None),
+ "places": (None, self.stop_places),
+ "placeobj": (self.start_placeobj, self.stop_placeobj),
+ "ptitle": (None, self.stop_ptitle),
+ "location": (self.start_location, None),
+ "lds_ord": (self.start_lds_ord, self.stop_lds_ord),
+ "temple": (self.start_temple, None),
+ "status": (self.start_status, None),
+ "sealed_to": (self.start_sealed_to, None),
+ "coord": (self.start_coord, None),
+ "patronymic": (None, self.stop_patronymic),
+ "pos": (self.start_pos, None),
+ "postal": (None, self.stop_postal),
+ "range": (self.start_range, None),
+ "researcher": (None, self.stop_research),
+ "resname": (None, self.stop_resname ),
+ "resaddr": (None, self.stop_resaddr ),
+ "rescity": (None, self.stop_rescity ),
+ "resstate": (None, self.stop_resstate ),
+ "rescountry": (None, self.stop_rescountry),
+ "respostal": (None, self.stop_respostal),
+ "resphone": (None, self.stop_resphone),
+ "resemail": (None, self.stop_resemail),
+ "sauthor": (None, self.stop_sauthor),
+ "sabbrev": (None, self.stop_sabbrev),
+ "scomments": (None, self.stop_scomments),
+ "source": (self.start_source, self.stop_source),
+ "sourceref": (self.start_sourceref, self.stop_sourceref),
+ "sources": (None, None),
+ "spage": (None, self.stop_spage),
+ "spubinfo": (None, self.stop_spubinfo),
+ "state": (None, self.stop_state),
+ "stext": (None, self.stop_stext),
+ "stitle": (None, self.stop_stitle),
+ "street": (None, self.stop_street),
+ "suffix": (None, self.stop_suffix),
+ "tag": (self.start_tag, None),
+ "text": (None, self.stop_text),
+ "title": (None, self.stop_title),
+ "url": (self.start_url, None),
+ "repository": (self.start_repo, self.stop_repo),
+ "reporef": (self.start_reporef, self.stop_reporef),
+ "rname": (None, self.stop_rname),
+ }
def find_person_by_gramps_id(self, gramps_id):
intid = self.gid2id.get(gramps_id)
@@ -1317,6 +1322,21 @@ class GrampsParser(UpdateCallback):
self.name.prefix = attrs.get('prefix', '')
self.name.group_as = attrs.get('group', '')
+ def start_tag(self, attrs):
+ tagtype = gen.lib.StyledTextTagType()
+ tagtype.set_from_xml_str(attrs['name'])
+
+ try:
+ tagvalue = attrs['value']
+ except KeyError:
+ tagvalue = None
+
+ self.note_tags.append(gen.lib.StyledTextTag(tagtype, tagvalue))
+
+ def start_range(self, attrs):
+ self.note_tags[-1].ranges.append((int(attrs['start']),
+ int(attrs['end'])))
+
def start_note(self, attrs):
self.in_note = 0
if 'handle' in attrs:
@@ -1339,6 +1359,13 @@ class GrampsParser(UpdateCallback):
self.info.add('merge-overwrite', NOTE_KEY, self.note)
self.note.format = int(attrs.get('format', gen.lib.Note.FLOWED))
self.note.type.set_from_xml_str(attrs['type'])
+
+ # Since StyledText was introduced (XML v1.2.1?) the clear text
+ # part of the note is moved between tags.
+ # To catch the different versions here we reset the note_text
+ # variable. It will be checked in stop_note() then.
+ self.note_text = None
+ self.note_tags = []
else:
# GRAMPS LEGACY: old notes that were written inside other objects
# We need to create a top-level note, it's type depends on
@@ -2174,14 +2201,20 @@ class GrampsParser(UpdateCallback):
attr.set_value(tag)
self.person.add_attribute(attr)
+ def stop_text(self, tag):
+ self.note_text = tag
+
def stop_note(self, tag):
self.in_note = 0
if self.use_p:
self.use_p = 0
text = fix_spaces(self.note_list)
+ elif self.note_text is not None:
+ text = self.note_text
else:
text = tag
- self.note.set(text)
+
+ self.note.set_styledtext(gen.lib.StyledText(text, self.note_tags))
if self.address:
self.address.add_note(self.note.handle)