Example #1
0
    def instance_from_struct(cls, struct):
        """
        Given a struct with metadata, create a Gramps object.

        self is class when called as a classmethod.
        """
        from gramps.gen.lib import (Person, Family, Event, Source, Place,
                                    Citation, Repository, Media, Note, Tag,
                                    Date)
        if isinstance(struct, dict):
            if "_class" in struct.keys():
                if struct["_class"] == "Person":
                    return Person.create(Person.from_struct(struct))
                elif struct["_class"] == "Family":
                    return Family.create(Family.from_struct(struct))
                elif struct["_class"] == "Event":
                    return Event.create(Event.from_struct(struct))
                elif struct["_class"] == "Source":
                    return Source.create(Source.from_struct(struct))
                elif struct["_class"] == "Place":
                    return Place.create(Place.from_struct(struct))
                elif struct["_class"] == "Citation":
                    return Citation.create(Citation.from_struct(struct))
                elif struct["_class"] == "Repository":
                    return Repository.create(Repository.from_struct(struct))
                elif struct["_class"] == "Media":
                    return Media.create(Media.from_struct(struct))
                elif struct["_class"] == "Note":
                    return Note.create(Note.from_struct(struct))
                elif struct["_class"] == "Tag":
                    return Tag.create(Tag.from_struct(struct))
                elif struct["_class"] == "Date":
                    return Date().unserialize(
                        Date.from_struct(struct, full=True))
        raise AttributeError("invalid struct: %s" % struct)
Example #2
0
def match_dates(
    db_handle: DbReadBase, gramps_class_name: str, handles: List[Handle], date_mask: str
):
    """Match dates based on a date mask or range."""
    check_range = False
    if "-" in date_mask:
        check_range = True
        start, end = date_mask.split("-")
        if "/" in start:
            year, month, day = start.split("/")
            start_date = Date((int(year), int(month), int(day)))
        else:
            start_date = None
        if "/" in end:
            year, month, day = end.split("/")
            end_date = Date((int(year), int(month), int(day)))
        else:
            end_date = None

    query_method = db_handle.method("get_%s_from_handle", gramps_class_name)
    result = []
    for handle in handles:
        obj = query_method(handle)
        date = obj.get_date_object()
        if date.is_valid():
            if check_range:
                if match_date_range(date, start_date, end_date):
                    result.append(handle)
            else:
                if match_date(date, date_mask):
                    result.append(handle)
    return result
Example #3
0
 def double_click(self, obj):
     # bring up events on this day
     year, month, day = self.gui.calendar.get_date()
     date = Date()
     date.set_yr_mon_day(year, month + 1, day)
     run_quick_report_by_name(self.gui.dbstate, self.gui.uistate,
                              'onthisday', date)
Example #4
0
 def set_end_date(self, date: Union[Date, str]):
     """Set optional timeline end date."""
     if isinstance(date, str):
         year, month, day = date.split("/")
         self.end_date = Date((int(year), int(month), int(day)))
     else:
         self.end_date = date
Example #5
0
 def write_report(self):
     """
     The short method that runs through each month and creates a page.
     """
     # initialize the dict to fill:
     self.calendar = {}
     # get the information, first from holidays:
     if self.country != 0:
         self.__get_holidays()
     # get data from database:
     self.collect_data()
     # generate the report:
     self.doc.start_paragraph('BIR-Title')
     if self.titletext == _(_TITLE0):
         title = self._("%(str1)s: %(str2)s") % {
             'str1': self._(_TITLE0),
             'str2': self._get_date(Date(self.year))
         }  # localized year
     else:
         title = self._("%(str1)s: %(str2)s") % {
             'str1': str(self.titletext),
             'str2': self._get_date(Date(self.year))
         }
     mark = IndexMark(title, INDEX_TYPE_TOC, 1)
     self.doc.write_text(title, mark)
     self.doc.end_paragraph()
     if self.text1.strip() != "":
         self.doc.start_paragraph('BIR-Text1style')
         text1 = str(self.text1)
         if text1 == _(_TITLE1):
             text1 = self._(_TITLE1)
         self.doc.write_text(text1)
         self.doc.end_paragraph()
     if self.text2.strip() != "":
         self.doc.start_paragraph('BIR-Text2style')
         text2 = str(self.text2)
         if text2 == _(_TITLE2):
             text2 = self._(_TITLE2)
         self.doc.write_text(text2)
         self.doc.end_paragraph()
     if self.text3.strip() != "":
         self.doc.start_paragraph('BIR-Text3style')
         self.doc.write_text(str(self.text3))
         self.doc.end_paragraph()
     if self.relationships:
         name = self.center_person.get_primary_name()
         self.doc.start_paragraph('BIR-Text3style')
         mark = utils.get_person_mark(self.database, self.center_person)
         # feature request 2356: avoid genitive form
         self.doc.write_text(
             self._("Relationships shown are to %s") %
             self._name_display.display_name(name), mark)
         self.doc.end_paragraph()
     with self._user.progress(_('Birthday and Anniversary Report'),
                              _('Formatting months...'), 12) as step:
         for month in range(1, 13):
             step()
             self.print_page(month)
Example #6
0
 def double_click(self, obj):
     # bring up events on this day
     year, month, day = self.gui.calendar.get_date()
     date = Date()
     date.set_yr_mon_day(year, month + 1, day)
     run_quick_report_by_name(self.gui.dbstate,
                              self.gui.uistate,
                              'onthisday',
                              date)
Example #7
0
def match_date_range(date: Date, start_date: Date, end_date: Date) -> bool:
    """Check if date falls in given range."""
    if start_date:
        if start_date.match(date, comparison=">"):
            return False
    if end_date:
        if end_date.match(date, comparison="<"):
            return False
    return True
Example #8
0
 def by_person_birthdate_key(self, handle):
     """Compare by birth date, if equal sorts by name."""
     obj = self.query_method(handle)
     birth = get_birth_or_fallback(self.database, obj)
     if birth:
         date = birth.get_date_object()
     else:
         date = Date()
     return "%08d" % date.get_sort_value() + str(
         self.by_person_surname_key(handle))
Example #9
0
def match_date(date: Date, mask: str) -> bool:
    """Check if date matches mask."""
    if date is not None and date.is_valid():
        year_mask, month_mask, day_mask = mask.split("/")
        date = gregorian(date)
        year = date.get_year()
        if year_mask == "*" or year == int(year_mask):
            month = date.get_month()
            if month_mask == "*" or month == int(month_mask):
                day = date.get_day()
                if day_mask == "*" or day == int(day_mask):
                    return True
    return False
Example #10
0
    def instance_from_struct(cls, struct):
        """
        Given a struct with metadata, create a Gramps object.

        self is class when called as a classmethod.
        """
        from  gramps.gen.lib import (Person, Family, Event, Source, Place, Citation,
                                     Repository, Media, Note, Tag, Date)
        if isinstance(struct, dict):
            if "_class" in struct.keys():
                if struct["_class"] == "Person":
                    return Person.create(Person.from_struct(struct))
                elif struct["_class"] == "Family":
                    return Family.create(Family.from_struct(struct))
                elif struct["_class"] == "Event":
                    return Event.create(Event.from_struct(struct))
                elif struct["_class"] == "Source":
                    return Source.create(Source.from_struct(struct))
                elif struct["_class"] == "Place":
                    return Place.create(Place.from_struct(struct))
                elif struct["_class"] == "Citation":
                    return Citation.create(Citation.from_struct(struct))
                elif struct["_class"] == "Repository":
                    return Repository.create(Repository.from_struct(struct))
                elif struct["_class"] == "Media":
                    return Media.create(Media.from_struct(struct))
                elif struct["_class"] == "Note":
                    return Note.create(Note.from_struct(struct))
                elif struct["_class"] == "Tag":
                    return Tag.create(Tag.from_struct(struct))
                elif struct["_class"] == "Date":
                    return Date().unserialize(Date.from_struct(struct, full=True))
        raise AttributeError("invalid struct: %s" % struct)
Example #11
0
def format_datetime(datestring):
    """
    Convert an exif timestamp into a string for display, using the
    standard Gramps date format.
    """
    try:
        timestamp = datetime.strptime(datestring, '%Y:%m:%d %H:%M:%S')
    except ValueError:
        return _('Invalid format')
    date_part = Date()
    date_part.set_yr_mon_day(timestamp.year, timestamp.month, timestamp.day)
    date_str = displayer.display(date_part)
    time_str = _('%(hr)02d:%(min)02d:%(sec)02d') % {'hr': timestamp.hour,
                                                    'min': timestamp.minute,
                                                    'sec': timestamp.second}
    return _('%(date)s %(time)s') % {'date': date_str, 'time': time_str}
Example #12
0
    def __init__(
        self,
        db_handle: DbReadBase,
        dates: Optional[str] = None,
        events: Optional[List[str]] = None,
        ratings: bool = False,
        relatives: Optional[List[str]] = None,
        relative_events: Optional[List[str]] = None,
        discard_empty: bool = True,
        omit_anchor: bool = True,
        precision: int = 1,
        locale: GrampsLocale = glocale,
    ):
        """Initialize timeline."""
        self.db_handle = db_handle
        self.timeline: List[Tuple[Event, Person, str, str]] = []
        self.dates = dates
        self.start_date = None
        self.end_date = None
        self.ratings = ratings
        self.discard_empty = discard_empty
        self.precision = precision
        self.locale = locale
        self.anchor_person = None
        self.omit_anchor = omit_anchor
        self.depth = 1
        self.eligible_events: Set[str] = set()
        self.event_filters: List[str] = events or []
        self.eligible_relative_events: Set[str] = set()
        self.relative_event_filters: List[str] = relative_events or []
        self.relative_filters: List[str] = relatives or []
        self.set_event_filters(self.event_filters)
        self.set_relative_event_filters(self.relative_event_filters)
        self.birth_dates: Dict[str, Date] = {}

        if dates and "-" in dates:
            start, end = dates.split("-")
            if "/" in start:
                year, month, day = start.split("/")
                self.start_date = Date((int(year), int(month), int(day)))
            else:
                self.start_date = None
            if "/" in end:
                year, month, day = end.split("/")
                self.end_date = Date((int(year), int(month), int(day)))
            else:
                self.end_date = None
Example #13
0
 def __get_sortvals(self, date):
     """
     Get the sort values representing the start and end of a Date object.
     """
     start = None
     stop = None
     if date.modifier == Date.MOD_NONE:
         start = date.sortval
         stop = date.sortval
     elif date.modifier == Date.MOD_AFTER:
         start = date.sortval
     elif date.modifier == Date.MOD_BEFORE:
         stop = date.sortval
     elif date.is_compound():
         date1, date2 = date.get_start_stop_range()
         start = Date(*date1).sortval
         stop = Date(*date2).sortval
     return (start, stop)
Example #14
0
 def draw_year_headings(self, year_low, year_high, start_pos, stop_pos):
     """
     Draws the column headings (years) for the page.
     """
     style_sheet = self.doc.get_style_sheet()
     label_font = style_sheet.get_paragraph_style('TLG-Label').get_font()
     label_y = self.header - (utils.pt2cm(label_font.get_size()) * 1.2)
     incr = (year_high - year_low) / 5
     delta = (stop_pos - start_pos) / 5
     for val in range(0, 6):
         xpos = start_pos + (val * delta)
         year_str = self._get_date(Date(year_low + int(incr * val)))
         self.doc.center_text('TLG-label', year_str, xpos, label_y)
Example #15
0
    def parse_date(self, field):
        if field == "0":
            return None
        date = Date()
        matches = _text_parse.match(field)
        if matches:
            groups = matches.groups()
            date.set_as_text(groups[0])
            date.set_modifier(Date.MOD_TEXTONLY)
            return date

        matches = _date_parse.match(field)
        if matches:
            groups = matches.groups()
            mod = _mod_map.get(groups[0], Date.MOD_NONE)
            if groups[3] == "..":
                mod = Date.MOD_SPAN
                cal2 = _cal_map.get(groups[5], Date.CAL_GREGORIAN)
                sub2 = self.sub_date(groups[4])
            else:
                sub2 = (0, 0, 0)
            cal1 = _cal_map.get(groups[2], Date.CAL_GREGORIAN)
            sub1 = self.sub_date(groups[1])
            try:
                date.set(Date.QUAL_NONE, mod, cal1,
                         (sub1[0], sub1[1], sub1[2], 0, sub2[0], sub2[1],
                          sub2[2], 0))
            except DateError as e:
                # TRANSLATORS: leave the {date} and {gw_snippet} untranslated
                # in the format string, but you may re-order them if needed.
                LOG.warning(
                    _("Invalid date {date} in {gw_snippet}, "
                      "preserving date as text.").format(
                          date=e.date.to_struct(), gw_snippet=field))
                date.set(modifier=Date.MOD_TEXTONLY, text=field)
            return date
        else:
            return None
Example #16
0
    def create_widget(self):
        cell = Gtk.CellRendererText()
        cell.set_property('width', self._FILTER_WIDTH)
        cell.set_property('ellipsize', self._FILTER_ELLIPSIZE)
        self.generic.pack_start(cell, True)
        self.generic.add_attribute(cell, 'text', 0)
        self.on_filters_changed('Person')

        cell = Gtk.CellRendererText()
        cell.set_property('width', self._FILTER_WIDTH)
        cell.set_property('ellipsize', self._FILTER_ELLIPSIZE)
        self.tag.pack_start(cell, True)
        self.tag.add_attribute(cell, 'text', 0)

        self.etype.get_child().set_width_chars(5)

        exdate1 = Date()
        exdate2 = Date()
        exdate1.set(Date.QUAL_NONE, Date.MOD_RANGE, Date.CAL_GREGORIAN,
                    (0, 0, 1800, False, 0, 0, 1900, False))
        exdate2.set(Date.QUAL_NONE, Date.MOD_BEFORE, Date.CAL_GREGORIAN,
                    (0, 0, 1850, False))

        msg1 = displayer.display(exdate1)
        msg2 = displayer.display(exdate2)

        self.add_text_entry(_('Name'), self.filter_name)
        self.add_text_entry(_('ID'), self.filter_id)
        self.add_entry(_('Gender'), self.filter_gender)
        self.add_text_entry(
            _('Birth date'), self.filter_birth,
            _('example: "%(msg1)s" or "%(msg2)s"') % {
                'msg1': msg1,
                'msg2': msg2
            })
        self.add_text_entry(
            _('Death date'), self.filter_death,
            _('example: "%(msg1)s" or "%(msg2)s"') % {
                'msg1': msg1,
                'msg2': msg2
            })
        self.add_entry(_('Event'), self.etype)
        self.add_text_entry(_('Note'), self.filter_note)
        self.add_entry(_('Tag'), self.tag)
        self.add_filter_entry(_('Custom filter'), self.generic)
        self.add_regex_entry(self.filter_regex)
Example #17
0
    def parse_date(self,field):
        if field == "0":
            return None
        date = Date()
        matches = _text_parse.match(field)
        if matches:
            groups = matches.groups()
            date.set_as_text(groups[0])
            date.set_modifier(Date.MOD_TEXTONLY)
            return date

        matches = _date_parse.match(field)
        if matches:
            groups = matches.groups()
            mod = _mod_map.get(groups[0],Date.MOD_NONE)
            if groups[3] == "..":
                mod = Date.MOD_SPAN
                cal2 = _cal_map.get(groups[5],Date.CAL_GREGORIAN)
                sub2 = self.sub_date(groups[4])
            else:
                sub2 = (0,0,0)
            cal1 = _cal_map.get(groups[2],Date.CAL_GREGORIAN)
            sub1 = self.sub_date(groups[1])
            try:
                date.set(Date.QUAL_NONE,mod, cal1,
                         (sub1[0],sub1[1],sub1[2],0,sub2[0],sub2[1],sub2[2],0))
            except DateError as e:
                # TRANSLATORS: leave the {date} and {gw_snippet} untranslated
                # in the format string, but you may re-order them if needed.
                LOG.warning(_(
                    "Invalid date {date} in {gw_snippet}, "
                    "preserving date as text."
                    ).format(date=e.date.to_struct(), gw_snippet=field))
                date.set(modifier=Date.MOD_TEXTONLY, text=field)
            return date
        else:
            return None
Example #18
0
    def _geteventdate(self, event_handle):
        """
        Get the event date

        @param: event_handle -- The handle for the event to use
        """
        event_date = Date.EMPTY
        event = self.r_db.get_event_from_handle(event_handle)
        if event:
            date = event.get_date_object()
            if date:

                # returns the date in YYYY-MM-DD format
                return Date(date.get_year_calendar("Gregorian"),
                            date.get_month(), date.get_day())

        # return empty date string
        return event_date
Example #19
0
    def add_birthday(self, fields, data):
        """Read the BDAY property of a VCard."""
        date_str = data.strip()
        date_match = VCardParser.DATE_RE.match(date_str)
        date = Date()
        if date_match:
            if date_match.group(2):
                date_str = "%s-%s-%s" % (date_match.group(2),
                                         date_match.group(3),
                                         date_match.group(4))
            else:
                date_str = date_match.group(1)
            y, m, d = [int(x, 10) for x in date_str.split('-')]
            try:
                date.set(value=(d, m, y, False))
            except DateError:
                # TRANSLATORS: leave the {vcard_snippet} untranslated
                # in the format string, but you may re-order it if needed.
                self.__add_msg(
                    _("Invalid date in BDAY {vcard_snippet}, "
                      "preserving date as text.").format(vcard_snippet=data),
                    self.line_num - 1)
                date.set(modifier=Date.MOD_TEXTONLY, text=data)
        else:
            if date_str:
                # TRANSLATORS: leave the {vcard_snippet} untranslated.
                self.__add_msg(
                    _("Date {vcard_snippet} not in appropriate format "
                      "yyyy-mm-dd, preserving date as text.").format(
                          vcard_snippet=date_str), self.line_num - 1)
                date.set(modifier=Date.MOD_TEXTONLY, text=date_str)
            else:  # silently ignore an empty BDAY record
                return
        event = Event()
        event.set_type(EventType(EventType.BIRTH))
        event.set_date_object(date)
        self.database.add_event(event, self.trans)

        event_ref = EventRef()
        event_ref.set_reference_handle(event.get_handle())
        self.person.set_birth_ref(event_ref)
Example #20
0
    def get_date_string(self, event):
        """
        return date string for an event label.

        Based on the data availability and preferences, we select one
        of the following for a given event:
            year only
            complete date
            empty string
        """
        if event and event.get_date_object() is not None:
            event_date = event.get_date_object()
            if event_date.get_year_valid():
                if self.event_choice in [4, 5]:
                    return self.get_date(  # localized year
                        Date(event_date.get_year()))
                elif self.event_choice in [1, 2, 3, 7]:
                    return self.get_date(event_date)
        return ''
Example #21
0
    def add_birthday(self, fields, data):
        """Read the BDAY property of a VCard."""
        date_str = data.strip()
        date_match = VCardParser.DATE_RE.match(date_str)
        date = Date()
        if date_match:
            if date_match.group(2):
                date_str = "%s-%s-%s" % (date_match.group(2),
                                       date_match.group(3), date_match.group(4))
            else:
                date_str = date_match.group(1)
            y, m, d = [int(x, 10) for x in date_str.split('-')]
            try:
                date.set(value=(d, m, y, False))
            except DateError:
                # TRANSLATORS: leave the {vcard_snippet} untranslated
                # in the format string, but you may re-order it if needed.
                self.__add_msg(_(
                    "Invalid date in BDAY {vcard_snippet}, "
                    "preserving date as text."
                    ).format(vcard_snippet=data), self.line_num - 1)
                date.set(modifier=Date.MOD_TEXTONLY, text=data)
        else:
            if date_str:
                # TRANSLATORS: leave the {vcard_snippet} untranslated.
                self.__add_msg(_(
                    "Date {vcard_snippet} not in appropriate format "
                    "yyyy-mm-dd, preserving date as text."
                    ).format(vcard_snippet=date_str), self.line_num - 1)
                date.set(modifier=Date.MOD_TEXTONLY, text=date_str)
            else:  # silently ignore an empty BDAY record
                return
        event = Event()
        event.set_type(EventType(EventType.BIRTH))
        event.set_date_object(date)
        self.database.add_event(event, self.trans)

        event_ref = EventRef()
        event_ref.set_reference_handle(event.get_handle())
        self.person.set_birth_ref(event_ref)
Example #22
0
    def create_widget(self):
        cell = Gtk.CellRendererText()
        cell.set_property('width', self._FILTER_WIDTH)
        cell.set_property('ellipsize', self._FILTER_ELLIPSIZE)
        self.generic.pack_start(cell, True)
        self.generic.add_attribute(cell, 'text', 0)
        self.on_filters_changed('Person')

        cell = Gtk.CellRendererText()
        cell.set_property('width', self._FILTER_WIDTH)
        cell.set_property('ellipsize', self._FILTER_ELLIPSIZE)
        self.tag.pack_start(cell, True)
        self.tag.add_attribute(cell, 'text', 0)

        self.etype.get_child().set_width_chars(5)

        exdate1 = Date()
        exdate2 = Date()
        exdate1.set(Date.QUAL_NONE, Date.MOD_RANGE,
                    Date.CAL_GREGORIAN, (0, 0, 1800, False,
                                                0, 0, 1900, False))
        exdate2.set(Date.QUAL_NONE, Date.MOD_BEFORE,
                    Date.CAL_GREGORIAN, (0, 0, 1850, False))

        msg1 = displayer.display(exdate1)
        msg2 = displayer.display(exdate2)

        self.add_text_entry(_('Name'), self.filter_name)
        self.add_text_entry(_('ID'), self.filter_id)
        self.add_entry(_('Gender'), self.filter_gender)
        self.add_text_entry(_('Birth date'), self.filter_birth,
                            _('example: "%(msg1)s" or "%(msg2)s"') % {'msg1':msg1, 'msg2':msg2})
        self.add_text_entry(_('Death date'), self.filter_death,
                            _('example: "%(msg1)s" or "%(msg2)s"') % {'msg1':msg1, 'msg2':msg2})
        self.add_entry(_('Event'), self.etype)
        self.add_text_entry(_('Note'), self.filter_note)
        self.add_entry(_('Tag'), self.tag)
        self.add_filter_entry(_('Custom filter'), self.generic)
        self.add_regex_entry(self.filter_regex)
Example #23
0
    def collect_data(self):
        """
        This method runs through the data, and collects the relevant dates
        and text.
        """
        db = self.database
        people = db.iter_person_handles()
        with self._user.progress(_('Calendar Report'), _('Applying Filter...'),
                                 db.get_number_of_people()) as step:
            people = self.filter.apply(self.database, people, step)

        ngettext = self._locale.translation.ngettext  # to see "nearby" comments

        with self._user.progress(_('Calendar Report'),
                                 _('Reading database...'),
                                 len(people)) as step:
            for person_handle in people:
                step()
                person = db.get_person_from_handle(person_handle)
                mark = ReportUtils.get_person_mark(db, person)
                birth_ref = person.get_birth_ref()
                birth_date = None
                if birth_ref:
                    birth_event = db.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 family_list:
                                if self.maiden_name == 'spouse_first':
                                    fhandle = family_list[0]
                                else:
                                    fhandle = family_list[-1]
                                fam = db.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 = db.get_person_from_handle(
                                            father_handle)
                                        if father:
                                            father_lastname = father.get_primary_name(
                                            ).get_surname()
                    short_name = self.get_name(person, father_lastname)
                    alive = probably_alive(person, db, prob_alive_date)

                    if not self.alive or alive:
                        if nyears == 0:
                            text = self._('%(person)s, birth') % {
                                'person': short_name
                            }
                        else:
                            # translators: leave all/any {...} untranslated
                            text = ngettext('{person}, {age}',
                                            '{person}, {age}',
                                            nyears).format(person=short_name,
                                                           age=nyears)
                        self.add_day_item(text, month, day, marks=[mark])
                if self.anniversaries:
                    family_list = person.get_family_handle_list()
                    for fhandle in family_list:
                        fam = db.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 = db.get_person_from_handle(spouse_handle)
                            if spouse:
                                s_m = ReportUtils.get_person_mark(db, 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 = db.get_event_from_handle(
                                        event_ref.ref)
                                    et = EventType
                                    rt = EventRoleType
                                    if event.type in [et.MARRIAGE,
                                                      et.MARR_ALT] and \
                                        (event_ref.get_role() == rt.FAMILY or
                                         event_ref.get_role() == rt.PRIMARY ):
                                        are_married = event
                                    elif event.type in [et.DIVORCE,
                                                        et.ANNULMENT,
                                                        et.DIV_FILING] and \
                                        (event_ref.get_role() == rt.FAMILY or
                                         event_ref.get_role() == rt.PRIMARY ):
                                        are_married = None
                                if are_married is not None:
                                    for event_ref in fam.get_event_ref_list():
                                        event = db.get_event_from_handle(
                                            event_ref.ref)
                                        event_obj = event.get_date_object()

                                        if event_obj.is_valid():
                                            event_obj = gregorian(event_obj)

                                            year = event_obj.get_year()
                                            month = event_obj.get_month()
                                            day = event_obj.get_day()

                                            prob_alive_date = Date(
                                                self.year, month, day)

                                            nyears = self.year - year
                                            if nyears == 0:
                                                text = self._(
                                                    '%(spouse)s and\n %(person)s, wedding'
                                                ) % {
                                                    'spouse': spouse_name,
                                                    'person': short_name,
                                                }
                                            else:
                                                # translators: leave all/any {...} untranslated
                                                text = ngettext(
                                                    "{spouse} and\n {person}, {nyears}",
                                                    "{spouse} and\n {person}, {nyears}",
                                                    nyears).format(
                                                        spouse=spouse_name,
                                                        person=short_name,
                                                        nyears=nyears)

                                            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,
                                                    marks=[mark, s_m])
def makedate(year, month=0, day=0, about=False):
    d = GrampsDate()
    d.set_yr_mon_day(year, month, day)
    if about:
        d.set_modifier(GrampsDate.MOD_ABOUT)
    return DateProxy(d)
Example #25
0
    def run_tool(self):
        self.progress = ProgressMeter(_('Running Date Test'),'',
                                        parent=self.parent_window)
        self.progress.set_pass(_('Generating dates'),
                               4)
        dates = []
        # first some valid dates
        calendar = Date.CAL_GREGORIAN
        for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED,
                        Date.QUAL_CALCULATED):
            for modifier in (Date.MOD_NONE, Date.MOD_BEFORE,
                             Date.MOD_AFTER, Date.MOD_ABOUT):
                for slash1 in (False,True):
                    for month in range(0,13):
                        for day in (0,5,27):
                            if not month and day:
                                continue
                            d = Date()
                            d.set(quality,modifier,calendar,(day,month,1789,slash1),"Text comment")
                            dates.append( d)
            for modifier in (Date.MOD_RANGE, Date.MOD_SPAN):
                for slash1 in (False,True):
                    for slash2 in (False,True):
                        for month in range(0,13):
                            for day in (0,5,27):
                                if not month and day:
                                    continue

                                d = Date()
                                d.set(quality,modifier,calendar,(day,month,1789,slash1,day,month,1876,slash2),"Text comment")
                                dates.append( d)

                                if not month:
                                    continue

                                d = Date()
                                d.set(quality,modifier,calendar,(day,month,1789,slash1,day,13-month,1876,slash2),"Text comment")
                                dates.append( d)

                                if not day:
                                    continue

                                d = Date()
                                d.set(quality,modifier,calendar,(day,month,1789,slash1,32-day,month,1876,slash2),"Text comment")
                                dates.append( d)
                                d = Date()
                                d.set(quality,modifier,calendar,(day,month,1789,slash1,32-day,13-month,1876,slash2),"Text comment")
                                dates.append( d)
            modifier = Date.MOD_TEXTONLY
            d = Date()
            d.set(quality,modifier,calendar,Date.EMPTY,
                  "This is a textual date")
            dates.append( d)
            self.progress.step()
        
        # test invalid dates
        #dateval = (4,7,1789,False,5,8,1876,False)
        #for l in range(1,len(dateval)):
        #    d = Date()
        #    try:
        #        d.set(Date.QUAL_NONE,Date.MOD_NONE,
        #              Date.CAL_GREGORIAN,dateval[:l],"Text comment")
        #        dates.append( d)
        #    except DateError, e:
        #        d.set_as_text("Date identified value correctly as invalid.\n%s" % e)
        #        dates.append( d)
        #    except:
        #        d = Date()
        #        d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
        #        dates.append( d)
        #for l in range(1,len(dateval)):
        #    d = Date()
        #    try:
        #        d.set(Date.QUAL_NONE,Date.MOD_SPAN,Date.CAL_GREGORIAN,dateval[:l],"Text comment")
        #        dates.append( d)
        #    except DateError, e:
        #        d.set_as_text("Date identified value correctly as invalid.\n%s" % e)
        #        dates.append( d)
        #    except:
        #        d = Date()
        #        d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
        #        dates.append( d)
        #self.progress.step()
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_NONE,
        #      Date.CAL_GREGORIAN,(44,7,1789,False),"Text comment")
        #dates.append( d)
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_NONE,
        #      Date.CAL_GREGORIAN,(4,77,1789,False),"Text comment")
        #dates.append( d)
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_SPAN,
        #      Date.CAL_GREGORIAN,
        #      (4,7,1789,False,55,8,1876,False),"Text comment")
        #dates.append( d)
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_SPAN,
        #      Date.CAL_GREGORIAN,
        #      (4,7,1789,False,5,88,1876,False),"Text comment")
        #dates.append( d)
        
        with DbTxn(_("Date Test Plugin"), self.db, batch=True) as self.trans:
            self.db.disable_signals()
            self.progress.set_pass(_('Generating dates'),
                                   len(dates))

            # create pass and fail tags
            pass_handle = self.create_tag(_('Pass'), '#0000FFFF0000')
            fail_handle = self.create_tag(_('Fail'), '#FFFF00000000')

            # now add them as birth to new persons
            i = 1
            for dateval in dates:
                person = Person()
                surname = Surname()
                surname.set_surname("DateTest")
                name = Name()
                name.add_surname(surname)
                name.set_first_name("Test %d" % i)
                person.set_primary_name(name)
                self.db.add_person(person, self.trans)
                bevent = Event()
                bevent.set_type(EventType.BIRTH)
                bevent.set_date_object(dateval)
                bevent.set_description("Date Test %d (source)" % i)
                bevent_h = self.db.add_event(bevent, self.trans)
                bevent_ref = EventRef()
                bevent_ref.set_reference_handle(bevent_h)
                # for the death event display the date as text and parse it back to a new date
                ndate = None
                try:
                    datestr = _dd.display( dateval)
                    try:
                        ndate = _dp.parse( datestr)
                        if not ndate:
                            ndate = Date()
                            ndate.set_as_text("DateParser None")
                            person.add_tag(fail_handle)
                        else:
                            person.add_tag(pass_handle)
                    except:
                        ndate = Date()
                        ndate.set_as_text("DateParser Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
                        person.add_tag(fail_handle)
                    else:
                        person.add_tag(pass_handle)
                except:
                    ndate = Date()
                    ndate.set_as_text("DateDisplay Exception: %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
                    person.add_tag(fail_handle)
                
                if dateval.get_modifier() != Date.MOD_TEXTONLY \
                       and ndate.get_modifier() == Date.MOD_TEXTONLY:
                    # parser was unable to correctly parse the string
                    ndate.set_as_text( "TEXTONLY: "+ndate.get_text())
                    person.add_tag(fail_handle)
                if dateval.get_modifier() == Date.MOD_TEXTONLY \
                        and dateval.get_text().count("Traceback") \
                        and pass_handle in person.get_tag_list():
                    person.add_tag(fail_handle)
                
                devent = Event()
                devent.set_type(EventType.DEATH)
                devent.set_date_object(ndate)
                devent.set_description("Date Test %d (result)" % i)
                devent_h = self.db.add_event(devent, self.trans)
                devent_ref = EventRef()
                devent_ref.set_reference_handle(devent_h)
                person.set_birth_ref(bevent_ref)
                person.set_death_ref(devent_ref)
                self.db.commit_person(person, self.trans)
                i = i + 1
                self.progress.step()
        self.db.enable_signals()
        self.db.request_rebuild()
        self.progress.close()
    def run(self):
        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

        current_date = Date()
        current_date.set_yr_mon_day(*time.localtime(time.time())[0:3])
        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 = QuickTable(self.sdb)
        self.table = stab
        stab.columns(_("Select"), _("Person"), _("Action"),
                     _("Birth Date"), _("Death Date"),
                     _("Evidence"), _("Relative"))
        self.results_write(_("Processing...\n"))
        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']

        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:
            with DbTxn("", self.db, batch=True) as self.trans:
                self.db.disable_signals()
                self.results_write(_("Removing old estimations... "))
                self.progress.set_pass((_("Removing '%s'...") % source_text),
                                       num_people)
                supdate = None
                for person_handle in people:
                    self.progress.step()
                    pupdate = 0
                    person = self.db.get_person_from_handle(person_handle)
                    birth_ref = person.get_birth_ref()
                    if birth_ref:
                        birth = self.db.get_event_from_handle(birth_ref.ref)
                        for citation_handle in birth.get_citation_list():
                            citation = self.db.get_citation_from_handle(citation_handle)
                            source_handle = citation.get_reference_handle()
                            #print "birth handle:", source_handle
                            source = self.db.get_source_from_handle(source_handle)
                            if source:
                                if source.get_title() == source_text:
                                    #print("birth event removed from:",
                                    #      person.gramps_id)
                                    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.remove_citation(citation_handle,
                                                            self.trans)
                                    pupdate = 1
                                    supdate = source  # found the source.
                                    break
                    death_ref = person.get_death_ref()
                    if death_ref:
                        death = self.db.get_event_from_handle(death_ref.ref)
                        for citation_handle in death.get_citation_list():
                            citation = self.db.get_citation_from_handle(citation_handle)
                            source_handle = citation.get_reference_handle()
                            #print "death handle:", source_handle
                            source = self.db.get_source_from_handle(source_handle)
                            if source:
                                if source.get_title() == source_text:
                                    #print("death event removed from:",
                                    #      person.gramps_id)
                                    person.set_death_ref(None)
                                    person.remove_handle_references('Event',[death_ref.ref])
                                    # remove note
                                    note_list = death.get_referenced_note_handles()
                                    death.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.remove_citation(citation_handle,
                                                            self.trans)
                                    pupdate = 1
                                    supdate = source  # found the source.
                                    break
                    if pupdate == 1:
                        self.db.commit_person(person, self.trans)
                if supdate:
                    self.db.remove_source(supdate.handle, self.trans)
            self.results_write(_("done!\n"))
            self.db.enable_signals()
            self.db.request_rebuild()
        if add_birth or add_death:
            self.results_write(_("Selecting... \n\n"))
            self.progress.set_pass(_('Selecting...'),
                                   num_people)
            row = 0
            for person_handle in people:
                self.progress.step()
                person = self.db.get_person_from_handle(person_handle)
                birth_ref = person.get_birth_ref()
                death_ref = person.get_death_ref()
                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:
                        if date1.match( current_date, "<"):
                            add_birth_event = True
                            date1.make_vague()
                        else:
                            date1 = Date()
                    else:
                        date1 = 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:
                        if date2.match( current_date, "<"):
                            add_death_event = True
                            date2.make_vague()
                        else:
                            date2 = Date()
                    else:
                        date2 = 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 = Date()
                    if add_death == 1 and not death_ref: # no date
                        date2 = Date()
                    if person == other:
                        other = None
                    stab.row("checkbox",
                             person,
                             action,
                             date1,
                             date2,
                             explain or "",
                             other or "")
                    if add_birth_event:
                        stab.set_cell_markup(3, row, "<b>%s</b>" % date_displayer.display(date1))
                    if add_death_event:
                        stab.set_cell_markup(4, row, "<b>%s</b>" % date_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.set_current_frame(_("Select"))
Example #27
0
    def __create_gui(self):
        vbox = Gtk.VBox(orientation=Gtk.Orientation.VERTICAL)
        vbox.set_spacing(4)

        label = Gtk.Label(
            _("This gramplet allows setting properties for multiple places at the same time"
              ))
        label.set_halign(Gtk.Align.START)
        label.set_line_wrap(True)
        vbox.pack_start(label, False, True, 0)

        pt_label = Gtk.Label(_('Place type:'))
        pt_label.set_halign(Gtk.Align.START)
        self.typecombo = Gtk.ComboBoxText.new_with_entry()
        self.typecombo.set_tooltip_text(
            _("New place type for the selected places"))
        self.__fill_combo(self.typecombo,
                          list(self.__typenames()),
                          wrap_width=4)

        tag_label = Gtk.Label(_('Tag:'))
        tag_label.set_halign(Gtk.Align.START)
        self.tagcombo = Gtk.ComboBoxText.new_with_entry()
        self.tagcombo.set_tooltip_text(_("New tag for the selected places"))
        self.__fill_combo(self.tagcombo, list(self.__tagnames()))

        date_label = Gtk.Label(_('Timespan:'))
        date_label.set_halign(Gtk.Align.START)
        self.date_entry = ValidatableMaskedEntry()
        date_button = Gtk.Button.new_from_icon_name("gramps-date", -1)
        timespan_tooltip = _("Set timespan for enclosing places")
        date_label.set_tooltip_text(timespan_tooltip)
        date_button.set_tooltip_text(timespan_tooltip)
        self.date_entry.set_tooltip_text(timespan_tooltip)
        self.date_object = Date()
        self.track = []
        self.date_field = MonitoredDate(self.date_entry, date_button,
                                        self.date_object, self.uistate,
                                        self.track)

        label1 = Gtk.Label(_("New enclosing place:"))
        label1.set_halign(Gtk.Align.START)
        label1.set_line_wrap(True)
        self.label1 = label1

        self.enclosing_place = Gtk.Label(_("None"))
        self.enclosing_place.set_halign(Gtk.Align.START)
        self.enclosing_place.set_tooltip_text(
            _("New enclosing place for the selected places"))

        pt_grid = Gtk.Grid(column_spacing=10, row_spacing=2)
        pt_grid.attach(pt_label, 0, 0, 1, 1)
        pt_grid.attach(self.typecombo, 1, 0, 1, 1)

        pt_grid.attach(tag_label, 0, 1, 1, 1)
        pt_grid.attach(self.tagcombo, 1, 1, 1, 1)

        pt_grid.attach(date_label, 0, 2, 1, 1)
        pt_grid.attach(self.date_entry, 1, 2, 1, 1)
        pt_grid.attach(date_button, 2, 2, 1, 1)

        pt_grid.attach(label1, 0, 3, 1, 1)
        pt_grid.attach(self.enclosing_place, 1, 3, 1, 1)

        vbox.pack_start(pt_grid, False, True, 0)

        but_set_enclosing = Gtk.Button(label=_('Select enclosing place'))
        but_set_enclosing.connect("clicked", self.cb_select)
        but_set_enclosing.set_tooltip_text(
            _("Select a new enclosing place for the selected places"))
        vbox.pack_start(but_set_enclosing, False, True, 10)

        self.clear_enclosing = Gtk.CheckButton(
            _("Clear original enclosing places"))
        self.clear_enclosing.set_tooltip_text(
            _("If checked then any previous enclosing place will be removed from the selected places"
              ))
        vbox.pack_start(self.clear_enclosing, False, True, 0)

        self.clear_tags = Gtk.CheckButton(_("Clear tags"))
        self.clear_tags.set_tooltip_text(
            _("If checked then any previous tag will be removed from the selected places"
              ))
        vbox.pack_start(self.clear_tags, False, True, 0)

        self.generate_hierarchy = Gtk.CheckButton(_("Generate hierarchy"))
        self.generate_hierarchy.connect("clicked",
                                        self.cb_select_generate_hierarchy)
        self.generate_hierarchy.set_tooltip_text(
            _("If checked then a place hierarchy will be generated, based on the names of the original places"
              ))
        vbox.pack_start(self.generate_hierarchy, False, True, 0)

        box1 = Gtk.VBox()
        box1.set_margin_left(20)

        box2 = Gtk.HBox()

        box2.pack_start(Gtk.Label(_("Separator:")), False, True, 0)

        group = None
        rownum = 0
        group = Gtk.RadioButton.new_with_label_from_widget(group, _("Comma"))
        group.connect("toggled", self.cb_set_sep, ',')
        group.set_tooltip_text(
            _("If selected then the original names will be split at commas to create the new hierarchy"
              ))
        group.set_sensitive(False)
        box2.pack_start(group, False, True, 0)
        group.set_active(True)

        rownum += 1
        group = Gtk.RadioButton.new_with_label_from_widget(group, _("Space"))
        group.connect("toggled", self.cb_set_sep, None)
        group.set_tooltip_text(
            _("If selected then the original names will be split at blank spaces to create the new hierarchy"
              ))
        group.set_sensitive(False)
        box2.pack_start(group, False, True, 0)
        self.sep_group = group

        box1.pack_start(box2, False, True, 0)

        self.reverse = Gtk.CheckButton(_("reverse hierarchy"))
        self.reverse.set_tooltip_text(
            _("If checked then the original name is assumed to start with the largest place in the hierarchy"
              ))
        self.reverse.set_sensitive(False)
        box1.pack_start(self.reverse, False, True, 0)

        vbox.pack_start(box1, False, True, 0)

        self.replace_text = Gtk.CheckButton(_("Replace text"))
        self.replace_text.set_tooltip_text(
            _("If checked then a specified text is replaced with a new text in the selected place names"
              ))
        self.replace_text.connect("clicked", self.cb_select_replace_text)

        self.use_regex = Gtk.CheckButton(_("Use regex"))
        self.use_regex.set_tooltip_text(
            _("If checked then the old text can be a regular expression and the new text can contain substitutions (\\1, \\2 etc.)"
              ))
        self.use_regex.set_sensitive(False)

        replace_text_box = Gtk.HBox()
        replace_text_box.pack_start(self.replace_text, False, True, 0)
        replace_text_box.pack_start(self.use_regex, False, True, 0)
        vbox.pack_start(replace_text_box, False, True, 0)

        old_text_label = Gtk.Label(_("Old text:"))
        self.old_text = Gtk.Entry()
        self.old_text.set_sensitive(False)
        self.old_text.set_tooltip_text(
            _("The original text (or regular expression) to be  replaced"))

        new_text_label = Gtk.Label(_("New text:"))
        self.new_text = Gtk.Entry()
        self.new_text.set_sensitive(False)
        self.new_text.set_tooltip_text(
            _("The new text that will replace the old text"))

        replace_grid = Gtk.Grid(column_spacing=10)
        replace_grid.set_margin_left(20)
        replace_grid.attach(old_text_label, 1, 0, 1, 1)
        replace_grid.attach(self.old_text, 2, 0, 1, 1)
        replace_grid.attach(new_text_label, 1, 1, 1, 1)
        replace_grid.attach(self.new_text, 2, 1, 1, 1)
        vbox.pack_start(replace_grid, False, True, 0)

        but_clear = Gtk.Button(label=_('Clear selections'))
        but_clear.connect("clicked", self.cb_clear)
        but_clear.set_tooltip_text(_("Clears all settings"))
        vbox.pack_start(but_clear, False, True, 10)

        but_apply = Gtk.Button(label=_('Apply to selected places'))
        but_apply.connect("clicked", self.cb__apply)
        but_apply.set_tooltip_text(
            _("Executes all specified operations for selected places"))
        vbox.pack_start(but_apply, False, True, 0)

        vbox.show_all()
        return vbox
Example #28
0
class Timeline:
    """Timeline class."""
    def __init__(
        self,
        db_handle: DbReadBase,
        dates: Optional[str] = None,
        events: Optional[List[str]] = None,
        ratings: bool = False,
        relatives: Optional[List[str]] = None,
        relative_events: Optional[List[str]] = None,
        discard_empty: bool = True,
        omit_anchor: bool = True,
        precision: int = 1,
        locale: GrampsLocale = glocale,
    ):
        """Initialize timeline."""
        self.db_handle = db_handle
        self.timeline: List[Tuple[Event, Person, str, str]] = []
        self.dates = dates
        self.start_date = None
        self.end_date = None
        self.ratings = ratings
        self.discard_empty = discard_empty
        self.precision = precision
        self.locale = locale
        self.anchor_person = None
        self.omit_anchor = omit_anchor
        self.depth = 1
        self.eligible_events: Set[str] = set()
        self.event_filters: List[str] = events or []
        self.eligible_relative_events: Set[str] = set()
        self.relative_event_filters: List[str] = relative_events or []
        self.relative_filters: List[str] = relatives or []
        self.set_event_filters(self.event_filters)
        self.set_relative_event_filters(self.relative_event_filters)
        self.birth_dates: Dict[str, Date] = {}

        if dates and "-" in dates:
            start, end = dates.split("-")
            if "/" in start:
                year, month, day = start.split("/")
                self.start_date = Date((int(year), int(month), int(day)))
            else:
                self.start_date = None
            if "/" in end:
                year, month, day = end.split("/")
                self.end_date = Date((int(year), int(month), int(day)))
            else:
                self.end_date = None

    def set_start_date(self, date: Union[Date, str]):
        """Set optional timeline start date."""
        if isinstance(date, str):
            year, month, day = date.split("/")
            self.start_date = Date((int(year), int(month), int(day)))
        else:
            self.start_date = date

    def set_end_date(self, date: Union[Date, str]):
        """Set optional timeline end date."""
        if isinstance(date, str):
            year, month, day = date.split("/")
            self.end_date = Date((int(year), int(month), int(day)))
        else:
            self.end_date = date

    def set_discard_empty(self, discard_empty: bool):
        """Set discard empty identifier."""
        self.discard_empty = discard_empty

    def set_precision(self, precision: int):
        """Set optional precision for span."""
        self.precision = precision

    def set_locale(self, locale: str):
        """Set optional locale for span."""
        self.locale = get_locale_for_language(locale, default=True)

    def set_event_filters(self, filters: Optional[List[str]] = None):
        """Prepare the event filter table."""
        self.event_filters = filters or []
        self.eligible_events = self._prepare_eligible_events(
            self.event_filters)

    def set_relative_event_filters(self, filters: Optional[List[str]] = None):
        """Prepare the relative event filter table."""
        self.relative_event_filters = filters or []
        self.eligible_relative_events = self._prepare_eligible_events(
            self.relative_event_filters)

    def _prepare_eligible_events(self, event_filters: List[str]):
        """Prepare an event filter list."""
        eligible_events = {"Birth", "Death"}
        event_type = EventType()
        default_event_types = event_type.get_standard_xml()
        default_event_map = event_type.get_map()
        custom_event_types = self.db_handle.get_event_types()
        for key in event_filters:
            if key in default_event_types:
                eligible_events.add(key)
                continue
            if key in custom_event_types:
                eligible_events.add(key)
                continue
            if key not in EVENT_CATEGORIES:
                raise ValueError(
                    f"{key} is not a valid event or event category")
        for entry in event_type.get_menu_standard_xml():
            event_key = entry[0].lower().replace("life events", "vital")
            if event_key in event_filters:
                for event_id in entry[1]:
                    if event_id in default_event_map:
                        eligible_events.add(default_event_map[event_id])
                break
        if "custom" in event_filters:
            for event_name in custom_event_types:
                eligible_events.add(event_name)
        return eligible_events

    def get_age(self, start_date: str, date: str):
        """Return calculated age or empty string otherwise."""
        age = ""
        if start_date:
            span = Span(start_date, date)
            if span.is_valid():
                age = str(
                    span.format(precision=self.precision,
                                dlocale=self.locale).strip("()"))
        return age

    def is_death_indicator(self, event: Event) -> bool:
        """Check if an event indicates death timeframe."""
        if event.type in DEATH_INDICATORS:
            return True
        for event_name in [
                "Funeral",
                "Interment",
                "Reinterment",
                "Inurnment",
                "Memorial",
                "Visitation",
                "Wake",
                "Shiva",
        ]:
            if self.locale.translation.sgettext(event_name) == str(event.type):
                return True
        return False

    def is_eligible(self, event: Event, relative: bool):
        """Check if an event is eligible for the timeline."""
        if relative:
            if self.relative_event_filters == []:
                return True
            return str(event.get_type()) in self.eligible_relative_events
        if self.event_filters == []:
            return True
        return str(event.get_type()) in self.eligible_events

    def add_event(self,
                  event: Tuple[Event, Person, str, str],
                  relative: bool = False):
        """Add event to timeline if needed."""
        if self.discard_empty:
            if event[0].date.sortval == 0:
                return
        if self.end_date:
            if self.end_date.match(event[0].date, comparison="<"):
                return
        if self.start_date:
            if self.start_date.match(event[0].date, comparison=">"):
                return
        for item in self.timeline:
            if item[0].handle == event[0].handle:
                return
        if self.is_eligible(event[0], relative):
            if self.ratings:
                count, confidence = get_rating(self.db_handle, event[0])
                event[0].citations = count
                event[0].confidence = confidence
            self.timeline.append(event)

    def add_person(
        self,
        handle: Handle,
        anchor: bool = False,
        start: bool = True,
        end: bool = True,
        ancestors: int = 1,
        offspring: int = 1,
    ):
        """Add events for a person to the timeline."""
        if self.anchor_person and handle == self.anchor_person.handle:
            return
        person = self.db_handle.get_person_from_handle(handle)
        if person.handle not in self.birth_dates:
            event = get_birth_or_fallback(self.db_handle, person)
            if event:
                self.birth_dates.update({person.handle: event.date})
        for event_ref in person.event_ref_list:
            event = self.db_handle.get_event_from_handle(event_ref.ref)
            role = event_ref.get_role().xml_str()
            self.add_event((event, person, "self", role))
        if anchor and not self.anchor_person:
            self.anchor_person = person
            self.depth = max(ancestors, offspring) + 1
            if self.start_date is None and self.end_date is None:
                if len(self.timeline) > 0:
                    if start or end:
                        self.timeline.sort(key=lambda x: x[0].get_date_object(
                        ).get_sort_value())
                        if start:
                            self.start_date = self.timeline[0][0].date
                        if end:
                            if self.is_death_indicator(self.timeline[-1][0]):
                                self.end_date = self.timeline[-1][0].date
                            else:
                                data = probably_alive_range(
                                    person, self.db_handle)
                                self.end_date = data[1]

            for family in person.parent_family_list:
                self.add_family(family, ancestors=ancestors)

            for family in person.family_list:
                self.add_family(family,
                                anchor=person,
                                ancestors=ancestors,
                                offspring=offspring)
        else:
            for family in person.family_list:
                self.add_family(family, anchor=person, events_only=True)

    def add_relative(self,
                     handle: Handle,
                     ancestors: int = 1,
                     offspring: int = 1):
        """Add events for a relative of the anchor person."""
        person = self.db_handle.get_person_from_handle(handle)
        calculator = get_relationship_calculator(reinit=True,
                                                 clocale=self.locale)
        calculator.set_depth(self.depth)
        relationship = calculator.get_one_relationship(self.db_handle,
                                                       self.anchor_person,
                                                       person)
        if self.relative_filters:
            found = False
            for relative in self.relative_filters:
                if relative in relationship:
                    found = True
                    break
            if not found:
                return

        if self.relative_event_filters:
            for event_ref in person.event_ref_list:
                event = self.db_handle.get_event_from_handle(event_ref.ref)
                role = event_ref.get_role().xml_str()
                self.add_event((event, person, relationship, role),
                               relative=True)

        event = get_birth_or_fallback(self.db_handle, person)
        if event:
            self.add_event((event, person, relationship, "Primary"),
                           relative=True)
            if person.handle not in self.birth_dates:
                self.birth_dates.update({person.handle: event.date})

        event = get_death_or_fallback(self.db_handle, person)
        if event:
            self.add_event((event, person, relationship, "Primary"),
                           relative=True)

        for family_handle in person.family_list:
            family = self.db_handle.get_family_from_handle(family_handle)

            event = get_marriage_or_fallback(self.db_handle, family)
            if event:
                self.add_event((event, person, relationship, "Family"),
                               relative=True)

            event = get_divorce_or_fallback(self.db_handle, family)
            if event:
                self.add_event((event, person, relationship, "Family"),
                               relative=True)

            if offspring > 1:
                for child_ref in family.child_ref_list:
                    self.add_relative(child_ref.ref, offspring=offspring - 1)

        if ancestors > 1:
            if "father" in relationship or "mother" in relationship:
                for family_handle in person.parent_family_list:
                    self.add_family(family_handle,
                                    include_children=False,
                                    ancestors=ancestors - 1)

    def add_family(
        self,
        handle: Handle,
        anchor: Optional[Person] = None,
        include_children: bool = True,
        ancestors: int = 1,
        offspring: int = 1,
        events_only: bool = False,
    ):
        """Add events for all family members to the timeline."""
        family = self.db_handle.get_family_from_handle(handle)
        if anchor:
            for event_ref in family.event_ref_list:
                event = self.db_handle.get_event_from_handle(event_ref.ref)
                role = event_ref.get_role().xml_str()
                self.add_event((event, anchor, "self", role))
            if events_only:
                return
        if self.anchor_person:
            if (family.father_handle
                    and family.father_handle != self.anchor_person.handle):
                self.add_relative(family.father_handle, ancestors=ancestors)
            if (family.mother_handle
                    and family.mother_handle != self.anchor_person.handle):
                self.add_relative(family.mother_handle, ancestors=ancestors)
            if include_children:
                for child in family.child_ref_list:
                    if child.ref != self.anchor_person.handle:
                        self.add_relative(child.ref, offspring=offspring)
        else:
            if family.father_handle:
                self.add_person(family.father_handle)
            if family.mother_handle:
                self.add_person(family.mother_handle)
            for child in family.child_ref_list:
                self.add_person(child.ref)

    def profile(self, page=0, pagesize=20):
        """Return a profile for the timeline."""
        profiles = []
        self.timeline.sort(
            key=lambda x: x[0].get_date_object().get_sort_value())
        events = self.timeline
        if page > 0:
            offset = (page - 1) * pagesize
            events = events[offset:offset + pagesize]
        for (event, person_object, relationship, role) in events:
            label = self.locale.translation.sgettext(str(event.type))
            if (person_object and self.anchor_person
                    and self.anchor_person.handle != person_object.handle
                    and relationship not in ["self", "", None]):
                label = f"{label} ({relationship.title()})"

            try:
                obj = self.db_handle.get_place_from_handle(event.place)
                place = get_place_profile_for_object(self.db_handle,
                                                     obj,
                                                     locale=self.locale)
                place["display_name"] = pd.display_event(self.db_handle, event)
                place["handle"] = event.place
            except HandleError:
                place = {}

            age = ""
            person = {}
            if person_object is not None:
                person_age = ""
                get_person = True
                if self.anchor_person:
                    if self.anchor_person.handle in self.birth_dates:
                        age = self.get_age(
                            self.birth_dates[self.anchor_person.handle],
                            event.date)
                    if self.anchor_person.handle == person_object.handle:
                        person_age = age
                        if self.omit_anchor:
                            get_person = False
                if get_person:
                    person = get_person_profile_for_object(self.db_handle,
                                                           person_object, {},
                                                           locale=self.locale)
                    if not person_age and person_object.handle in self.birth_dates:
                        person_age = self.get_age(
                            self.birth_dates[person_object.handle], event.date)
                        if not age:
                            age = person_age
                    person["age"] = person_age

            profile = {
                "date": self.locale.date_displayer.display(event.date),
                "description": event.description,
                "gramps_id": event.gramps_id,
                "handle": event.handle,
                "label": self.locale.translation.sgettext(label),
                "media": [x.ref for x in event.media_list],
                "person": person,
                "place": place,
                "age": age,
                "type": event.type,
                "role": self.locale.translation.gettext(role),
            }
            profile["person"]["relationship"] = str(relationship)
            if self.ratings:
                profile["citations"] = event.citations
                profile["confidence"] = event.confidence
            profiles.append(profile)
        return profiles
Example #29
0
    def write_people(self):
        """ write the people """

        self.doc.add_comment('')

        # If we're going to attempt to include images, then use the HTML style
        # of .gv file.
        use_html_output = False
        if self._incimages:
            use_html_output = True

        # loop through all the people we need to output
        for handle in sorted(self._people): # enable a diff
            person = self._db.get_person_from_handle(handle)
            name = self._name_display.display(person)
            p_id = person.get_gramps_id()

            # figure out what colour to use
            gender = person.get_gender()
            colour = self._colorunknown
            if gender == Person.MALE:
                colour = self._colormales
            elif gender == Person.FEMALE:
                colour = self._colorfemales

            # see if we have surname colours that match this person
            surname = person.get_primary_name().get_surname()
            surname = surname.encode('iso-8859-1', 'xmlcharrefreplace')
            if surname in self._surnamecolors:
                colour = self._surnamecolors[surname]

            # see if we have a birth/death or fallback dates we can use
            if self._incdates or self._incplaces:
                bth_event = get_birth_or_fallback(self._db, person)
                dth_event = get_death_or_fallback(self._db, person)
            else:
                bth_event = None
                dth_event = None

            # output the birth or fallback event
            birth_str = None
            if bth_event and self._incdates:
                date = bth_event.get_date_object()
                if self._just_years and date.get_year_valid():
                    birth_str = self._get_date( # localized year
                        Date(date.get_year()))
                else:
                    birth_str = self._get_date(date)

            # get birth place (one of:  hamlet, village, town, city, parish,
            # county, province, region, state or country)
            birthplace = None
            if bth_event and self._incplaces:
                birthplace = self.get_event_place(bth_event)

            # see if we have a deceased date we can use
            death_str = None
            if dth_event and self._incdates:
                date = dth_event.get_date_object()
                if self._just_years and date.get_year_valid():
                    death_str = self._get_date( # localized year
                        Date(date.get_year()))
                else:
                    death_str = self._get_date(date)

            # get death place (one of:  hamlet, village, town, city, parish,
            # county, province, region, state or country)
            deathplace = None
            if dth_event and self._incplaces:
                deathplace = self.get_event_place(dth_event)

            # see if we have an image to use for this person
            image_path = None
            if self._incimages:
                media_list = person.get_media_list()
                if len(media_list) > 0:
                    media_handle = media_list[0].get_reference_handle()
                    media = self._db.get_media_from_handle(media_handle)
                    media_mime_type = media.get_mime_type()
                    if media_mime_type[0:5] == "image":
                        image_path = get_thumbnail_path(
                            media_path_full(self._db, media.get_path()),
                            rectangle=media_list[0].get_rectangle(),
                            size=self._imagesize)

            # put the label together and output this person
            label = ""
            line_delimiter = '\\n'
            if use_html_output:
                line_delimiter = '<BR/>'

            # if we have an image, then start an HTML table;
            # remember to close the table afterwards!
            if image_path:
                label = ('<TABLE BORDER="0" CELLSPACING="2" CELLPADDING="0" '
                         'CELLBORDER="0"><TR><TD><IMG SRC="%s"/></TD>' %
                         image_path)
                if self._imageonside == 0:
                    label += '</TR><TR>'
                label += '<TD>'

            # at the very least, the label must have the person's name
            name = name.replace('"', '&#34;')
            label += name.replace('<', '&#60;').replace('>', '&#62;')
            if self.includeid == 1: # same line
                label += " (%s)" % p_id
            elif self.includeid == 2: # own line
                label += "%s(%s)" % (line_delimiter, p_id)

            if birth_str or death_str:
                label += '%s(' % line_delimiter
                if birth_str:
                    label += '%s' % birth_str
                label += ' – '
                if death_str:
                    label += '%s' % death_str
                label += ')'
            if birthplace or deathplace:
                if birthplace == deathplace:
                    deathplace = None    # no need to print the same name twice
                label += '%s' % line_delimiter
                if birthplace:
                    label += '%s' % birthplace
                if birthplace and deathplace:
                    label += ' / '
                if deathplace:
                    label += '%s' % deathplace

            # see if we have a table that needs to be terminated
            if image_path:
                label += '</TD></TR></TABLE>'
            else:
                # non html label is enclosed by "" so escape other "
                label = label.replace('"', '\\\"')

            shape = "box"
            style = "solid"
            border = colour
            fill = colour

            # do not use colour if this is B&W outline
            if self._colorize == 'outline':
                border = ""
                fill = ""

            if gender == person.FEMALE and ("f" in self._useroundedcorners):
                style = "rounded"
            elif gender == person.MALE and ("m" in self._useroundedcorners):
                style = "rounded"
            elif gender == person.UNKNOWN:
                shape = "hexagon"

            # if we're filling the entire node:
            if self._colorize == 'filled':
                style += ",filled"
                border = ""

            # we're done -- add the node
            self.doc.add_node(p_id,
                              label=label,
                              shape=shape,
                              color=border,
                              style=style,
                              fillcolor=fill,
                              htmloutput=use_html_output)
    def run(self):
        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

        current_date = Date()
        current_date.set_yr_mon_day(*time.localtime(time.time())[0:3])
        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 = QuickTable(self.sdb)
        self.table = stab
        stab.columns(_("Select"), _("Person"), _("Action"),
                     _("Birth Date"), _("Death Date"),
                     _("Evidence"), _("Relative"))
        self.results_write(_("Processing...\n"))
        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']

        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:
            with DbTxn("", self.db, batch=True) as self.trans:
                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:
                    self.progress.step()
                    pupdate = 0
                    person = self.db.get_person_from_handle(person_handle)
                    birth_ref = person.get_birth_ref()
                    if birth_ref:
                        birth = self.db.get_event_from_handle(birth_ref.ref)
                        for citation_handle in birth.get_citation_list():
                            citation = self.db.get_citation_from_handle(citation_handle)
                            source_handle = citation.get_reference_handle()
                            #print "birth handle:", source_handle
                            source = self.db.get_source_from_handle(source_handle)
                            if source:
                                #print "birth source:", source, source.get_title()
                                if source.get_title() == source_text:
                                    person.set_birth_ref(None)
                                    person.remove_handle_references('Event',[birth_ref.ref])
                                    # 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
                                    break
                    death_ref = person.get_death_ref()
                    if death_ref:
                        death = self.db.get_event_from_handle(death_ref.ref)
                        for citation_handle in death.get_citation_list():
                            citation = self.db.get_citation_from_handle(citation_handle)
                            source_handle = citation.get_reference_handle()
                            #print "death handle:", source_handle
                            source = self.db.get_source_from_handle(source_handle)
                            if source:
                                #print "death source:", source, source.get_title()
                                if source.get_title() == source_text:
                                    person.set_death_ref(None)
                                    person.remove_handle_references('Event',[death_ref.ref])
                                    # 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.enable_signals()
                self.db.request_rebuild()
        if add_birth or add_death:
            self.results_write(_("Selecting... \n\n"))
            self.progress.set_pass(_('Selecting...'),
                                   num_people)
            row = 0
            for person_handle in people:
                self.progress.step()
                person = self.db.get_person_from_handle(person_handle)
                birth_ref = person.get_birth_ref()
                death_ref = person.get_death_ref()
                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:
                        if date1.match( current_date, "<"):
                            add_birth_event = True
                            date1.make_vague()
                        else:
                            date1 = Date()
                    else:
                        date1 = 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:
                        if date2.match( current_date, "<"):
                            add_death_event = True
                            date2.make_vague()
                        else:
                            date2 = Date()
                    else:
                        date2 = 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 = Date()
                    if add_death == 1 and not death_ref: # no date
                        date2 = Date()
                    if person == other:
                        other = None
                    stab.row("checkbox",
                             person,
                             action,
                             date1,
                             date2,
                             explain or "",
                             other or "")
                    if add_birth_event:
                        stab.set_cell_markup(3, row, "<b>%s</b>" % date_displayer.display(date1))
                    if add_death_event:
                        stab.set_cell_markup(4, row, "<b>%s</b>" % date_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()
        self.set_current_frame(_("Select"))
Example #31
0
    def print_page(self, month):
        """
        This method actually writes the calendar page.
        """
        style_sheet = self.doc.get_style_sheet()
        ptitle = style_sheet.get_paragraph_style("CAL-Title")
        ptext = style_sheet.get_paragraph_style("CAL-Text")
        pdaynames = style_sheet.get_paragraph_style("CAL-Daynames")
        pnumbers = style_sheet.get_paragraph_style("CAL-Numbers")
        numpos = pt2cm(pnumbers.get_font().get_size())
        ptext1style = style_sheet.get_paragraph_style("CAL-Text1style")
        long_days = self._ldd.long_days

        self.doc.start_page()
        width = self.doc.get_usable_width()
        height = self.doc.get_usable_height()
        header = 2.54 # one inch
        mark = None
        if month == 1:
            mark = IndexMark(self._('Calendar Report'), INDEX_TYPE_TOC, 1)
        self.draw_rectangle("CAL-Border", 0, 0, width, height)
        self.doc.draw_box("CAL-Title", "", 0, 0, width, header, mark)
        self.doc.draw_line("CAL-Border", 0, header, width, header)
        year = self.year
        # assume every calendar header in the world is "<month-name> <year>"
        title = "%s %s" % (self._ldd.long_months[month].capitalize(),
                           self._get_date(Date(self.year))) # localized year
        mark = IndexMark(title, INDEX_TYPE_TOC, 2)
        font_height = pt2cm(ptitle.get_font().get_size())
        self.doc.center_text("CAL-Title", title,
                             width/2, font_height * 0.25, mark)
        cell_width = width / 7
        cell_height = (height - header)/ 6
        current_date = datetime.date(year, month, 1)
        spacing = pt2cm(1.25 * ptext.get_font().get_size()) # 158
        if current_date.isoweekday() != g2iso(self.start_dow + 1):
            # Go back to previous first day of week, and start from there
            current_ord = (current_date.toordinal() -
                           ((current_date.isoweekday() + 7) -
                            g2iso(self.start_dow + 1)) % 7)
        else:
            current_ord = current_date.toordinal()
        for day_col in range(7):
            font_height = pt2cm(pdaynames.get_font().get_size())
            self.doc.center_text("CAL-Daynames",
                                 long_days[(day_col+ g2iso(self.start_dow + 1))
                                                        % 7 + 1].capitalize(),
                                 day_col * cell_width + cell_width/2,
                                 header - font_height * 1.5)
        for week_row in range(6):
            something_this_week = 0
            for day_col in range(7):
                thisday = current_date.fromordinal(current_ord)
                if thisday.month == month:
                    something_this_week = 1
                    self.draw_rectangle("CAL-Border", day_col * cell_width,
                                        header + week_row * cell_height,
                                        (day_col + 1) * cell_width,
                                        header + (week_row + 1) * cell_height)
                    last_edge = (day_col + 1) * cell_width
                    self.doc.center_text("CAL-Numbers", str(thisday.day),
                                         day_col * cell_width + cell_width/2,
                                         header + week_row * cell_height)
                    list_ = self.calendar.get(month, {}).get(thisday.day, [])
                    list_.sort() # to get CAL-Holiday on bottom
                    position = spacing
                    for (format, p, m_list) in list_:
                        for line in reversed(p.split("\n")):
                            # make sure text will fit:
                            if position - 0.1 >= cell_height - numpos: # font daynums
                                break
                            font = ptext.get_font()
                            line = string_trim(font, line, cm2pt(cell_width + 0.2))
                            self.doc.draw_text(format, line,
                                               day_col * cell_width + 0.1,
                                               header + (week_row + 1) * cell_height - position - 0.1, m_list[0])
                            if len(m_list) > 1: # index the spouse too
                                self.doc.draw_text(format, "",0,0, m_list[1])
                            position += spacing
                current_ord += 1
        if not something_this_week:
            last_edge = 0
        font_height = pt2cm(1.5 * ptext1style.get_font().get_size())
        x = last_edge + (width - last_edge)/2
        text1 = str(self.text1)
        if text1 == _(_TITLE1):
            text1 = self._(_TITLE1)
        self.doc.center_text("CAL-Text1style", text1,
                             x, height - font_height * 3)
        text2 = str(self.text2)
        if text2 == _(_TITLE2):
            text2 = self._(_TITLE2)
        self.doc.center_text("CAL-Text2style", text2,
                             x, height - font_height * 2)
        self.doc.center_text("CAL-Text3style", self.text3,
                             x, height - font_height * 1)
        self.doc.end_page()
Example #32
0
def find_records(db,
                 filter,
                 top_size,
                 callname,
                 trans_text=glocale.translation.sgettext,
                 name_format=None,
                 living_mode=LivingProxyDb.MODE_INCLUDE_ALL):
    """
    @param trans_text: allow deferred translation of strings
    @type trans_text: a GrampsLocale sgettext instance
    trans_text is a defined keyword (see po/update_po.py, po/genpot.sh)
    :param name_format: optional format to control display of person's name
    :type name_format: None or int
    :param living_mode: enable optional control of living people's records
    :type living_mode: int
    """
    def get_unfiltered_person_from_handle(person_handle):
        if living_mode == LivingProxyDb.MODE_INCLUDE_ALL:
            return db.get_person_from_handle(person_handle)
        else:  # we are in the proxy so get the person before proxy changes
            return db.get_unfiltered_person(person_handle)

    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)
        unfil_person = get_unfiltered_person_from_handle(person_handle)
        if person is None:
            continue

        # FIXME this should check for a "fallback" birth also/instead
        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 = _get_styled_primary_name(person,
                                        callname,
                                        trans_text=trans_text,
                                        name_format=name_format)

        if death_date is None:
            if probably_alive(unfil_person, db):
                # Still living, look for age records
                _record(person_youngestliving, person_oldestliving,
                        today_date - birth_date, name, 'Person', person_handle,
                        top_size)
        elif _good_date(death_date):
            # Already died, look for age records
            _record(person_youngestdied, person_oldestdied,
                    death_date - birth_date, name, 'Person', person_handle,
                    top_size)

        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, top_size)

            if _good_date(divorce_date):
                _record(person_youngestdivorced, person_oldestdivorced,
                        divorce_date - birth_date, name, 'Person',
                        person_handle, top_size)

            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)

                # FIXME this should check for a "fallback" birth also/instead
                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, top_size)
                elif person.get_gender() == person.FEMALE:
                    _record(person_youngestmother, person_oldestmother,
                            child_birth_date - birth_date, name, 'Person',
                            person_handle, top_size)

    # Family records
    family_mostchildren = []
    family_youngestmarried = []
    family_oldestmarried = []
    family_shortest = []
    family_longest = []
    family_smallestagediff = []
    family_biggestagediff = []

    for family in db.iter_families():
        #family = db.get_family_from_handle(family_handle)
        if living_mode != LivingProxyDb.MODE_INCLUDE_ALL:
            # FIXME no iter_families method in LivingProxyDb so do it this way
            family = db.get_family_from_handle(family.get_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)
        unfil_father = get_unfiltered_person_from_handle(father_handle)
        if father is None:
            continue
        mother = db.get_person_from_handle(mother_handle)
        unfil_mother = get_unfiltered_person_from_handle(mother_handle)
        if mother is None:
            continue

        name = StyledText(trans_text("%(father)s and %(mother)s")) % {
            'father':
            _get_styled_primary_name(father,
                                     callname,
                                     trans_text=trans_text,
                                     name_format=name_format),
            'mother':
            _get_styled_primary_name(mother,
                                     callname,
                                     trans_text=trans_text,
                                     name_format=name_format)
        }

        if (living_mode == LivingProxyDb.MODE_INCLUDE_ALL
                or (not probably_alive(unfil_father, db)
                    and not probably_alive(unfil_mother, db))):
            _record(None, family_mostchildren,
                    len(family.get_child_ref_list()), name, 'Family',
                    family.handle, top_size)

        father_birth_ref = father.get_birth_ref()
        if father_birth_ref:
            father_birth_date = db.get_event_from_handle(
                father_birth_ref.ref).get_date_object()
        else:
            father_birth_date = None

        mother_birth_ref = mother.get_birth_ref()
        if mother_birth_ref:
            mother_birth_date = db.get_event_from_handle(
                mother_birth_ref.ref).get_date_object()
        else:
            mother_birth_date = None

        if _good_date(father_birth_date) and _good_date(mother_birth_date):
            if father_birth_date >> mother_birth_date:
                _record(family_smallestagediff, family_biggestagediff,
                        father_birth_date - mother_birth_date, name, 'Family',
                        family.handle, top_size)
            elif mother_birth_date >> father_birth_date:
                _record(family_smallestagediff, family_biggestagediff,
                        mother_birth_date - father_birth_date, name, 'Family',
                        family.handle, top_size)

        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(unfil_father, db)
                and not _good_date(father_death_date)):
            # Father died but death date unknown or inexact
            continue

        if (not probably_alive(unfil_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(unfil_father, db)
                    and probably_alive(unfil_mother, db)):
                _record(family_youngestmarried, family_oldestmarried,
                        today_date - marriage_date, name, 'Family',
                        family.handle, top_size)
        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, top_size)
    #python 3 workaround: assign locals to tmp so we work with runtime version
    tmp = locals()
    return [(trans_text(text), varname, tmp[varname])
            for (text, varname, default) in RECORDS]
Example #33
0
 def column_date(self,data):
     if data[10]:
         date = Date()
         date.unserialize(data[10])
         return displayer.display(date)
     return ''
Example #34
0
 def _convert_date(self, date_in):
     """Convert the change date to the preferred date format and return a string"""
     change_date = Date()
     change_date.set_yr_mon_day(*time.localtime(date_in)[0:3])
     return gramps.gen.datehandler.displayer.display(change_date)
    def collect_data(self):
        """
        This method runs through the data, and collects the relevant dates
        and text.
        """
        people = self.database.iter_person_handles()
        people = self.filter.apply(self.database, people, user=self._user)

        ngettext = self._locale.translation.ngettext  # to see "nearby" comments
        rel_calc = get_relationship_calculator(reinit=True,
                                               clocale=self._locale)

        with self._user.progress(_('Birthday and Anniversary Report'),
                                 _('Reading database...'),
                                 len(people)) as step:
            for person_handle in people:
                step()
                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,
                                olocale=self._locale)
                            if relation:
                                # FIXME this won't work for RTL languages
                                comment = " --- %s" % relation
                        if nyears == 0:
                            text = self._('%(person)s, birth%(relation)s') % {
                                'person': short_name,
                                'relation': comment
                            }
                        else:
                            # translators: leave all/any {...} untranslated
                            text = ngettext('{person}, {age}{relation}',
                                            '{person}, {age}{relation}',
                                            nyears).format(person=short_name,
                                                           age=nyears,
                                                           relation=comment)

                        self.add_day_item(text, month, day, person)
                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 = self._(
                                                    "%(spouse)s and\n %(person)s, wedding"
                                                ) % {
                                                    'spouse': spouse_name,
                                                    'person': short_name
                                                }
                                            else:
                                                # translators: leave all/any {...} untranslated
                                                text = ngettext(
                                                    "{spouse} and\n {person}, {nyears}",
                                                    "{spouse} and\n {person}, {nyears}",
                                                    nyears).format(
                                                        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,
                                                        spouse)
Example #36
0
 def column_date(self,data):
     if data[10]:
         date = Date()
         date.unserialize(data[10])
         return displayer.display(date)
     return ''
Example #37
0
    def write_families(self):
        """ write the families """

        self.doc.add_comment('')
        ngettext = self._locale.translation.ngettext # to see "nearby" comments

        # loop through all the families we need to output
        for family_handle in sorted(self._families): # enable a diff
            family = self._db.get_family_from_handle(family_handle)
            fgid = family.get_gramps_id()

            # figure out a wedding date or placename we can use
            wedding_date = None
            wedding_place = None
            if self._incdates or self._incplaces:
                for event_ref in family.get_event_ref_list():
                    event = self._db.get_event_from_handle(event_ref.ref)
                    if (event.get_type() == EventType.MARRIAGE and
                            (event_ref.get_role() == EventRoleType.FAMILY or
                             event_ref.get_role() == EventRoleType.PRIMARY)):
                        # get the wedding date
                        if self._incdates:
                            date = event.get_date_object()
                            if self._just_years and date.get_year_valid():
                                wedding_date = self._get_date( # localized year
                                    Date(date.get_year()))
                            else:
                                wedding_date = self._get_date(date)
                        # get the wedding location
                        if self._incplaces:
                            wedding_place = self.get_event_place(event)
                        break

            # figure out the number of children (if any)
            children_str = None
            if self._incchildcount:
                child_count = len(family.get_child_ref_list())
                if child_count >= 1:
                    # translators: leave all/any {...} untranslated
                    children_str = ngettext("{number_of} child",
                                            "{number_of} children", child_count
                                           ).format(number_of=child_count)

            label = ''
            fgid_already = False
            if wedding_date:
                if label != '':
                    label += '\\n'
                label += '%s' % wedding_date
                if self.includeid == 1 and not fgid_already: # same line
                    label += " (%s)" % fgid
                    fgid_already = True
            if wedding_place:
                if label != '':
                    label += '\\n'
                label += '%s' % wedding_place
                if self.includeid == 1 and not fgid_already: # same line
                    label += " (%s)" % fgid
                    fgid_already = True
            if self.includeid == 1 and not label:
                label = "(%s)" % fgid
                fgid_already = True
            elif self.includeid == 2 and not label: # own line
                label = "(%s)" % fgid
                fgid_already = True
            elif self.includeid == 2 and label and not fgid_already:
                label += "\\n(%s)" % fgid
                fgid_already = True
            if children_str:
                if label != '':
                    label += '\\n'
                label += '%s' % children_str
                if self.includeid == 1 and not fgid_already: # same line
                    label += " (%s)" % fgid
                    fgid_already = True

            shape = "ellipse"
            style = "solid"
            border = self._colorfamilies
            fill = self._colorfamilies

            # do not use colour if this is B&W outline
            if self._colorize == 'outline':
                border = ""
                fill = ""

            # if we're filling the entire node:
            if self._colorize == 'filled':
                style += ",filled"
                border = ""

            # we're done -- add the node
            self.doc.add_node(fgid, label, shape, border, style, fill)

        # now that we have the families written,
        # go ahead and link the parents and children to the families
        for family_handle in self._families:

            # get the parents for this family
            family = self._db.get_family_from_handle(family_handle)
            fgid = family.get_gramps_id()
            father_handle = family.get_father_handle()
            mother_handle = family.get_mother_handle()

            self.doc.add_comment('')

            if self._usesubgraphs and father_handle and mother_handle:
                self.doc.start_subgraph(fgid)

            # see if we have a father to link to this family
            if father_handle:
                if father_handle in self._people:
                    father = self._db.get_person_from_handle(father_handle)
                    father_rn = father.get_primary_name().get_regular_name()
                    comment = self._("father: %s") % father_rn
                    self.doc.add_link(father.get_gramps_id(), fgid, "",
                                      self._arrowheadstyle, self._arrowtailstyle,
                                      comment=comment)

            # see if we have a mother to link to this family
            if mother_handle:
                if mother_handle in self._people:
                    mother = self._db.get_person_from_handle(mother_handle)
                    mother_rn = mother.get_primary_name().get_regular_name()
                    comment = self._("mother: %s") % mother_rn
                    self.doc.add_link(mother.get_gramps_id(), fgid, "",
                                      self._arrowheadstyle, self._arrowtailstyle,
                                      comment=comment)

            if self._usesubgraphs and father_handle and mother_handle:
                self.doc.end_subgraph()

            # link the children to the family
            for childref in family.get_child_ref_list():
                if childref.ref in self._people:
                    child = self._db.get_person_from_handle(childref.ref)
                    child_rn = child.get_primary_name().get_regular_name()
                    comment = self._("child: %s") % child_rn
                    self.doc.add_link(fgid, child.get_gramps_id(), "",
                                      self._arrowheadstyle, self._arrowtailstyle,
                                      comment=comment)
Example #38
0
    def run_tool(self):
        self.progress = ProgressMeter(_('Running Date Test'),
                                      '',
                                      parent=self.parent_window)
        self.progress.set_pass(_('Generating dates'), 4)
        dates = []
        # first some valid dates
        calendar = Date.CAL_GREGORIAN
        for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED,
                        Date.QUAL_CALCULATED):
            for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER,
                             Date.MOD_ABOUT):
                for slash1 in (False, True):
                    for month in range(0, 13):
                        for day in (0, 5, 27):
                            if not month and day:
                                continue
                            d = Date()
                            d.set(quality, modifier, calendar,
                                  (day, month, 1789, slash1), "Text comment")
                            dates.append(d)
            for modifier in (Date.MOD_RANGE, Date.MOD_SPAN):
                for slash1 in (False, True):
                    for slash2 in (False, True):
                        for month in range(0, 13):
                            for day in (0, 5, 27):
                                if not month and day:
                                    continue

                                d = Date()
                                d.set(quality, modifier, calendar,
                                      (day, month, 1789, slash1, day, month,
                                       1876, slash2), "Text comment")
                                dates.append(d)

                                if not month:
                                    continue

                                d = Date()
                                d.set(quality, modifier, calendar,
                                      (day, month, 1789, slash1, day,
                                       13 - month, 1876, slash2),
                                      "Text comment")
                                dates.append(d)

                                if not day:
                                    continue

                                d = Date()
                                d.set(quality, modifier, calendar,
                                      (day, month, 1789, slash1, 32 - day,
                                       month, 1876, slash2), "Text comment")
                                dates.append(d)
                                d = Date()
                                d.set(quality, modifier, calendar,
                                      (day, month, 1789, slash1, 32 - day,
                                       13 - month, 1876, slash2),
                                      "Text comment")
                                dates.append(d)
            modifier = Date.MOD_TEXTONLY
            d = Date()
            d.set(quality, modifier, calendar, Date.EMPTY,
                  "This is a textual date")
            dates.append(d)
            self.progress.step()

        # test invalid dates
        #dateval = (4,7,1789,False,5,8,1876,False)
        #for l in range(1,len(dateval)):
        #    d = Date()
        #    try:
        #        d.set(Date.QUAL_NONE,Date.MOD_NONE,
        #              Date.CAL_GREGORIAN,dateval[:l],"Text comment")
        #        dates.append( d)
        #    except DateError, e:
        #        d.set_as_text("Date identified value correctly as invalid.\n%s" % e)
        #        dates.append( d)
        #    except:
        #        d = Date()
        #        d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
        #        dates.append( d)
        #for l in range(1,len(dateval)):
        #    d = Date()
        #    try:
        #        d.set(Date.QUAL_NONE,Date.MOD_SPAN,Date.CAL_GREGORIAN,dateval[:l],"Text comment")
        #        dates.append( d)
        #    except DateError, e:
        #        d.set_as_text("Date identified value correctly as invalid.\n%s" % e)
        #        dates.append( d)
        #    except:
        #        d = Date()
        #        d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
        #        dates.append( d)
        #self.progress.step()
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_NONE,
        #      Date.CAL_GREGORIAN,(44,7,1789,False),"Text comment")
        #dates.append( d)
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_NONE,
        #      Date.CAL_GREGORIAN,(4,77,1789,False),"Text comment")
        #dates.append( d)
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_SPAN,
        #      Date.CAL_GREGORIAN,
        #      (4,7,1789,False,55,8,1876,False),"Text comment")
        #dates.append( d)
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_SPAN,
        #      Date.CAL_GREGORIAN,
        #      (4,7,1789,False,5,88,1876,False),"Text comment")
        #dates.append( d)

        with DbTxn(_("Date Test Plugin"), self.db, batch=True) as self.trans:
            self.db.disable_signals()
            self.progress.set_pass(_('Generating dates'), len(dates))

            # create pass and fail tags
            pass_handle = self.create_tag(_('Pass'), '#0000FFFF0000')
            fail_handle = self.create_tag(_('Fail'), '#FFFF00000000')

            # now add them as birth to new persons
            i = 1
            for dateval in dates:
                person = Person()
                surname = Surname()
                surname.set_surname("DateTest")
                name = Name()
                name.add_surname(surname)
                name.set_first_name("Test %d" % i)
                person.set_primary_name(name)
                self.db.add_person(person, self.trans)
                bevent = Event()
                bevent.set_type(EventType.BIRTH)
                bevent.set_date_object(dateval)
                bevent.set_description("Date Test %d (source)" % i)
                bevent_h = self.db.add_event(bevent, self.trans)
                bevent_ref = EventRef()
                bevent_ref.set_reference_handle(bevent_h)
                # for the death event display the date as text and parse it back to a new date
                ndate = None
                try:
                    datestr = _dd.display(dateval)
                    try:
                        ndate = _dp.parse(datestr)
                        if not ndate:
                            ndate = Date()
                            ndate.set_as_text("DateParser None")
                            person.add_tag(fail_handle)
                        else:
                            person.add_tag(pass_handle)
                    except:
                        ndate = Date()
                        ndate.set_as_text("DateParser Exception %s" % ("".join(
                            traceback.format_exception(*sys.exc_info())), ))
                        person.add_tag(fail_handle)
                    else:
                        person.add_tag(pass_handle)
                except:
                    ndate = Date()
                    ndate.set_as_text("DateDisplay Exception: %s" % ("".join(
                        traceback.format_exception(*sys.exc_info())), ))
                    person.add_tag(fail_handle)

                if dateval.get_modifier() != Date.MOD_TEXTONLY \
                       and ndate.get_modifier() == Date.MOD_TEXTONLY:
                    # parser was unable to correctly parse the string
                    ndate.set_as_text("TEXTONLY: " + ndate.get_text())
                    person.add_tag(fail_handle)
                if dateval.get_modifier() == Date.MOD_TEXTONLY \
                        and dateval.get_text().count("Traceback") \
                        and pass_handle in person.get_tag_list():
                    person.add_tag(fail_handle)

                devent = Event()
                devent.set_type(EventType.DEATH)
                devent.set_date_object(ndate)
                devent.set_description("Date Test %d (result)" % i)
                devent_h = self.db.add_event(devent, self.trans)
                devent_ref = EventRef()
                devent_ref.set_reference_handle(devent_h)
                person.set_birth_ref(bevent_ref)
                person.set_death_ref(devent_ref)
                self.db.commit_person(person, self.trans)
                i = i + 1
                self.progress.step()
        self.db.enable_signals()
        self.db.request_rebuild()
        self.progress.close()