gramps/src/plugins/quickview/lineage.py
2009-01-16 21:39:51 +00:00

259 lines
9.1 KiB
Python

#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2007 Jerome Rapinat, B. Malengier
# Copyright (C) 2008 Brian G. Matherly
#
# 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$
"""
Display a person's father or mother lineage
"""
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import gen.lib
from Simple import SimpleAccess, SimpleDoc, SimpleTable
from gettext import gettext as _
from gen.plug import PluginManager
from ReportBase import CATEGORY_QR_PERSON
__FMT = "%-30s\t%-12s\t%-12s"
__FMT_REM = " %s: %s"
__MAX_GEN = 100
def run_father(database, document, person):
""" Function writing the father lineage quick report
"""
sa = SimpleAccess(database)
sd = SimpleDoc(document)
# display the results
sd.title(_("Father lineage for %s") % sa.name(person))
sd.paragraph("")
sd.paragraph(_(""
"This report shows the father lineage, also called patronymic lineage"
" or Y-line."
" People in this lineage all share the same Y-chromosone."
))
sd.paragraph("")
stab = SimpleTable(sa)
stab.columns(_("Name Father"), _("Birth Date"), _("Death Date"), _("Remark"))
make_details(gen.lib.Person.MALE, person, sa, sd, database, stab)
stab.write(sd)
sd.paragraph("")
if person.gender == gen.lib.Person.FEMALE :
return
sd.header2((_("Direct line male descendants")))
sd.paragraph("")
make_details_child(gen.lib.Person.MALE, person, sa, sd, database)
def run_mother(database, document, person):
""" Function writing the mother lineage quick report
"""
sa = SimpleAccess(database)
sd = SimpleDoc(document)
# display the results
sd.title(_("Mother lineage for %s") % sa.name(person))
sd.paragraph("")
sd.paragraph(_(""
"This report shows the mother lineage, also called matronymic lineage "
"or M-line."
" People in this lineage all share the same RNA."
))
sd.paragraph("")
stab = SimpleTable(sa)
stab.columns(_("Name Mother"), _("Birth"), _("Death Date"), _("Remark"))
make_details(gen.lib.Person.FEMALE, person, sa, sd, database, stab)
stab.write(sd)
sd.paragraph("")
if person.gender == gen.lib.Person.MALE :
return
sd.header2((_("Direct line female descendants")))
sd.paragraph("")
make_details_child(gen.lib.Person.FEMALE, person, sa, sd, database)
def make_details(gender, person, sa, sd, database, stab) :
""" Function writing one line of ancestry on the document in
direct lineage
"""
# avoid infinite loop:
personsprinted = 0
# loop as long as there are fathers/mothers
rem_str = ""
while person:
person_handle = person.handle
stab.row(person, sa.birth_date_obj(person),
sa.death_date_obj(person), rem_str)
#if rem_str:
# sd.paragraph(__FMT_REM % (_("Remark"), rem_str))
personsprinted += 1
if personsprinted > __MAX_GEN :
sd.paragraph("")
sd.paragraph(_("ERROR : Too many levels in the tree "
"(perhaps a loop?)."))
return
# obtain the first father/mother we find in the list
parent_handle_list = person.get_parent_family_handle_list()
person = None
for parent in parent_handle_list:
rem_str = ""
family_id = parent_handle_list[0]
family = database.get_family_from_handle(family_id)
childrel = [(ref.get_mother_relation(),
ref.get_father_relation()) for ref in
family.get_child_ref_list()
if ref.ref == person_handle]
if gender == gen.lib.Person.MALE :
person = database.get_person_from_handle(
family.get_father_handle())
refnr = 1
else :
person = database.get_person_from_handle(
family.get_mother_handle())
refnr = 0
#We do not allow for same sex marriages when going up
# that would complicate the code
#Also, we assume the birth relation is in the FIRST
# family of the person, so we go up on non-birth
if not childrel[0][refnr] == gen.lib.ChildRefType.BIRTH :
rem_str = add_rem(rem_str, _("No birth relation with child"))
if person and person.gender == gender :
break
elif person and person.gender == gen.lib.Person.UNKNOWN :
rem_str = add_rem(rem_str, _("Unknown gender"))
break
else :
person = None
def make_details_child(gender, person, sa, sd, database) :
""" Function that prints the details of the children in the
male/female lineage
"""
def make_child_line(child, prepend, generation) :
""" Recursively called funcion to write one child line
Person is the child, prepend is the string that preceeds it
on print. As the recursion grows, prepend is increased
Gen is the generation level
"""
if generation > __MAX_GEN :
raise RuntimeError
#we use some global var from make_details_child !
rem_str = ""
if child.gender == gen.lib.Person.UNKNOWN :
rem_str = add_rem(rem_str, _("Unknown gender"))
if rem_str :
rem_str = _("Remark")+": "+rem_str
front = ""
if prepend :
front = prepend + "-"
sd.paragraph(front + "%s (%s - %s) %s" % (sa.name(child),
sa.birth_date(child),
sa.death_date(child), rem_str))
#obtain families in which child is a parent
family_handles = child.get_family_handle_list()
for fam_handle in family_handles :
fam = database.get_family_from_handle(fam_handle)
#what parent is the previous child? We are fancy and allow
# for same sex marriage
if fam.get_father_handle() == child.handle :
childrelnr = 2
elif fam.get_mother_handle() == child.handle :
childrelnr = 1
else :
#something wrong with this family, continue with next
continue
childrel = [(ref.ref, ref.get_mother_relation(),
ref.get_father_relation()) for ref in
fam.get_child_ref_list()]
for childdet in childrel:
#relation with parent must be by birth
if not childdet[childrelnr] == gen.lib.ChildRefType.BIRTH :
continue
newchild = database.get_person_from_handle(childdet[0])
# person must have the required gender
if newchild and newchild.gender == gender :
make_child_line(newchild, prepend + ' |', generation+1)
# loop over all children of gender and output, start with no prepend
try :
make_child_line(person, "", 0)
except RuntimeError:
sd.paragraph("")
sd.paragraph(_("ERROR : Too many levels in the tree "
"(perhaps a loop?)."))
def add_rem(remark, text):
""" Allow for extension of remark, return new remark string
"""
if remark:
return remark + ', ' + text
else:
return text
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
pmgr = PluginManager.get_instance()
pmgr.register_quick_report(
name = 'father_lineage',
category = CATEGORY_QR_PERSON,
run_func = run_father,
translated_name = _("Father lineage"),
status = _("Stable"),
description= _("Display father lineage"),
author_name="B. Malengier",
author_email="benny.malengier@gramps-project.org"
)
pmgr.register_quick_report(
name = 'mother_lineage',
category = CATEGORY_QR_PERSON,
run_func = run_mother,
translated_name = _("Mother lineage"),
status = _("Stable"),
description= _("Display mother lineage"),
author_name="B. Malengier",
author_email="benny.malengier@gramps-project.org"
)