Versions of Reinhard Müller's WhatsNext and Records gramplets
svn: r11526
This commit is contained in:
parent
f22c6835a2
commit
e9bf31ef33
654
src/plugins/Records.py
Normal file
654
src/plugins/Records.py
Normal file
@ -0,0 +1,654 @@
|
|||||||
|
# encoding:utf-8
|
||||||
|
#
|
||||||
|
# Gramps - a GTK+/GNOME based genealogy program - Records plugin
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008 Reinhard Müller
|
||||||
|
#
|
||||||
|
# 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: $
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Standard Python modules
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# GRAMPS modules
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
from gen.lib import Date, EventType, Name
|
||||||
|
import BaseDoc
|
||||||
|
from BasicUtils import name_displayer
|
||||||
|
from DataViews import register, Gramplet
|
||||||
|
from gen.plug.menu import (BooleanOption, EnumeratedListOption,
|
||||||
|
FilterOption, PersonOption)
|
||||||
|
from ReportBase import Report, ReportUtils, MenuReportOptions, \
|
||||||
|
CATEGORY_TEXT
|
||||||
|
from gen.plug import PluginManager
|
||||||
|
|
||||||
|
MODE_GUI = PluginManager.REPORT_MODE_GUI
|
||||||
|
MODE_BKI = PluginManager.REPORT_MODE_BKI
|
||||||
|
MODE_CLI = PluginManager.REPORT_MODE_CLI
|
||||||
|
|
||||||
|
# from TransUtils import sgettext as _
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Global functions
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def _find_records(db, filter, callname):
|
||||||
|
|
||||||
|
today = datetime.date.today()
|
||||||
|
today_date = Date(today.year, today.month, today.day)
|
||||||
|
|
||||||
|
# Person records
|
||||||
|
person_youngestliving = []
|
||||||
|
person_oldestliving = []
|
||||||
|
person_youngestdied = []
|
||||||
|
person_oldestdied = []
|
||||||
|
person_youngestmarried = []
|
||||||
|
person_oldestmarried = []
|
||||||
|
person_youngestdivorced = []
|
||||||
|
person_oldestdivorced = []
|
||||||
|
person_youngestfather = []
|
||||||
|
person_youngestmother = []
|
||||||
|
person_oldestfather = []
|
||||||
|
person_oldestmother = []
|
||||||
|
|
||||||
|
person_handle_list = db.get_person_handles(sort_handles=False)
|
||||||
|
|
||||||
|
if filter:
|
||||||
|
person_handle_list = filter.apply(db, person_handle_list)
|
||||||
|
|
||||||
|
for person_handle in person_handle_list:
|
||||||
|
person = db.get_person_from_handle(person_handle)
|
||||||
|
|
||||||
|
birth_ref = person.get_birth_ref()
|
||||||
|
|
||||||
|
if not birth_ref:
|
||||||
|
# No birth event, so we can't calculate any age.
|
||||||
|
continue
|
||||||
|
|
||||||
|
birth = db.get_event_from_handle(birth_ref.ref)
|
||||||
|
birth_date = birth.get_date_object()
|
||||||
|
|
||||||
|
death_ref = person.get_death_ref()
|
||||||
|
if death_ref:
|
||||||
|
death = db.get_event_from_handle(death_ref.ref)
|
||||||
|
death_date = death.get_date_object()
|
||||||
|
else:
|
||||||
|
death_date = None
|
||||||
|
|
||||||
|
if not birth_date.is_regular():
|
||||||
|
# Birth date unknown or incomplete, so we can't calculate any age.
|
||||||
|
continue
|
||||||
|
|
||||||
|
name = _person_get_display_name(person, callname)
|
||||||
|
|
||||||
|
if death_ref is None:
|
||||||
|
# Still living, look for age records
|
||||||
|
_record(person_youngestliving, person_oldestliving,
|
||||||
|
today_date - birth_date, name, 'Person', person_handle)
|
||||||
|
elif death_date.is_regular():
|
||||||
|
# Already died, look for age records
|
||||||
|
_record(person_youngestdied, person_oldestdied,
|
||||||
|
death_date - birth_date, name, 'Person', person_handle)
|
||||||
|
|
||||||
|
for family_handle in person.get_family_handle_list():
|
||||||
|
family = db.get_family_from_handle(family_handle)
|
||||||
|
|
||||||
|
marriage_date = None
|
||||||
|
divorce_date = None
|
||||||
|
for event_ref in family.get_event_ref_list():
|
||||||
|
event = db.get_event_from_handle(event_ref.ref)
|
||||||
|
if event.get_type() == EventType.MARRIAGE:
|
||||||
|
marriage_date = event.get_date_object()
|
||||||
|
elif event.get_type() == EventType.DIVORCE:
|
||||||
|
divorce_date = event.get_date_object()
|
||||||
|
|
||||||
|
if marriage_date is not None and marriage_date.is_regular():
|
||||||
|
_record(person_youngestmarried, person_oldestmarried,
|
||||||
|
marriage_date - birth_date,
|
||||||
|
name, 'Person', person_handle)
|
||||||
|
|
||||||
|
if divorce_date is not None and divorce_date.is_regular():
|
||||||
|
_record(person_youngestdivorced, person_oldestdivorced,
|
||||||
|
divorce_date - birth_date,
|
||||||
|
name, 'Person', person_handle)
|
||||||
|
|
||||||
|
for child_ref in family.get_child_ref_list():
|
||||||
|
child = db.get_person_from_handle(child_ref.ref)
|
||||||
|
|
||||||
|
child_birth_ref = child.get_birth_ref()
|
||||||
|
if not child_birth_ref:
|
||||||
|
continue
|
||||||
|
|
||||||
|
child_birth = db.get_event_from_handle(child_birth_ref.ref)
|
||||||
|
child_birth_date = child_birth.get_date_object()
|
||||||
|
|
||||||
|
if not child_birth_date.is_regular():
|
||||||
|
continue
|
||||||
|
|
||||||
|
if person.get_gender() == person.MALE:
|
||||||
|
_record(person_youngestfather, person_oldestfather,
|
||||||
|
child_birth_date - birth_date,
|
||||||
|
name, 'Person', person_handle)
|
||||||
|
elif person.get_gender() == person.FEMALE:
|
||||||
|
_record(person_youngestmother, person_oldestmother,
|
||||||
|
child_birth_date - birth_date,
|
||||||
|
name, 'Person', person_handle)
|
||||||
|
|
||||||
|
|
||||||
|
# Family records
|
||||||
|
family_mostchildren = []
|
||||||
|
family_youngestmarried = []
|
||||||
|
family_oldestmarried = []
|
||||||
|
family_shortest = []
|
||||||
|
family_longest = []
|
||||||
|
|
||||||
|
for family_handle in db.get_family_handles():
|
||||||
|
family = db.get_family_from_handle(family_handle)
|
||||||
|
|
||||||
|
father_handle = family.get_father_handle()
|
||||||
|
if not father_handle:
|
||||||
|
continue
|
||||||
|
mother_handle = family.get_mother_handle()
|
||||||
|
if not mother_handle:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Test if either father or mother are in filter
|
||||||
|
if filter:
|
||||||
|
if not filter.apply(db, [father_handle, mother_handle]):
|
||||||
|
continue
|
||||||
|
|
||||||
|
father = db.get_person_from_handle(father_handle)
|
||||||
|
mother = db.get_person_from_handle(mother_handle)
|
||||||
|
|
||||||
|
name = _("%s and %s") % (
|
||||||
|
_person_get_display_name(father, callname),
|
||||||
|
_person_get_display_name(mother, callname))
|
||||||
|
|
||||||
|
_record(None, family_mostchildren,
|
||||||
|
len(family.get_child_ref_list()),
|
||||||
|
name, 'Family', family_handle)
|
||||||
|
|
||||||
|
marriage = None
|
||||||
|
divorce = None
|
||||||
|
marriage_date = None
|
||||||
|
divorce_date = None
|
||||||
|
for event_ref in family.get_event_ref_list():
|
||||||
|
event = db.get_event_from_handle(event_ref.ref)
|
||||||
|
if event.get_type() == EventType.MARRIAGE:
|
||||||
|
marriage = event
|
||||||
|
marriage_date = event.get_date_object()
|
||||||
|
elif event.get_type() == EventType.DIVORCE:
|
||||||
|
divorce = event
|
||||||
|
divorce_date = event.get_date_object()
|
||||||
|
|
||||||
|
father_death = None
|
||||||
|
father_death_date = None
|
||||||
|
father_death_ref = father.get_death_ref()
|
||||||
|
if father_death_ref:
|
||||||
|
father_death = db.get_event_from_handle(father_death_ref.ref)
|
||||||
|
father_death_date = father_death.get_date_object()
|
||||||
|
|
||||||
|
mother_death = None
|
||||||
|
mother_death_date = None
|
||||||
|
mother_death_ref = mother.get_death_ref()
|
||||||
|
if mother_death_ref:
|
||||||
|
mother_death = db.get_event_from_handle(mother_death_ref.ref)
|
||||||
|
mother_death_date = mother_death.get_date_object()
|
||||||
|
|
||||||
|
if not marriage or not marriage_date.is_regular():
|
||||||
|
# Not married or marriage date unknown
|
||||||
|
continue
|
||||||
|
|
||||||
|
if divorce and not divorce_date.is_regular():
|
||||||
|
# Divorced, but divorce date unknown
|
||||||
|
continue
|
||||||
|
|
||||||
|
if father_death and (not father_death_date or not father_death_date.is_regular()):
|
||||||
|
# Father dead, but death date unknown
|
||||||
|
continue
|
||||||
|
|
||||||
|
if mother_death and (not mother_death_date or not mother_death_date.is_regular()):
|
||||||
|
# Mother dead, but death date unknown
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not divorce and not father_death and not mother_death:
|
||||||
|
# Still married and alive
|
||||||
|
_record(family_youngestmarried, family_oldestmarried,
|
||||||
|
today_date - marriage_date,
|
||||||
|
name, 'Family', family_handle)
|
||||||
|
else:
|
||||||
|
end = None
|
||||||
|
if father_death and mother_death:
|
||||||
|
end = min(father_death_date, mother_death_date)
|
||||||
|
elif father_death:
|
||||||
|
end = father_death_date
|
||||||
|
elif mother_death:
|
||||||
|
end = mother_death_date
|
||||||
|
if divorce:
|
||||||
|
if end:
|
||||||
|
end = min(end, divorce_date)
|
||||||
|
else:
|
||||||
|
end = divorce_date
|
||||||
|
duration = end - marriage_date
|
||||||
|
|
||||||
|
_record(family_shortest, family_longest,
|
||||||
|
end - marriage_date, name, 'Family', family_handle)
|
||||||
|
|
||||||
|
return [(text, varname, locals()[varname]) for (text, varname, default) in RECORDS]
|
||||||
|
|
||||||
|
|
||||||
|
def _person_get_display_name(person, callname):
|
||||||
|
|
||||||
|
# Make a copy of the name object so we don't mess around with the real
|
||||||
|
# data.
|
||||||
|
n = Name(source=person.get_primary_name())
|
||||||
|
|
||||||
|
if n.call:
|
||||||
|
if callname == RecordsReportOptions.CALLNAME_REPLACE:
|
||||||
|
n.first_name = n.call
|
||||||
|
elif callname == RecordsReportOptions.CALLNAME_UNDERLINE_ADD:
|
||||||
|
if n.call in n.first_name:
|
||||||
|
(before, after) = n.first_name.split(n.call)
|
||||||
|
n.first_name = "%(before)s<u>%(call)s</u>%(after)s" % {
|
||||||
|
'before': before,
|
||||||
|
'call': n.call,
|
||||||
|
'after': after}
|
||||||
|
else:
|
||||||
|
n.first_name = "\"%(call)s\" (%(first)s)" % {
|
||||||
|
'call': n.call,
|
||||||
|
'first': n.first_name}
|
||||||
|
|
||||||
|
return name_displayer.display_name(n)
|
||||||
|
|
||||||
|
|
||||||
|
def _record(lowest, highest, value, text, handle_type, handle):
|
||||||
|
|
||||||
|
if lowest is not None:
|
||||||
|
lowest.append((value, text, handle_type, handle))
|
||||||
|
lowest.sort(lambda a,b: cmp(a[0], b[0]))
|
||||||
|
for i in range(3, len(lowest)):
|
||||||
|
if lowest[i-1][0] < lowest[i][0]:
|
||||||
|
del lowest[i:]
|
||||||
|
break
|
||||||
|
|
||||||
|
if highest is not None:
|
||||||
|
highest.append((value, text, handle_type, handle))
|
||||||
|
highest.sort(reverse=True)
|
||||||
|
for i in range(3, len(highest)):
|
||||||
|
if highest[i-1][0] > highest[i][0]:
|
||||||
|
del highest[i:]
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
def _output(value):
|
||||||
|
|
||||||
|
if isinstance(value, tuple) and len(value) == 3:
|
||||||
|
# time span as years, months, days
|
||||||
|
(years, months, days) = value
|
||||||
|
result = []
|
||||||
|
if years == 1:
|
||||||
|
result.append(_("1 year"))
|
||||||
|
elif years != 0:
|
||||||
|
result.append(_("%s years") % years)
|
||||||
|
if months == 1:
|
||||||
|
result.append(_("1 month"))
|
||||||
|
elif months != 0:
|
||||||
|
result.append(_("%s months") % months)
|
||||||
|
if days == 1:
|
||||||
|
result.append(_("1 day"))
|
||||||
|
elif days != 0:
|
||||||
|
result.append(_("%s days") % days)
|
||||||
|
if not result:
|
||||||
|
result.append(_("0 days"))
|
||||||
|
return ", ".join(result)
|
||||||
|
else:
|
||||||
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# The Gramplet
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
class RecordsGramplet(Gramplet):
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
self.set_use_markup(True)
|
||||||
|
self.tooltip = _("Double-click name for details")
|
||||||
|
self.set_text(_("No Family Tree loaded."))
|
||||||
|
|
||||||
|
|
||||||
|
def db_changed(self):
|
||||||
|
|
||||||
|
self.dbstate.db.connect('person-add', self.update)
|
||||||
|
self.dbstate.db.connect('person-delete', self.update)
|
||||||
|
self.dbstate.db.connect('person-update', self.update)
|
||||||
|
self.dbstate.db.connect('family-add', self.update)
|
||||||
|
self.dbstate.db.connect('family-delete', self.update)
|
||||||
|
self.dbstate.db.connect('family-update', self.update)
|
||||||
|
|
||||||
|
|
||||||
|
def main(self):
|
||||||
|
|
||||||
|
self.set_text(_("Processing...") + "\n")
|
||||||
|
records = _find_records(self.dbstate.db, None,
|
||||||
|
RecordsReportOptions.CALLNAME_DONTUSE)
|
||||||
|
self.set_text("")
|
||||||
|
for (text, varname, top3) in records:
|
||||||
|
self.render_text("<b>%s</b>" % text)
|
||||||
|
last_value = None
|
||||||
|
rank = 0
|
||||||
|
for (number, (value, name, handletype, handle)) in enumerate(top3):
|
||||||
|
if value != last_value:
|
||||||
|
last_value = value
|
||||||
|
rank = number
|
||||||
|
self.append_text("\n %s. " % (rank+1))
|
||||||
|
# TODO: When linktype 'Family' is introduced, use this:
|
||||||
|
# self.link(name, handletype, handle)
|
||||||
|
# TODO: instead of this:
|
||||||
|
if handletype == 'Family':
|
||||||
|
family = self.dbstate.db.get_family_from_handle(handle)
|
||||||
|
father_handle = family.get_father_handle()
|
||||||
|
father = self.dbstate.db.get_person_from_handle(father_handle)
|
||||||
|
father_name = _person_get_display_name(father, RecordsReportOptions.CALLNAME_DONTUSE)
|
||||||
|
self.link(father_name, 'Person', father_handle)
|
||||||
|
self.append_text(_(" and "))
|
||||||
|
mother_handle = family.get_mother_handle()
|
||||||
|
mother = self.dbstate.db.get_person_from_handle(mother_handle)
|
||||||
|
mother_name = _person_get_display_name(mother, RecordsReportOptions.CALLNAME_DONTUSE)
|
||||||
|
self.link(mother_name, 'Person', mother_handle)
|
||||||
|
else:
|
||||||
|
self.link(name, handletype, handle)
|
||||||
|
# TODO: end.
|
||||||
|
self.append_text(" (%s)" % _output(value))
|
||||||
|
self.append_text("\n")
|
||||||
|
self.append_text("", scroll_to='begin')
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# The Report
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
class RecordsReport(Report):
|
||||||
|
|
||||||
|
def __init__(self, database, options_class):
|
||||||
|
|
||||||
|
Report.__init__(self, database, options_class)
|
||||||
|
menu = options_class.menu
|
||||||
|
|
||||||
|
self.filter_option = menu.get_option_by_name('filter')
|
||||||
|
self.filter = self.filter_option.get_filter()
|
||||||
|
|
||||||
|
self.callname = menu.get_option_by_name('callname').get_value()
|
||||||
|
|
||||||
|
self.include = {}
|
||||||
|
for (text, varname, default) in RECORDS:
|
||||||
|
self.include[varname] = menu.get_option_by_name(varname).get_value()
|
||||||
|
|
||||||
|
|
||||||
|
def write_report(self):
|
||||||
|
"""
|
||||||
|
Build the actual report.
|
||||||
|
"""
|
||||||
|
|
||||||
|
records = _find_records(self.database, self.filter, self.callname)
|
||||||
|
|
||||||
|
self.doc.start_paragraph('REC-Title')
|
||||||
|
self.doc.write_text(_("Records"))
|
||||||
|
self.doc.end_paragraph()
|
||||||
|
|
||||||
|
for (text, varname, top3) in records:
|
||||||
|
if not self.include[varname]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.doc.start_paragraph('REC-Heading')
|
||||||
|
self.doc.write_text(text)
|
||||||
|
self.doc.end_paragraph()
|
||||||
|
|
||||||
|
last_value = None
|
||||||
|
rank = 0
|
||||||
|
for (number, (value, name, handletype, handle)) in enumerate(top3):
|
||||||
|
if value != last_value:
|
||||||
|
last_value = value
|
||||||
|
rank = number
|
||||||
|
self.doc.start_paragraph('REC-Normal')
|
||||||
|
self.doc.write_text(_("%(number)s. %(name)s (%(value)s)") % {
|
||||||
|
'number': rank+1,
|
||||||
|
'name': name,
|
||||||
|
'value': _output(value)})
|
||||||
|
self.doc.end_paragraph()
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# MenuReportOptions
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
class RecordsReportOptions(MenuReportOptions):
|
||||||
|
"""
|
||||||
|
Defines options and provides handling interface.
|
||||||
|
"""
|
||||||
|
|
||||||
|
CALLNAME_DONTUSE = 0
|
||||||
|
CALLNAME_REPLACE = 1
|
||||||
|
CALLNAME_UNDERLINE_ADD = 2
|
||||||
|
|
||||||
|
def __init__(self, name, dbase):
|
||||||
|
|
||||||
|
self.__pid = None
|
||||||
|
self.__filter = None
|
||||||
|
self.__db = dbase
|
||||||
|
MenuReportOptions.__init__(self, name, dbase)
|
||||||
|
|
||||||
|
|
||||||
|
def add_menu_options(self, menu):
|
||||||
|
|
||||||
|
category_name = _("Report Options")
|
||||||
|
|
||||||
|
self.__filter = FilterOption(_("Filter"), 0)
|
||||||
|
self.__filter.set_help(
|
||||||
|
_("Determines what people are included in the report"))
|
||||||
|
menu.add_option(category_name, "filter", self.__filter)
|
||||||
|
self.__filter.connect('value-changed', self.__filter_changed)
|
||||||
|
|
||||||
|
self.__pid = PersonOption(_("Filter Person"))
|
||||||
|
self.__pid.set_help(_("The center person for the filter"))
|
||||||
|
menu.add_option(category_name, "pid", self.__pid)
|
||||||
|
self.__pid.connect('value-changed', self.__update_filters)
|
||||||
|
|
||||||
|
self.__update_filters()
|
||||||
|
|
||||||
|
callname = EnumeratedListOption(_("Use call name"), self.CALLNAME_DONTUSE)
|
||||||
|
callname.set_items([
|
||||||
|
(self.CALLNAME_DONTUSE, _("Don't use call name")),
|
||||||
|
(self.CALLNAME_REPLACE, _("Replace first name with call name")),
|
||||||
|
(self.CALLNAME_UNDERLINE_ADD, _("Underline call name in first name / add call name to first name"))])
|
||||||
|
menu.add_option(category_name, "callname", callname)
|
||||||
|
|
||||||
|
for (text, varname, default) in RECORDS:
|
||||||
|
option = BooleanOption(text, default)
|
||||||
|
if varname.startswith('person'):
|
||||||
|
category_name = _("Person Records")
|
||||||
|
elif varname.startswith('family'):
|
||||||
|
category_name = _("Family Records")
|
||||||
|
menu.add_option(category_name, varname, option)
|
||||||
|
|
||||||
|
|
||||||
|
def __update_filters(self):
|
||||||
|
"""
|
||||||
|
Update the filter list based on the selected person
|
||||||
|
"""
|
||||||
|
gid = self.__pid.get_value()
|
||||||
|
person = self.__db.get_person_from_gramps_id(gid)
|
||||||
|
filter_list = ReportUtils.get_person_filters(person, False)
|
||||||
|
self.__filter.set_filters(filter_list)
|
||||||
|
|
||||||
|
|
||||||
|
def __filter_changed(self):
|
||||||
|
"""
|
||||||
|
Handle filter change. If the filter is not specific to a person,
|
||||||
|
disable the person option
|
||||||
|
"""
|
||||||
|
filter_value = self.__filter.get_value()
|
||||||
|
if filter_value in [1, 2, 3, 4]:
|
||||||
|
# Filters 1, 2, 3 and 4 rely on the center person
|
||||||
|
self.__pid.set_available(True)
|
||||||
|
else:
|
||||||
|
# The rest don't
|
||||||
|
self.__pid.set_available(False)
|
||||||
|
|
||||||
|
|
||||||
|
def make_default_style(self, default_style):
|
||||||
|
|
||||||
|
#Paragraph Styles
|
||||||
|
font = BaseDoc.FontStyle()
|
||||||
|
font.set_type_face(BaseDoc.FONT_SANS_SERIF)
|
||||||
|
font.set_size(10)
|
||||||
|
font.set_bold(0)
|
||||||
|
para = BaseDoc.ParagraphStyle()
|
||||||
|
para.set_font(font)
|
||||||
|
para.set_description(_('The basic style used for the text display.'))
|
||||||
|
default_style.add_paragraph_style('REC-Normal', para)
|
||||||
|
|
||||||
|
font = BaseDoc.FontStyle()
|
||||||
|
font.set_type_face(BaseDoc.FONT_SANS_SERIF)
|
||||||
|
font.set_size(10)
|
||||||
|
font.set_bold(1)
|
||||||
|
para = BaseDoc.ParagraphStyle()
|
||||||
|
para.set_font(font)
|
||||||
|
para.set_description(_('The style used for headings.'))
|
||||||
|
default_style.add_paragraph_style('REC-Heading', para)
|
||||||
|
|
||||||
|
font = BaseDoc.FontStyle()
|
||||||
|
font.set_type_face(BaseDoc.FONT_SANS_SERIF)
|
||||||
|
font.set_size(12)
|
||||||
|
font.set_bold(1)
|
||||||
|
para = BaseDoc.ParagraphStyle()
|
||||||
|
para.set_font(font)
|
||||||
|
para.set_description(_("The style used for the report title"))
|
||||||
|
default_style.add_paragraph_style('REC-Title', para)
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Translation hack
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
mytranslation = {
|
||||||
|
u"Records" : u"Rekorde",
|
||||||
|
u"%s and %s" : u"%s und %s",
|
||||||
|
u" and " : u" und ",
|
||||||
|
u"1 year" : u"1 Jahr",
|
||||||
|
u"%s years" : u"%s Jahre",
|
||||||
|
u"1 month" : u"1 Monat",
|
||||||
|
u"%s months" : u"%s Monate",
|
||||||
|
u"1 day" : u"1 Tag",
|
||||||
|
u"%s days" : u"%s Tage",
|
||||||
|
u"0 days" : u"0 Tage",
|
||||||
|
u"Youngest living person" : u"Nesthäkchen",
|
||||||
|
u"Oldest living person" : u"Älteste lebende Person",
|
||||||
|
u"Person died at youngest age" : u"Am jüngsten gestorbene Person",
|
||||||
|
u"Person died at oldest age" : u"Im höchsten Alter gestorbene Person",
|
||||||
|
u"Person married at youngest age" : u"Am jüngsten geheiratete Person",
|
||||||
|
u"Person married at oldest age" : u"Am ältesten geheiratete Person",
|
||||||
|
u"Person divorced at youngest age": u"Am jüngsten geschiedene Person",
|
||||||
|
u"Person divorced at oldest age" : u"Am ältesten geschiedene Person",
|
||||||
|
u"Youngest father" : u"Jüngster Vater",
|
||||||
|
u"Youngest mother" : u"Jüngste Mutter",
|
||||||
|
u"Oldest father" : u"Ältester Vater",
|
||||||
|
u"Oldest mother" : u"Älteste Mutter",
|
||||||
|
u"Couple with most children" : u"Familie mit den meisten Kindern",
|
||||||
|
u"Couple married most recently" : u"Zuletzt geheiratetes Paar",
|
||||||
|
u"Couple married most long ago" : u"Am längsten verheiratetes Paar",
|
||||||
|
u"Shortest marriage" : u"Kürzeste Ehe",
|
||||||
|
u"Longest marriage" : u"Längste Ehe"}
|
||||||
|
|
||||||
|
from gettext import gettext
|
||||||
|
import locale
|
||||||
|
lang = locale.getdefaultlocale()[0]
|
||||||
|
if lang:
|
||||||
|
lang = lang.split('_')[0]
|
||||||
|
def _(string):
|
||||||
|
if lang == 'de':
|
||||||
|
print string
|
||||||
|
return mytranslation.get(string, gettext(string))
|
||||||
|
else:
|
||||||
|
return gettext(string)
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# List of records (must be defined after declaration of _())
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
RECORDS = [
|
||||||
|
(_("Youngest living person"), 'person_youngestliving', True),
|
||||||
|
(_("Oldest living person"), 'person_oldestliving', True),
|
||||||
|
(_("Person died at youngest age"), 'person_youngestdied', False),
|
||||||
|
(_("Person died at oldest age"), 'person_oldestdied', True),
|
||||||
|
(_("Person married at youngest age"), 'person_youngestmarried', True),
|
||||||
|
(_("Person married at oldest age"), 'person_oldestmarried', True),
|
||||||
|
(_("Person divorced at youngest age"), 'person_youngestdivorced', False),
|
||||||
|
(_("Person divorced at oldest age"), 'person_oldestdivorced', False),
|
||||||
|
(_("Youngest father"), 'person_youngestfather', True),
|
||||||
|
(_("Youngest mother"), 'person_youngestmother', True),
|
||||||
|
(_("Oldest father"), 'person_oldestfather', True),
|
||||||
|
(_("Oldest mother"), 'person_oldestmother', True),
|
||||||
|
(_("Couple with most children"), 'family_mostchildren', True),
|
||||||
|
(_("Couple married most recently"), 'family_youngestmarried', True),
|
||||||
|
(_("Couple married most long ago"), 'family_oldestmarried', True),
|
||||||
|
(_("Shortest marriage"), 'family_shortest', False),
|
||||||
|
(_("Longest marriage"), 'family_longest', True)]
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Register the gramplet and the report
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
pmgr = PluginManager.get_instance()
|
||||||
|
register(
|
||||||
|
type="gramplet",
|
||||||
|
name= "Records Gramplet",
|
||||||
|
tname=_("Records Gramplet"),
|
||||||
|
height=230,
|
||||||
|
expand=True,
|
||||||
|
content = RecordsGramplet,
|
||||||
|
title=_("Records"))
|
||||||
|
|
||||||
|
pmgr.register_report(
|
||||||
|
name = 'records',
|
||||||
|
category = CATEGORY_TEXT,
|
||||||
|
report_class = RecordsReport,
|
||||||
|
options_class = RecordsReportOptions,
|
||||||
|
modes = MODE_GUI | MODE_BKI | MODE_CLI,
|
||||||
|
translated_name = _("Records Report"),
|
||||||
|
status = _("Stable"),
|
||||||
|
author_name = u"Reinhard Müller",
|
||||||
|
author_email = "reinhard.mueller@bytewise.at",
|
||||||
|
description = _(
|
||||||
|
"Shows some interesting records about people and families"))
|
475
src/plugins/WhatsNext.py
Normal file
475
src/plugins/WhatsNext.py
Normal file
@ -0,0 +1,475 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
#
|
||||||
|
# Gramps - a GTK+/GNOME based genealogy program - What Next Gramplet plugin
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008 Reinhard Mueller
|
||||||
|
#
|
||||||
|
# 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: $
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# GRAMPS modules
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
from gen.lib import EventType, FamilyRelType
|
||||||
|
from BasicUtils import name_displayer
|
||||||
|
from DataViews import register, Gramplet
|
||||||
|
from ReportBase import ReportUtils
|
||||||
|
#from TransUtils import sgettext as _
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# The Gramplet
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
class WhatNextGramplet(Gramplet):
|
||||||
|
|
||||||
|
# Minimum number of lines we want to see. Further lines with the same
|
||||||
|
# distance to the main person will be added on top of this.
|
||||||
|
TODOS_WANTED = 10
|
||||||
|
|
||||||
|
# How many generations of descendants to process before we go up to the
|
||||||
|
# next level of ancestors.
|
||||||
|
DOWNS_PER_UP = 2
|
||||||
|
|
||||||
|
# After an ancestor was processed, how many extra rounds to delay until the
|
||||||
|
# descendants of this ancestor are processed.
|
||||||
|
ANCESTOR_DELAY = 1
|
||||||
|
|
||||||
|
# After a spouse was processed, how many extra rounds to delay until the
|
||||||
|
# ancestors of this spouse are processed.
|
||||||
|
SPOUSE_DELAY = 1
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
|
||||||
|
self.tooltip = _("Double-click name for details")
|
||||||
|
self.set_text(_("No Family Tree loaded."))
|
||||||
|
|
||||||
|
|
||||||
|
def db_changed(self):
|
||||||
|
|
||||||
|
self.dbstate.db.connect('person-add', self.update)
|
||||||
|
self.dbstate.db.connect('person-delete', self.update)
|
||||||
|
self.dbstate.db.connect('person-update', self.update)
|
||||||
|
self.dbstate.db.connect('family-add', self.update)
|
||||||
|
self.dbstate.db.connect('family-delete', self.update)
|
||||||
|
self.dbstate.db.connect('family-update', self.update)
|
||||||
|
|
||||||
|
|
||||||
|
def main(self):
|
||||||
|
|
||||||
|
default_person = self.dbstate.db.get_default_person()
|
||||||
|
if default_person == None:
|
||||||
|
self.set_text(_("No Home Person set."))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.__counter = 0
|
||||||
|
self.__level = 1
|
||||||
|
|
||||||
|
self.set_text("")
|
||||||
|
|
||||||
|
|
||||||
|
# List of already processed persons and families, to avoid recursing
|
||||||
|
# back down to ourselves or meeting the same person through different
|
||||||
|
# paths.
|
||||||
|
self.__processed_persons = {default_person.get_handle(): True}
|
||||||
|
self.__processed_families = {}
|
||||||
|
|
||||||
|
# List of lists of ancestors in currently processed generation. We go
|
||||||
|
# up one generation in each round.
|
||||||
|
# The lists are separated into my own ancestors, the ancestors of my
|
||||||
|
# spouses, the ancestors of my children's spouses, the ancestors of my
|
||||||
|
# parent's other spouses, the ancestors of my grandchildren's spouses,
|
||||||
|
# the ancestors of my sibling's spouses etc.
|
||||||
|
ancestors = [[default_person]]
|
||||||
|
ancestors_queue = [[[default_person]]] + [[]] * self.ANCESTOR_DELAY
|
||||||
|
|
||||||
|
# List of lists of families of relatives in currently processed
|
||||||
|
# distance. We go up one level of distance in each round.
|
||||||
|
# For example, at the end of the third round, this is (potentially) a
|
||||||
|
# list of 4 lists:
|
||||||
|
# 1. my own great-grandchildren
|
||||||
|
# 2. grandchildren of my parents (= my nephews and nieces)
|
||||||
|
# 3. children of my grandparents (= my uncles and aunts)
|
||||||
|
# 4. my great-grandparents
|
||||||
|
# At the beginning of the fourth round, the other families of my
|
||||||
|
# great-grandparents are added (if they were married more than once).
|
||||||
|
# The separation into these levels is done to allow the spouses of the
|
||||||
|
# earlier level to be listed before the kins of the later level, e.g.
|
||||||
|
# the spouses of my nephews and nieces are listed before my uncles and
|
||||||
|
# aunts.
|
||||||
|
# Not that this may slightly vary with the parameters given at the
|
||||||
|
# beginning of this class definition, but the principle remains the
|
||||||
|
# same.
|
||||||
|
families = []
|
||||||
|
families_queue = [[]] * self.ANCESTOR_DELAY
|
||||||
|
|
||||||
|
# List of spouses to add to ancestors list so we track ancestors of
|
||||||
|
# spouses, too, but delayed as defined by the parameter.
|
||||||
|
spouses = []
|
||||||
|
spouses_queue = [[]] * self.SPOUSE_DELAY
|
||||||
|
|
||||||
|
while (ancestors or families):
|
||||||
|
# (Other) families of parents
|
||||||
|
for ancestor_group in ancestors_queue.pop(0):
|
||||||
|
new_family_group = []
|
||||||
|
new_spouses_group = []
|
||||||
|
for person in ancestor_group:
|
||||||
|
for family in self.__get_families(person):
|
||||||
|
spouse = self.__get_spouse(person, family)
|
||||||
|
if spouse:
|
||||||
|
self.__process_person(spouse)
|
||||||
|
new_spouses_group.append(spouse)
|
||||||
|
elif family.get_relationship() == FamilyRelType.MARRIED:
|
||||||
|
self.__missing_spouse(person)
|
||||||
|
self.__process_family(family, person, spouse)
|
||||||
|
new_family_group.append(family)
|
||||||
|
if new_family_group:
|
||||||
|
families.append(new_family_group)
|
||||||
|
if new_spouses_group:
|
||||||
|
spouses.append(new_spouses_group)
|
||||||
|
if self.__counter >= self.TODOS_WANTED:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Now add the spouses of last round to the list
|
||||||
|
spouses_queue.append(spouses)
|
||||||
|
ancestors += spouses_queue.pop(0)
|
||||||
|
|
||||||
|
# Separator between rounds
|
||||||
|
if self.__counter > 0:
|
||||||
|
self.append_text("\n")
|
||||||
|
self.__level += 1
|
||||||
|
|
||||||
|
# Next generation of children
|
||||||
|
spouses = []
|
||||||
|
for down in range(self.DOWNS_PER_UP):
|
||||||
|
new_families = []
|
||||||
|
for family_group in families:
|
||||||
|
children = []
|
||||||
|
for family in family_group:
|
||||||
|
for child in self.__get_children(family):
|
||||||
|
self.__process_person(child)
|
||||||
|
children.append(child)
|
||||||
|
if self.__counter >= self.TODOS_WANTED:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Families of children
|
||||||
|
new_family_group = []
|
||||||
|
new_spouses_group = []
|
||||||
|
for person in children:
|
||||||
|
for family in self.__get_families(person):
|
||||||
|
spouse = self.__get_spouse(person, family)
|
||||||
|
if spouse:
|
||||||
|
self.__process_person(spouse)
|
||||||
|
new_spouses_group.append(spouse)
|
||||||
|
elif family.get_relationship() == FamilyRelType.MARRIED:
|
||||||
|
self.__missing_spouse(person)
|
||||||
|
self.__process_family(family, person, spouse)
|
||||||
|
new_family_group.append(family)
|
||||||
|
if new_family_group:
|
||||||
|
new_families.append(new_family_group)
|
||||||
|
if new_spouses_group:
|
||||||
|
spouses.append(new_spouses_group)
|
||||||
|
if self.__counter >= self.TODOS_WANTED:
|
||||||
|
break
|
||||||
|
families = new_families
|
||||||
|
if self.__counter >= self.TODOS_WANTED:
|
||||||
|
break
|
||||||
|
if self.__counter >= self.TODOS_WANTED:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Parents
|
||||||
|
new_ancestors = []
|
||||||
|
new_families = []
|
||||||
|
for ancestor_group in ancestors:
|
||||||
|
new_ancestor_group = []
|
||||||
|
new_family_group = []
|
||||||
|
for person in ancestor_group:
|
||||||
|
(father, mother, family) = self.__get_parents(person)
|
||||||
|
if family:
|
||||||
|
if father:
|
||||||
|
self.__process_person(father)
|
||||||
|
new_ancestor_group.append(father)
|
||||||
|
elif family.get_relationship() == FamilyRelType.MARRIED:
|
||||||
|
self.__missing_father(person)
|
||||||
|
if mother:
|
||||||
|
self.__process_person(mother)
|
||||||
|
new_ancestor_group.append(mother)
|
||||||
|
else:
|
||||||
|
self.__missing_mother(person)
|
||||||
|
self.__process_family(family, father, mother)
|
||||||
|
new_family_group.append(family)
|
||||||
|
else:
|
||||||
|
self.__missing_parents(person)
|
||||||
|
if new_ancestor_group:
|
||||||
|
new_ancestors.append(new_ancestor_group)
|
||||||
|
if new_family_group:
|
||||||
|
new_families.append(new_family_group)
|
||||||
|
if self.__counter >= self.TODOS_WANTED:
|
||||||
|
break
|
||||||
|
ancestors = new_ancestors
|
||||||
|
ancestors_queue.append(ancestors)
|
||||||
|
families_queue.append(new_families)
|
||||||
|
families += families_queue.pop(0)
|
||||||
|
if self.__counter >= self.TODOS_WANTED:
|
||||||
|
break
|
||||||
|
|
||||||
|
self.append_text("", scroll_to='begin')
|
||||||
|
|
||||||
|
|
||||||
|
def __process_person(self, person):
|
||||||
|
|
||||||
|
self.__processed_persons[person.get_handle()] = True
|
||||||
|
|
||||||
|
missingbits = []
|
||||||
|
|
||||||
|
primary_name = person.get_primary_name()
|
||||||
|
|
||||||
|
if not primary_name.get_first_name():
|
||||||
|
missingbits.append(_("first name unknown"))
|
||||||
|
|
||||||
|
if not primary_name.get_surname():
|
||||||
|
missingbits.append(_("surname unknown"))
|
||||||
|
|
||||||
|
name = name_displayer.display_name(primary_name)
|
||||||
|
if not name:
|
||||||
|
name = _("(person with unknown name)")
|
||||||
|
|
||||||
|
has_birth = False
|
||||||
|
|
||||||
|
for event_ref in person.get_primary_event_ref_list():
|
||||||
|
event = self.dbstate.db.get_event_from_handle(event_ref.ref)
|
||||||
|
if event.get_type() not in [EventType.BIRTH, EventType.DEATH]:
|
||||||
|
continue
|
||||||
|
missingbits.extend(self.__process_event(event))
|
||||||
|
if event.get_type() == EventType.BIRTH:
|
||||||
|
has_birth = True
|
||||||
|
|
||||||
|
if not has_birth:
|
||||||
|
missingbits.append(_("birth event missing"))
|
||||||
|
|
||||||
|
if missingbits:
|
||||||
|
self.link(name, 'Person', person.get_handle())
|
||||||
|
self.append_text(_(": %(list)s\n") % {
|
||||||
|
'list': _(", ").join(missingbits)})
|
||||||
|
self.__counter += 1
|
||||||
|
|
||||||
|
|
||||||
|
def __process_family(self, family, person1, person2):
|
||||||
|
|
||||||
|
self.__processed_families[family.get_handle()] = True
|
||||||
|
|
||||||
|
missingbits = []
|
||||||
|
|
||||||
|
if person1:
|
||||||
|
name1 = name_displayer.display(person1)
|
||||||
|
if not name1:
|
||||||
|
name1 = _("(person with unknown name)")
|
||||||
|
else:
|
||||||
|
name1 = _("(unknown person)")
|
||||||
|
|
||||||
|
if person2:
|
||||||
|
name2 = name_displayer.display(person2)
|
||||||
|
if not name2:
|
||||||
|
name2 = _("(person with unknown name)")
|
||||||
|
else:
|
||||||
|
name2 = _("(unknown person)")
|
||||||
|
|
||||||
|
name = _("%(name1)s and %(name2)s") % {
|
||||||
|
'name1': name1,
|
||||||
|
'name2': name2}
|
||||||
|
|
||||||
|
has_marriage = False
|
||||||
|
|
||||||
|
for event_ref in family.get_event_ref_list():
|
||||||
|
event = self.dbstate.db.get_event_from_handle(event_ref.ref)
|
||||||
|
if event.get_type() not in [EventType.MARRIAGE, EventType.DIVORCE]:
|
||||||
|
continue
|
||||||
|
missingbits.extend(self.__process_event(event))
|
||||||
|
if event.get_type() == EventType.MARRIAGE:
|
||||||
|
has_marriage = True
|
||||||
|
|
||||||
|
if family.get_relationship() == FamilyRelType.MARRIED:
|
||||||
|
if not has_marriage:
|
||||||
|
missingbits.append(_("marriage event missing"))
|
||||||
|
elif family.get_relationship() == FamilyRelType.UNKNOWN:
|
||||||
|
missingbits.append(_("relation type unknown"))
|
||||||
|
|
||||||
|
if missingbits:
|
||||||
|
# TODO: When linktype 'Family' is introduced, use this:
|
||||||
|
# self.link(name, 'Family', family.get_handle())
|
||||||
|
# TODO: instead of this:
|
||||||
|
if person1:
|
||||||
|
self.link(name1, 'Person', person1.get_handle())
|
||||||
|
else:
|
||||||
|
self.append_text(name1)
|
||||||
|
self.append_text(_(" and "))
|
||||||
|
if person2:
|
||||||
|
self.link(name2, 'Person', person2.get_handle())
|
||||||
|
else:
|
||||||
|
self.append_text(name2)
|
||||||
|
# TODO: end.
|
||||||
|
self.append_text(_(": %(list)s\n") % {
|
||||||
|
'list': _(", ").join(missingbits)})
|
||||||
|
self.__counter += 1
|
||||||
|
|
||||||
|
|
||||||
|
def __process_event(self, event):
|
||||||
|
|
||||||
|
missingbits = []
|
||||||
|
|
||||||
|
date = event.get_date_object()
|
||||||
|
if date.is_empty():
|
||||||
|
missingbits.append(_("date unknown"))
|
||||||
|
elif not date.is_regular():
|
||||||
|
missingbits.append(_("date incomplete"))
|
||||||
|
|
||||||
|
place_handle = event.get_place_handle()
|
||||||
|
if not place_handle:
|
||||||
|
missingbits.append(_("place unknown"))
|
||||||
|
|
||||||
|
if missingbits:
|
||||||
|
return [_("%(type)s: %(list)s") % {
|
||||||
|
'type': event.get_type(),
|
||||||
|
'list': _(", ").join(missingbits)}]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def __missing_spouse(self, person):
|
||||||
|
self.__missing_link(person, _("spouse missing"))
|
||||||
|
|
||||||
|
|
||||||
|
def __missing_father(self, person):
|
||||||
|
self.__missing_link(person, _("father missing"))
|
||||||
|
|
||||||
|
|
||||||
|
def __missing_mother(self, person):
|
||||||
|
self.__missing_link(person, _("mother missing"))
|
||||||
|
|
||||||
|
|
||||||
|
def __missing_parents(self, person):
|
||||||
|
self.__missing_link(person, _("parents missing"))
|
||||||
|
|
||||||
|
|
||||||
|
def __missing_link(self, person, text):
|
||||||
|
|
||||||
|
name = name_displayer.display(person)
|
||||||
|
self.link(name, 'Person', person.get_handle())
|
||||||
|
self.append_text(_(": %s\n") % text)
|
||||||
|
self.__counter += 1
|
||||||
|
|
||||||
|
|
||||||
|
def __get_spouse(self, person, family):
|
||||||
|
|
||||||
|
spouse_handle = ReportUtils.find_spouse(person, family)
|
||||||
|
if not spouse_handle:
|
||||||
|
return None
|
||||||
|
if spouse_handle in self.__processed_persons:
|
||||||
|
return None
|
||||||
|
return self.dbstate.db.get_person_from_handle(spouse_handle)
|
||||||
|
|
||||||
|
|
||||||
|
def __get_children(self, family):
|
||||||
|
|
||||||
|
for child_ref in family.get_child_ref_list():
|
||||||
|
if child_ref.ref in self.__processed_persons:
|
||||||
|
continue
|
||||||
|
yield self.dbstate.db.get_person_from_handle(child_ref.ref)
|
||||||
|
|
||||||
|
|
||||||
|
def __get_families(self, person):
|
||||||
|
|
||||||
|
for family_handle in person.get_family_handle_list():
|
||||||
|
if family_handle in self.__processed_families:
|
||||||
|
continue
|
||||||
|
yield self.dbstate.db.get_family_from_handle(family_handle)
|
||||||
|
|
||||||
|
|
||||||
|
def __get_parents(self, person):
|
||||||
|
|
||||||
|
family_handle = person.get_main_parents_family_handle()
|
||||||
|
if not family_handle or family_handle in self.__processed_families:
|
||||||
|
return (None, None, None)
|
||||||
|
|
||||||
|
family = self.dbstate.db.get_family_from_handle(family_handle)
|
||||||
|
|
||||||
|
father_handle = family.get_father_handle()
|
||||||
|
if father_handle and father_handle not in self.__processed_persons:
|
||||||
|
father = self.dbstate.db.get_person_from_handle(father_handle)
|
||||||
|
else:
|
||||||
|
father = None
|
||||||
|
|
||||||
|
mother_handle = family.get_mother_handle()
|
||||||
|
if mother_handle and mother_handle not in self.__processed_persons:
|
||||||
|
mother = self.dbstate.db.get_person_from_handle(mother_handle)
|
||||||
|
else:
|
||||||
|
mother = None
|
||||||
|
|
||||||
|
return (father, mother, family)
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Translation hack
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
mytranslation = {
|
||||||
|
u"first name unknown" : u"Vorname unbekannt",
|
||||||
|
u"surname unknown" : u"Familienname unbekannt",
|
||||||
|
u"(person with unknown name)": u"(Person mit unbekanntem Namen)",
|
||||||
|
u"birth event missing" : u"Geburtsereignis fehlt",
|
||||||
|
u"(unknown person)" : u"(unbekannte Person)",
|
||||||
|
u"%(name1)s and %(name2)s" : u"%(name1)s und %(name2)s",
|
||||||
|
u" and " : u" und ",
|
||||||
|
u"marriage event missing" : u"Hochzeitsereignis fehlt",
|
||||||
|
u"relation type unknown" : u"Beziehungstyp unbekannt",
|
||||||
|
u"date unknown" : u"Datum unbekannt",
|
||||||
|
u"date incomplete" : u"Datum unvollständig",
|
||||||
|
u"place unknown" : u"Ort unbekannt",
|
||||||
|
u"spouse missing" : u"Partner fehlt",
|
||||||
|
u"father missing" : u"Vater fehlt",
|
||||||
|
u"mother missing" : u"Mutter fehlt",
|
||||||
|
u"parents missing" : u"Eltern fehlen"}
|
||||||
|
|
||||||
|
from gettext import gettext
|
||||||
|
import locale
|
||||||
|
lang = locale.getdefaultlocale()[0]
|
||||||
|
if lang:
|
||||||
|
lang = lang.split('_')[0]
|
||||||
|
def _(string):
|
||||||
|
if lang == 'de':
|
||||||
|
print string
|
||||||
|
return mytranslation.get(string, gettext(string))
|
||||||
|
else:
|
||||||
|
return gettext(string)
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Register the gramplet
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
register(
|
||||||
|
type = "gramplet",
|
||||||
|
name = "What's Next Gramplet",
|
||||||
|
tname =_("What's Next Gramplet"),
|
||||||
|
height = 230,
|
||||||
|
expand = True,
|
||||||
|
content = WhatNextGramplet,
|
||||||
|
title = _("What's Next?"))
|
Loading…
Reference in New Issue
Block a user