diff --git a/src/plugins/tool/CalculateEstimatedDates.py b/src/plugins/tool/CalculateEstimatedDates.py
index 4fdcf6849..1935a6b59 100644
--- a/src/plugins/tool/CalculateEstimatedDates.py
+++ b/src/plugins/tool/CalculateEstimatedDates.py
@@ -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, "%s" % DateHandler.displayer.display(date1))
+ if add_death_event:
+ stab.set_cell_markup(4, row, "%s" % 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)