class TagReport(Report): """ Tag Report """ def __init__(self, database, options, user): """ Create the TagReport object that produces the report. The arguments are: database - the GRAMPS database instance options - instance of the Options class for this report user - a gen.user.User() instance This report needs the following parameters (class variables) that come in the options class. tag - The tag each object must match to be included. name_format - Preferred format to display names of people 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 lang = menu.get_option_by_name('trans').get_value() rlocale = self.set_locale(lang) stdoptions.run_private_data_option(self, menu) living_opt = stdoptions.run_living_people_option(self, menu, rlocale) self.database = CacheProxyDb(self.database) self._lv = menu.get_option_by_name('living_people').get_value() for (value, description) in living_opt.get_items(xml_items=True): if value == self._lv: living_desc = self._(description) break self.living_desc = self._("(Living people: %(option_name)s)") % { 'option_name': living_desc } self.tag = menu.get_option_by_name('tag').get_value() if not self.tag: raise ReportError( _('Tag Report'), _('You must first create a tag before running this report.')) stdoptions.run_name_format_option(self, menu) def write_report(self): self.doc.start_paragraph("TR-Title") # feature request 2356: avoid genitive form title = self._("Tag Report for %s Items") % self.tag mark = IndexMark(title, INDEX_TYPE_TOC, 1) self.doc.write_text(title, mark) self.doc.end_paragraph() if self._lv != LivingProxyDb.MODE_INCLUDE_ALL: self.doc.start_paragraph("TR-ReportSubtitle") self.doc.write_text(self.living_desc) self.doc.end_paragraph() self.write_people() self.write_families() self.write_events() self.write_places() self.write_notes() self.write_media() self.write_repositories() self.write_sources() self.write_citations() def write_people(self): """ write the people associated with the tag """ plist = self.database.iter_person_handles() filter_class = GenericFilterFactory('Person') a_filter = filter_class() a_filter.add_rule(rules.person.HasTag([self.tag])) ind_list = a_filter.apply(self.database, plist) if not ind_list: return self.doc.start_paragraph("TR-Heading") header = self._("People") mark = IndexMark(header, INDEX_TYPE_TOC, 2) self.doc.write_text(header, mark) self.doc.end_paragraph() self.doc.start_table('PeopleTable', 'TR-Table') self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Id")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Name")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Birth")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Death")) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() for person_handle in ind_list: person = self.database.get_person_from_handle(person_handle) self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(person.get_gid()) self.doc.end_paragraph() self.doc.end_cell() name = self._name_display.display(person) mark = utils.get_person_mark(self.database, person) self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(name, mark) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') birth_ref = person.get_birth_ref() if birth_ref: event = self.database.get_event_from_handle(birth_ref.ref) self.doc.write_text(self._get_date(event.get_date_object())) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') death_ref = person.get_death_ref() if death_ref: event = self.database.get_event_from_handle(death_ref.ref) self.doc.write_text(self._get_date(event.get_date_object())) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() self.doc.end_table() def write_families(self): """ write the families associated with the tag """ flist = self.database.iter_family_handles() filter_class = GenericFilterFactory('Family') a_filter = filter_class() a_filter.add_rule(rules.family.HasTag([self.tag])) fam_list = a_filter.apply(self.database, flist) if not fam_list: return self.doc.start_paragraph("TR-Heading") header = self._("Families") mark = IndexMark(header, INDEX_TYPE_TOC, 2) self.doc.write_text(header, mark) self.doc.end_paragraph() self.doc.start_table('FamilyTable', 'TR-Table') self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Id")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Father")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Mother")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Relationship")) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() for family_handle in fam_list: family = self.database.get_family_from_handle(family_handle) self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(family.get_gid()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') father_handle = family.get_father_handle() if father_handle: father = self.database.get_person_from_handle(father_handle) mark = utils.get_person_mark(self.database, father) self.doc.write_text(self._name_display.display(father), mark) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') mother_handle = family.get_mother_handle() if mother_handle: mother = self.database.get_person_from_handle(mother_handle) mark = utils.get_person_mark(self.database, mother) self.doc.write_text(self._name_display.display(mother), mark) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') relation = family.get_relationship() self.doc.write_text(str(relation)) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() self.doc.end_table() def write_events(self): """ write the events associated with the tag """ elist = self.database.get_event_handles() filter_class = GenericFilterFactory('Event') a_filter = filter_class() a_filter.add_rule(rules.event.HasTag([self.tag])) event_list = a_filter.apply(self.database, elist) if not event_list: return self.doc.start_paragraph("TR-Heading") header = self._("Events") mark = IndexMark(header, INDEX_TYPE_TOC, 2) self.doc.write_text(header, mark) self.doc.end_paragraph() self.doc.start_table('EventTable', 'TR-Table') self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Id")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Type")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Participants")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Date")) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() for event_handle in event_list: event = self.database.get_event_from_handle(event_handle) self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(event.get_gid()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(self._(self._get_type(event.get_type()))) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text( get_participant_from_event(self.database, event_handle)) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') date = self._get_date(event.get_date_object()) if date: self.doc.write_text(date) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() self.doc.end_table() def write_places(self): """ write the places associated with the tag """ plist = self.database.get_place_handles() filter_class = GenericFilterFactory('Place') a_filter = filter_class() a_filter.add_rule(rules.place.HasTag([self.tag])) place_list = a_filter.apply(self.database, plist) if not place_list: return self.doc.start_paragraph("TR-Heading") header = self._("Places") mark = IndexMark(header, INDEX_TYPE_TOC, 2) self.doc.write_text(header, mark) self.doc.end_paragraph() self.doc.start_table('PlaceTable', 'TR-Table') self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Id")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Title")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Name")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Type")) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() for place_handle in place_list: place = self.database.get_place_from_handle(place_handle) place_title = _pd.display(self.database, place) self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(place.get_gid()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(place_title) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(place.get_name()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(str(place.get_type())) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() self.doc.end_table() def write_notes(self): """ write the notes associated with the tag """ nlist = self.database.get_note_handles() filter_class = GenericFilterFactory('Note') a_filter = filter_class() a_filter.add_rule(rules.note.HasTag([self.tag])) note_list = a_filter.apply(self.database, nlist) if not note_list: return self.doc.start_paragraph("TR-Heading") header = self._("Notes") mark = IndexMark(header, INDEX_TYPE_TOC, 2) self.doc.write_text(header, mark) self.doc.end_paragraph() self.doc.start_table('NoteTable', 'TR-Table') self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Id")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Type")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell', 2) self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Text")) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() for note_handle in note_list: note = self.database.get_note_from_handle(note_handle) self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(note.get_gid()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') note_type = note.get_type() self.doc.write_text(str(note_type)) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell', 2) self.doc.write_styled_note( note.get_styledtext(), note.get_format(), 'TR-Note', contains_html=((note.get_type() == NoteType.HTML_CODE))) self.doc.end_cell() self.doc.end_row() self.doc.end_table() def write_media(self): """ write the media associated with the tag """ mlist = self.database.get_media_handles(sort_handles=True) filter_class = GenericFilterFactory('Media') a_filter = filter_class() a_filter.add_rule(rules.media.HasTag([self.tag])) media_list = a_filter.apply(self.database, mlist) if not media_list: return self.doc.start_paragraph("TR-Heading") header = self._("Media") mark = IndexMark(header, INDEX_TYPE_TOC, 2) self.doc.write_text(header, mark) self.doc.end_paragraph() self.doc.start_table('MediaTable', 'TR-Table') self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Id")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Title")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Type")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Date")) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() for media_handle in media_list: media = self.database.get_media_from_handle(media_handle) self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(media.get_gid()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') title = media.get_description() self.doc.write_text(str(title)) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') mime_type = media.get_mime_type() self.doc.write_text(str(mime_type)) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') date = self._get_date(media.get_date_object()) if date: self.doc.write_text(date) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() self.doc.end_table() def write_repositories(self): """ write the repositories associated with the tag """ rlist = self.database.get_repository_handles() filter_class = GenericFilterFactory('Repository') a_filter = filter_class() a_filter.add_rule(rules.repository.HasTag([self.tag])) repo_list = a_filter.apply(self.database, rlist) if not repo_list: return self.doc.start_paragraph("TR-Heading") header = self._("Repositories") mark = IndexMark(header, INDEX_TYPE_TOC, 2) self.doc.write_text(header, mark) self.doc.end_paragraph() self.doc.start_table('ReopTable', 'TR-Table') self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Id")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Name")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Type")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Email Address")) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() for repo_handle in repo_list: repo = self.database.get_repository_from_handle(repo_handle) self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(repo.get_gid()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(repo.get_name()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(str(repo.get_type())) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') home_page = '' for url in repo.get_url_list(): if url.get_type() == UrlType.EMAIL: home_page = url.get_path() break self.doc.write_text(home_page) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() self.doc.end_table() def write_sources(self): """ write the sources associated with the tag """ slist = self.database.get_source_handles(sort_handles=True) filter_class = GenericFilterFactory('Source') a_filter = filter_class() a_filter.add_rule(rules.source.HasTag([self.tag])) source_list = a_filter.apply(self.database, slist) if not source_list: return self.doc.start_paragraph("TR-Heading") header = self._("Source") mark = IndexMark(header, INDEX_TYPE_TOC, 2) self.doc.write_text(header, mark) self.doc.end_paragraph() self.doc.start_table('SourceTable', 'TR-Table') self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Id")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Title")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Author")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Publication Information")) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() for source_handle in source_list: source = self.database.get_source_from_handle(source_handle) self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(source.get_gid()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(source.get_title()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(source.get_author()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(source.get_publication_info()) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() self.doc.end_table() def write_citations(self): """ write the citations associated with the tag """ clist = self.database.get_citation_handles(sort_handles=True) filter_class = GenericFilterFactory('Citation') a_filter = filter_class() a_filter.add_rule(rules.citation.HasTag([self.tag])) citation_list = a_filter.apply(self.database, clist) if not citation_list: return self.doc.start_paragraph("TR-Heading") header = self._("Citations") mark = IndexMark(header, INDEX_TYPE_TOC, 2) self.doc.write_text(header, mark) self.doc.end_paragraph() self.doc.start_table('CitationTable', 'TR-Table') self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Id")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Volume/Page")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Date")) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal-Bold') self.doc.write_text(self._("Source")) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() for citation_handle in citation_list: citation = self.database.get_citation_from_handle(citation_handle) self.doc.start_row() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(citation.get_gid()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') self.doc.write_text(citation.get_page()) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') date = self._get_date(citation.get_date_object()) if date: self.doc.write_text(date) self.doc.end_paragraph() self.doc.end_cell() self.doc.start_cell('TR-TableCell') self.doc.start_paragraph('TR-Normal') source_handle = citation.get_reference_handle() source = self.database.get_source_from_handle(source_handle) self.doc.write_text(source.get_title()) self.doc.end_paragraph() self.doc.end_cell() self.doc.end_row() self.doc.end_table()
class TimeLine(Report): """ TimeLine Report """ def __init__(self, database, options, user): """ Create the Timeline object that produces the report. The arguments are: database - the GRAMPS database instance options - instance of the Options class for this report user - instance of gen.user.User() This report needs the following parameters (class variables) that come in the options class. filter - Filter to be applied to the people of the database. The option class carries its number, and the function returning the list of filters. sortby - Sorting method to be used. name_format - Preferred format to display names 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) self._user = user menu = options.menu lang = options.menu.get_option_by_name('trans').get_value() rlocale = self.set_locale(lang) stdoptions.run_private_data_option(self, menu) living_opt = stdoptions.run_living_people_option(self, menu, rlocale) self.database = CacheProxyDb(self.database) self.filter = menu.get_option_by_name('filter').get_filter() self.fil_name = "(%s)" % self.filter.get_name(rlocale) living_value = menu.get_option_by_name('living_people').get_value() 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 } stdoptions.run_name_format_option(self, menu) sort_func_num = menu.get_option_by_name('sortby').get_value() sort_functions = _get_sort_functions(Sort(self.database)) self.sort_name = self._(sort_functions[sort_func_num][0]) self.sort_func = sort_functions[sort_func_num][1] self.calendar = config.get('preferences.calendar-format-report') self.plist = [] self.header = 2.6 def write_report(self): # Apply the filter with self._user.progress(_('Timeline'), _('Applying filter...'), self.database.get_number_of_people()) as step: self.plist = self.filter.apply(self.database, self.database.iter_person_handles(), step) # Find the range of dates to include (low, high) = self.find_year_range() # Generate the actual timeline self.generate_timeline(low, high) def generate_timeline(self, low, high): """ generate the timeline """ st_size = self.name_size() style_sheet = self.doc.get_style_sheet() font = style_sheet.get_paragraph_style('TLG-Name').get_font() incr = utils.pt2cm(font.get_size()) pad = incr * 0.75 _x1, _x2, _y1, _y2 = (0, 0, 0, 0) start = st_size + 0.5 stop = self.doc.get_usable_width() - 0.5 size = stop - start self.header = 2.6 # Sort the people as requested with self._user.progress(_('Timeline'), _('Sorting dates...'), 0) as step: self.plist.sort(key=self.sort_func) self.doc.start_page() self.build_grid(low, high, start, stop, True) index = 1 current = 1 length = len(self.plist) with self._user.progress(_('Timeline'), _('Calculating timeline...'), length) as step: for p_id in self.plist: person = self.database.get_person_from_handle(p_id) birth = get_birth_or_fallback(self.database, person) if birth: bth = birth.get_date_object() bth = bth.to_calendar(self.calendar).get_year() else: bth = None death = get_death_or_fallback(self.database, person) if death: dth = death.get_date_object() dth = dth.to_calendar(self.calendar).get_year() else: dth = None dname = self._name_display.display(person) mark = utils.get_person_mark(self.database, person) self.doc.draw_text('TLG-text', dname, incr + pad, self.header + (incr + pad) * index, mark) _y1 = self.header + (pad + incr) * index _y2 = self.header + ((pad + incr) * index) + incr _y3 = (_y1 + _y2) / 2.0 w05 = 0.05 if bth: start_offset = ((float(bth - low) / float(high - low)) * size) _x1 = start + start_offset path = [(_x1, _y1), (_x1 + w05, _y3), (_x1, _y2), (_x1 - w05, _y3)] self.doc.draw_path('TLG-line', path) if dth: start_offset = ((float(dth - low) / float(high - low)) * size) _x1 = start + start_offset path = [(_x1, _y1), (_x1 + w05, _y3), (_x1, _y2), (_x1 - w05, _y3)] self.doc.draw_path('TLG-solid', path) if bth and dth: start_offset = ( (float(bth - low) / float(high - low)) * size) + w05 stop_offset = ( (float(dth - low) / float(high - low)) * size) - w05 _x1 = start + start_offset _x2 = start + stop_offset self.doc.draw_line('open', _x1, _y3, _x2, _y3) if (_y2 + incr) >= self.doc.get_usable_height(): if current != length: self.doc.end_page() self.doc.start_page() self.build_grid(low, high, start, stop) index = 1 _x1, _x2, _y1, _y2 = (0, 0, 0, 0) else: index += 1 current += 1 step() self.doc.end_page() def build_grid(self, year_low, year_high, start_pos, stop_pos, toc=False): """ Draws the grid outline for the chart. Sets the document label, draws the vertical lines, and adds the year labels. Arguments are: year_low - lowest year on the chart year_high - highest year on the chart start_pos - x position of the lowest leftmost grid line stop_pos - x position of the rightmost grid line """ self.draw_title(toc) self.draw_columns(start_pos, stop_pos) if year_high is not None and year_low is not None: self.draw_year_headings(year_low, year_high, start_pos, stop_pos) else: self.draw_no_date_heading() def draw_columns(self, start_pos, stop_pos): """ Draws the columns out of vertical lines. start_pos - x position of the lowest leftmost grid line stop_pos - x position of the rightmost grid line """ top_y = self.header bottom_y = self.doc.get_usable_height() delta = (stop_pos - start_pos) / 5 for val in range(0, 6): xpos = start_pos + (val * delta) self.doc.draw_line('TLG-grid', xpos, top_y, xpos, bottom_y) def draw_title(self, toc): """ Draws the title for the page. """ width = self.doc.get_usable_width() title = "%(str1)s -- %(str2)s" % { 'str1': self._("Timeline Chart"), # feature request 2356: avoid genitive form 'str2': self._("Sorted by %s") % self.sort_name } title3 = self.living_desc mark = None if toc: mark = IndexMark(title, INDEX_TYPE_TOC, 1) self.doc.center_text('TLG-title', title, width / 2.0, 0, mark) style_sheet = self.doc.get_style_sheet() title_font = style_sheet.get_paragraph_style('TLG-Title').get_font() title_y = 1.2 - (utils.pt2cm(title_font.get_size()) * 1.2) self.doc.center_text('TLG-title', self.fil_name, width / 2.0, title_y) title_y = 1.8 - (utils.pt2cm(title_font.get_size()) * 1.2) self.doc.center_text('TLG-title', title3, width / 2.0, title_y) def draw_year_headings(self, year_low, year_high, start_pos, stop_pos): """ Draws the column headings (years) for the page. """ style_sheet = self.doc.get_style_sheet() label_font = style_sheet.get_paragraph_style('TLG-Label').get_font() label_y = self.header - (utils.pt2cm(label_font.get_size()) * 1.2) incr = (year_high - year_low) / 5 delta = (stop_pos - start_pos) / 5 for val in range(0, 6): xpos = start_pos + (val * delta) year_str = str(int(year_low + (incr * val))) self.doc.center_text('TLG-label', year_str, xpos, label_y) def draw_no_date_heading(self): """ Draws a single heading that says "No Date Information" """ width = self.doc.get_usable_width() style_sheet = self.doc.get_style_sheet() label_font = style_sheet.get_paragraph_style('TLG-Label').get_font() label_y = self.header - (utils.pt2cm(label_font.get_size()) * 1.2) self.doc.center_text('TLG-label', self._("No Date Information"), width / 2.0, label_y) def find_year_range(self): """ Finds the range of years that will be displayed on the chart. Returns a tuple of low and high years. If no dates are found, the function returns (None, None). """ low = None high = None def min_max_year(low, high, year): """ convenience function """ if year is not None and year != 0: if low is not None: low = min(low, year) else: low = year if high is not None: high = max(high, year) else: high = year return (low, high) with self._user.progress(_('Timeline'), _('Finding date range...'), len(self.plist)) as step: for p_id in self.plist: person = self.database.get_person_from_handle(p_id) birth = get_birth_or_fallback(self.database, person) if birth: bth = birth.get_date_object() bth = bth.to_calendar(self.calendar).get_year() (low, high) = min_max_year(low, high, bth) death = get_death_or_fallback(self.database, person) if death: dth = death.get_date_object() dth = dth.to_calendar(self.calendar).get_year() (low, high) = min_max_year(low, high, dth) step() # round the dates to the nearest decade if low is not None: low = int((low / 10)) * 10 else: low = high if high is not None: high = int(((high + 9) / 10)) * 10 else: high = low # Make sure the difference is a multiple of 50 so # all year ranges land on a decade. if low is not None and high is not None: low -= 50 - ((high - low) % 50) return (low, high) def name_size(self): """ get the length of the name """ self.plist = self.filter.apply(self.database, self.database.iter_person_handles()) style_sheet = self.doc.get_style_sheet() gstyle = style_sheet.get_draw_style('TLG-text') pname = gstyle.get_paragraph_style() pstyle = style_sheet.get_paragraph_style(pname) font = pstyle.get_font() size = 0 for p_id in self.plist: person = self.database.get_person_from_handle(p_id) dname = self._name_display.display(person) size = max(self.doc.string_width(font, dname), size) return utils.pt2cm(size)