3831: Childref notes are lost on merging of children

svn: r15096
This commit is contained in:
Doug Blank 2010-04-13 02:23:56 +00:00
parent 73ed8a51dc
commit 9e505f3419

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program # Gramps - a GTK+/GNOME based genealogy program
# #
# Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2010 Michiel D. Nauta
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -433,7 +434,7 @@ class MergePeople(object):
self.db.set_birth_death_index(new) self.db.set_birth_death_index(new)
# add other attributes to new, which may alreay have # add other attributes to new, which may already have
# some attributes from the merger # some attributes from the merger
map(new.add_attribute, self.p1.get_attribute_list() + map(new.add_attribute, self.p1.get_attribute_list() +
self.p2.get_attribute_list()) self.p2.get_attribute_list())
@ -595,33 +596,69 @@ class MergePeople(object):
self.old_handle, trans) self.old_handle, trans)
new.add_parent_family_handle(family_handle) new.add_parent_family_handle(family_handle)
def merge_childref(self, ref_one, ref_two):
"""
Add the content of two child-references together where ref_one is the
preferred.
Data typically lost is: mrel/frel of ref_two.
"""
self.copy_note(ref_one, ref_two)
self.copy_sources(ref_one, ref_two)
ref_one.set_privacy(ref_one.get_privacy() or ref_two.get_privacy())
one_frel = ref_one.get_father_relation()
one_mrel = ref_one.get_mother_relation()
two_frel = ref_two.get_father_relation()
two_mrel = ref_two.get_mother_relation()
if (one_mrel != two_mrel) or (one_frel != two_frel):
if one_mrel == gen.lib.ChildRefType.UNKNOWN:
ref_one.set_mother_relation(two_mrel)
if one_frel == gen.lib.ChildRefType.UNKNOWN:
ref_one.set_father_relation(two_frel)
def convert_child_ids(self, fhandle, new_handle, old_handle, trans): def convert_child_ids(self, fhandle, new_handle, old_handle, trans):
""" """
Search the family associated with fhandle, and replace Search the family associated with fhandle, and replace
old handle with the new handle in all child references. old handle with the new handle in all child references.
There are three situations: The child references list contains
a reference to new_handle, but not old_handle, vice versa and
references to both new AND old_handle. In the first case nothing needs
to be done, in the second case the old_handle needs replacement by
new_handle and in the latter case the references must be merged.
:param fhandle: Handle of the family to process.
:type fhandle: database handle
:param new_handle: Handle that should replace any old_handle.
:type new_handle: database handle
:param old_handle: Handle of obsolete person.
:type old_handle: database handle
:param trans: database transaction
:type trans: I don't know, probably string
""" """
family = self.db.get_family_from_handle(fhandle) family = self.db.get_family_from_handle(fhandle)
orig_ref_list = family.get_child_ref_list() orig_ref_list = family.get_child_ref_list()
new_ref_list = [] new_ref_list = []
# loop through original child list. If a handle matches the old_ref = [x for x in orig_ref_list if x.ref == old_handle]
# old handle, replace it with the new handle if the new handle if old_ref:
# is not already in the list old_ref = old_ref[0]
new_ref = [x for x in orig_ref_list if x.ref == new_handle]
if new_ref:
new_ref = new_ref[0]
if old_ref:
for child_ref in orig_ref_list: for child_ref in orig_ref_list:
if child_ref.ref == old_handle: if child_ref.ref == old_handle:
if new_handle not in [ref.ref for ref in new_ref_list]: if new_ref:
new_ref = gen.lib.ChildRef() continue # go on to child_ref.ref == new_handle
new_ref.unserialize(child_ref.serialize()) else:
new_ref.ref = new_handle child_ref.ref = new_handle
new_ref_list.append(new_ref) elif child_ref.ref == new_handle:
elif child_ref.ref not in [ref.ref for ref in new_ref_list]: self.merge_childref(child_ref, old_ref)
new_ref_list.append(child_ref) new_ref_list.append(child_ref)
# compare the new list with the original list. If this list # save changes to database
# is different, we need to save the changes to the database.
if [ref.ref for ref in new_ref_list] \
!= [ref.ref for ref in orig_ref_list]:
family.set_child_ref_list(new_ref_list) family.set_child_ref_list(new_ref_list)
self.db.commit_family(family, trans) self.db.commit_family(family, trans)
@ -771,6 +808,27 @@ class MergePeople(object):
return myfamily return myfamily
def merge_existing_family(self, new, src_family, tgt_family, trans): def merge_existing_family(self, new, src_family, tgt_family, trans):
"""
Removes the family object that becomes superfluous because of the
merger of a person.
If a person is merged with another, there can be a situation that two
families that are in the database also need to merge; that is one
family stays on and receives extra data, the other family is removed.
Removal of a family involves removal of parentin attributes in a person,
removal of childof attributes from children and actual removal of the
family from the db. The merging of data from both families is performed
in its own method.
:param new: The person that is merging.
:type new: :class:`~gen.lib.person.Person`
:param src_family: Family `new` is a parent in and that will be removed.
:type src_family: :class:`~gen.lib.family.Family`
:param tgt_family: Family `new` is and will stay a parent in.
:type src_family: :class:`~gen.lib.family.Family`
:param trans: db-transaction
:type trans: I do not know, string probably
"""
src_family_handle = src_family.get_handle() src_family_handle = src_family.get_handle()
@ -815,13 +873,38 @@ class MergePeople(object):
new.add_family_handle(tgt_family.get_handle()) new.add_family_handle(tgt_family.get_handle())
def merge_family_pair(self, tgt_family, src_family, trans): def merge_family_pair(self, tgt_family, src_family, trans):
"""
Add data from src_family to tgt_family.
This is typically called when src_family is about to be removed because
it became superfluous by a person merger. The data transfered from
source to target family is everything except id, father and mother.
Data typically lost is: marker and rel of the src-family.
Missing: lds_ord, Merged Gramps ID attribute and privacy; make own patch
:param tgt_family: Family receiving data from src_family.
:type src_family: :class:`~gen.lib.family.Family`
:param src_family: Family adding data to tgt_family.
:type src_family: :class:`~gen.lib.family.Family`
:param trans: db-transaction
:type trans: I do not know, string probably
"""
childrefs_in_both = {}
tgtlist = tgt_family.get_child_ref_list()
for child_ref in src_family.get_child_ref_list():
for tgt_child_ref in tgtlist:
if tgt_child_ref.ref == child_ref.ref:
childrefs_in_both[child_ref.ref] = tgt_child_ref
break
tgt_family_child_handles = \
[ref.ref for ref in tgt_family.get_child_ref_list()]
# copy children from source to target # copy children from source to target
for child_ref in src_family.get_child_ref_list(): for child_ref in src_family.get_child_ref_list():
child_handle = child_ref.ref child_handle = child_ref.ref
if child_handle not in tgt_family_child_handles: if child_handle in childrefs_in_both:
tgt_child_ref = childrefs_in_both[child_handle]
self.merge_childref(tgt_child_ref, child_ref)
else:
child = self.db.get_person_from_handle(child_handle) child = self.db.get_person_from_handle(child_handle)
parents = child.get_parent_family_handle_list() parents = child.get_parent_family_handle_list()
tgt_family.add_child_ref(child_ref) tgt_family.add_child_ref(child_ref)