Enhanced Calculate Estimated Dates tool
svn: r14014
This commit is contained in:
parent
746e934937
commit
2d60b8763a
@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
@ -38,12 +39,17 @@ import time
|
||||
#------------------------------------------------------------------------
|
||||
from PluginUtils import Tool, PluginWindows, MenuToolOptions
|
||||
from gen.plug.menu import BooleanOption, NumberOption, StringOption, \
|
||||
FilterOption, PersonOption
|
||||
FilterOption, PersonOption, EnumeratedListOption
|
||||
import gen.lib
|
||||
import config
|
||||
from BasicUtils import name_displayer
|
||||
import Errors
|
||||
from ReportBase import ReportUtils
|
||||
from docgen import TextBufDoc
|
||||
from Simple import make_basic_stylesheet, SimpleAccess, SimpleDoc, SimpleTable
|
||||
from QuestionDialog import QuestionDialog
|
||||
from Utils import create_id
|
||||
import DateHandler
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -54,7 +60,11 @@ class CalcEstDateOptions(MenuToolOptions):
|
||||
""" Calculate Estimated Date options """
|
||||
def __init__(self, name, person_id=None, dbstate=None):
|
||||
self.__db = dbstate.get_database()
|
||||
self.__dbstate = dbstate
|
||||
MenuToolOptions.__init__(self, name, person_id, dbstate)
|
||||
|
||||
def get_dbstate(self):
|
||||
return self.__dbstate
|
||||
|
||||
def add_menu_options(self, menu):
|
||||
|
||||
@ -78,24 +88,25 @@ class CalcEstDateOptions(MenuToolOptions):
|
||||
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"))
|
||||
remove = BooleanOption(_("Remove previously added events, notes, and source"), True)
|
||||
remove.set_help(_("Remove calculated events, notes, and source; occurs immediately on Execute"))
|
||||
menu.add_option(category_name, "remove", remove)
|
||||
|
||||
birth = BooleanOption(_("Add estimated birth dates"), True)
|
||||
birth.set_help(_("Add"))
|
||||
birth = EnumeratedListOption(_("Birth"), 0)
|
||||
birth.add_item(0, _("Do not add birth events"))
|
||||
birth.add_item(1, _("Add birth events without dates"))
|
||||
birth.add_item(2, _("Add birth events with dates"))
|
||||
birth.set_help( _("Add a birth events with or without estimated dates"))
|
||||
menu.add_option(category_name, "add_birth", birth)
|
||||
|
||||
death = BooleanOption(_("Add estimated death dates"), True)
|
||||
death.set_help(_("Add estimated death dates"))
|
||||
death = EnumeratedListOption(_("Death"), 0)
|
||||
death.add_item(0, _("Do not add death events"))
|
||||
death.add_item(1, _("Add death events without dates"))
|
||||
death.add_item(2, _("Add death events with dates"))
|
||||
death.set_help( _("Add death events with or without estimated dates"))
|
||||
menu.add_option(category_name, "add_death", death)
|
||||
|
||||
display_details = BooleanOption(_("Display detailed results"), False)
|
||||
display_details.set_help(_("Show details for every date entered"))
|
||||
menu.add_option(category_name, "display_details", display_details)
|
||||
|
||||
# -----------------------------------------------------
|
||||
category_name = _("Config")
|
||||
num = NumberOption(_("Maximum age"),
|
||||
config.get('behavior.max-age-prob-alive'),
|
||||
0, 200)
|
||||
@ -145,34 +156,91 @@ class CalcEstDateOptions(MenuToolOptions):
|
||||
|
||||
class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
PluginWindows.ToolManagedWindowBatch.__init__(self, *args, **kwargs)
|
||||
self.help_page = self.add_page("Help")
|
||||
self.write_to_page(self.help_page,
|
||||
"The Calculate Estimated Dates Tool is used to add and remove "
|
||||
"birth and death events for people that are missing these "
|
||||
"events.\n\n"
|
||||
"To use:\n"
|
||||
"1. Go to the Options tab\n"
|
||||
"2. Check the [ ] Remove option to remove previous estimates\n"
|
||||
"3. Select the Add date options to date events with or without dates\n"
|
||||
"4. Click on Execute\n"
|
||||
"5. Select the people with which to add events\n"
|
||||
"6. Click on 'Add Selected Events' button to create\n\n"
|
||||
"NOTES: if you decide to make an event permanent, remove it from "
|
||||
"the Source. Otherwise, it will get removed the next time you "
|
||||
"automatically remove these events.\n\n"
|
||||
"You may have to run the tool repeatedly (without removing previous "
|
||||
"events) to add all of the events possible.")
|
||||
|
||||
def get_title(self):
|
||||
return _("Calculate Estimated Dates")
|
||||
|
||||
def initial_frame(self):
|
||||
return _("Options")
|
||||
|
||||
def set_reselect(self):
|
||||
self.reselect = True
|
||||
|
||||
def run(self):
|
||||
self.add_results_frame(_("Results"))
|
||||
BUTTONS = ((_("Select All"), self.select_all),
|
||||
(_("Select None"), self.select_none),
|
||||
(_("Toggle Selection"), self.toggle_select),
|
||||
(_("Add Selected Events"), self.apply_selection),
|
||||
)
|
||||
|
||||
if hasattr(self, "table") and self.table:
|
||||
self.reselect = False
|
||||
if self.options.handler.options_dict['remove']:
|
||||
QuestionDialog(_("Remove Events, Notes, and Source and Reselect Data"),
|
||||
_("Are you sure you want to remove previous events, notes, and source and reselect data?"),
|
||||
_("Remove and Run Select Again"),
|
||||
self.set_reselect,
|
||||
self.window)
|
||||
else:
|
||||
QuestionDialog(_("Reselect Data"),
|
||||
_("Are you sure you want to reselect data?"),
|
||||
_("Run Select Again"),
|
||||
self.set_reselect,
|
||||
self.window)
|
||||
if not self.reselect:
|
||||
return
|
||||
self.action = {}
|
||||
widget = self.add_results_frame(_("Select"))
|
||||
document = TextBufDoc(make_basic_stylesheet(), None)
|
||||
document.dbstate = self.dbstate
|
||||
document.uistate = self.uistate
|
||||
document.open("", container=widget)
|
||||
self.sdb = SimpleAccess(self.db)
|
||||
sdoc = SimpleDoc(document)
|
||||
stab = SimpleTable(self.sdb)
|
||||
self.table = stab
|
||||
stab.columns(_("Select"), _("Person"), _("Action"),
|
||||
_("Birth Date"), _("Death Date"),
|
||||
_("Evidence"), _("Relative"))
|
||||
self.results_write(_("Processing...\n"))
|
||||
self.trans = self.db.transaction_begin("",batch=True)
|
||||
self.db.disable_signals()
|
||||
self.filter_option = self.options.menu.get_option_by_name('filter')
|
||||
self.filter = self.filter_option.get_filter() # the actual filter
|
||||
people = self.filter.apply(self.db,
|
||||
self.db.iter_person_handles())
|
||||
num_people = self.db.get_number_of_people()
|
||||
source_text = self.options.handler.options_dict['source_text']
|
||||
source = None
|
||||
add_birth = self.options.handler.options_dict['add_birth']
|
||||
add_death = self.options.handler.options_dict['add_death']
|
||||
remove_old = self.options.handler.options_dict['remove']
|
||||
display_details = self.options.handler.options_dict['display_details']
|
||||
|
||||
self.MIN_GENERATION_YEARS = self.options.handler.options_dict['MIN_GENERATION_YEARS']
|
||||
self.MAX_SIB_AGE_DIFF = self.options.handler.options_dict['MAX_SIB_AGE_DIFF']
|
||||
self.MAX_AGE_PROB_ALIVE = self.options.handler.options_dict['MAX_AGE_PROB_ALIVE']
|
||||
self.AVG_GENERATION_GAP = self.options.handler.options_dict['AVG_GENERATION_GAP']
|
||||
if remove_old:
|
||||
self.results_write(_("Replacing...\n"))
|
||||
self.trans = self.db.transaction_begin("",batch=True)
|
||||
self.db.disable_signals()
|
||||
self.results_write(_("Removing old estimations... "))
|
||||
self.progress.set_pass((_("Removing '%s'...") % source_text),
|
||||
num_people)
|
||||
for person_handle in people:
|
||||
@ -191,6 +259,12 @@ class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
|
||||
if source.get_title() == source_text:
|
||||
person.set_birth_ref(None)
|
||||
person.remove_handle_references('Event',[birth_ref.ref])
|
||||
# remove note
|
||||
note_list = birth.get_referenced_note_handles()
|
||||
birth.remove_handle_references('Note',
|
||||
[note_handle for (obj_type, note_handle) in note_list])
|
||||
for (obj_type, note_handle) in note_list:
|
||||
self.db.remove_note(note_handle, self.trans)
|
||||
self.db.remove_event(birth_ref.ref, self.trans)
|
||||
self.db.commit_source(source, self.trans)
|
||||
pupdate = 1
|
||||
@ -207,64 +281,197 @@ class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
|
||||
if source.get_title() == source_text:
|
||||
person.set_death_ref(None)
|
||||
person.remove_handle_references('Event',[death_ref.ref])
|
||||
# remove note
|
||||
note_list = death.get_referenced_note_handles()
|
||||
birth.remove_handle_references('Note',
|
||||
[note_handle for (obj_type, note_handle) in note_list])
|
||||
for (obj_type, note_handle) in note_list:
|
||||
self.db.remove_note(note_handle, self.trans)
|
||||
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 source:
|
||||
self.db.remove_source(source.handle, self.trans)
|
||||
self.results_write(_("done!\n"))
|
||||
self.db.transaction_commit(self.trans, _("Removed date estimates"))
|
||||
self.db.enable_signals()
|
||||
self.db.request_rebuild()
|
||||
if add_birth or add_death:
|
||||
self.results_write(_("Calculating...\n"))
|
||||
self.progress.set_pass(_('Calculating estimated dates...'),
|
||||
self.results_write(_("Selecting... \n\n"))
|
||||
self.progress.set_pass(_('Selecting...'),
|
||||
num_people)
|
||||
source = self.get_or_create_source(source_text)
|
||||
row = 0
|
||||
for person_handle in people:
|
||||
self.progress.step()
|
||||
added_birth, added_death = 0, 0
|
||||
person = self.db.get_person_from_handle(person_handle)
|
||||
birth_ref = person.get_birth_ref()
|
||||
death_ref = person.get_death_ref()
|
||||
#print birth_ref, death_ref
|
||||
date1, date2 = self.calc_estimates(person, birth_ref, death_ref)
|
||||
#print date1, date2
|
||||
if not birth_ref and add_birth and date1:
|
||||
#print "added birth"
|
||||
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)
|
||||
added_birth = 1
|
||||
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 # FIXME: sometimes adds one in future?
|
||||
add_birth_event, add_death_event = False, False
|
||||
if not birth_ref or not death_ref:
|
||||
date1, date2, explain, other = self.calc_estimates(person)
|
||||
if birth_ref:
|
||||
ev = self.db.get_event_from_handle(birth_ref.ref)
|
||||
date1 = ev.get_date_object()
|
||||
elif not birth_ref and add_birth and date1:
|
||||
add_birth_event = True
|
||||
date1.make_vague()
|
||||
else:
|
||||
#print "added death"
|
||||
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)
|
||||
added_death = 1
|
||||
if (added_birth or added_death) and display_details:
|
||||
self.results_write_link(name_displayer.display(person),
|
||||
person, person_handle)
|
||||
if added_birth:
|
||||
self.results_write(_(" added birth on %s") % date1)
|
||||
if added_death:
|
||||
self.results_write(_(" added death on %s") % date2)
|
||||
self.results_write("\n")
|
||||
self.db.transaction_commit(self.trans, _("Calculate date estimates"))
|
||||
date1 = gen.lib.Date()
|
||||
if death_ref:
|
||||
ev = self.db.get_event_from_handle(death_ref.ref)
|
||||
date2 = ev.get_date_object()
|
||||
elif 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 date2.match( current_date, "<"):
|
||||
add_death_event = True
|
||||
date2.make_vague()
|
||||
else:
|
||||
date2 = gen.lib.Date()
|
||||
else:
|
||||
date2 = gen.lib.Date()
|
||||
# Describe
|
||||
if add_birth_event and add_death_event:
|
||||
action = _("Add birth and death events")
|
||||
elif add_birth_event:
|
||||
action = _("Add birth event")
|
||||
elif add_death_event:
|
||||
action = _("Add death event")
|
||||
else:
|
||||
continue
|
||||
#stab.columns(_("Select"), _("Person"), _("Action"),
|
||||
# _("Birth Date"), _("Death Date"), _("Evidence"), _("Relative"))
|
||||
if add_birth == 1 and not birth_ref: # no date
|
||||
date1 = gen.lib.Date()
|
||||
if add_death == 1 and not death_ref: # no date
|
||||
date2 = gen.lib.Date()
|
||||
stab.row("checkbox",
|
||||
person,
|
||||
action,
|
||||
date1,
|
||||
date2,
|
||||
explain or "",
|
||||
other or "")
|
||||
if add_birth_event:
|
||||
stab.set_cell_markup(3, row, "<b>%s</b>" % DateHandler.displayer.display(date1))
|
||||
if add_death_event:
|
||||
stab.set_cell_markup(4, row, "<b>%s</b>" % DateHandler.displayer.display(date2))
|
||||
self.action[person.handle] = (add_birth_event, add_death_event)
|
||||
row += 1
|
||||
if row > 0:
|
||||
self.results_write(" ")
|
||||
for text, function in BUTTONS:
|
||||
self.make_button(text, function, widget)
|
||||
self.results_write("\n")
|
||||
stab.write(sdoc)
|
||||
self.results_write(" ")
|
||||
for text, function in BUTTONS:
|
||||
self.make_button(text, function, widget)
|
||||
self.results_write("\n")
|
||||
else:
|
||||
self.results_write(_("No events to be added."))
|
||||
self.results_write("\n")
|
||||
self.results_write("\n")
|
||||
self.progress.close()
|
||||
|
||||
def make_button(self, text, function, widget):
|
||||
import gtk
|
||||
button = gtk.Button(text)
|
||||
buffer = widget.get_buffer()
|
||||
iter = buffer.get_end_iter()
|
||||
anchor = buffer.create_child_anchor(iter)
|
||||
widget.add_child_at_anchor(button, anchor)
|
||||
button.connect("clicked", function)
|
||||
button.show()
|
||||
self.results_write(" ")
|
||||
|
||||
def select_all(self, obj):
|
||||
select_col = self.table.model_index_of_column[_("Select")]
|
||||
for row in self.table.treeview.get_model():
|
||||
row[select_col] = True
|
||||
|
||||
def select_none(self, obj):
|
||||
select_col = self.table.model_index_of_column[_("Select")]
|
||||
for row in self.table.treeview.get_model():
|
||||
row[select_col] = False
|
||||
|
||||
def toggle_select(self, obj):
|
||||
select_col = self.table.model_index_of_column[_("Select")]
|
||||
for row in self.table.treeview.get_model():
|
||||
row[select_col] = not row[select_col]
|
||||
|
||||
def apply_selection(self, *args, **kwargs):
|
||||
# Do not add birth or death event if one exists, no matter what
|
||||
if self.table.treeview.get_model() is None:
|
||||
return
|
||||
self.pre_run()
|
||||
source_text = self.options.handler.options_dict['source_text']
|
||||
select_col = self.table.model_index_of_column[_("Select")]
|
||||
source = self.get_or_create_source(source_text)
|
||||
self.trans = self.db.transaction_begin("",batch=True)
|
||||
self.db.disable_signals()
|
||||
self.results_write(_("Selecting... "))
|
||||
self.progress.set_pass((_("Adding events '%s'...") % source_text),
|
||||
len(self.table.treeview.get_model()))
|
||||
self.trans = self.db.transaction_begin("",batch=True)
|
||||
count = 0
|
||||
for row in self.table.treeview.get_model():
|
||||
self.progress.step()
|
||||
select = row[select_col] # live select value
|
||||
if not select:
|
||||
continue
|
||||
pupdate = False
|
||||
index = row[0] # order put in
|
||||
row_data = self.table.get_raw_data(index)
|
||||
person = row_data[1] # check, person, action, date1, date2
|
||||
date1 = row_data[3] # date
|
||||
date2 = row_data[4] # date
|
||||
evidence = row_data[5] # evidence
|
||||
other = row_data[6] # other person
|
||||
add_birth_event, add_death_event = self.action[person.handle]
|
||||
birth_ref = person.get_birth_ref()
|
||||
death_ref = person.get_death_ref()
|
||||
if not birth_ref and add_birth_event:
|
||||
other_name = self.sdb.name(other)
|
||||
if other_name:
|
||||
explanation = _("Added birth event based on %s, from %s") % (evidence, other_name)
|
||||
else:
|
||||
explanation = _("Added birth event based on %s") % evidence
|
||||
birth = self.create_event(_("Estimated birth date"),
|
||||
gen.lib.EventType.BIRTH,
|
||||
date1, source, explanation)
|
||||
event_ref = gen.lib.EventRef()
|
||||
event_ref.set_reference_handle(birth.get_handle())
|
||||
person.set_birth_ref(event_ref)
|
||||
pupdate = True
|
||||
count += 1
|
||||
if not death_ref and add_death_event:
|
||||
other_name = self.sdb.name(other)
|
||||
if other_name:
|
||||
explanation = _("Added death event based on %s, from %s") % (evidence, other_name)
|
||||
else:
|
||||
explanation = _("Added death event based on %s") % evidence
|
||||
death = self.create_event(_("Estimated death date"),
|
||||
gen.lib.EventType.DEATH,
|
||||
date2, source, explanation)
|
||||
event_ref = gen.lib.EventRef()
|
||||
event_ref.set_reference_handle(death.get_handle())
|
||||
person.set_death_ref(event_ref)
|
||||
pupdate = True
|
||||
count += 1
|
||||
if pupdate:
|
||||
self.db.commit_person(person, self.trans)
|
||||
self.results_write(_(" Done! Committing..."))
|
||||
self.results_write("\n")
|
||||
self.db.transaction_commit(self.trans, _("Add date estimates"))
|
||||
self.db.enable_signals()
|
||||
self.db.request_rebuild()
|
||||
self.results_write(_("Done!\n"))
|
||||
self.results_write(_("Added %d events.") % count)
|
||||
self.results_write("\n\n")
|
||||
self.progress.close()
|
||||
|
||||
def get_or_create_source(self, source_text):
|
||||
source_list = self.db.get_source_handles()
|
||||
@ -278,9 +485,16 @@ class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
|
||||
return source
|
||||
|
||||
def create_event(self, description=_("Estimated date"),
|
||||
type=None, date=None, source=None):
|
||||
type=None, date=None, source=None,
|
||||
note_text=""):
|
||||
event = gen.lib.Event()
|
||||
event.set_description(description)
|
||||
note = gen.lib.Note()
|
||||
note.handle = create_id()
|
||||
note.type.set(gen.lib.NoteType.EVENT)
|
||||
note.set(note_text)
|
||||
self.db.add_note(note, self.trans)
|
||||
event.add_note(note.handle)
|
||||
if type:
|
||||
event.set_type(gen.lib.EventType(type))
|
||||
if date:
|
||||
@ -296,54 +510,65 @@ class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
|
||||
self.db.add_event(event, self.trans)
|
||||
return event
|
||||
|
||||
def calc_estimates(self, person, birth_ref, death_ref):
|
||||
def calc_estimates(self, person, is_spouse=False):
|
||||
if person is None:
|
||||
return (None, None, "", None)
|
||||
birth_ref = person.get_birth_ref()
|
||||
death_ref = person.get_death_ref()
|
||||
death_date = None
|
||||
birth_date = None
|
||||
explain = ""
|
||||
# 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:
|
||||
if death_ref and death_ref.get_role().is_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 ev.type in [gen.lib.EventType.CAUSE_DEATH,
|
||||
gen.lib.EventType.BURIAL,
|
||||
gen.lib.EventType.CREMATION]:
|
||||
if not death_date:
|
||||
if not death_date:
|
||||
for ev_ref in person.get_primary_event_ref_list():
|
||||
ev = self.db.get_event_from_handle(ev_ref.ref)
|
||||
if ev and ev.type.is_death_fallback():
|
||||
death_date = ev.get_date_object()
|
||||
explain = _("death-related evidence")
|
||||
|
||||
# If they were born within 100 years before current year then
|
||||
# If they were born within X 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:
|
||||
if not birth_date:
|
||||
if birth_ref and birth_ref.get_role().is_primary():
|
||||
birth = self.db.get_event_from_handle(birth_ref.ref)
|
||||
if birth.get_date_object().get_start_date() != gen.lib.Date.EMPTY:
|
||||
birth_date = birth.get_date_object()
|
||||
|
||||
#print " calculating...", birth_date, death_date
|
||||
# Look for Baptism, etc events.
|
||||
# These are fairly good indications that someone's birth.
|
||||
if not birth_date:
|
||||
for ev_ref in person.get_primary_event_ref_list():
|
||||
ev = self.db.get_event_from_handle(ev_ref.ref)
|
||||
if ev and ev.type.is_birth_fallback():
|
||||
birth_date = ev.get_date_object()
|
||||
explain = _("birth-related evidence")
|
||||
|
||||
if not birth_date and death_date:
|
||||
# person died more than MAX after current year
|
||||
birth_date = death_date.copy_offset_ymd(year=-self.MAX_AGE_PROB_ALIVE)
|
||||
|
||||
explain = _("death date")
|
||||
|
||||
if not death_date and birth_date:
|
||||
# person died more than MAX after current year
|
||||
death_date = birth_date.copy_offset_ymd(year=self.MAX_AGE_PROB_ALIVE)
|
||||
|
||||
explain = _("birth date")
|
||||
|
||||
if death_date and birth_date:
|
||||
return (birth_date, death_date)
|
||||
return (birth_date, death_date, explain, "") # direct self evidence
|
||||
|
||||
# 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.
|
||||
|
||||
#print " searching family..."
|
||||
# at siblings. If a sibling was born more than X years past,
|
||||
# or more than Z future, then probably this person is
|
||||
# not alive. If the sibling died more than X years
|
||||
# past, or more than X years future, then probably not alive.
|
||||
|
||||
family_list = person.get_parent_family_handle_list()
|
||||
for family_handle in family_list:
|
||||
@ -351,28 +576,70 @@ class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
|
||||
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 - self.MAX_SIB_AGE_DIFF),
|
||||
gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF + self.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 - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE),
|
||||
gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF))
|
||||
# Go through once looking for direct evidence:
|
||||
for ev_ref in child.get_primary_event_ref_list():
|
||||
ev = self.db.get_event_from_handle(ev_ref.ref)
|
||||
if ev and ev.type.is_birth():
|
||||
dobj = ev.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 - self.MAX_SIB_AGE_DIFF),
|
||||
gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF + self.MAX_AGE_PROB_ALIVE),
|
||||
_("sibling birth date"),
|
||||
child)
|
||||
elif ev and ev.type.is_death():
|
||||
dobj = ev.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 - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE),
|
||||
gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF),
|
||||
_("sibling death date"),
|
||||
child)
|
||||
# Go through again looking for fallback:
|
||||
for ev_ref in child.get_primary_event_ref_list():
|
||||
ev = self.db.get_event_from_handle(ev_ref.ref)
|
||||
if ev and ev.type.is_birth_fallback():
|
||||
dobj = ev.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 - self.MAX_SIB_AGE_DIFF),
|
||||
gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF + self.MAX_AGE_PROB_ALIVE),
|
||||
_("sibling birth-related date"),
|
||||
child)
|
||||
elif ev and ev.type.is_death_fallback():
|
||||
dobj = ev.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 - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE),
|
||||
gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF),
|
||||
_("sibling death-related date"),
|
||||
child)
|
||||
|
||||
if not is_spouse: # if you are not doing a spouse lookup, then let's do:
|
||||
mother_handle = family.get_mother_handle()
|
||||
father_handle = family.get_father_handle()
|
||||
if mother_handle == person.handle and father_handle:
|
||||
father = self.db.get_person_from_handle(father_handle)
|
||||
date1, date2, explain, other = self.calc_estimates(father, is_spouse=True)
|
||||
if date1 and date2:
|
||||
return date1, date2, _("a spouse, ") + explain, other
|
||||
elif father_handle == person.handle and mother_handle:
|
||||
mother = self.db.get_person_from_handle(mother_handle)
|
||||
date1, date2, explain, other = self.calc_estimates(father, is_spouse=True)
|
||||
if date1 and date2:
|
||||
return date1, date2, _("a spouse, ") + explain, other
|
||||
|
||||
# Try looking for descendants that were born more than a lifespan
|
||||
# ago.
|
||||
@ -392,32 +659,58 @@ class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
|
||||
val = d.get_start_date()
|
||||
val = d.get_year() - years
|
||||
d.set_year(val)
|
||||
return (d, d.copy_offset_ymd(self.MAX_AGE_PROB_ALIVE))
|
||||
return (d, d.copy_offset_ymd(self.MAX_AGE_PROB_ALIVE),
|
||||
_("descendent birth date"),
|
||||
child)
|
||||
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_ymd(- self.MIN_GENERATION_YEARS),
|
||||
dobj.copy_offset_ymd(- self.MIN_GENERATION_YEARS + self.MAX_AGE_PROB_ALIVE))
|
||||
date1, date2 = descendants_too_old (child, years + self.MIN_GENERATION_YEARS)
|
||||
dobj.copy_offset_ymd(- self.MIN_GENERATION_YEARS + self.MAX_AGE_PROB_ALIVE),
|
||||
_("descendent death date"),
|
||||
child)
|
||||
date1, date2, explain, other = descendants_too_old (child, years + self.MIN_GENERATION_YEARS)
|
||||
if date1 and date2:
|
||||
return date1, date2
|
||||
return (None, None)
|
||||
return date1, date2, explain, other
|
||||
# Check fallback data:
|
||||
for ev_ref in child.get_primary_event_ref_list():
|
||||
ev = self.db.get_event_from_handle(ev_ref.ref)
|
||||
if ev and ev.type.is_birth_fallback():
|
||||
dobj = ev.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(self.MAX_AGE_PROB_ALIVE),
|
||||
_("descendent birth-related date"),
|
||||
child)
|
||||
|
||||
elif ev and ev.type.is_death_fallback():
|
||||
dobj = ev.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_ymd(- self.MIN_GENERATION_YEARS),
|
||||
dobj.copy_offset_ymd(- self.MIN_GENERATION_YEARS + self.MAX_AGE_PROB_ALIVE),
|
||||
_("descendent death-related date"),
|
||||
child)
|
||||
|
||||
return (None, 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
|
||||
date1, date2, explain, other = None, None, "", None
|
||||
try:
|
||||
date1, date2 = descendants_too_old(person, self.MIN_GENERATION_YEARS)
|
||||
date1, date2, explain, other = descendants_too_old(person, self.MIN_GENERATION_YEARS)
|
||||
except RuntimeError:
|
||||
raise Errors.DatabaseError(
|
||||
_("Database error: %s is defined as his or her own ancestor") %
|
||||
name_displayer.display(person))
|
||||
|
||||
if date1 and date2:
|
||||
return (date1, date2)
|
||||
return (date1, date2, explain, other)
|
||||
|
||||
def ancestors_too_old(person, year):
|
||||
family_handle = person.get_main_parents_family_handle()
|
||||
@ -427,53 +720,104 @@ class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
|
||||
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:
|
||||
if father_birth_ref and father_birth_ref.get_role().is_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 + self.MAX_AGE_PROB_ALIVE))
|
||||
dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE),
|
||||
_("ancestor birth date"),
|
||||
father)
|
||||
father_death_ref = father.get_death_ref()
|
||||
if father_death_ref and father_death_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
|
||||
if father_death_ref and father_death_ref.get_role().is_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 - self.MAX_AGE_PROB_ALIVE),
|
||||
dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE))
|
||||
date1, date2 = ancestors_too_old (father, year - self.AVG_GENERATION_GAP)
|
||||
dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE),
|
||||
_("ancestor death date"),
|
||||
father)
|
||||
|
||||
# Check fallback data:
|
||||
for ev_ref in father.get_primary_event_ref_list():
|
||||
ev = self.db.get_event_from_handle(ev_ref.ref)
|
||||
if ev and ev.type.is_birth_fallback():
|
||||
dobj = ev.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_ymd(- year),
|
||||
dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE),
|
||||
_("ancestor birth-related date"),
|
||||
father)
|
||||
|
||||
elif ev and ev.type.is_death_fallback():
|
||||
dobj = ev.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE),
|
||||
dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE),
|
||||
_("ancestor death-related date"),
|
||||
father)
|
||||
|
||||
date1, date2, explain, other = ancestors_too_old (father, year - self.AVG_GENERATION_GAP)
|
||||
if date1 and date2:
|
||||
return date1, date2
|
||||
return date1, date2, explain, other
|
||||
|
||||
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:
|
||||
if mother_birth_ref and mother_birth_ref.get_role().is_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 + self.MAX_AGE_PROB_ALIVE))
|
||||
dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE),
|
||||
_("ancestor birth date"),
|
||||
mother)
|
||||
mother_death_ref = mother.get_death_ref()
|
||||
if mother_death_ref and mother_death_ref.get_role() == gen.lib.EventRoleType.PRIMARY:
|
||||
if mother_death_ref and mother_death_ref.get_role().is_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 - self.MAX_AGE_PROB_ALIVE),
|
||||
dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE))
|
||||
date1, date2 = ancestors_too_old (mother, year - self.AVG_GENERATION_GAP)
|
||||
dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE),
|
||||
_("ancestor death date"),
|
||||
mother)
|
||||
|
||||
# Check fallback data:
|
||||
for ev_ref in mother.get_primary_event_ref_list():
|
||||
ev = self.db.get_event_from_handle(ev_ref.ref)
|
||||
if ev and ev.type.is_birth_fallback():
|
||||
dobj = ev.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_ymd(- year),
|
||||
dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE),
|
||||
_("ancestor birth-related date"),
|
||||
mother)
|
||||
|
||||
elif ev and ev.type.is_death_fallback():
|
||||
dobj = ev.get_date_object()
|
||||
if dobj.get_start_date() != gen.lib.Date.EMPTY:
|
||||
return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE),
|
||||
dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE),
|
||||
_("ancestor death-related date"),
|
||||
mother)
|
||||
|
||||
date1, date2, explain, other = ancestors_too_old (mother, year - self.AVG_GENERATION_GAP)
|
||||
if date1 and date2:
|
||||
return (date1, date2)
|
||||
return (None, None)
|
||||
return (date1, date2, explain, other)
|
||||
|
||||
return (None, 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, - self.MIN_GENERATION_YEARS)
|
||||
date1, date2, explain, other = ancestors_too_old (person, - self.MIN_GENERATION_YEARS)
|
||||
if date1 and date2:
|
||||
return (date1, date2)
|
||||
#print " FAIL"
|
||||
return (date1, date2, explain, other)
|
||||
|
||||
# If we can't find any reason to believe that they are dead we
|
||||
# must assume they are alive.
|
||||
return (None, None)
|
||||
|
||||
return (None, None, "", None)
|
||||
|
Loading…
Reference in New Issue
Block a user