def revalidate(self, obj = None): """ If anything changed, revalidate the date and enable/disable the "OK" button based on the result. """ (the_quality, the_modifier, the_calendar, the_value, the_text, the_newyear) = self.build_date_from_ui() LOG.debug("revalidate: {0} changed, value: {1}".format( obj, the_value)) d = Date(self.date) if not self.ok_button.get_sensitive(): self.statusbar.pop(1) try: d.set( quality=the_quality, modifier=the_modifier, calendar=the_calendar, value=the_value, text=the_text, newyear=the_newyear) # didn't throw yet? self.validated_date = d LOG.debug("validated_date set to: {0}".format(d.to_struct())) self.ok_button.set_sensitive(1) self.calendar_box.set_sensitive(1) return True except DateError as e: self.ok_button.set_sensitive(0) self.calendar_box.set_sensitive(0) self.statusbar.push(1, _("Correct the date or switch from `{cur_mode}' to `{text_mode}'" ).format( cur_mode = MOD_TEXT[self.type_box.get_active()][1], text_mode = MOD_TEXT[-1][1])) return False
def revalidate(self, obj=None): """ If anything changed, revalidate the date and enable/disable the "OK" button based on the result. """ (the_quality, the_modifier, the_calendar, the_value, the_text, the_newyear) = self.build_date_from_ui() LOG.debug("revalidate: {0} changed, value: {1}".format( obj, the_value)) dat = Date(self.date) if not self.ok_button.get_sensitive(): self.statusbar.pop(1) try: dat.set(quality=the_quality, modifier=the_modifier, calendar=the_calendar, value=the_value, text=the_text, newyear=the_newyear) # didn't throw yet? self.validated_date = dat LOG.debug("validated_date set to: {0}".format(dat.__dict__)) self.ok_button.set_sensitive(1) self.calendar_box.set_sensitive(1) return True except DateError as dummy_err: self.ok_button.set_sensitive(0) self.calendar_box.set_sensitive(0) curmode = MOD_TEXT[self.type_box.get_active()][1] txtmode = MOD_TEXT[-1][1] self.statusbar.push(1, _("Correct the date or switch from `{cur_mode}'" " to `{text_mode}'").format( cur_mode=curmode, text_mode=txtmode)) return False
def set_date_from_ymd(self, y, m, d, text=""): """ Sets Date fields from a year, month, and day. """ gdate = GDate(y, m, d) gdate.text = text self.set_date_from_gdate(gdate)
def __calculate(self, database, person): """Calculate the age and days until birthday""" today = Today() birth_ref = person.get_birth_ref() death_ref = person.get_death_ref() if (birth_ref and not death_ref): birth = database.get_event_from_handle(birth_ref.ref) birth_date = birth.get_date_object() if birth_date.is_regular(): birthday_this_year = Date(today.get_year(), birth_date.get_month(), birth_date.get_day()) next_age = birthday_this_year - birth_date # (0 year, months, days) between now and birthday of this # year (positive if passed): diff = today - birthday_this_year # about number of days the diff is: diff_days = diff[1] * 30 + diff[2] if next_age[0] < self.max_age: if diff_days <= 0: # not yet passed self.result.append((diff_days, next_age, birth_date, person)) else: # passed; add it for next year's birthday self.result.append((diff_days - 365, next_age[0] + 1, birth_date, person))
def main(self): self.set_text(_("Processing...")) database = self.dbstate.db personList = database.iter_people() result = [] text = '' today = Today() for cnt, person in enumerate(personList): birth_ref = person.get_birth_ref() death_ref = person.get_death_ref() if (birth_ref and not death_ref): birth = database.get_event_from_handle(birth_ref.ref) birth_date = birth.get_date_object() if birth_date.is_regular(): birthday_this_year = Date(today.get_year(), birth_date.get_month(), birth_date.get_day()) next_age = birthday_this_year - birth_date # (0 year, months, days) between now and birthday of this year (positive if passed): diff = today - birthday_this_year # about number of days the diff is: diff_days = diff[1] * 30 + diff[2] if next_age[0] < self.max_age: if diff_days <= 0: #not yet passed result.append((diff_days, next_age, birth_date, person)) else: #passed; add it for next year's birthday result.append((diff_days - 365, next_age[0] + 1, birth_date, person)) # Reverse sort on number of days from now: result.sort(key=lambda item: -item[0]) self.clear_text() for diff, age, date, person in result: name = person.get_primary_name() self.append_text("%s: " % gramps.gen.datehandler.displayer.display(date)) self.link(name_displayer.display_name(name), "Person", person.handle) self.append_text(" (%s)\n" % age) self.append_text("", scroll_to="begin")
def get_year(self, event): "return year for given event" date = event.get_date_object() if date: year = date.get_year() if year: return [self._get_date(Date(year))] # localized year return [_T_("Date(s) missing")]
def main(self): """Search the database for the last person records changed.""" self.set_text(_("Processing...") + "\n") counter = 0 yield True handles = sorted(self.dbstate.db.get_person_handles(), key=self._getTimestamp) yield True self.clear_text() for handle in reversed(handles[-10:]): person = self.dbstate.db.get_person_from_handle(handle) self.append_text(" %d. " % (counter + 1, )) self.link(person.get_primary_name().get_name(), 'Person', person.handle) change_date = Date() change_date.set_yr_mon_day(*time.localtime(person.change)[0:3]) self.append_text(" (%s %s)" % (_('changed on'), gramps.gen.datehandler.displayer.display(change_date))) self.append_text("\n") if (counter % _YIELD_INTERVAL): yield True counter += 1
def __init__(self, uistate, track): Gtk.Box.__init__(self) self.entry = ValidatableMaskedEntry() self.entry.set_width_chars(13) self.pack_start(self.entry, True, True, 0) image = Gtk.Image() image.set_from_stock('gramps-date-edit', Gtk.IconSize.BUTTON) button = Gtk.Button() button.set_image(image) button.set_relief(Gtk.ReliefStyle.NORMAL) self.pack_start(button, False, True, 0) self.date = Date() self.date_entry = MonitoredDate(self.entry, button, self.date, uistate, track) self.show_all()
def build_date_from_ui(self): """ Collect information from the UI controls and return 5-tuple of (quality,modifier,calendar,value,text) """ # It is important to not set date based on these controls. # For example, changing the caledar makes the date inconsistent # until the callback of the calendar menu is finished. # We need to be able to use this function from that callback, # so here we just report on the state of all widgets, without # actually modifying the date yet. modifier = MOD_TEXT[self.type_box.get_active()][0] text = self.text_entry.get_text() if modifier == Date.MOD_TEXTONLY: return (Date.QUAL_NONE, Date.MOD_TEXTONLY, Date.CAL_GREGORIAN, Date.EMPTY, text, Date.NEWYEAR_JAN1) quality = QUAL_TEXT[self.quality_box.get_active()][0] if modifier in (Date.MOD_RANGE, Date.MOD_SPAN): value = ( self.start_day.get_value_as_int(), self.start_month_box.get_active(), self.start_year.get_value_as_int(), self.dual_dated.get_active(), self.stop_day.get_value_as_int(), self.stop_month_box.get_active(), self.stop_year.get_value_as_int(), self.dual_dated.get_active()) else: value = ( self.start_day.get_value_as_int(), self.start_month_box.get_active(), self.start_year.get_value_as_int(), self.dual_dated.get_active()) calendar = self.calendar_box.get_active() newyear = Date.newyear_to_code(self.new_year.get_text()) return (quality, modifier, calendar, value, text, newyear)
def __init__(self, text, fname): """""" self.dflt_text = ImportEntry(text) self.dflt_file = ImportEntry(fname) self.dflt_date = Date()
def __init__(self, date, uistate, track): """ Initiate and display the dialog. """ ManagedWindow.__init__(self, uistate, track, self) # Create self.date as a copy of the given Date object. self.date = Date(date) self.top = Glade() self.set_window( self.top.toplevel, self.top.get_object('title'), _('Date selection')) self.setup_configs('interface.editdate', 620, 320) self.statusbar = self.top.get_object('statusbar') self.ok_button = self.top.get_object('ok_button') self.calendar_box = self.top.get_object('calendar_box') for name in Date.ui_calendar_names: self.calendar_box.get_model().append([name]) self.new_year = self.top.get_object('newyear') self.new_year.set_text(self.date.newyear_to_str()) cal = self.date.get_calendar() self.calendar_box.set_active(cal) self.align_newyear_ui_with_calendar(cal) self.calendar_box.connect('changed', self.switch_calendar) self.quality_box = self.top.get_object('quality_box') for item_number, item in enumerate(QUAL_TEXT): self.quality_box.append_text(item[1]) if self.date.get_quality() == item[0]: self.quality_box.set_active(item_number) self.type_box = self.top.get_object('type_box') for item_number, item in enumerate(MOD_TEXT): self.type_box.append_text(item[1]) if self.date.get_modifier() == item[0]: self.type_box.set_active(item_number) self.type_box.connect('changed', self.switch_type) self.start_month_box = self.top.get_object('start_month_box') self.stop_month_box = self.top.get_object('stop_month_box') month_names = CAL_TO_MONTHS_NAMES[self.date.get_calendar()] for name in month_names: self.start_month_box.append_text(name) self.stop_month_box.append_text(name) self.start_month_box.set_active(self.date.get_month()) self.stop_month_box.set_active(self.date.get_stop_month()) self.start_day = self.top.get_object('start_day') self.start_day.set_value(self.date.get_day()) self.start_year = self.top.get_object('start_year') self.start_year.set_value(self.date.get_year()) self.stop_day = self.top.get_object('stop_day') self.stop_day.set_value(self.date.get_stop_day()) self.stop_year = self.top.get_object('stop_year') self.stop_year.set_value(self.date.get_stop_year()) self.dual_dated = self.top.get_object('dualdated') # Disable second date controls if not compound date if not self.date.is_compound(): self.stop_day.set_sensitive(0) self.stop_month_box.set_sensitive(0) self.stop_year.set_sensitive(0) # Disable the rest of controls if a text-only date if self.date.get_modifier() == Date.MOD_TEXTONLY: self.start_day.set_sensitive(0) self.start_month_box.set_sensitive(0) self.start_year.set_sensitive(0) self.calendar_box.set_sensitive(0) self.quality_box.set_sensitive(0) self.dual_dated.set_sensitive(0) self.new_year.set_sensitive(0) self.text_entry = self.top.get_object('date_text_entry') self.text_entry.set_text(self.date.get_text()) if self.date.get_slash(): self.dual_dated.set_active(1) self.calendar_box.set_sensitive(0) self.calendar_box.set_active(Date.CAL_JULIAN) self.dual_dated.connect('toggled', self.switch_dual_dated) cal = config.get('preferences.calendar-format-input') self.calendar_box.set_active(cal) # The dialog is modal -- since dates don't have names, we don't # want to have several open dialogs, since then the user will # loose track of which is which. Much like opening files. self.validated_date = self.return_date = None for obj in self.top.get_objects(): if obj != self.ok_button: for signal in ['changed', 'value-changed']: try: obj.connect_after(signal, self.revalidate) except TypeError: # some of them don't support the signal, ignore them... pass self.revalidate() self.show() while True: response = self.window.run() LOG.debug("response: {0}".format(response)) if response == Gtk.ResponseType.HELP: display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC) elif response == Gtk.ResponseType.DELETE_EVENT: break else: if response == Gtk.ResponseType.OK: # if the user pressed OK/enter while inside an edit field, # e.g., the year, # build_date_from_ui won't pick up the new text in the # run of revalidate that allowed the OK! if not self.revalidate(): continue self.return_date = Date() self.return_date.copy(self.validated_date) self.close() break
class EditDate(ManagedWindow): """ Dialog allowing to build the date precisely, to correct possible limitations of parsing and/or underlying structure of :class:`.Date`. """ def __init__(self, date, uistate, track): """ Initiate and display the dialog. """ ManagedWindow.__init__(self, uistate, track, self) # Create self.date as a copy of the given Date object. self.date = Date(date) self.top = Glade() self.set_window( self.top.toplevel, self.top.get_object('title'), _('Date selection')) self.setup_configs('interface.editdate', 620, 320) self.statusbar = self.top.get_object('statusbar') self.ok_button = self.top.get_object('ok_button') self.calendar_box = self.top.get_object('calendar_box') for name in Date.ui_calendar_names: self.calendar_box.get_model().append([name]) self.new_year = self.top.get_object('newyear') self.new_year.set_text(self.date.newyear_to_str()) cal = self.date.get_calendar() self.calendar_box.set_active(cal) self.align_newyear_ui_with_calendar(cal) self.calendar_box.connect('changed', self.switch_calendar) self.quality_box = self.top.get_object('quality_box') for item_number, item in enumerate(QUAL_TEXT): self.quality_box.append_text(item[1]) if self.date.get_quality() == item[0]: self.quality_box.set_active(item_number) self.type_box = self.top.get_object('type_box') for item_number, item in enumerate(MOD_TEXT): self.type_box.append_text(item[1]) if self.date.get_modifier() == item[0]: self.type_box.set_active(item_number) self.type_box.connect('changed', self.switch_type) self.start_month_box = self.top.get_object('start_month_box') self.stop_month_box = self.top.get_object('stop_month_box') month_names = CAL_TO_MONTHS_NAMES[self.date.get_calendar()] for name in month_names: self.start_month_box.append_text(name) self.stop_month_box.append_text(name) self.start_month_box.set_active(self.date.get_month()) self.stop_month_box.set_active(self.date.get_stop_month()) self.start_day = self.top.get_object('start_day') self.start_day.set_value(self.date.get_day()) self.start_year = self.top.get_object('start_year') self.start_year.set_value(self.date.get_year()) self.stop_day = self.top.get_object('stop_day') self.stop_day.set_value(self.date.get_stop_day()) self.stop_year = self.top.get_object('stop_year') self.stop_year.set_value(self.date.get_stop_year()) self.dual_dated = self.top.get_object('dualdated') # Disable second date controls if not compound date if not self.date.is_compound(): self.stop_day.set_sensitive(0) self.stop_month_box.set_sensitive(0) self.stop_year.set_sensitive(0) # Disable the rest of controls if a text-only date if self.date.get_modifier() == Date.MOD_TEXTONLY: self.start_day.set_sensitive(0) self.start_month_box.set_sensitive(0) self.start_year.set_sensitive(0) self.calendar_box.set_sensitive(0) self.quality_box.set_sensitive(0) self.dual_dated.set_sensitive(0) self.new_year.set_sensitive(0) self.text_entry = self.top.get_object('date_text_entry') self.text_entry.set_text(self.date.get_text()) if self.date.get_slash(): self.dual_dated.set_active(1) self.calendar_box.set_sensitive(0) self.calendar_box.set_active(Date.CAL_JULIAN) self.dual_dated.connect('toggled', self.switch_dual_dated) cal = config.get('preferences.calendar-format-input') self.calendar_box.set_active(cal) # The dialog is modal -- since dates don't have names, we don't # want to have several open dialogs, since then the user will # loose track of which is which. Much like opening files. self.validated_date = self.return_date = None for obj in self.top.get_objects(): if obj != self.ok_button: for signal in ['changed', 'value-changed']: try: obj.connect_after(signal, self.revalidate) except TypeError: # some of them don't support the signal, ignore them... pass self.revalidate() self.show() while True: response = self.window.run() LOG.debug("response: {0}".format(response)) if response == Gtk.ResponseType.HELP: display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC) elif response == Gtk.ResponseType.DELETE_EVENT: break else: if response == Gtk.ResponseType.OK: # if the user pressed OK/enter while inside an edit field, # e.g., the year, # build_date_from_ui won't pick up the new text in the # run of revalidate that allowed the OK! if not self.revalidate(): continue self.return_date = Date() self.return_date.copy(self.validated_date) self.close() break def revalidate(self, obj=None): """ If anything changed, revalidate the date and enable/disable the "OK" button based on the result. """ (the_quality, the_modifier, the_calendar, the_value, the_text, the_newyear) = self.build_date_from_ui() LOG.debug("revalidate: {0} changed, value: {1}".format( obj, the_value)) dat = Date(self.date) if not self.ok_button.get_sensitive(): self.statusbar.pop(1) try: dat.set(quality=the_quality, modifier=the_modifier, calendar=the_calendar, value=the_value, text=the_text, newyear=the_newyear) # didn't throw yet? self.validated_date = dat LOG.debug("validated_date set to: {0}".format(dat.__dict__)) self.ok_button.set_sensitive(1) self.calendar_box.set_sensitive(1) return True except DateError as dummy_err: self.ok_button.set_sensitive(0) self.calendar_box.set_sensitive(0) curmode = MOD_TEXT[self.type_box.get_active()][1] txtmode = MOD_TEXT[-1][1] self.statusbar.push(1, _("Correct the date or switch from `{cur_mode}'" " to `{text_mode}'").format( cur_mode=curmode, text_mode=txtmode)) return False def build_menu_names(self, obj): """ Define the menu entry for the :class:`.ManagedWindow` """ return (_("Date selection"), None) def build_date_from_ui(self): """ Collect information from the UI controls and return 5-tuple of (quality,modifier,calendar,value,text) """ # It is important to not set date based on these controls. # For example, changing the caledar makes the date inconsistent # until the callback of the calendar menu is finished. # We need to be able to use this function from that callback, # so here we just report on the state of all widgets, without # actually modifying the date yet. modifier = MOD_TEXT[self.type_box.get_active()][0] text = self.text_entry.get_text() if modifier == Date.MOD_TEXTONLY: return (Date.QUAL_NONE, Date.MOD_TEXTONLY, Date.CAL_GREGORIAN, Date.EMPTY, text, Date.NEWYEAR_JAN1) quality = QUAL_TEXT[self.quality_box.get_active()][0] if modifier in (Date.MOD_RANGE, Date.MOD_SPAN): value = ( self.start_day.get_value_as_int(), self.start_month_box.get_active(), self.start_year.get_value_as_int(), self.dual_dated.get_active(), self.stop_day.get_value_as_int(), self.stop_month_box.get_active(), self.stop_year.get_value_as_int(), self.dual_dated.get_active()) else: value = ( self.start_day.get_value_as_int(), self.start_month_box.get_active(), self.start_year.get_value_as_int(), self.dual_dated.get_active()) calendar = self.calendar_box.get_active() newyear = Date.newyear_to_code(self.new_year.get_text()) return (quality, modifier, calendar, value, text, newyear) def switch_type(self, obj): """ Disable/enable various date controls depending on the date type selected via the menu. """ the_modifier = MOD_TEXT[self.type_box.get_active()][0] # Disable/enable second date controls based on whether # the type allows compound dates if the_modifier in (Date.MOD_RANGE, Date.MOD_SPAN): stop_date_sensitivity = 1 else: stop_date_sensitivity = 0 self.stop_day.set_sensitive(stop_date_sensitivity) self.stop_month_box.set_sensitive(stop_date_sensitivity) self.stop_year.set_sensitive(stop_date_sensitivity) # Disable/enable the rest of the controls if the type is text-only. date_sensitivity = not the_modifier == Date.MOD_TEXTONLY self.start_day.set_sensitive(date_sensitivity) self.start_month_box.set_sensitive(date_sensitivity) self.start_year.set_sensitive(date_sensitivity) self.calendar_box.set_sensitive(date_sensitivity) self.quality_box.set_sensitive(date_sensitivity) self.dual_dated.set_sensitive(date_sensitivity) self.new_year.set_sensitive(date_sensitivity) def switch_dual_dated(self, obj): """ Changed whether this is a dual dated year, or not. Dual dated years are represented in the Julian calendar so that the day/months don't changed in the Text representation. """ if self.dual_dated.get_active(): self.calendar_box.set_active(Date.CAL_JULIAN) self.calendar_box.set_sensitive(0) else: self.calendar_box.set_sensitive(1) def align_newyear_ui_with_calendar(self, cal): if calendar_has_fixed_newyear(cal): LOG.debug("new year disabled for cal {0}".format(cal)) self.new_year.set_sensitive(0) self.new_year.set_text('') else: LOG.debug("new year enabled for cal {0}".format(cal)) self.new_year.set_sensitive(1) def switch_calendar(self, obj): """ Change month names and convert the date based on the calendar selected via the menu. """ old_cal = self.date.get_calendar() new_cal = self.calendar_box.get_active() LOG.debug(">>>switch_calendar: {0} changed, {1} -> {2}".format( obj, old_cal, new_cal)) self.align_newyear_ui_with_calendar(new_cal) (the_quality, the_modifier, dummy_the_calendar, the_value, the_text, the_newyear) = self.build_date_from_ui() try: self.date.set(quality=the_quality, modifier=the_modifier, calendar=old_cal, value=the_value, text=the_text, newyear=the_newyear) except DateError: pass else: if not self.date.is_empty(): self.date.convert_calendar(new_cal) self.start_month_box.get_model().clear() self.stop_month_box.get_model().clear() month_names = CAL_TO_MONTHS_NAMES[new_cal] for name in month_names: self.start_month_box.append_text(name) self.stop_month_box.append_text(name) self.start_day.set_value(self.date.get_day()) self.start_month_box.set_active(self.date.get_month()) self.start_year.set_value(self.date.get_year()) self.stop_day.set_value(self.date.get_stop_day()) self.stop_month_box.set_active(self.date.get_stop_month()) self.stop_year.set_value(self.date.get_stop_year()) LOG.debug("<<<switch_calendar: {0} changed, {1} -> {2}".format( obj, old_cal, new_cal))
def list_people_changed(self, object_type): """ List all records with last change date """ nb_items = 0 def sort_on_change(handle): """ sort records based on the last change time """ obj = fct(handle) timestamp = obj.get_change_time() return timestamp if object_type == Person: fct = self.report.database.get_person_from_handle fct_link = self.new_person_link elif object_type == Family: fct = self.report.database.get_family_from_handle fct_link = self.family_link elif object_type == Event: fct = self.report.database.get_event_from_handle elif object_type == Place: fct = self.report.database.get_place_from_handle fct_link = self.place_link elif object_type == Source: fct = self.report.database.get_place_from_handle fct_link = self.source_link elif object_type == Repository: fct = self.report.database.get_place_from_handle fct_link = self.repository_link elif object_type == Media: fct = self.report.database.get_place_from_handle obj_list = sorted(self.report.obj_dict[object_type], key=sort_on_change, reverse=True) with Html("table", class_="list", id="list") as section: for handle in obj_list: date = obj = None name = "" obj = fct(handle) if object_type == Person: name = fct_link(handle) elif object_type == Family: name = self.report.get_family_name(obj) name = fct_link(handle, name) elif object_type == Event: otype = obj.get_type() date = obj.get_date_object() if int(otype) in _EVENTMAP: handle_list = set( self.report.database.find_backlink_handles( handle, include_classes=['Family', 'Person'])) else: handle_list = set( self.report.database.find_backlink_handles( handle, include_classes=['Person'])) if handle_list: name = Html("span", self._(otype.xml_str())+" ") for obj_t, r_handle in handle_list: if obj_t == 'Person': name += self.new_person_link(r_handle) else: srbd = self.report.database fam = srbd.get_family_from_handle(r_handle) srgfn = self.report.get_family_name name += self.family_link(r_handle, srgfn(fam)) elif object_type == Place: name = _pd.display(self.report.database, obj) name = fct_link(handle, name) elif object_type == Source: name = obj.get_title() name = fct_link(handle, name) elif object_type == Repository: name = obj.get_name() name = fct_link(handle, name) elif object_type == Media: name = obj.get_description() url = self.report.build_url_fname_html(handle, "img") name = Html("a", name, href=url, title=name) if obj: timestamp = obj.get_change_time() if timestamp - self.maxdays > 0: nb_items += 1 if nb_items > self.nbr: break tims = localtime(timestamp) odat = Date(tims.tm_year, tims.tm_mon, tims.tm_mday) date = self.rlocale.date_displayer.display(odat) date += strftime(' %X', tims) row = Html("tr") section += row row += Html("td", date, class_="date") row += Html("td", name) return section
_in.step() main.add_variable(test.parse_format(testing_what)) else: _in.parse_format(main) main.combine_all() state, line = main.get_string() if state is TXT.remove: return None else: return line from gramps.gen.lib.date import Date y_or_n = () date_to_test = Date() def date_set(): date_to_test.set_yr_mon_day(1970 if 0 in y_or_n else 0, 9 if 1 in y_or_n else 0, 3 if 2 in y_or_n else 0) #print date_to_test line_in = "<Z>$(yyy) <a>$(<Z>Mm)<b>$(mm){<c>$(d)}{<d>$(yyyy)<e>}<f>$(yy)" consume_str = ConsumableString(line_in) print(line_in) print("#None are known") tmp = main_level_test(consume_str, DateFormat, date_to_test) print(tmp) print("Good" if tmp == " " else "!! bad !!")
def __init__(self, database, options, user): """ Initialize the report class. database - the GRAMPS database instance options - instance of the Options class for this report user - a gramps.gen.user.User() instance """ Report.__init__(self, database, options, user) menu = options.menu # BUG: somehow when calculating if we've reached the max # generations limit the report is stopping at one generation # before the max requested, so I'm bumping this up by one to # compensate until I find where the calculation is wrong. self.max_generations = menu.get_option_by_name('maxgen').get_value() + 1 pid = menu.get_option_by_name('pid').get_value() self.center_person = database.get_person_from_gramps_id(pid) if (self.center_person == None) : raise ReportError(_("Person %s is not in the Database") % pid ) self.show_parent_tags = menu.get_option_by_name('showcaptions').get_value() self.parent_tag_len = pt2cm(self.doc.string_width(self.get_font('PC-box'), _("Mother"))) self.parent_tag_height = self.get_font_height('PC-box') name = name_displayer.display_formal(self.center_person) self.title = _("Pedigree Chart for %s") % name report_date = Date() report_date.set_yr_mon_day(*time.localtime()[0:3]) # researcher = self.database.get_researcher() # self.footer = escape("%s: %s <%s>\n%s" % (_('Researcher'), # researcher.get_name(), # researcher.get_email(), # gramps.gen.datehandler.displayer.display(report_date))) self.footer = gramps.gen.datehandler.displayer.display(report_date) self.map = {} self.page_number = PageCounter(1) self.page_link_counter = PageCounter(2) self.generation_index = 1 page_width = self.doc.get_usable_width() page_height = self.doc.get_usable_height() self.columns = [_GUTTER_SIZE, page_width * 6 / 40, page_width * 12 / 40, page_width * 25 / 40, page_width * 32 / 40 ] #print "[DEBUG] page_width = %s, columns = %s" % (page_width, self.columns) # The third column (index 2) has the smallest space available, so I # base the box sizes on it. #self.em_size = pt2cm(self.doc.string_width(self.get_font('PC-box'), 'm')) self.max_box_size = self.columns[3] - self.columns[2] - _GUTTER_SIZE #self.name_max_len = self.max_box_size / self.em_size #print "[DEBUG] columns", repr(self.columns) #print "[DEBUG] em size: %s, max_box_size: %s, max_name_len: %s" % (self.em_size, self.max_box_size, self.name_max_len) self.coordinates = { 1: (self.columns[0], page_height * 32 / 64), # second generation 2: (self.columns[1], page_height * 16 / 64), 3: (self.columns[1], page_height * 48 / 64), # third generation 4: (self.columns[2], page_height * 8 / 64), 5: (self.columns[2], page_height * 24 / 64), 6: (self.columns[2], page_height * 40 / 64), 7: (self.columns[2], page_height * 56 / 64), # fourth generation 8: (self.columns[3], page_height * 4 / 64), # 3/64 9: (self.columns[3], page_height * 13 / 64), # 15/64 10: (self.columns[3], page_height * 20 / 64), # 20/64 11: (self.columns[3], page_height * 28 / 64), # 30 12: (self.columns[3], page_height * 36 / 64), # 35 13: (self.columns[3], page_height * 45 / 64), # 47 14: (self.columns[3], page_height * 52 / 64), # 51 15: (self.columns[3], page_height * 60 / 64) # 60 }
def __init__(self, date, uistate, track): """ Initiate and display the dialog. """ ManagedWindow.__init__(self, uistate, track, self) # Create self.date as a copy of the given Date object. self.date = Date(date) self.top = Glade() self.set_window( self.top.toplevel, self.top.get_object('title'), _('Date selection')) self.statusbar = self.top.get_object('statusbar') self.ok_button = self.top.get_object('ok_button') self.calendar_box = self.top.get_object('calendar_box') for name in Date.ui_calendar_names: self.calendar_box.get_model().append([name]) self.new_year = self.top.get_object('newyear') self.new_year.set_text(self.date.newyear_to_str()) cal = self.date.get_calendar() self.calendar_box.set_active(cal) self.align_newyear_ui_with_calendar(cal) self.calendar_box.connect('changed', self.switch_calendar) self.quality_box = self.top.get_object('quality_box') for item_number in range(len(QUAL_TEXT)): self.quality_box.append_text(QUAL_TEXT[item_number][1]) if self.date.get_quality() == QUAL_TEXT[item_number][0]: self.quality_box.set_active(item_number) self.type_box = self.top.get_object('type_box') for item_number in range(len(MOD_TEXT)): self.type_box.append_text(MOD_TEXT[item_number][1]) if self.date.get_modifier() == MOD_TEXT[item_number][0]: self.type_box.set_active(item_number) self.type_box.connect('changed', self.switch_type) self.start_month_box = self.top.get_object('start_month_box') self.stop_month_box = self.top.get_object('stop_month_box') month_names = CAL_TO_MONTHS_NAMES[self.date.get_calendar()] for name in month_names: self.start_month_box.append_text(name) self.stop_month_box.append_text(name) self.start_month_box.set_active(self.date.get_month()) self.stop_month_box.set_active(self.date.get_stop_month()) self.start_day = self.top.get_object('start_day') self.start_day.set_value(self.date.get_day()) self.start_year = self.top.get_object('start_year') self.start_year.set_value(self.date.get_year()) self.stop_day = self.top.get_object('stop_day') self.stop_day.set_value(self.date.get_stop_day()) self.stop_year = self.top.get_object('stop_year') self.stop_year.set_value(self.date.get_stop_year()) self.dual_dated = self.top.get_object('dualdated') # Disable second date controls if not compound date if not self.date.is_compound(): self.stop_day.set_sensitive(0) self.stop_month_box.set_sensitive(0) self.stop_year.set_sensitive(0) # Disable the rest of controls if a text-only date if self.date.get_modifier() == Date.MOD_TEXTONLY: self.start_day.set_sensitive(0) self.start_month_box.set_sensitive(0) self.start_year.set_sensitive(0) self.calendar_box.set_sensitive(0) self.quality_box.set_sensitive(0) self.dual_dated.set_sensitive(0) self.new_year.set_sensitive(0) self.text_entry = self.top.get_object('date_text_entry') self.text_entry.set_text(self.date.get_text()) if self.date.get_slash(): self.dual_dated.set_active(1) self.calendar_box.set_sensitive(0) self.calendar_box.set_active(Date.CAL_JULIAN) self.dual_dated.connect('toggled', self.switch_dual_dated) # The dialog is modal -- since dates don't have names, we don't # want to have several open dialogs, since then the user will # loose track of which is which. Much like opening files. self.validated_date = self.return_date = None for o in self.top.get_objects(): if o != self.ok_button: for signal in ['changed', 'value-changed']: try: o.connect_after(signal, self.revalidate) except TypeError: pass # some of them don't support the signal, ignore them... self.revalidate() self.show() while True: response = self.window.run() LOG.debug("response: {0}".format(response)) if response == Gtk.ResponseType.HELP: display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC) elif response == Gtk.ResponseType.DELETE_EVENT: break else: if response == Gtk.ResponseType.OK: # if the user pressed OK/enter while inside an edit field, # e.g., the year, # build_date_from_ui won't pick up the new text in the # run of revalidate that allowed the OK! if not self.revalidate(): continue self.return_date = Date() self.return_date.copy(self.validated_date) self.close() break
class EditDate(ManagedWindow): """ Dialog allowing to build the date precisely, to correct possible limitations of parsing and/or underlying structure of :class:`.Date`. """ def __init__(self, date, uistate, track): """ Initiate and display the dialog. """ ManagedWindow.__init__(self, uistate, track, self) # Create self.date as a copy of the given Date object. self.date = Date(date) self.top = Glade() self.set_window( self.top.toplevel, self.top.get_object('title'), _('Date selection')) self.statusbar = self.top.get_object('statusbar') self.ok_button = self.top.get_object('ok_button') self.calendar_box = self.top.get_object('calendar_box') for name in Date.ui_calendar_names: self.calendar_box.get_model().append([name]) self.new_year = self.top.get_object('newyear') self.new_year.set_text(self.date.newyear_to_str()) cal = self.date.get_calendar() self.calendar_box.set_active(cal) self.align_newyear_ui_with_calendar(cal) self.calendar_box.connect('changed', self.switch_calendar) self.quality_box = self.top.get_object('quality_box') for item_number in range(len(QUAL_TEXT)): self.quality_box.append_text(QUAL_TEXT[item_number][1]) if self.date.get_quality() == QUAL_TEXT[item_number][0]: self.quality_box.set_active(item_number) self.type_box = self.top.get_object('type_box') for item_number in range(len(MOD_TEXT)): self.type_box.append_text(MOD_TEXT[item_number][1]) if self.date.get_modifier() == MOD_TEXT[item_number][0]: self.type_box.set_active(item_number) self.type_box.connect('changed', self.switch_type) self.start_month_box = self.top.get_object('start_month_box') self.stop_month_box = self.top.get_object('stop_month_box') month_names = CAL_TO_MONTHS_NAMES[self.date.get_calendar()] for name in month_names: self.start_month_box.append_text(name) self.stop_month_box.append_text(name) self.start_month_box.set_active(self.date.get_month()) self.stop_month_box.set_active(self.date.get_stop_month()) self.start_day = self.top.get_object('start_day') self.start_day.set_value(self.date.get_day()) self.start_year = self.top.get_object('start_year') self.start_year.set_value(self.date.get_year()) self.stop_day = self.top.get_object('stop_day') self.stop_day.set_value(self.date.get_stop_day()) self.stop_year = self.top.get_object('stop_year') self.stop_year.set_value(self.date.get_stop_year()) self.dual_dated = self.top.get_object('dualdated') # Disable second date controls if not compound date if not self.date.is_compound(): self.stop_day.set_sensitive(0) self.stop_month_box.set_sensitive(0) self.stop_year.set_sensitive(0) # Disable the rest of controls if a text-only date if self.date.get_modifier() == Date.MOD_TEXTONLY: self.start_day.set_sensitive(0) self.start_month_box.set_sensitive(0) self.start_year.set_sensitive(0) self.calendar_box.set_sensitive(0) self.quality_box.set_sensitive(0) self.dual_dated.set_sensitive(0) self.new_year.set_sensitive(0) self.text_entry = self.top.get_object('date_text_entry') self.text_entry.set_text(self.date.get_text()) if self.date.get_slash(): self.dual_dated.set_active(1) self.calendar_box.set_sensitive(0) self.calendar_box.set_active(Date.CAL_JULIAN) self.dual_dated.connect('toggled', self.switch_dual_dated) # The dialog is modal -- since dates don't have names, we don't # want to have several open dialogs, since then the user will # loose track of which is which. Much like opening files. self.validated_date = self.return_date = None for o in self.top.get_objects(): if o != self.ok_button: for signal in ['changed', 'value-changed']: try: o.connect_after(signal, self.revalidate) except TypeError: pass # some of them don't support the signal, ignore them... self.revalidate() self.show() while True: response = self.window.run() LOG.debug("response: {0}".format(response)) if response == Gtk.ResponseType.HELP: display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC) elif response == Gtk.ResponseType.DELETE_EVENT: break else: if response == Gtk.ResponseType.OK: # if the user pressed OK/enter while inside an edit field, # e.g., the year, # build_date_from_ui won't pick up the new text in the # run of revalidate that allowed the OK! if not self.revalidate(): continue self.return_date = Date() self.return_date.copy(self.validated_date) self.close() break def revalidate(self, obj = None): """ If anything changed, revalidate the date and enable/disable the "OK" button based on the result. """ (the_quality, the_modifier, the_calendar, the_value, the_text, the_newyear) = self.build_date_from_ui() LOG.debug("revalidate: {0} changed, value: {1}".format( obj, the_value)) d = Date(self.date) if not self.ok_button.get_sensitive(): self.statusbar.pop(1) try: d.set( quality=the_quality, modifier=the_modifier, calendar=the_calendar, value=the_value, text=the_text, newyear=the_newyear) # didn't throw yet? self.validated_date = d LOG.debug("validated_date set to: {0}".format(d.to_struct())) self.ok_button.set_sensitive(1) self.calendar_box.set_sensitive(1) return True except DateError as e: self.ok_button.set_sensitive(0) self.calendar_box.set_sensitive(0) self.statusbar.push(1, _("Correct the date or switch from `{cur_mode}' to `{text_mode}'" ).format( cur_mode = MOD_TEXT[self.type_box.get_active()][1], text_mode = MOD_TEXT[-1][1])) return False def build_menu_names(self, obj): """ Define the menu entry for the :class:`.ManagedWindow` """ return (_("Date selection"), None) def build_date_from_ui(self): """ Collect information from the UI controls and return 5-tuple of (quality,modifier,calendar,value,text) """ # It is important to not set date based on these controls. # For example, changing the caledar makes the date inconsistent # until the callback of the calendar menu is finished. # We need to be able to use this function from that callback, # so here we just report on the state of all widgets, without # actually modifying the date yet. modifier = MOD_TEXT[self.type_box.get_active()][0] text = self.text_entry.get_text() if modifier == Date.MOD_TEXTONLY: return (Date.QUAL_NONE, Date.MOD_TEXTONLY, Date.CAL_GREGORIAN, Date.EMPTY, text, Date.NEWYEAR_JAN1) quality = QUAL_TEXT[self.quality_box.get_active()][0] if modifier in (Date.MOD_RANGE, Date.MOD_SPAN): value = ( self.start_day.get_value_as_int(), self.start_month_box.get_active(), self.start_year.get_value_as_int(), self.dual_dated.get_active(), self.stop_day.get_value_as_int(), self.stop_month_box.get_active(), self.stop_year.get_value_as_int(), self.dual_dated.get_active()) else: value = ( self.start_day.get_value_as_int(), self.start_month_box.get_active(), self.start_year.get_value_as_int(), self.dual_dated.get_active()) calendar = self.calendar_box.get_active() newyear = Date.newyear_to_code(self.new_year.get_text()) return (quality, modifier, calendar, value, text, newyear) def switch_type(self, obj): """ Disable/enable various date controls depending on the date type selected via the menu. """ the_modifier = MOD_TEXT[self.type_box.get_active()][0] # Disable/enable second date controls based on whether # the type allows compound dates if the_modifier in (Date.MOD_RANGE, Date.MOD_SPAN): stop_date_sensitivity = 1 else: stop_date_sensitivity = 0 self.stop_day.set_sensitive(stop_date_sensitivity) self.stop_month_box.set_sensitive(stop_date_sensitivity) self.stop_year.set_sensitive(stop_date_sensitivity) # Disable/enable the rest of the controls if the type is text-only. date_sensitivity = not the_modifier == Date.MOD_TEXTONLY self.start_day.set_sensitive(date_sensitivity) self.start_month_box.set_sensitive(date_sensitivity) self.start_year.set_sensitive(date_sensitivity) self.calendar_box.set_sensitive(date_sensitivity) self.quality_box.set_sensitive(date_sensitivity) self.dual_dated.set_sensitive(date_sensitivity) self.new_year.set_sensitive(date_sensitivity) def switch_dual_dated(self, obj): """ Changed whether this is a dual dated year, or not. Dual dated years are represented in the Julian calendar so that the day/months don't changed in the Text representation. """ if self.dual_dated.get_active(): self.calendar_box.set_active(Date.CAL_JULIAN) self.calendar_box.set_sensitive(0) else: self.calendar_box.set_sensitive(1) def align_newyear_ui_with_calendar(self, cal): if calendar_has_fixed_newyear(cal): LOG.debug("new year disabled for cal {0}".format(cal)) self.new_year.set_sensitive(0) self.new_year.set_text('') else: LOG.debug("new year enabled for cal {0}".format(cal)) self.new_year.set_sensitive(1) def switch_calendar(self, obj): """ Change month names and convert the date based on the calendar selected via the menu. """ old_cal = self.date.get_calendar() new_cal = self.calendar_box.get_active() LOG.debug(">>>switch_calendar: {0} changed, {1} -> {2}".format( obj, old_cal, new_cal)) self.align_newyear_ui_with_calendar(new_cal) (the_quality, the_modifier, the_calendar, the_value, the_text, the_newyear) = self.build_date_from_ui() try: self.date.set( quality=the_quality, modifier=the_modifier, calendar=old_cal, value=the_value, text=the_text, newyear=the_newyear) except DateError: pass else: if not self.date.is_empty(): self.date.convert_calendar(new_cal) self.start_month_box.get_model().clear() self.stop_month_box.get_model().clear() month_names = CAL_TO_MONTHS_NAMES[new_cal] for name in month_names: self.start_month_box.append_text(name) self.stop_month_box.append_text(name) self.start_day.set_value(self.date.get_day()) self.start_month_box.set_active(self.date.get_month()) self.start_year.set_value(self.date.get_year()) self.stop_day.set_value(self.date.get_stop_day()) self.stop_month_box.set_active(self.date.get_stop_month()) self.stop_year.set_value(self.date.get_stop_year()) LOG.debug("<<<switch_calendar: {0} changed, {1} -> {2}".format( obj, old_cal, new_cal))
def __init__(self, database, options, user): """ Create the Statistics object that produces the report. Uses the Extractor class to extract the data from the database. The arguments are: database - the Gramps database instance options - instance of the Options class for this report user - a gen.user.User() instance incl_private - Whether to include private data living_people - How to handle living people years_past_death - Consider as living this many years after death """ Report.__init__(self, database, options, user) menu = options.menu self._user = user self.set_locale(menu.get_option_by_name('trans').get_value()) # override default gettext, or English output will have "person|Title" self._ = self._locale.translation.sgettext stdoptions.run_private_data_option(self, menu) living_opt = stdoptions.run_living_people_option( self, menu, self._locale) self.database = CacheProxyDb(self.database) get_option_by_name = menu.get_option_by_name get_value = lambda name: get_option_by_name(name).get_value() filter_opt = get_option_by_name('filter') self.filter = filter_opt.get_filter() self.fil_name = "(%s)" % self.filter.get_name(self._locale) self.bar_items = get_value('bar_items') self.show_empty_information = get_value('show_empty_information') year_from = get_value('year_from') year_to = get_value('year_to') gender = get_value('gender') living_value = get_value('living_people') for (value, description) in living_opt.get_items(xml_items=True): if value == living_value: living_desc = self._(description) break self.living_desc = self._("(Living people: %(option_name)s)") % { 'option_name': living_desc } # title needs both data extraction method name + gender name if gender == Person.MALE: genders = self._("Men") elif gender == Person.FEMALE: genders = self._("Women") else: genders = None if genders: span_string = self._("%s born") % genders else: span_string = self._("Persons born") span_string += " %s-%s" % ( self._get_date(Date(year_from)), # localized self._get_date(Date(year_to))) people = self.filter.apply(self.database, self.database.iter_person_handles(), user=self._user) # extract requested items from the database and count them self._user.begin_progress(_('Statistics Charts'), _('Collecting data...'), self.database.get_number_of_people()) tables = _Extract.collect_data(self.database, people, menu, gender, year_from, year_to, get_value('no_years'), self._user.step_progress, self._locale) self._user.end_progress() self._user.begin_progress(_('Statistics Charts'), _('Sorting data...'), len(tables)) self.data = [] sortby = get_value('sortby') reverse = get_value('reverse') for table in tables: # generate sorted item lookup index index lookup = self.index_items(table[1], sortby, reverse) # document heading heading = "%(str1)s -- %(str2)s" % { 'str1': self._(table[0]), 'str2': span_string } self.data.append((heading, table[0], table[1], lookup)) self._user.step_progress() self._user.end_progress()
def list_notes(self): """ List all notes with last change date """ nb_items = 0 section = "" def sort_on_change(handle): """ sort records based on the last change time """ fct = self.report.database.get_note_from_handle obj = fct(handle) timestamp = obj.get_change_time() return timestamp note_list = self.report.database.get_note_handles() obj_list = sorted(note_list, key=sort_on_change, reverse=True) with Html("table", class_="list", id="list") as section: for handle in obj_list: show = False date = obj = None obj = self.report.database.get_note_from_handle(handle) if obj: text = html_escape(obj.get()[:50]) timestamp = obj.get_change_time() if timestamp - self.maxdays > 0: handle_list = set( self.report.database.find_backlink_handles( handle, include_classes=['Person', 'Family', 'Event', 'Place', 'Media', 'Source', 'Citation', 'Repository', ])) tims = localtime(timestamp) odat = Date(tims.tm_year, tims.tm_mon, tims.tm_mday) date = self.rlocale.date_displayer.display(odat) date += strftime(' %X', tims) if handle_list: srbd = self.report.database srbkref = self.report.bkref_dict for obj_t, r_handle in handle_list: if obj_t == 'Person': if r_handle in srbkref[Person]: name = self.new_person_link(r_handle) show = True elif obj_t == 'Family': if r_handle in srbkref[Family]: fam = srbd.get_family_from_handle( r_handle) fam = self._("Family") name = self.family_link(r_handle, fam) if self.inc_families: show = True elif obj_t == 'Place': if r_handle in srbkref[Place]: plc = srbd.get_place_from_handle( r_handle) plcn = _pd.display(self.report.database, plc) name = self.place_link(r_handle, plcn) if self.inc_places: show = True elif obj_t == 'Event': if r_handle in srbkref[Event]: evt = srbd.get_event_from_handle( r_handle) evtn = self._(evt.get_type().xml_str()) name = self.event_link(r_handle, evtn) if self.inc_events: show = True elif obj_t == 'Media': if r_handle in srbkref[Media]: media = srbd.get_media_from_handle( r_handle) evtn = media.get_description() name = self.media_link(r_handle, evtn, evtn, usedescr=False) if self.inc_gallery: show = True elif obj_t == 'Citation': if r_handle in srbkref[Citation]: cit = srbd.get_event_from_handle( r_handle) citsrc = cit.source_handle evtn = self._("Citation") name = self.source_link(citsrc, evtn) if self.inc_sources: show = True elif obj_t == 'Source': if r_handle in srbkref[Source]: src = srbd.get_source_from_handle( r_handle) evtn = src.get_title() name = self.source_link(r_handle, evtn) if self.inc_sources: show = True elif obj_t == 'Repository': if r_handle in srbkref[Repository]: rep = srbd.get_repository_from_handle( r_handle) evtn = rep.get_name() name = self.repository_link(r_handle, evtn) if self.inc_repository: show = True if show: row = Html("tr") section += row row += Html("td", date, class_="date") row += Html("td", text) row += Html("td", name) nb_items += 1 if nb_items > self.nbr: break return section