GEDCOM import. Fix handling of notes. Notes could get duplicate Gramps IDs. If a note was going to be assigned the next Gramps ID, then there was no check whether the Gramps ID had already been allocated to a note that had been encountered as a linked note, but not yet committed. Also handle change date and time for notes. Also media objects attached to a source citation were parsed with the wrong level, so they swallowed the following tags (this had been a problem with the previous source references processing).
svn: r18824
This commit is contained in:
parent
2ff608e798
commit
b6df7d2a49
@ -1499,6 +1499,7 @@ class CurrentState(object):
|
|||||||
self.event = event
|
self.event = event
|
||||||
self.event_ref = event_ref
|
self.event_ref = event_ref
|
||||||
self.source_ref = None
|
self.source_ref = None
|
||||||
|
self.note = None
|
||||||
self.msg = ""
|
self.msg = ""
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
@ -1630,15 +1631,24 @@ class IdMapper(object):
|
|||||||
self.swap = {}
|
self.swap = {}
|
||||||
|
|
||||||
def __getitem__(self, gid):
|
def __getitem__(self, gid):
|
||||||
gid = self.clean(gid)
|
if gid == "":
|
||||||
if gid in self.swap:
|
# We need to find the next gramps ID provided it is not already
|
||||||
return self.swap[gid]
|
# the target of a swap
|
||||||
else:
|
new_val = self.find_next()
|
||||||
if self.trans.get(str(gid)):
|
while new_val in self.swap.values():
|
||||||
new_val = self.find_next()
|
new_val = self.find_next()
|
||||||
|
else:
|
||||||
|
gid = self.clean(gid)
|
||||||
|
if gid in self.swap:
|
||||||
|
return self.swap[gid]
|
||||||
else:
|
else:
|
||||||
new_val = gid
|
if self.trans.get(str(gid)) or (gid in self.swap.values()):
|
||||||
self.swap[gid] = new_val
|
new_val = self.find_next()
|
||||||
|
while new_val in self.swap.values():
|
||||||
|
new_val = self.find_next()
|
||||||
|
else:
|
||||||
|
new_val = gid
|
||||||
|
self.swap[gid] = new_val
|
||||||
return new_val
|
return new_val
|
||||||
|
|
||||||
def clean(self, gid):
|
def clean(self, gid):
|
||||||
@ -2382,6 +2392,24 @@ class GedcomParser(UpdateCallback):
|
|||||||
TOKEN_FORM : self.__place_form,
|
TOKEN_FORM : self.__place_form,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parse table for <<NOTE_RECORD>> below the level 0 NOTE tag
|
||||||
|
#
|
||||||
|
# n @<XREF:NOTE>@ NOTE <SUBMITTER_TEXT> {1:1}
|
||||||
|
# +1 [ CONC | CONT] <SUBMITTER_TEXT> {0:M}
|
||||||
|
# +1 <<SOURCE_CITATION>> {0:M}
|
||||||
|
# +1 REFN <USER_REFERENCE_NUMBER> {0:M}
|
||||||
|
# +2 TYPE <USER_REFERENCE_TYPE> {0:1}
|
||||||
|
# +1 RIN <AUTOMATED_RECORD_ID> {0:1}
|
||||||
|
# +1 <<CHANGE_DATE>> {0:1}
|
||||||
|
|
||||||
|
self.note_parse_tbl = {
|
||||||
|
TOKEN_SOUR : self.__ignore,
|
||||||
|
TOKEN_REFN : self.__ignore,
|
||||||
|
TOKEN_RIN : self.__ignore,
|
||||||
|
TOKEN_CHAN : self.__note_chan,
|
||||||
|
}
|
||||||
|
|
||||||
# look for existing place titles, build a map
|
# look for existing place titles, build a map
|
||||||
self.place_names = {}
|
self.place_names = {}
|
||||||
cursor = dbase.get_place_cursor()
|
cursor = dbase.get_place_cursor()
|
||||||
@ -4406,6 +4434,10 @@ class GedcomParser(UpdateCallback):
|
|||||||
@param state: The current state
|
@param state: The current state
|
||||||
@type state: CurrentState
|
@type state: CurrentState
|
||||||
"""
|
"""
|
||||||
|
LOG.debug("Line %5d: %s %s %s" % (line.line,
|
||||||
|
line.level,
|
||||||
|
line.token_text,
|
||||||
|
line.data))
|
||||||
state.note = line.data
|
state.note = line.data
|
||||||
|
|
||||||
def __family_adopt(self, line, state):
|
def __family_adopt(self, line, state):
|
||||||
@ -4575,6 +4607,7 @@ class GedcomParser(UpdateCallback):
|
|||||||
if line.data and line.data[0] == '@':
|
if line.data and line.data[0] == '@':
|
||||||
self.__not_recognized(line, state.level, state)
|
self.__not_recognized(line, state.level, state)
|
||||||
else:
|
else:
|
||||||
|
# FIXME this should probably be level+1
|
||||||
(form, filename, title, note) = self.__obje(state.level, state)
|
(form, filename, title, note) = self.__obje(state.level, state)
|
||||||
self.build_media_object(state.place, form, filename, title, note)
|
self.build_media_object(state.place, form, filename, title, note)
|
||||||
|
|
||||||
@ -5127,7 +5160,7 @@ class GedcomParser(UpdateCallback):
|
|||||||
if line.data and line.data[0] == '@':
|
if line.data and line.data[0] == '@':
|
||||||
self.__not_recognized(line, state.level, state)
|
self.__not_recognized(line, state.level, state)
|
||||||
else:
|
else:
|
||||||
(form, filename, title, note) = self.__obje(state.level, state)
|
(form, filename, title, note) = self.__obje(state.level+1, state)
|
||||||
self.build_media_object(state.citation, form, filename, title, note)
|
self.build_media_object(state.citation, form, filename, title, note)
|
||||||
|
|
||||||
def __citation_refn(self, line, state):
|
def __citation_refn(self, line, state):
|
||||||
@ -6011,18 +6044,35 @@ class GedcomParser(UpdateCallback):
|
|||||||
self.def_src.set_author(line.data)
|
self.def_src.set_author(line.data)
|
||||||
|
|
||||||
def __parse_note(self, line, obj, level, state):
|
def __parse_note(self, line, obj, level, state):
|
||||||
|
LOG.debug("Line %5d: %s %s %s" % (line.line,
|
||||||
|
line.level,
|
||||||
|
line.token_text,
|
||||||
|
line.data))
|
||||||
if line.token == TOKEN_RNOTE:
|
if line.token == TOKEN_RNOTE:
|
||||||
# reference to a named note defined elsewhere
|
# reference to a named note defined elsewhere
|
||||||
|
#NOTE_STRUCTURE: =
|
||||||
|
# n NOTE @<XREF:NOTE>@ {1:1}
|
||||||
|
# +1 SOUR @<XREF:SOUR>@ {0:M}
|
||||||
gid = line.data.strip()
|
gid = line.data.strip()
|
||||||
obj.add_note(self.__find_note_handle(self.nid_map[gid]))
|
gramps_id = self.nid_map[gid]
|
||||||
|
obj.add_note(self.__find_note_handle(gramps_id))
|
||||||
|
LOG.debug("Note linked: mapped gid %s\n" % gramps_id)
|
||||||
else:
|
else:
|
||||||
|
# Embedded note
|
||||||
|
#NOTE_STRUCTURE: =
|
||||||
|
# n NOTE [<SUBMITTER_TEXT> | <NULL>] {1:1}
|
||||||
|
# +1 [ CONC | CONT ] <SUBMITTER_TEXT> {0:M}
|
||||||
|
# +1 SOUR @<XREF:SOUR>@ {0:M}
|
||||||
if not line.data:
|
if not line.data:
|
||||||
self.__add_msg(_("Empty note ignored"), line, state)
|
self.__add_msg(_("Empty note ignored"), line, state)
|
||||||
self.__skip_subordinate_levels(level+1, state)
|
self.__skip_subordinate_levels(level+1, state)
|
||||||
else:
|
else:
|
||||||
new_note = gen.lib.Note(line.data)
|
new_note = gen.lib.Note(line.data)
|
||||||
|
new_note.set_gramps_id(self.nid_map[""])
|
||||||
new_note.set_handle(Utils.create_id())
|
new_note.set_handle(Utils.create_id())
|
||||||
self.dbase.add_note(new_note, self.trans)
|
self.dbase.commit_note(new_note, self.trans)
|
||||||
|
LOG.debug("Note commited: mapped gid %s\n" %
|
||||||
|
new_note.get_gramps_id())
|
||||||
self.__skip_subordinate_levels(level+1, state)
|
self.__skip_subordinate_levels(level+1, state)
|
||||||
obj.add_note(new_note.get_handle())
|
obj.add_note(new_note.get_handle())
|
||||||
|
|
||||||
@ -6044,6 +6094,10 @@ class GedcomParser(UpdateCallback):
|
|||||||
+1 RIN <AUTOMATED_RECORD_ID> {0:1}
|
+1 RIN <AUTOMATED_RECORD_ID> {0:1}
|
||||||
+1 <<CHANGE_DATE>> {0:1}
|
+1 <<CHANGE_DATE>> {0:1}
|
||||||
"""
|
"""
|
||||||
|
LOG.debug("Line %5d: %s %s %s" % (line.line,
|
||||||
|
line.level,
|
||||||
|
line.token_text,
|
||||||
|
line.data))
|
||||||
state = CurrentState()
|
state = CurrentState()
|
||||||
gid = self.nid_map[line.token_text]
|
gid = self.nid_map[line.token_text]
|
||||||
handle = self.nid2id.get(gid)
|
handle = self.nid2id.get(gid)
|
||||||
@ -6054,12 +6108,23 @@ class GedcomParser(UpdateCallback):
|
|||||||
new_note = gen.lib.Note(line.data)
|
new_note = gen.lib.Note(line.data)
|
||||||
new_note.set_handle(handle)
|
new_note.set_handle(handle)
|
||||||
new_note.set_gramps_id(gid)
|
new_note.set_gramps_id(gid)
|
||||||
self.dbase.add_note(new_note, self.trans)
|
|
||||||
|
sub_state = CurrentState(level=state.level+1)
|
||||||
|
sub_state.note = new_note
|
||||||
|
self.__parse_level(sub_state, self.note_parse_tbl, self.__undefined)
|
||||||
|
state.msg += sub_state.msg
|
||||||
|
|
||||||
|
self.dbase.commit_note(new_note, self.trans, new_note.change)
|
||||||
|
LOG.debug("Note commited: mapped gid %s\n" %
|
||||||
|
new_note.get_gramps_id())
|
||||||
self.nid2id[new_note.gramps_id] = new_note.handle
|
self.nid2id[new_note.gramps_id] = new_note.handle
|
||||||
self.__skip_subordinate_levels(level, state)
|
|
||||||
self.__check_msgs("NOTE Gramps ID %s" % new_note.get_gramps_id(),
|
self.__check_msgs("NOTE Gramps ID %s" % new_note.get_gramps_id(),
|
||||||
state, None, self.trans)
|
state, None, self.trans)
|
||||||
|
|
||||||
|
def __note_chan(self, line, state):
|
||||||
|
if state.note:
|
||||||
|
self.__parse_change(line, state.note, state.level+1, state)
|
||||||
|
|
||||||
def __parse_source_reference(self, citation, level, handle, state):
|
def __parse_source_reference(self, citation, level, handle, state):
|
||||||
"""
|
"""
|
||||||
Read the data associated with a SOUR reference.
|
Read the data associated with a SOUR reference.
|
||||||
@ -6199,7 +6264,9 @@ class GedcomParser(UpdateCallback):
|
|||||||
oref = gen.lib.MediaRef()
|
oref = gen.lib.MediaRef()
|
||||||
oref.set_reference_handle(photo.handle)
|
oref.set_reference_handle(photo.handle)
|
||||||
if note:
|
if note:
|
||||||
oref.add_note(self.__find_note_handle(self.nid_map[note]))
|
gramps_id = self.nid_map[note]
|
||||||
|
oref.add_note(self.__find_note_handle(gramps_id))
|
||||||
|
LOG.debug("Note linked: mapped gid %s\n" % gramps_id)
|
||||||
obj.add_media_reference(oref)
|
obj.add_media_reference(oref)
|
||||||
|
|
||||||
def __build_event_pair(self, state, event_type, event_map, description):
|
def __build_event_pair(self, state, event_type, event_map, description):
|
||||||
|
Loading…
Reference in New Issue
Block a user