179 lines
8.0 KiB
Python
179 lines
8.0 KiB
Python
#
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
#
|
|
# Copyright (C) 2000-2007 Donald N. Allingham
|
|
# Copyright (C) 2010 Michiel D. Nauta
|
|
# Copyright (C) 2010 Jakim Friant
|
|
#
|
|
# 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
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
|
|
# $Id$
|
|
|
|
"""
|
|
Provide merge capabilities for persons.
|
|
"""
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# Gramps modules
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
from gen.db import DbTxn
|
|
from gen.ggettext import sgettext as _
|
|
from Errors import MergeError
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# MergePersonQuery
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
class MergePersonQuery(object):
|
|
"""
|
|
Create database query to merge two persons.
|
|
"""
|
|
def __init__(self, database, phoenix, titanic):
|
|
self.database = database
|
|
self.phoenix = phoenix
|
|
self.titanic = titanic
|
|
if self.check_for_spouse(self.phoenix, self.titanic):
|
|
raise MergeError(_("Spouses cannot be merged. To merge these "
|
|
"people, you must first break the relationship between them."))
|
|
if self.check_for_child(self.phoenix, self.titanic):
|
|
raise MergeError(_("A parent and child cannot be merged. To merge "
|
|
"these people, you must first break the relationship between "
|
|
"them."))
|
|
|
|
def check_for_spouse(self, person1, person2):
|
|
"""Return if person1 and person2 are spouses of eachother."""
|
|
fs1 = set(person1.get_family_handle_list())
|
|
fs2 = set(person2.get_family_handle_list())
|
|
return len(fs1.intersection(fs2)) != 0
|
|
|
|
def check_for_child(self, person1, person2):
|
|
"""Return if person1 and person2 have a child-parent relationship."""
|
|
fs1 = set(person1.get_family_handle_list())
|
|
fp1 = set(person1.get_parent_family_handle_list())
|
|
fs2 = set(person2.get_family_handle_list())
|
|
fp2 = set(person2.get_parent_family_handle_list())
|
|
return len(fs1.intersection(fp2)) != 0 or len(fs2.intersection(fp1))
|
|
|
|
def merge_families(self, main_family_handle, family, trans):
|
|
"""
|
|
Merge content of family into the family with handle main_family_handle.
|
|
"""
|
|
new_handle = self.phoenix.get_handle() if self.phoenix else None
|
|
old_handle = self.titanic.get_handle() if self.titanic else None
|
|
family_handle = family.get_handle()
|
|
main_family = self.database.get_family_from_handle(main_family_handle)
|
|
main_family.merge(family)
|
|
for childref in family.get_child_ref_list():
|
|
child = self.database.get_person_from_handle(
|
|
childref.get_reference_handle())
|
|
if main_family_handle in child.parent_family_list:
|
|
child.remove_handle_references('Family', [family_handle])
|
|
else:
|
|
child.replace_handle_reference('Family', family_handle,
|
|
main_family_handle)
|
|
self.database.commit_person(child, trans)
|
|
if self.phoenix:
|
|
self.phoenix.remove_family_handle(family_handle)
|
|
self.database.commit_person(self.phoenix, trans)
|
|
family_father_handle = family.get_father_handle()
|
|
spouse_handle = family.get_mother_handle() if \
|
|
new_handle == family_father_handle else family_father_handle
|
|
spouse = self.database.get_person_from_handle(spouse_handle)
|
|
if spouse:
|
|
spouse.remove_family_handle(family_handle)
|
|
self.database.commit_person(spouse, trans)
|
|
# replace the family in lds ordinances
|
|
for (dummy, person_handle) in self.database.find_backlink_handles(
|
|
family_handle, ['Person']):
|
|
if person_handle == old_handle:
|
|
continue
|
|
person = self.database.get_person_from_handle(person_handle)
|
|
person.replace_handle_reference('Family', family_handle,
|
|
main_family_handle)
|
|
self.database.commit_person(person, trans)
|
|
self.database.remove_family(family_handle, trans)
|
|
self.database.commit_family(main_family, trans)
|
|
|
|
def execute(self, family_merger=True, trans=None):
|
|
"""
|
|
Merges two persons into a single person.
|
|
"""
|
|
if trans is None:
|
|
with DbTxn(_('Merge Person'), self.database) as trans:
|
|
self.__execute(family_merger, trans)
|
|
else:
|
|
self.__execute(family_merger, trans)
|
|
|
|
def __execute(self, family_merger, trans):
|
|
"""
|
|
Merges two persons into a single person; trans is compulsory.
|
|
"""
|
|
new_handle = self.phoenix.get_handle()
|
|
old_handle = self.titanic.get_handle()
|
|
|
|
self.phoenix.merge(self.titanic)
|
|
self.database.commit_person(self.phoenix, trans)
|
|
|
|
for (dummy, person_handle) in self.database.find_backlink_handles(
|
|
old_handle, ['Person']):
|
|
person = self.database.get_person_from_handle(person_handle)
|
|
assert person.has_handle_reference('Person', old_handle)
|
|
person.replace_handle_reference('Person', old_handle, new_handle)
|
|
if person_handle != old_handle:
|
|
self.database.commit_person(person, trans)
|
|
|
|
for family_handle in self.phoenix.get_parent_family_handle_list():
|
|
family = self.database.get_family_from_handle(family_handle)
|
|
if family.has_handle_reference('Person', old_handle):
|
|
family.replace_handle_reference('Person', old_handle,new_handle)
|
|
self.database.commit_family(family, trans)
|
|
|
|
family_merge_guard = False
|
|
parent_list = []
|
|
parent_list_orig = []
|
|
family_handle_list = self.phoenix.get_family_handle_list()[:]
|
|
for family_handle in family_handle_list:
|
|
family = self.database.get_family_from_handle(family_handle)
|
|
parents = (family.get_father_handle(), family.get_mother_handle())
|
|
parent_list_orig.append(parents)
|
|
if family.has_handle_reference('Person', old_handle):
|
|
if family_merger and parent_list_orig.count(parents) > 1:
|
|
raise MergeError(_("A person with multiple relations with "
|
|
"the same spouse is about to be merged. This is beyond "
|
|
"the capabilities of the merge routine. The merge is "
|
|
"aborted."))
|
|
family.replace_handle_reference('Person', old_handle,new_handle)
|
|
parents = (family.get_father_handle(),
|
|
family.get_mother_handle())
|
|
# prune means merging families in this case.
|
|
if family_merger and parents in parent_list:
|
|
# also merge when father_handle or mother_handle == None!
|
|
if family_merge_guard:
|
|
raise MergeError(_("Multiple families get merged. "
|
|
"This is unusual, the merge is aborted."))
|
|
idx = parent_list.index(parents)
|
|
main_family_handle = family_handle_list[idx]
|
|
self.merge_families(main_family_handle, family, trans)
|
|
family_merge_guard = True
|
|
continue
|
|
self.database.commit_family(family, trans)
|
|
parent_list.append(parents)
|
|
|
|
self.database.remove_person(old_handle, trans)
|