2007-12-02 Douglas S.Blank <dblank@cs.brynmawr.edu>
* src/gen/lib/date.py: added new method copy_ymd() * src/plugins/CalculateEstimatedDates.py: new tool based on MenuOptions: calculates estimated dates * src/PluginUtils/_PluginWindows.py: refactoring, cleanup * po/POTFILES.in: renamed PluginStatus.py -> PluginWindows.py svn: r9438
This commit is contained in:
parent
c545e281f4
commit
ea61a85402
@ -1,3 +1,9 @@
|
||||
2007-12-02 Douglas S.Blank <dblank@cs.brynmawr.edu>
|
||||
* src/gen/lib/date.py: added new method copy_ymd()
|
||||
* src/plugins/CalculateEstimatedDates.py: new tool based on
|
||||
MenuOptions: calculates estimated dates
|
||||
* src/PluginUtils/_PluginWindows.py: refactoring, cleanup
|
||||
|
||||
2007-12-01 Douglas S.Blank <dblank@cs.brynmawr.edu>
|
||||
* src/Editors/_EditFamily.py: fixed issues with latin american
|
||||
surname guessing
|
||||
@ -36,7 +42,7 @@
|
||||
Added a change column in repoview, model, database column storage
|
||||
|
||||
2007-11-29 Douglas S.Blank <dblank@cs.brynmawr.edu>
|
||||
* po//POTFILES.in: renamed PluginStatus.py -> PluginWindows.py
|
||||
* po/POTFILES.in: renamed PluginStatus.py -> PluginWindows.py
|
||||
|
||||
2007-11-29 Douglas S. Blank <dblank@cs.brynmawr.edu>
|
||||
* src/plugins/ImportCSV.py: add progress meter
|
||||
|
@ -44,6 +44,7 @@ import ManagedWindow
|
||||
import Errors
|
||||
import _PluginMgr as PluginMgr
|
||||
import _Tool as Tool
|
||||
from BasicUtils import name_displayer
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -156,18 +157,16 @@ class PluginTrace(ManagedWindow.ManagedWindow):
|
||||
# Main window for a batch tool
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class ToolManagedWindowBatch(Tool.BatchTool, ManagedWindow.ManagedWindow):
|
||||
class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
|
||||
"""
|
||||
Copied from src/ReportBase/_BareReportDialog.py BareReportDialog
|
||||
"""
|
||||
frame_pad = 5
|
||||
border_pad = 6
|
||||
HELP_TOPIC = None
|
||||
def __init__(self, dbstate, uistate, options_class, name, callback=None):
|
||||
def __init__(self, dbstate, uistate, option_class, name, callback=None):
|
||||
self.dbstate = dbstate
|
||||
self.uistate = uistate
|
||||
|
||||
Tool.BatchTool.__init__(self,dbstate,options_class,name)
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, [], self)
|
||||
|
||||
self.extra_menu = None
|
||||
@ -177,12 +176,13 @@ class ToolManagedWindowBatch(Tool.BatchTool, ManagedWindow.ManagedWindow):
|
||||
self.format_menu = None
|
||||
self.style_button = None
|
||||
|
||||
window = gtk.Dialog('GRAMPS')
|
||||
window = gtk.Dialog('Tool')
|
||||
self.set_window(window,None,self.get_title())
|
||||
self.window.set_has_separator(False)
|
||||
|
||||
#self.window.connect('response', self.close)
|
||||
self.cancel = self.window.add_button(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL)
|
||||
self.cancel.connect('clicked',self.on_cancel)
|
||||
self.cancel.connect('clicked',self.close)
|
||||
|
||||
self.ok = self.window.add_button(gtk.STOCK_OK,gtk.RESPONSE_OK)
|
||||
self.ok.connect('clicked',self.on_ok_clicked)
|
||||
@ -221,14 +221,39 @@ class ToolManagedWindowBatch(Tool.BatchTool, ManagedWindow.ManagedWindow):
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
def on_cancel(self,*obj):
|
||||
pass
|
||||
pass # cancel just closes
|
||||
|
||||
def on_ok_clicked(self, obj):
|
||||
"""The user is satisfied with the dialog choices. Parse all options
|
||||
and close the window."""
|
||||
|
||||
# Save options
|
||||
self.options.parse_user_options(self)
|
||||
self.options.handler.save_options()
|
||||
self.pre_run()
|
||||
self.run() # activate results tab
|
||||
self.post_run()
|
||||
|
||||
def pre_run(self):
|
||||
from Utils import ProgressMeter
|
||||
self.progress = ProgressMeter(_('Tool'))
|
||||
|
||||
def run(self):
|
||||
raise NotImplementedError, "tool needs to define a run() method"
|
||||
|
||||
def post_run(self):
|
||||
self.progress.close()
|
||||
|
||||
def on_center_person_change_clicked(self,*obj):
|
||||
from Selectors import selector_factory
|
||||
SelectPerson = selector_factory('Person')
|
||||
sel_person = SelectPerson(self.dbstate,self.uistate,self.track)
|
||||
new_person = sel_person.run()
|
||||
if new_person:
|
||||
self.new_person = new_person
|
||||
new_name = name_displayer.display(new_person)
|
||||
if new_name:
|
||||
self.person_label.set_text( "<i>%s</i>" % new_name )
|
||||
self.person_label.set_use_markup(True)
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -237,7 +262,7 @@ class ToolManagedWindowBatch(Tool.BatchTool, ManagedWindow.ManagedWindow):
|
||||
#------------------------------------------------------------------------
|
||||
def get_title(self):
|
||||
"""The window title for this dialog"""
|
||||
return "%s - GRAMPS Book" % "FIXME"
|
||||
return "Tool"
|
||||
|
||||
def get_header(self, name):
|
||||
"""The header line to put at the top of the contents of the
|
||||
@ -245,8 +270,8 @@ class ToolManagedWindowBatch(Tool.BatchTool, ManagedWindow.ManagedWindow):
|
||||
selected person. Most subclasses will customize this to give
|
||||
some indication of what the report will be, i.e. 'Descendant
|
||||
Report for %s'."""
|
||||
return _("%(report_name)s for GRAMPS Book") % {
|
||||
'report_name' : "FIXME"}
|
||||
return _("%(tool_name)s for GRAMPS") % {
|
||||
'tool_name' : "Tool"}
|
||||
|
||||
def setup_title(self):
|
||||
"""Set up the title bar of the dialog. This function relies
|
||||
@ -265,29 +290,29 @@ class ToolManagedWindowBatch(Tool.BatchTool, ManagedWindow.ManagedWindow):
|
||||
title = self.get_header(self.name)
|
||||
label = gtk.Label('<span size="larger" weight="bold">%s</span>' % title)
|
||||
label.set_use_markup(True)
|
||||
self.window.vbox.pack_start(label, True, True,
|
||||
ToolManagedWindowBatch.border_pad)
|
||||
self.window.vbox.pack_start(label, True, True, self.border_pad)
|
||||
|
||||
def setup_center_person(self):
|
||||
"""Set up center person labels and change button.
|
||||
Should be overwritten by standalone report dialogs. """
|
||||
pass
|
||||
|
||||
center_label = gtk.Label("<b>%s</b>" % _("Center Person"))
|
||||
center_label.set_use_markup(True)
|
||||
center_label.set_alignment(0.0,0.5)
|
||||
self.tbl.set_border_width(12)
|
||||
self.tbl.attach(center_label,0,4,self.col,self.col+1)
|
||||
self.col += 1
|
||||
# center_label = gtk.Label("<b>%s</b>" % _("Center Person"))
|
||||
# center_label.set_use_markup(True)
|
||||
# center_label.set_alignment(0.0,0.5)
|
||||
# self.tbl.set_border_width(12)
|
||||
# self.tbl.attach(center_label,0,4,self.col,self.col+1)
|
||||
# self.col += 1
|
||||
|
||||
#name = name_displayer.display(self.person)
|
||||
#self.person_label = gtk.Label( "%s" % name )
|
||||
#self.person_label.set_alignment(0.0,0.5)
|
||||
#self.tbl.attach(self.person_label,2,3,self.col,self.col+1)
|
||||
# name = name_displayer.display(self.person)
|
||||
# self.person_label = gtk.Label( "%s" % name )
|
||||
# self.person_label.set_alignment(0.0,0.5)
|
||||
# self.tbl.attach(self.person_label,2,3,self.col,self.col+1)
|
||||
|
||||
#change_button = gtk.Button("%s..." % _('C_hange') )
|
||||
#change_button.connect('clicked',self.on_center_person_change_clicked)
|
||||
#self.tbl.attach(change_button,3,4,self.col,self.col+1,gtk.SHRINK)
|
||||
#self.col += 1
|
||||
# change_button = gtk.Button("%s..." % _('C_hange') )
|
||||
# change_button.connect('clicked',self.on_center_person_change_clicked)
|
||||
# self.tbl.attach(change_button,3,4,self.col,self.col+1,gtk.SHRINK)
|
||||
# self.col += 1
|
||||
|
||||
def add_frame_option(self,frame_name,label_text,widget,tooltip=None):
|
||||
"""Similar to add_option this method takes a frame_name, a
|
||||
@ -344,4 +369,14 @@ class ToolManagedWindowBatch(Tool.BatchTool, ManagedWindow.ManagedWindow):
|
||||
this task."""
|
||||
self.options.add_user_options(self)
|
||||
|
||||
class ToolManagedWindowBatch(Tool.BatchTool, ToolManagedWindowBase):
|
||||
def __init__(self, dbstate, uistate, options_class, name, callback=None):
|
||||
Tool.BatchTool.__init__(self,dbstate,options_class,name)
|
||||
ToolManagedWindowBase.__init__(self, dbstate, uistate, options_class,
|
||||
name, callback)
|
||||
|
||||
class ToolManagedWindow(Tool.Tool, ToolManagedWindowBase):
|
||||
def __init__(self, dbstate, uistate, options_class, name, callback=None):
|
||||
Tool.Tool.__init__(self,dbstate,options_class,name)
|
||||
ToolManagedWindowBase.__init__(self, dbstate, uistate, options_class,
|
||||
name, callback)
|
||||
|
@ -563,6 +563,14 @@ class Date:
|
||||
retval.set_yr_mon_day_offset(year, month, day)
|
||||
return retval
|
||||
|
||||
def copy_ymd(self, year=0, month=0, day=0):
|
||||
"""
|
||||
Returns a Date copy with year, month, and day set
|
||||
"""
|
||||
retval = Date(self)
|
||||
retval.set_yr_mon_day(year, month, day)
|
||||
return retval
|
||||
|
||||
def set_year(self, year):
|
||||
"""
|
||||
Sets the year value
|
||||
|
381
src/plugins/CalculateEstimatedDates.py
Normal file
381
src/plugins/CalculateEstimatedDates.py
Normal file
@ -0,0 +1,381 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2007 Donald N. Allingham
|
||||
#
|
||||
# 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: $
|
||||
|
||||
"Calculate Estimated Dates"
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
import time
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from PluginUtils import Tool, register_tool, PluginWindows, \
|
||||
MenuToolOptions, BooleanOption, FilterListOption, StringOption
|
||||
import gen.lib
|
||||
import Config
|
||||
|
||||
_MAX_AGE_PROB_ALIVE = Config.get(Config.MAX_AGE_PROB_ALIVE)
|
||||
_MAX_SIB_AGE_DIFF = Config.get(Config.MAX_SIB_AGE_DIFF)
|
||||
_MIN_GENERATION_YEARS = Config.get(Config.MIN_GENERATION_YEARS)
|
||||
_AVG_GENERATION_GAP = Config.get(Config.AVG_GENERATION_GAP)
|
||||
|
||||
class CalcEstDateOptions(MenuToolOptions):
|
||||
""" Calculate Estimated Date options """
|
||||
|
||||
def add_menu_options(self, menu):
|
||||
""" Adds the options """
|
||||
category_name = _("Options")
|
||||
|
||||
filter = FilterListOption(_("Filter"))
|
||||
filter.add_item("person")
|
||||
filter.set_help(_("Select filter to restrict people"))
|
||||
menu.add_option(category_name,"filter", filter)
|
||||
|
||||
source_text = StringOption(_("Source text"), _("Calculated Date Estimates"))
|
||||
source_text.set_help(_("Source to remove and/or add"))
|
||||
menu.add_option(category_name, "source_text", source_text)
|
||||
|
||||
remove = BooleanOption(_("Remove previously added dates"), True)
|
||||
remove.set_help(_("Remove"))
|
||||
menu.add_option(category_name, "remove", remove)
|
||||
|
||||
birth = BooleanOption(_("Add estimated birth dates"), True)
|
||||
birth.set_help(_("Add"))
|
||||
menu.add_option(category_name, "add_birth", birth)
|
||||
|
||||
death = BooleanOption(_("Add estimated death dates"), True)
|
||||
death.set_help(_("Add estimated death dates"))
|
||||
menu.add_option(category_name, "add_death", death)
|
||||
|
||||
class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
|
||||
|
||||
def run(self):
|
||||
self.trans = self.db.transaction_begin("",batch=True)
|
||||
self.db.disable_signals()
|
||||
self.filter = self.options.handler.options_dict['filter']
|
||||
people = self.filter.apply(self.db,
|
||||
self.db.get_person_handles(sort_handles=False))
|
||||
source_text = self.options.handler.options_dict['source_text']
|
||||
add_birth = self.options.handler.options_dict['add_birth']
|
||||
add_death = self.options.handler.options_dict['add_death']
|
||||
if self.options.handler.options_dict['remove']:
|
||||
self.progress.set_pass(_("Removing '%s'..." % source_text), len(people))
|
||||
for person_handle in people:
|
||||
self.progress.step()
|
||||
pupdate = 0
|
||||
person = self.db.get_person_from_handle(person_handle)
|
||||
birth_ref = person.get_birth_ref()
|
||||
if birth_ref:
|
||||
birth = self.db.get_event_from_handle(birth_ref.ref)
|
||||
source_list = birth.get_source_references()
|
||||
for source_ref in source_list:
|
||||
#print "birth handle:", source_ref
|
||||
source = self.db.get_source_from_handle(source_ref.ref)
|
||||
if source:
|
||||
#print "birth source:", source, source.get_title()
|
||||
if source.get_title() == source_text:
|
||||
person.set_birth_ref(None)
|
||||
person.remove_handle_references('Event',[birth_ref.ref])
|
||||
self.db.remove_event(birth_ref.ref, self.trans)
|
||||
self.db.commit_source(source, self.trans)
|
||||
pupdate = 1
|
||||
break
|
||||
death_ref = person.get_death_ref()
|
||||
if death_ref:
|
||||
death = self.db.get_event_from_handle(death_ref.ref)
|
||||
source_list = death.get_source_references()
|
||||
for source_ref in source_list:
|
||||
#print "death handle:", source_ref
|
||||
source = self.db.get_source_from_handle(source_ref.ref)
|
||||
if source:
|
||||
#print "death source:", source, source.get_title()
|
||||
if source.get_title() == source_text:
|
||||
person.set_death_ref(None)
|
||||
person.remove_handle_references('Event',[death_ref.ref])
|
||||
self.db.remove_event(death_ref.ref, self.trans)
|
||||
self.db.commit_source(source, self.trans)
|
||||
pupdate = 1
|
||||
break
|
||||
if pupdate == 1:
|
||||
self.db.commit_person(person, self.trans)
|
||||
if add_birth or add_death:
|
||||
self.progress.set_pass(_('Calculating estimated dates...'), len(people))
|
||||
source = self.get_or_create_source(source_text)
|
||||
for person_handle in people:
|
||||
self.progress.step()
|
||||
person = self.db.get_person_from_handle(person_handle)
|
||||
birth_ref = person.get_birth_ref()
|
||||
death_ref = person.get_death_ref()
|
||||
if birth_ref != None or death_ref != None:
|
||||
date1, date2 = self.calc_estimates(person, birth_ref, death_ref)
|
||||
if not birth_ref and add_birth and date1:
|
||||
birth = self.create_event("Estimated birth date",
|
||||
gen.lib.EventType.BIRTH, date1, source)
|
||||
event_ref = gen.lib.EventRef()
|
||||
event_ref.set_reference_handle(birth.get_handle())
|
||||
person.set_birth_ref(event_ref)
|
||||
self.db.commit_person(person, self.trans)
|
||||
if not death_ref and add_death and date2:
|
||||
current_date = gen.lib.Date()
|
||||
current_date.set_yr_mon_day(*time.localtime(time.time())[0:3])
|
||||
if current_date.match( date2, "<<"):
|
||||
# don't add events in the future!
|
||||
pass
|
||||
else:
|
||||
death = self.create_event("Estimated death date",
|
||||
gen.lib.EventType.DEATH, date2, source)
|
||||
event_ref = gen.lib.EventRef()
|
||||
event_ref.set_reference_handle(death.get_handle())
|
||||
person.set_death_ref(event_ref)
|
||||
self.db.commit_person(person, self.trans)
|
||||
self.db.transaction_commit(self.trans, _("Calculate date estimates"))
|
||||
self.db.enable_signals()
|
||||
self.db.request_rebuild()
|
||||
|
||||
def get_or_create_source(self, source_text):
|
||||
source_list = self.db.get_source_handles()
|
||||
for source_handle in source_list:
|
||||
source = self.db.get_source_from_handle(source_handle)
|
||||
if source.get_title() == source_text:
|
||||
return source
|
||||
source = gen.lib.Source()
|
||||
source.set_title(source_text)
|
||||
self.db.add_source(source, self.trans)
|
||||
return source
|
||||
|
||||
def create_event(self, description="Estimated date",
|
||||
type=None, date=None, source=None):
|
||||
event = gen.lib.Event()
|
||||
event.set_description(description)
|
||||
if type:
|
||||
event.set_type(gen.lib.EventType(type))
|
||||
if date:
|
||||
date.set_modifier(gen.lib.Date.MOD_ABOUT)
|
||||
date.set_yr_mon_day(date.get_year(), 0, 0)
|
||||
event.set_date_object(date)
|
||||
if source:
|
||||
sref = gen.lib.SourceRef()
|
||||
sref.set_reference_handle(source.get_handle())
|
||||
event.add_source_reference(sref)
|
||||
self.db.commit_source(source, self.trans)
|
||||
self.db.add_event(event, self.trans)
|
||||
return event
|
||||
|
||||
def calc_estimates(self, person, birth_ref, death_ref):
|
||||
death_date = None
|
||||
birth_date = None
|
||||
# If the recorded death year is before current year then
|
||||
# things are simple.
|
||||
if death_ref and death_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
|
||||
death = self.db.get_event_from_handle(death_ref.ref)
|
||||
if death.get_date_object().get_start_date() != gen.lib.Date.EMPTY:
|
||||
death_date = death.get_date_object()
|
||||
|
||||
# Look for Cause Of Death, Burial or Cremation events.
|
||||
# These are fairly good indications that someone's not alive.
|
||||
for ev_ref in person.get_primary_event_ref_list():
|
||||
ev = self.db.get_event_from_handle(ev_ref.ref)
|
||||
if ev and int(ev.get_type()) in [gen.lib.EventType.CAUSE_DEATH,
|
||||
gen.lib.EventType.BURIAL,
|
||||
gen.lib.EventType.CREMATION]:
|
||||
if not death_date:
|
||||
death_date = ev.get_date_object()
|
||||
|
||||
# If they were born within 100 years before current year then
|
||||
# assume they are alive (we already know they are not dead).
|
||||
if birth_ref and birth_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
|
||||
birth = self.db.get_event_from_handle(birth_ref.ref)
|
||||
if birth.get_date_object().get_start_date() != gen.lib.Date.EMPTY:
|
||||
if not birth_date:
|
||||
birth_date = birth.get_date_object()
|
||||
|
||||
if not birth_date and death_date:
|
||||
# person died more than MAX after current year
|
||||
birth_date = death_date.copy_offset_ymd(year=-_MAX_AGE_PROB_ALIVE)
|
||||
|
||||
if not death_date and birth_date:
|
||||
# person died more than MAX after current year
|
||||
death_date = birth_date.copy_offset_ymd(year=_MAX_AGE_PROB_ALIVE)
|
||||
|
||||
if death_date and birth_date:
|
||||
return (birth_date, death_date)
|
||||
|
||||
# Neither birth nor death events are available. Try looking
|
||||
# at siblings. If a sibling was born more than 120 years past,
|
||||
# or more than 20 future, then probably this person is
|
||||
# not alive. If the sibling died more than 120 years
|
||||
# past, or more than 120 years future, then probably not alive.
|
||||
|
||||
family_list = person.get_parent_family_handle_list()
|
||||
for family_handle in family_list:
|
||||
family = self.db.get_family_from_handle(family_handle)
|
||||
for child_ref in family.get_child_ref_list():
|
||||
child_handle = child_ref.ref
|
||||
child = self.db.get_person_from_handle(child_handle)
|
||||
child_birth_ref = child.get_birth_ref()
|
||||
if child_birth_ref:
|
||||
child_birth = self.db.get_event_from_handle(child_birth_ref.ref)
|
||||
dobj = child_birth.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
# if sibling birth date too far away, then not alive:
|
||||
year = dobj.get_year()
|
||||
if year != 0:
|
||||
# sibling birth date
|
||||
return (gen.lib.Date().copy_ymd(year - _MAX_SIB_AGE_DIFF),
|
||||
gen.lib.Date().copy_ymd(year + _MAX_SIB_AGE_DIFF + _MAX_AGE_PROB_ALIVE))
|
||||
child_death_ref = child.get_death_ref()
|
||||
if child_death_ref:
|
||||
child_death = self.db.get_event_from_handle(child_death_ref.ref)
|
||||
dobj = child_death.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
# if sibling death date too far away, then not alive:
|
||||
year = dobj.get_year()
|
||||
if year != 0:
|
||||
# sibling death date
|
||||
return (gen.lib.Date().copy_ymd(year - _MAX_SIB_AGE_DIFF - _MAX_AGE_PROB_ALIVE),
|
||||
gen.lib.Date().copy_ymd(year + _MAX_SIB_AGE_DIFF))
|
||||
|
||||
# Try looking for descendants that were born more than a lifespan
|
||||
# ago.
|
||||
|
||||
def descendants_too_old (person, years):
|
||||
for family_handle in person.get_family_handle_list():
|
||||
family = self.db.get_family_from_handle(family_handle)
|
||||
for child_ref in family.get_child_ref_list():
|
||||
child_handle = child_ref.ref
|
||||
child = self.db.get_person_from_handle(child_handle)
|
||||
child_birth_ref = child.get_birth_ref()
|
||||
if child_birth_ref:
|
||||
child_birth = self.db.get_event_from_handle(child_birth_ref.ref)
|
||||
dobj = child_birth.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
d = gen.lib.Date(dobj)
|
||||
val = d.get_start_date()
|
||||
val = d.get_year() - years
|
||||
d.set_year(val)
|
||||
return (d, d.copy_offset_ymd(_MAX_AGE_PROB_ALIVE))
|
||||
child_death_ref = child.get_death_ref()
|
||||
if child_death_ref:
|
||||
child_death = self.db.get_event_from_handle(child_death_ref.ref)
|
||||
dobj = child_death.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_dmy(- _MIN_GENERATION_YEARS),
|
||||
d.copy_offset_ymd(- _MIN_GENERATION_YEARS + _MAX_AGE_PROB_ALIVE))
|
||||
date1, date2 = descendants_too_old (child, years + _MIN_GENERATION_YEARS)
|
||||
if date1 and date2:
|
||||
return date1, date2
|
||||
return (None, None)
|
||||
|
||||
# If there are descendants that are too old for the person to have
|
||||
# been alive in the current year then they must be dead.
|
||||
|
||||
date1, date2 = None, None
|
||||
try:
|
||||
date1, date2 = descendants_too_old(person, _MIN_GENERATION_YEARS)
|
||||
except RuntimeError:
|
||||
raise Errors.DatabaseError(
|
||||
_("Database error: %s is defined as his or her own ancestor") %
|
||||
name_displayer.display(person))
|
||||
|
||||
def ancestors_too_old(person, year):
|
||||
family_handle = person.get_main_parents_family_handle()
|
||||
if family_handle:
|
||||
family = self.db.get_family_from_handle(family_handle)
|
||||
father_handle = family.get_father_handle()
|
||||
if father_handle:
|
||||
father = self.db.get_person_from_handle(father_handle)
|
||||
father_birth_ref = father.get_birth_ref()
|
||||
if father_birth_ref and father_birth_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
|
||||
father_birth = self.db.get_event_from_handle(
|
||||
father_birth_ref.ref)
|
||||
dobj = father_birth.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_ymd(- year),
|
||||
dobj.copy_offset_ymd(- year + _MAX_AGE_PROB_ALIVE))
|
||||
father_death_ref = father.get_death_ref()
|
||||
if father_death_ref and father_death_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
|
||||
father_death = self.db.get_event_from_handle(
|
||||
father_death_ref.ref)
|
||||
dobj = father_death.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_ymd(- year - _MAX_AGE_PROB_ALIVE),
|
||||
dobj.copy_offset_ymd(- year - _MAX_AGE_PROB_ALIVE + _MAX_AGE_PROB_ALIVE))
|
||||
date1, date2 = ancestors_too_old (father, year - _AVG_GENERATION_GAP)
|
||||
if date1 and date2:
|
||||
return date1, date2
|
||||
mother_handle = family.get_mother_handle()
|
||||
if mother_handle:
|
||||
mother = self.db.get_person_from_handle(mother_handle)
|
||||
mother_birth_ref = mother.get_birth_ref()
|
||||
if mother_birth_ref and mother_birth_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
|
||||
mother_birth = self.db.get_event_from_handle(mother_birth_ref.ref)
|
||||
dobj = mother_birth.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_ymd(- year),
|
||||
dobj.copy_offset_ymd(- year + _MAX_AGE_PROB_ALIVE))
|
||||
mother_death_ref = mother.get_death_ref()
|
||||
if mother_death_ref and mother_death_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
|
||||
mother_death = self.db.get_event_from_handle(
|
||||
mother_death_ref.ref)
|
||||
dobj = mother_death.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_ymd(- year - _MAX_AGE_PROB_ALIVE),
|
||||
dobj.copy_offset_ymd(- year - _MAX_AGE_PROB_ALIVE + _MAX_AGE_PROB_ALIVE))
|
||||
date1, date2 = ancestors_too_old (mother, year - _AVG_GENERATION_GAP)
|
||||
if date1 and date2:
|
||||
return (date1, date2)
|
||||
return (None, None)
|
||||
|
||||
# If there are ancestors that would be too old in the current year
|
||||
# then assume our person must be dead too.
|
||||
date1, date2 = ancestors_too_old (person, - _MIN_GENERATION_YEARS)
|
||||
if date1 and date2:
|
||||
return (date1, date2)
|
||||
|
||||
# If we can't find any reason to believe that they are dead we
|
||||
# must assume they are alive.
|
||||
return (None, None)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Register the tool
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
register_tool(
|
||||
name = 'calculateestimateddates',
|
||||
category = Tool.TOOL_DBPROC,
|
||||
tool_class = CalcToolManagedWindow,
|
||||
options_class = CalcEstDateOptions,
|
||||
modes = Tool.MODE_GUI,
|
||||
translated_name = _("Calculate Estimated Dates"),
|
||||
status = _("Beta"),
|
||||
author_name = "Douglas S. Blank",
|
||||
author_email = "dblank@cs.brynmawr.edu",
|
||||
description=_("Calculates estimated dates for birth and death.")
|
||||
)
|
Loading…
Reference in New Issue
Block a user