def __init__(self, dbase, mode, current_year=None, years_after_death=0): """ Create a new LivingProxyDb instance. @param dbase: The database to be a proxy for @type dbase: DbBase @param mode: The method for handling living people. LivingProxyDb.MODE_EXCLUDE_ALL will remove living people altogether. LivingProxyDb.MODE_INCLUDE_LAST_NAME_ONLY will remove all information and change their given name to "[Living]" or what has been set in Preferences -> Text. LivingProxyDb.MODE_INCLUDE_FULL_NAME_ONLY will remove all information but leave the entire name intact. @type mode: int @param current_year: The current year to use for living determination. If None is supplied, the current year will be found from the system. @type current_year: int or None @param years_after_death: The number of years after a person's death to still consider them living. @type years_after_death: int """ ProxyDbBase.__init__(self, dbase) self.mode = mode if current_year is not None: self.current_date = Date() self.current_date.set_year(current_year) else: self.current_date = None self.years_after_death = years_after_death
def parse(self, text): """ Parses the text, returning a Date object. """ new_date = Date() try: self.set_date(new_date, text) except DateError: new_date.set_as_text(text) return new_date
def by_birthdate_key(self, first_id): """Sort routine for comparing two people by birth dates. If the birth dates are equal, sorts by name""" first = self.database.get_person_from_handle(first_id) birth1 = get_birth_or_fallback(self.database, first) if birth1: date1 = birth1.get_date_object() else: date1 = Date() dsv1 = date1.get_sort_value() return "%08d" % dsv1 + self.by_last_name_key(first_id)
def by_birthdate(self, first_id, second_id): """Sort routine for comparing two people by birth dates. If the birth dates are equal, sorts by name""" first = self.database.get_person_from_handle(first_id) second = self.database.get_person_from_handle(second_id) birth1 = get_birth_or_fallback(self.database, first) if birth1: date1 = birth1.get_date_object() else: date1 = Date() birth2 = get_birth_or_fallback(self.database, second) if birth2: date2 = birth2.get_date_object() else: date2 = Date() dsv1 = date1.get_sort_value() dsv2 = date2.get_sort_value() val = cmp(dsv1, dsv2) if val == 0: return self.by_last_name(first_id, second_id) return val
def _find_records(db, filter, callname): today = datetime.date.today() today_date = Date(today.year, today.month, today.day) # Person records person_youngestliving = [] person_oldestliving = [] person_youngestdied = [] person_oldestdied = [] person_youngestmarried = [] person_oldestmarried = [] person_youngestdivorced = [] person_oldestdivorced = [] person_youngestfather = [] person_youngestmother = [] person_oldestfather = [] person_oldestmother = [] person_handle_list = db.iter_person_handles() if filter: person_handle_list = filter.apply(db, person_handle_list) for person_handle in person_handle_list: person = db.get_person_from_handle(person_handle) birth_ref = person.get_birth_ref() if not birth_ref: # No birth event, so we can't calculate any age. continue birth = db.get_event_from_handle(birth_ref.ref) birth_date = birth.get_date_object() death_date = _find_death_date(db, person) if not _good_date(birth_date): # Birth date unknown or incomplete, so we can't calculate any age. continue name = _Person_get_styled_primary_name(person, callname) if death_date is None: if probably_alive(person, db): # Still living, look for age records _record(person_youngestliving, person_oldestliving, today_date - birth_date, name, 'Person', person_handle) elif _good_date(death_date): # Already died, look for age records _record(person_youngestdied, person_oldestdied, death_date - birth_date, name, 'Person', person_handle) for family_handle in person.get_family_handle_list(): family = db.get_family_from_handle(family_handle) marriage_date = None divorce_date = None for event_ref in family.get_event_ref_list(): event = db.get_event_from_handle(event_ref.ref) if (event.get_type().is_marriage() and (event_ref.get_role().is_family() or event_ref.get_role().is_primary())): marriage_date = event.get_date_object() elif (event.get_type().is_divorce() and (event_ref.get_role().is_family() or event_ref.get_role().is_primary())): divorce_date = event.get_date_object() if _good_date(marriage_date): _record(person_youngestmarried, person_oldestmarried, marriage_date - birth_date, name, 'Person', person_handle) if _good_date(divorce_date): _record(person_youngestdivorced, person_oldestdivorced, divorce_date - birth_date, name, 'Person', person_handle) for child_ref in family.get_child_ref_list(): if person.get_gender() == person.MALE: relation = child_ref.get_father_relation() elif person.get_gender() == person.FEMALE: relation = child_ref.get_mother_relation() else: continue if relation != ChildRefType.BIRTH: continue child = db.get_person_from_handle(child_ref.ref) child_birth_ref = child.get_birth_ref() if not child_birth_ref: continue child_birth = db.get_event_from_handle(child_birth_ref.ref) child_birth_date = child_birth.get_date_object() if not _good_date(child_birth_date): continue if person.get_gender() == person.MALE: _record(person_youngestfather, person_oldestfather, child_birth_date - birth_date, name, 'Person', person_handle) elif person.get_gender() == person.FEMALE: _record(person_youngestmother, person_oldestmother, child_birth_date - birth_date, name, 'Person', person_handle) # Family records family_mostchildren = [] family_youngestmarried = [] family_oldestmarried = [] family_shortest = [] family_longest = [] for family in db.iter_families(): #family = db.get_family_from_handle(family_handle) father_handle = family.get_father_handle() if not father_handle: continue mother_handle = family.get_mother_handle() if not mother_handle: continue # Test if either father or mother are in filter if filter: if not filter.apply(db, [father_handle, mother_handle]): continue father = db.get_person_from_handle(father_handle) mother = db.get_person_from_handle(mother_handle) name = StyledText(_("%(father)s and %(mother)s")) % { 'father': _Person_get_styled_primary_name(father, callname), 'mother': _Person_get_styled_primary_name(mother, callname) } _record(None, family_mostchildren, len(family.get_child_ref_list()), name, 'Family', family.handle) marriage_date = None divorce = None divorce_date = None for event_ref in family.get_event_ref_list(): event = db.get_event_from_handle(event_ref.ref) if (event.get_type().is_marriage() and (event_ref.get_role().is_family() or event_ref.get_role().is_primary())): marriage_date = event.get_date_object() if (event and event.get_type().is_divorce() and (event_ref.get_role().is_family() or event_ref.get_role().is_primary())): divorce = event divorce_date = event.get_date_object() father_death_date = _find_death_date(db, father) mother_death_date = _find_death_date(db, mother) if not _good_date(marriage_date): # Not married or marriage date unknown continue if divorce is not None and not _good_date(divorce_date): # Divorced but date unknown or inexact continue if not probably_alive(father, db) and not _good_date(father_death_date): # Father died but death date unknown or inexact continue if not probably_alive(mother, db) and not _good_date(mother_death_date): # Mother died but death date unknown or inexact continue if divorce_date is None and father_death_date is None and mother_death_date is None: # Still married and alive if probably_alive(father, db) and probably_alive(mother, db): _record(family_youngestmarried, family_oldestmarried, today_date - marriage_date, name, 'Family', family.handle) elif (_good_date(divorce_date) or _good_date(father_death_date) or _good_date(mother_death_date)): end = None if _good_date(father_death_date) and _good_date(mother_death_date): end = min(father_death_date, mother_death_date) elif _good_date(father_death_date): end = father_death_date elif _good_date(mother_death_date): end = mother_death_date if _good_date(divorce_date): if end: end = min(end, divorce_date) else: end = divorce_date duration = end - marriage_date _record(family_shortest, family_longest, duration, name, 'Family', family.handle) return [(text, varname, locals()[varname]) for (text, varname, default) in RECORDS]
class LivingProxyDb(ProxyDbBase): """ A proxy to a Gramps database. This proxy will act like a Gramps database, but all living people will be hidden from the user. """ MODE_EXCLUDE_ALL = 0 MODE_INCLUDE_LAST_NAME_ONLY = 1 MODE_INCLUDE_FULL_NAME_ONLY = 2 def __init__(self, dbase, mode, current_year=None, years_after_death=0): """ Create a new LivingProxyDb instance. @param dbase: The database to be a proxy for @type dbase: DbBase @param mode: The method for handling living people. LivingProxyDb.MODE_EXCLUDE_ALL will remove living people altogether. LivingProxyDb.MODE_INCLUDE_LAST_NAME_ONLY will remove all information and change their given name to "[Living]" or what has been set in Preferences -> Text. LivingProxyDb.MODE_INCLUDE_FULL_NAME_ONLY will remove all information but leave the entire name intact. @type mode: int @param current_year: The current year to use for living determination. If None is supplied, the current year will be found from the system. @type current_year: int or None @param years_after_death: The number of years after a person's death to still consider them living. @type years_after_death: int """ ProxyDbBase.__init__(self, dbase) self.mode = mode if current_year is not None: self.current_date = Date() self.current_date.set_year(current_year) else: self.current_date = None self.years_after_death = years_after_death def get_person_from_handle(self, handle): """ Finds a Person in the database from the passed gramps ID. If no such Person exists, None is returned. """ person = self.db.get_person_from_handle(handle) if person and self.__is_living(person): if self.mode == self.MODE_EXCLUDE_ALL: person = None else: person = self.__restrict_person(person) return person def get_family_from_handle(self, handle): """ Finds a Family in the database from the passed handle. If no such Family exists, None is returned. """ family = self.db.get_family_from_handle(handle) family = self.__remove_living_from_family(family) return family def iter_people(self): """ Protected version of iter_people """ for person in ifilter(None, self.db.iter_people()): if self.__is_living(person): if self.mode == self.MODE_EXCLUDE_ALL: continue else: yield self.__restrict_person(person) else: yield person def get_person_from_gramps_id(self, val): """ Finds a Person in the database from the passed GRAMPS ID. If no such Person exists, None is returned. """ person = self.db.get_person_from_gramps_id(val) if person and self.__is_living(person): if self.mode == self.MODE_EXCLUDE_ALL: return None else: return self.__restrict_person(person) else: return person def get_family_from_gramps_id(self, val): """ Finds a Family in the database from the passed GRAMPS ID. If no such Family exists, None is returned. """ family = self.db.get_family_from_gramps_id(val) family = self.__remove_living_from_family(family) return family def include_person(self, handle): if self.mode == self.MODE_EXCLUDE_ALL: person = self.get_unfiltered_person(handle) if person and self.__is_living(person): return False return True def get_default_person(self): """returns the default Person of the database""" person_handle = self.db.get_default_handle() return self.get_person_from_handle(person_handle) def get_default_handle(self): """returns the default Person of the database""" person_handle = self.db.get_default_handle() if self.get_person_from_handle(person_handle): return person_handle return None def has_person_handle(self, handle): """ returns True if the handle exists in the current Person database. """ if self.get_person_from_handle(handle): return True return False def find_backlink_handles(self, handle, include_classes=None): """ Find all objects that hold a reference to the object handle. Returns an iterator over a list of (class_name, handle) tuples. @param handle: handle of the object to search for. @type handle: database handle @param include_classes: list of class names to include in the results. Default: None means include all classes. @type include_classes: list of class names This default implementation does a sequential scan through all the primary object databases and is very slow. Backends can override this method to provide much faster implementations that make use of additional capabilities of the backend. Note that this is a generator function, it returns a iterator for use in loops. If you want a list of the results use: > result_list = list(find_backlink_handles(handle)) """ handle_itr = self.db.find_backlink_handles(handle, include_classes) for (class_name, handle) in handle_itr: if class_name == 'Person': if not self.get_person_from_handle(handle): continue yield (class_name, handle) return def __is_living(self, person): """ Check if a person is considered living. Returns True if the person is considered living. Returns False if the person is not considered living. """ person_handle = person.get_handle() unfil_person = self.get_unfiltered_person(person_handle) return probably_alive(unfil_person, self.db, self.current_date, self.years_after_death) def __remove_living_from_family(self, family): """ Remove information from a family that pertains to living people. Returns a family instance with information about living people removed. Returns None if family is None. """ if family is None: return None parent_is_living = False father_handle = family.get_father_handle() if father_handle: father = self.db.get_person_from_handle(father_handle) if father and self.__is_living(father): parent_is_living = True if self.mode == self.MODE_EXCLUDE_ALL: family.set_father_handle(None) mother_handle = family.get_mother_handle() if mother_handle: mother = self.db.get_person_from_handle(mother_handle) if mother and self.__is_living(mother): parent_is_living = True if self.mode == self.MODE_EXCLUDE_ALL: family.set_mother_handle(None) if parent_is_living: # Clear all events for families where a parent is living. family.set_event_ref_list([]) if self.mode == self.MODE_EXCLUDE_ALL: for child_ref in family.get_child_ref_list(): child_handle = child_ref.get_reference_handle() child = self.db.get_person_from_handle(child_handle) if child and self.__is_living(child): family.remove_child_ref(child_ref) return family def __restrict_person(self, person): """ Remove information from a person and replace the first name with "[Living]" or what has been set in Preferences -> Text. """ new_person = Person() new_name = Name() old_name = person.get_primary_name() new_name.set_group_as(old_name.get_group_as()) new_name.set_sort_as(old_name.get_sort_as()) new_name.set_display_as(old_name.get_display_as()) new_name.set_type(old_name.get_type()) if self.mode == self.MODE_INCLUDE_LAST_NAME_ONLY: new_name.set_first_name( config.get('preferences.private-given-text')) new_name.set_title("") else: # self.mode == self.MODE_INCLUDE_FULL_NAME_ONLY new_name.set_first_name(old_name.get_first_name()) new_name.set_suffix(old_name.get_suffix()) new_name.set_title(old_name.get_title()) surnlst = [] for surn in old_name.get_surname_list(): surname = Surname(source=surn) if int(surname.origintype) in [ NameOriginType.PATRONYMIC, NameOriginType.MATRONYMIC ]: surname.set_surname( config.get('preferences.private-surname-text')) surnlst.append(surname) new_name.set_surname_list(surnlst) new_person.set_primary_name(new_name) new_person.set_privacy(person.get_privacy()) new_person.set_gender(person.get_gender()) new_person.set_gramps_id(person.get_gramps_id()) new_person.set_handle(person.get_handle()) new_person.set_change_time(person.get_change_time()) new_person.set_family_handle_list(person.get_family_handle_list()) new_person.set_parent_family_handle_list( person.get_parent_family_handle_list()) new_person.set_tag_list(person.get_tag_list()) return new_person
def collect_data(self): """ This method runs through the data, and collects the relevant dates and text. """ people = self.database.iter_person_handles() self._user.begin_progress(_('Birthday and Anniversary Report'), _('Applying Filter...'), self.database.get_number_of_people()) people = self.filter.apply(self.database, people, self._user.step_progress) self._user.end_progress() rel_calc = Relationship.get_relationship_calculator() self._user.begin_progress(_('Birthday and Anniversary Report'), _('Reading database...'), len(people)) for person_handle in people: self._user.step_progress() person = self.database.get_person_from_handle(person_handle) birth_ref = person.get_birth_ref() birth_date = None if birth_ref: birth_event = self.database.get_event_from_handle(birth_ref.ref) birth_date = birth_event.get_date_object() if (self.birthdays and birth_date is not None and birth_date.is_valid()): birth_date = gregorian(birth_date) year = birth_date.get_year() month = birth_date.get_month() day = birth_date.get_day() prob_alive_date = Date(self.year, month, day) nyears = self.year - year # add some things to handle maiden name: father_lastname = None # husband, actually if self.maiden_name in ['spouse_first', 'spouse_last']: # get husband's last name: if person.get_gender() == Person.FEMALE: family_list = person.get_family_handle_list() if len(family_list) > 0: if self.maiden_name == 'spouse_first': fhandle = family_list[0] else: fhandle = family_list[-1] fam = self.database.get_family_from_handle(fhandle) father_handle = fam.get_father_handle() mother_handle = fam.get_mother_handle() if mother_handle == person_handle: if father_handle: father = self.database.get_person_from_handle(father_handle) if father is not None: primary_name = father.get_primary_name() if primary_name: father_lastname = Surname.get_surname(primary_name.get_primary_surname()) short_name = self.get_name(person, father_lastname) alive = probably_alive(person, self.database, prob_alive_date) if ((self.alive and alive) or not self.alive): comment = "" if self.relationships: relation = rel_calc.get_one_relationship( self.database, self.center_person, person) if relation: comment = " --- %s" % relation if nyears == 0: text = _('%(person)s, birth%(relation)s') % { 'person' : short_name, 'relation' : comment} else: text = (ngettext('%(person)s, %(age)d%(relation)s', '%(person)s, %(age)d%(relation)s', nyears) % {'person' : short_name, 'age' : nyears, 'relation' : comment}) self.add_day_item(text, month, day) if self.anniversaries: family_list = person.get_family_handle_list() for fhandle in family_list: fam = self.database.get_family_from_handle(fhandle) father_handle = fam.get_father_handle() mother_handle = fam.get_mother_handle() if father_handle == person.get_handle(): spouse_handle = mother_handle else: continue # with next person if the father is not "person" # this will keep from duplicating the anniversary if spouse_handle: spouse = self.database.get_person_from_handle(spouse_handle) if spouse: spouse_name = self.get_name(spouse) short_name = self.get_name(person) # TEMP: this will handle ordered events # GRAMPS 3.0 will have a new mechanism for start/stop events are_married = None for event_ref in fam.get_event_ref_list(): event = self.database.get_event_from_handle(event_ref.ref) if event.type in [EventType.MARRIAGE, EventType.MARR_ALT]: are_married = event elif event.type in [EventType.DIVORCE, EventType.ANNULMENT, EventType.DIV_FILING]: are_married = None if are_married is not None: for event_ref in fam.get_event_ref_list(): event = self.database.get_event_from_handle(event_ref.ref) event_obj = event.get_date_object() if event_obj is not Date.EMPTY and event_obj.is_valid(): event_obj = gregorian(event_obj) year = event_obj.get_year() month = event_obj.get_month() day = event_obj.get_day() nyears = self.year - year if event_obj.is_valid(): if nyears == 0: text = _("%(spouse)s and\n %(person)s, wedding") % { 'spouse' : spouse_name, 'person' : short_name} else: text = (ngettext("%(spouse)s and\n %(person)s, %(nyears)d", "%(spouse)s and\n %(person)s, %(nyears)d", nyears) % {'spouse' : spouse_name, 'person' : short_name, 'nyears' : nyears}) prob_alive_date = Date(self.year, month, day) alive1 = probably_alive(person, self.database, prob_alive_date) alive2 = probably_alive(spouse, self.database, prob_alive_date) if (self.alive and alive1 and alive2) or not self.alive: self.add_day_item(text, month, day) self._user.end_progress()