示例#1
0
 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
示例#2
0
 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
示例#3
0
    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)
示例#4
0
    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
示例#5
0
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]
示例#6
0
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
示例#7
0
    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()