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
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()
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() people = self.filter.apply(self.database, people, user=self._user) 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 = utils.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 = utils.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 get_info(self, person_handle, generation): """ get info about a person """ person = self.database.get_person_from_handle(person_handle) p_pn = person.get_primary_name() self.calendar = config.get('preferences.calendar-format-report') birth = get_birth_or_fallback(self.database, person) bth = "" if birth: bth = birth.get_date_object() bth = self._get_date( Date(bth.to_calendar(self.calendar).get_year())) # localized if bth == 0: bth = "" elif birth.get_type() != EventType.BIRTH: bth += '*' death = get_death_or_fallback(self.database, person) dth = "" if death: dth = death.get_date_object() dth = self._get_date( Date(dth.to_calendar(self.calendar).get_year())) # localized if dth == 0: dth = "" elif death.get_type() != EventType.DEATH: dth += '*' if bth and dth: val = "%s - %s" % (str(bth), str(dth)) elif bth: val = "* %s" % (str(bth)) elif dth: val = "+ %s" % (str(dth)) else: val = "" if generation > 7: if (p_pn.get_first_name() != "") and (p_pn.get_surname() != ""): name = p_pn.get_first_name() + " " + p_pn.get_surname() else: name = p_pn.get_first_name() + p_pn.get_surname() if (name != "") and (val != ""): string = name + self._(", ") + val # Arabic OK else: string = name + val return [string] elif generation == 7: if (p_pn.get_first_name() != "") and (p_pn.get_surname() != ""): name = p_pn.get_first_name() + " " + p_pn.get_surname() else: name = p_pn.get_first_name() + p_pn.get_surname() if self.circle == FULL_CIRCLE: return [name, val] elif self.circle == HALF_CIRCLE: return [name, val] else: if (name != "") and (val != ""): string = name + self._(", ") + val # Arabic OK else: string = name + val return [string] elif generation == 6: if self.circle == FULL_CIRCLE: return [p_pn.get_first_name(), p_pn.get_surname(), val] elif self.circle == HALF_CIRCLE: return [p_pn.get_first_name(), p_pn.get_surname(), val] else: if (p_pn.get_first_name() != "") and (p_pn.get_surname() != ""): name = p_pn.get_first_name() + " " + p_pn.get_surname() else: name = p_pn.get_first_name() + p_pn.get_surname() return [name, val] else: return [p_pn.get_first_name(), p_pn.get_surname(), val]
def find_records(db, filter, top_size, callname, trans_text=glocale.translation.sgettext, name_format=None, living_mode=LivingProxyDb.MODE_INCLUDE_ALL, user=None): """ @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_mostkidsfather = [] person_mostkidsmother = [] person_mostgrandkidsfather = [] person_mostgrandkidsmother = [] person_handle_list = db.iter_person_handles() # the next "if" will turn person_handle_list from a generator into a # list, but only when this code is called from a report (which has a # filter) and not when called from a gramplet (which has no filter); # so the next line drains the generator and turns it into a list # always, so the gramplet can use it later, in the second loop person_handle_list = list(person_handle_list) if filter: person_handle_list = filter.apply(db, person_handle_list, user=user) 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) for person_handle in person_handle_list: # this "person loop" doesn't care about a person's birth or death person = db.get_person_from_handle(person_handle) if person is None: continue name = _get_styled_primary_name(person, callname, trans_text=trans_text, name_format=name_format) person_child_list = get_birth_children(db, person) if person.get_gender() == person.MALE: _record(None, person_mostkidsfather, len(person_child_list), name, 'Person', person_handle, top_size) elif person.get_gender() == person.FEMALE: _record(None, person_mostkidsmother, len(person_child_list), name, 'Person', person_handle, top_size) person_grandchild_list = [] for child in person_child_list: person_grandchild_list += get_birth_children(db, child) if person.get_gender() == person.MALE: _record(None, person_mostgrandkidsfather, len(person_grandchild_list), name, 'Person', person_handle, top_size) elif person.get_gender() == person.FEMALE: _record(None, person_mostgrandkidsmother, len(person_grandchild_list), 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: # we don't want many progress reports popping up, so no user=user 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]
def find_records(db, filter, top_size, callname, trans_text=glocale.translation.sgettext): """ @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) """ 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) # 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) if death_date is None: if probably_alive(person, db): # Still living, look for age records _record(person_youngestliving, person_oldestliving, today_date - birth_date, name, 'Person', person_handle, 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 = [] for family in db.iter_families(): #family = db.get_family_from_handle(family_handle) father_handle = family.get_father_handle() if not father_handle: continue mother_handle = family.get_mother_handle() if not mother_handle: continue # Test if either father or mother are in filter if filter: if not filter.apply(db, [father_handle, mother_handle]): continue father = db.get_person_from_handle(father_handle) mother = db.get_person_from_handle(mother_handle) name = StyledText(trans_text("%(father)s and %(mother)s")) % { 'father': _get_styled_primary_name(father, callname), 'mother': _get_styled_primary_name(mother, callname)} _record(None, family_mostchildren, len(family.get_child_ref_list()), 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(father, db) and not _good_date(father_death_date): # Father died but death date unknown or inexact continue if not probably_alive(mother, db) and not _good_date(mother_death_date): # Mother died but death date unknown or inexact continue if (divorce_date is None and father_death_date is None and mother_death_date is None): # Still married and alive if probably_alive(father, db) and probably_alive(mother, db): _record(family_youngestmarried, family_oldestmarried, today_date - marriage_date, name, 'Family', family.handle, 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]
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 deadtxt = "" if (not alive): deadtxt = self.deadtxt yeartxt = "" if self.showyear: yeartxt = "(%s) " % year if nyears == 0: text = self._( '* %(person)s, birth%(relation)s') % { 'person': short_name, 'relation': comment } else: # translators: leave all/any {...} untranslated text = ngettext( '* {year}{person}{dead}, {age}{relation}', '* {year}{person}{dead}, {age}{relation}', nyears).format(year=yeartxt, person=short_name, dead=deadtxt, 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(): 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) deadtxt1 = "" deadtxt2 = "" if (not alive1): deadtxt1 = self.deadtxt if (not alive2): deadtxt2 = self.deadtxt yeartxt = "" if self.showyear: yeartxt = "(%s) " % 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( "⚭ {year}{spouse}{deadtxt2} and\n {person}{deadtxt1}, {nyears}", "⚭ {year}{spouse}{deadtxt2} and\n {person}{deadtxt1}, {nyears}", nyears).format( year=yeartxt, spouse=spouse_name, deadtxt2=deadtxt2, person=short_name, deadtxt1=deadtxt1, nyears=nyears) if (self.alive and alive1 and alive2 ) or not self.alive: self.add_day_item( text, month, day, spouse) death_ref = person.get_death_ref() death_date = None if death_ref: death_event = self.database.get_event_from_handle( death_ref.ref) death_date = death_event.get_date_object() if (self.death_anniversaries and death_date is not None and death_date.is_valid()): death_date = gregorian(death_date) year = death_date.get_year() month = death_date.get_month() day = death_date.get_day() nyears = self.year - year 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 yeartxt = "" if self.showyear: yeartxt = "(%s) " % year if nyears == 0: text = _('✝ {person}, death {relation}').format( person=short_name, relation=comment) else: text = ngettext('✝ {year}{person}, {age}{relation}', '✝ {year}{person}, {age}{relation}', nyears).format(year=yeartxt, person=short_name, age=nyears, relation=comment) self.add_day_item(text, month, day, person)
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('"', '"') label += name.replace('<', '<').replace('>', '>') 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 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)
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"))
def column_date(self, data): if data[10]: date = Date() date.unserialize(data[10]) return displayer.display(date) return ''
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 _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 __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.__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.__fill_combo(self.tagcombo, list(self.__tagnames())) 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) 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) pt_grid = Gtk.Grid(column_spacing=10) 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(label1, 0, 2, 1, 1) pl_grid = Gtk.Grid(column_spacing=10) pl_grid.set_margin_left(20) #pt_grid.attach(self.enclosing_place, 1, 2, 1, 1) pl_grid.attach(date_label, 1, 4, 1, 1) pl_grid.attach(self.date_entry, 2, 4, 1, 1) pl_grid.attach(date_button, 3, 4, 1, 1) vbox.pack_start(pt_grid, False, True, 0) vbox.pack_start(pl_grid, False, True, 0) self.but_set_enclosing = Gtk.Button(label=_('Select')) self.but_set_enclosing.connect("clicked", self.cb_select) #vbox.pack_start(self.but_set_enclosing, False, True, 10) pt_grid.attach(self.but_set_enclosing, 1, 2, 1, 1) self.clear_enclosing = Gtk.CheckButton( _("Clear original enclosing places")) vbox.pack_start(self.clear_enclosing, False, True, 0) self.clear_tags = Gtk.CheckButton(_("Clear tags")) 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) vbox.pack_start(self.generate_hierarchy, False, True, 0) butbox1 = Gtk.VBox() butbox1.set_margin_left(20) self.spaces = Gtk.CheckButton(_("use spaces as separator")) self.spaces.set_sensitive(False) butbox1.pack_start(self.spaces, False, True, 0) self.reverse = Gtk.CheckButton(_("reverse hierarchy")) self.reverse.set_sensitive(False) butbox1.pack_start(self.reverse, False, True, 0) vbox.pack_start(butbox1, False, True, 0) self.replace_text = Gtk.CheckButton(_("Replace text")) self.replace_text.connect("clicked", self.cb_select_replace_text) self.use_regex = Gtk.CheckButton(_("Use regex")) 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) new_text_label = Gtk.Label(_("New text:")) self.new_text = Gtk.Entry() self.new_text.set_sensitive(False) 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) vbox.pack_start(but_clear, False, True, 10) but_apply = Gtk.Button(label=_('Apply to selected places')) but_apply.connect("clicked", self.cb__apply) vbox.pack_start(but_apply, False, True, 0) vbox.show_all() return vbox