def run(database, document, *args, **kwargs): """ Loops through the families that the person is a child in, and display the information about the other children. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # display the title sdoc.title(_("All Names of All People")) sdoc.paragraph("") matches = 0 stab.columns(_("Name"), _("Primary Name"), _("Name Type")) names = [] # name, person for person in database.iter_people(): primary_name = person.get_primary_name() if primary_name: names += [(nd.display_name(primary_name), person, str(primary_name.get_type()))] names += [(nd.display_name(name), person, str(name.get_type())) for name in person.get_alternate_names()] matches = 0 for (name, person, name_type) in sorted(names, key=lambda x: x[0]): stab.row(name, person, name_type) matches += 1 sdoc.paragraph(_("Total names %d") % matches) sdoc.paragraph("") stab.write(sdoc)
def __init__(self, database, document, person): self.database = database self.person = person self.sdb = SimpleAccess(database) self.sdoc = SimpleDoc(document) self.rel_class = get_relationship_calculator(glocale) self.msg_list = []
def run(database, document, person): """ Display a person's timeline. """ sa = SimpleAccess(database) sd = SimpleDoc(document) sd.title(_("Timeline for %s") % sa.name(person)) sd.paragraph("") stab = QuickTable(sa) stab.columns(_("Date"), _("Event"), _("Age"), _("Place"), _("People involved")) stab.set_link_col(4) handled = {} birth_ref = gramps.gen.lib.Person.get_birth_ref(person) birth_date = get_event_date_from_ref(database, birth_ref) event_list = [] process(database, sa, event_list, handled, person, False, person) for (event, obj, desc) in sorted(event_list, key=by_date): edate = sa.event_date_obj(event) span_str, span_int = format_date(birth_date, edate, obj == person) if desc == None: desc = event stab.row(edate, desc, span_str, sa.event_place(event), obj) stab.row_sort_val(2, span_int) today = Today() span_str, span_int = format_date(birth_date, today, False) stab.row(today, _("Today"), span_str, "", person) stab.row_sort_val(2, span_int) stab.write(sd) sd.paragraph("")
def run(database, document, person): """ Loops through the families that the person is a child in, and display the information about the other children. """ global cache cache = {} # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # display the title sdoc.title(_("Descendant Count")) sdoc.paragraph("") stab.columns(_("Person"), _("Number of Descendants")) people = database.get_person_handles(sort_handles=True) for person_handle in people: result = countem(database, handle2internal(person_handle)) cache[person_handle] = len(result) matches = 0 for person_handle in cache: person = database.get_person_from_handle(person_handle) stab.row(person, cache[person_handle]) matches += 1 sdoc.paragraph(_("There are %d people.\n") % matches) stab.write(sdoc)
def run_fam(database, document, family): """ Loops through the family events and the events of all parents, displaying the basic details of the event """ sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # get the family events event_list = [(_('Family'), x) for x in sdb.events(family)] # get the events of father and mother #fathername = sdb.first_name(sdb.father(family)) event_list += [(sdb.father(family), x) for x in sdb.events(sdb.father(family))] #mothername = sdb.first_name(sdb.mother(family)) event_list += [(sdb.mother(family), x) for x in sdb.events(sdb.mother(family))] # children events event_list_children = [] for child in sdb.children(family): #name = sdb.first_name(child) event_list_children += [(child, x) for x in sdb.events(child)] # Sort the events by their date event_list.sort(key=lambda x: x[1].get_date_object()) event_list_children.sort(key=lambda x: x[1].get_date_object()) # display the results sdoc.title( _("Sorted events of family\n %(father)s - %(mother)s") % { 'father': sdb.name(sdb.father(family)), 'mother': sdb.name(sdb.mother(family)) }) sdoc.paragraph("") document.has_data = False stab.columns(_("Family Member"), _("Event Type"), _("Event Date"), _("Event Place")) for (person, event) in event_list: stab.row(person, sdb.event_type(event), sdb.event_date_obj(event), sdb.event_place(event)) document.has_data = True stab.write(sdoc) stab = QuickTable(sdb) sdoc.header1(_("Personal events of the children")) stab.columns(_("Family Member"), _("Event Type"), _("Event Date"), _("Event Place")) for (person, event) in event_list_children: stab.row(person, sdb.event_type(event), sdb.event_date_obj(event), sdb.event_place(event)) document.has_data = True stab.write(sdoc)
def eval(self): """ Execute the query. """ self.sdb = SimpleAccess(self.database) self.stab = QuickTable(self.sdb) self.select = 0 start_time = time.time() self.process_table(self.stab) # a class that has .row(1, 2, 3, ...) if self.select > 0: self.stab.columns(*self.clean_titles(self.columns)) self.sdoc = SimpleDoc(self.document) self.sdoc.title(self.query_text) self.sdoc.paragraph("\n") self.sdoc.paragraph("%d rows processed in %s seconds.\n" % (self.select, time.time() - start_time)) self.stab.write(self.sdoc) self.sdoc.paragraph("") return _("%d rows processed in %s seconds.\n") % (self.select, time.time() - start_time)
def run(database, document, repo): """ Display back-references (sources) for this repository. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # First we find repository and add its text sdoc.title('%s\n' % repo.get_name()) # Go over all the sources that refer to this repository repo_handle = repo.handle source_list = [item[1] for item in database.find_backlink_handles(repo_handle, ['Source' ])] stab.columns(_("Source"), _("Type of media"), _("Call number")) document.has_data = False for source_handle in source_list: src = database.get_source_from_handle(source_handle) # Get the list of references from this source to our repo # (can be more than one, technically) for reporef in src.get_reporef_list(): if reporef.ref == repo_handle: # Determine the text for this source media = str(reporef.get_media_type()) call = reporef.get_call_number() stab.row(src.get_title(), media, call) document.has_data = True if document.has_data: stab.write(sdoc) else: sdoc.header1(_("Not found"))
def run(database, document, repo): """ Display back-references (sources) for this repository. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # First we find repository and add its text sdoc.title('%s\n' % repo.get_name()) # Go over all the sources that refer to this repository repo_handle = repo.handle source_list = [ item[1] for item in database.find_backlink_handles(repo_handle, ['Source']) ] stab.columns(_("Source"), _("Type of media"), _("Call number")) document.has_data = False for source_handle in source_list: src = database.get_source_from_handle(source_handle) # Get the list of references from this source to our repo # (can be more than one, technically) for reporef in src.get_reporef_list(): if reporef.ref == repo_handle: # Determine the text for this source media = str(reporef.get_media_type()) call = reporef.get_call_number() stab.row(src.get_title(), media, call) document.has_data = True stab.write(sdoc)
def run_fam(database, document, family): """ Loops through the family events and the events of all parents, displaying the basic details of the event """ sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # get the family events event_list = [(_('Family'), x) for x in sdb.events(family)] # get the events of father and mother #fathername = sdb.first_name(sdb.father(family)) event_list += [(sdb.father(family), x) for x in sdb.events(sdb.father(family))] #mothername = sdb.first_name(sdb.mother(family)) event_list += [(sdb.mother(family), x) for x in sdb.events(sdb.mother(family))] # children events event_list_children = [] for child in sdb.children(family) : #name = sdb.first_name(child) event_list_children += [(child, x) for x in sdb.events(child)] # Sort the events by their date event_list.sort(key=lambda x: x[1].get_date_object()) event_list_children.sort(key=lambda x: x[1].get_date_object()) # display the results sdoc.title(_("Sorted events of family\n %(father)s - %(mother)s") % { 'father' : sdb.name(sdb.father(family)), 'mother' : sdb.name(sdb.mother(family)) }) sdoc.paragraph("") document.has_data = False stab.columns(_("Family Member"), _("Event Type"), _("Event Date"), _("Event Place")) for (person, event) in event_list: stab.row(person, sdb.event_type(event), sdb.event_date_obj(event), sdb.event_place(event)) document.has_data = True stab.write(sdoc) stab = QuickTable(sdb) sdoc.header1(_("Personal events of the children")) stab.columns(_("Family Member"), _("Event Type"), _("Event Date"), _("Event Place")) for (person, event) in event_list_children: stab.row(person, sdb.event_type(event), sdb.event_date_obj(event), sdb.event_place(event)) document.has_data = True stab.write(sdoc)
def run(database, document, person): """ Loops through the person events and the family events of any family in which the person is a parent (to catch Marriage events), displaying the basic details of the event """ sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # get the personal events event_list = sdb.events(person) # get the events of each family in which the person is # a parent for family in sdb.parent_in(person): event_list += sdb.events(family) # Sort the events by their date event_list.sort(key=lambda x: x.get_date_object()) # display the results # feature request 2356: avoid genitive form sdoc.title(_("Sorted events of %s") % sdb.name(person)) sdoc.paragraph("") stab.columns(_("Event Type"), _("Event Date"), _("Event Place")) document.has_data = False for event in event_list: stab.row(event, sdb.event_date_obj(event), sdb.event_place(event)) document.has_data = True stab.write(sdoc)
def run(database, document, person): """ Loops through the families that the person is a child in, and display the information about the other children. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) rel_class = get_relationship_calculator(glocale) # display the title # feature request 2356: avoid genitive form sdoc.title(_("Siblings of %s") % sdb.name(person)) sdoc.paragraph("") stab.columns(_("Sibling"), _("Gender"), _("Birth Date"), _("Type")) # grab our current id (self): gid = sdb.gid(person) # loop through each family in which the person is a child document.has_data = False for family in sdb.child_in(person): # loop through each child in the family for child in sdb.children(family): # only display if this child is not the active person if sdb.gid(child) != gid: rel_str = rel_class.get_sibling_relationship_string( rel_class.get_sibling_type(database, person, child), person.get_gender(), child.get_gender()) else: rel_str = _('self') # pass row the child object to make link: stab.row(child, sdb.gender(child), sdb.birth_or_fallback(child), rel_str) document.has_data = True stab.write(sdoc)
def run(database, document, attribute, value=None): sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) sdoc.title(_("People who have the '%s' Attribute") % attribute) sdoc.paragraph("") stab.columns(_("Person"), str(attribute)) matches = 0 for person_handle in database.iter_person_handles(): person = database.get_person_from_handle(person_handle) matched = False for attr in person.attribute_list: if str(attr.type) == attribute: stab.row(person, str(attr.get_value())) matched = True if matched: matches += 1 document.has_data = matches > 0 sdoc.paragraph( _("There are %d people with a matching attribute name.\n") % matches) if document.has_data: stab.write(sdoc) else: sdoc.header1(_("Not found"))
def run_given(database, document, person): """ Loops through the families that the person is a child in, and displays the information about the other children. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) if isinstance(person, Person): rgivenname = person.get_primary_name().get_first_name() else: rgivenname = person if " " in rgivenname.strip(): rgivenname, second = rgivenname.strip().split(" ", 1) # display the title sdoc.title(_("People with the given name '%s'") % rgivenname) sdoc.paragraph("") stab.columns(_("Person"), _("Birth Date"), _("Name type")) filter = GenericFilterFactory('Person')() if rgivenname != '': rule = SameGiven([rgivenname]) else: rule = IncompleteGiven([]) filter.add_rule(rule) people = filter.apply(database, database.iter_person_handles()) matches = 0 for person_handle in people: person = database.get_person_from_handle(person_handle) stab.row(person, sdb.birth_or_fallback(person), str(person.get_primary_name().get_type())) matches += 1 document.has_data = matches > 0 sdoc.paragraph( # Translators: leave all/any {...} untranslated ngettext( "There is {number_of} person " "with a matching name, or alternate name.\n", "There are {number_of} people " "with a matching name, or alternate name.\n", matches).format(number_of=matches)) stab.write(sdoc)
def run(database, document, attribute, value=None): sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) sdoc.title(_("People who have the '%s' Attribute") % attribute) sdoc.paragraph("") stab.columns(_("Person"), str(attribute)) matches = 0 for person_handle in database.iter_person_handles(): person = database.get_person_from_handle(person_handle) matched = False for attr in person.attribute_list: if str(attr.type) == attribute: stab.row(person, str(attr.get_value())) matched = True if matched: matches += 1 document.has_data = matches > 0 sdoc.paragraph(_("There are %d people with a matching attribute name.\n") % matches) if document.has_data: stab.write(sdoc) else: sdoc.header1(_("Not found"))
def run(database, document, person): """Handle quick view report generation.""" sdoc = SimpleDoc(document) name = gramps.gen.display.name.displayer.display(person) sdoc.title(_("Number of %s's ancestors") % name) sdoc.paragraph("") stab = QuickTable(document) stab.columns(_("Generation"), _("Found"), _("Theoretical"), _("Percent")) num_lst = count_ancestors(database, person) for entry in num_lst[1:-1]: stab.row(*entry) stab.write(sdoc) vals = num_lst[-1][1:] sdoc.paragraph( _("There were {} of {} ancestors ({}) found.\n" "Only individual ancestors were counted. Duplicates " "caused by pedigree collapse were ignored.").format(*vals))
def run(database, document, person): """ Loops through the families that the person is a child in, and displays the information about the other children. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) if isinstance(person, Person): surname = sdb.surname(person) rsurname = person.get_primary_name().get_group_name() else: surname = person rsurname = person # display the title sdoc.title(_("People sharing the surname '%s'") % surname) sdoc.paragraph("") stab.columns(_("Person"), _("Birth Date"), _("Name type")) filter = GenericFilterFactory('Person')() if rsurname != '': rule = SameSurname([rsurname]) else: rule = IncompleteSurname([]) filter.add_rule(rule) people = filter.apply(database, database.iter_person_handles()) matches = 0 for person_handle in people: person = database.get_person_from_handle(person_handle) stab.row(person, sdb.birth_or_fallback(person), str(person.get_primary_name().get_type())) matches += 1 document.has_data = matches > 0 sdoc.paragraph( # translators: leave all/any {...} untranslated ngettext("There is {number_of} person " "with a matching name, or alternate name.\n", "There are {number_of} people " "with a matching name, or alternate name.\n", matches ).format(number_of=matches) ) stab.write(sdoc)
def run(database, document, obj): """ Display link references for this note. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # display the title sdoc.title(_("Link References for this note")) sdoc.paragraph("\n") stab.columns(_("Type"), _("Reference"), _("Link check")) for (ldomain, ltype, lprop, lvalue) in obj.get_links(): if ldomain == "gramps": tagtype = _(ltype) ref_obj = sdb.get_link(ltype, lprop, lvalue) if ref_obj: tagvalue = ref_obj tagcheck = _("Ok") else: tagvalue = lvalue tagcheck = _("Failed: missing object") else: tagtype = _("Internet") tagvalue = lvalue tagcheck = "" stab.row(tagtype, tagvalue, tagcheck) if stab.get_row_count() > 0: stab.write(sdoc) document.has_data = True else: sdoc.paragraph(_("No link references for this note")) sdoc.paragraph("") document.has_data = False sdoc.paragraph("")
def run(database, document, date): """ Display people probably alive and their ages on a particular date. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) if not date.get_valid(): sdoc.paragraph("Date is not a valid date.") return # display the title if date.get_day_valid(): sdoc.title(_("People and their ages the %s") % displayer.display(date)) else: sdoc.title(_("People and their ages on %s") % displayer.display(date)) stab.columns(_("Person"), _("Age"), _("Status")) # Actual Date makes column unicode alive_matches = 0 dead_matches = 0 for person in sdb.all_people(): alive, birth, death, explain, relative = \ probably_alive(person, database, date, return_range=True) # Doesn't show people probably alive but no way of figuring an age: if alive: if birth: diff_span = (date - birth) stab.row(person, str(diff_span), _("Alive: %s") % explain) stab.row_sort_val(1, int(diff_span)) else: stab.row(person, "", _("Alive: %s") % explain) stab.row_sort_val(1, 0) alive_matches += 1 else: # not alive if birth: diff_span = (date - birth) stab.row(person, str(diff_span), _("Deceased: %s") % explain) stab.row_sort_val(1, int(diff_span)) else: stab.row(person, "", _("Deceased: %s") % explain) stab.row_sort_val(1, 1) dead_matches += 1 document.has_data = (alive_matches + dead_matches) > 0 sdoc.paragraph( _("\nLiving matches: %(alive)d, " "Deceased matches: %(dead)d\n") % { 'alive': alive_matches, 'dead': dead_matches }) stab.write(sdoc) sdoc.paragraph("")
def run(database, document, filter_name, *args, **kwargs): """ Loops through the families that the person is a child in, and display the information about the other children. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) if (filter_name == 'all'): sdoc.title(_("Summary counts of current selection")) sdoc.paragraph("") sdoc.paragraph(_("Right-click row (or press ENTER) to see selected items.")) sdoc.paragraph("") stab.columns(_("Object"), _("Count/Total")) if hasattr(database, "db"): stab.row([_("People"), "Filter", "Person"], "%d/%d" % (len(database.get_person_handles()), len(database.db.get_person_handles()))) stab.row([_("Families"), "Filter", "Family"], "%d/%d" % (len(database.get_family_handles()), len(database.db.get_family_handles()))) stab.row([_("Events"), "Filter", "Event"], "%d/%d" % (len(database.get_event_handles()), len(database.db.get_event_handles()))) stab.row([_("Places"), "Filter", "Place"], "%d/%d" % (len(database.get_place_handles()), len(database.db.get_place_handles()))) stab.row([_("Sources"), "Filter", "Source"], "%d/%d" % (len(database.get_source_handles()), len(database.db.get_source_handles()))) stab.row([_("Repositories"), "Filter", "Repository"], "%d/%d" % (len(database.get_repository_handles()), len(database.db.get_repository_handles()))) stab.row([_("Media"), "Filter", "MediaObject"], "%d/%d" % (len(database.get_media_object_handles()), len(database.db.get_media_object_handles()))) stab.row([_("Notes"), "Filter", "Note"], "%d/%d" % (len(database.get_note_handles()), len(database.db.get_note_handles()))) else: stab.row([_("People"), "Filter", "Person"], "%d/%d" % (len(database.get_person_handles()), len(database.basedb.get_person_handles()))) stab.row([_("Families"), "Filter", "Family"], "%d/%d" % (len(database.get_family_handles()), len(database.basedb.get_family_handles()))) stab.row([_("Events"), "Filter", "Event"], "%d/%d" % (len(database.get_event_handles()), len(database.basedb.get_event_handles()))) stab.row([_("Places"), "Filter", "Place"], "%d/%d" % (len(database.get_place_handles()), len(database.basedb.get_place_handles()))) stab.row([_("Sources"), "Filter", "Source"], "%d/%d" % (len(database.get_source_handles()), len(database.basedb.get_source_handles()))) stab.row([_("Repositories"), "Filter", "Repository"], "%d/%d" % (len(database.get_repository_handles()), len(database.basedb.get_repository_handles()))) stab.row([_("Media"), "Filter", "MediaObject"], "%d/%d" % (len(database.get_media_object_handles()), len(database.basedb.get_media_object_handles()))) stab.row([_("Notes"), "Filter", "Note"], "%d/%d" % (len(database.get_note_handles()), len(database.basedb.get_note_handles()))) sdoc.paragraph("") stab.write(sdoc) return # display the title if filter_name in fname_map: sdoc.title(_("Filtering on %s") % fname_map[filter_name]) # listed above else: sdoc.title(_("Filtering on %s") % _(filter_name)) sdoc.paragraph("") matches = 0 if (filter_name == 'Inverse Person'): sdb.dbase = database.db stab.columns(_("Person"), _("Gramps ID"), _("Birth Date")) proxy_handles = set(database.iter_person_handles()) for person in database.db.iter_people(): if person.handle not in proxy_handles: stab.row(person, person.gramps_id, sdb.birth_or_fallback(person)) matches += 1 elif (filter_name == 'Inverse Family'): sdb.dbase = database.db stab.columns(_("Family"), _("Gramps ID")) proxy_handles = set(database.iter_family_handles()) for family in database.db.iter_families(): if family.handle not in proxy_handles: stab.row(family, family.gramps_id) matches += 1 elif (filter_name == 'Inverse Event'): sdb.dbase = database.db stab.columns(_("Event"), _("Gramps ID")) proxy_handles = set(database.iter_event_handles()) for event in database.db.iter_events(): if event.handle not in proxy_handles: stab.row(event, event.gramps_id) matches += 1 elif (filter_name == 'Inverse Place'): sdb.dbase = database.db stab.columns(_("Place"), _("Gramps ID")) proxy_handles = set(database.iter_place_handles()) for place in database.db.iter_places(): if place.handle not in proxy_handles: stab.row(place, place.gramps_id) matches += 1 elif (filter_name == 'Inverse Source'): sdb.dbase = database.db stab.columns(_("Source"), _("Gramps ID")) proxy_handles = set(database.iter_source_handles()) for source in database.db.iter_sources(): if source.handle not in proxy_handles: stab.row(source, source.gramps_id) matches += 1 elif (filter_name == 'Inverse Repository'): sdb.dbase = database.db stab.columns(_("Repository"), _("Gramps ID")) proxy_handles = set(database.iter_repository_handles()) for repository in database.db.iter_repositories(): if repository.handle not in proxy_handles: stab.row(repository, repository.gramps_id) matches += 1 elif (filter_name == 'Inverse MediaObject'): sdb.dbase = database.db stab.columns(_("Media"), _("Gramps ID")) proxy_handles = set(database.iter_media_object_handles()) for media in database.db.iter_media_objects(): if media.handle not in proxy_handles: stab.row(media, media.gramps_id) matches += 1 elif (filter_name == 'Inverse Note'): sdb.dbase = database.db stab.columns(_("Note"), _("Gramps ID")) proxy_handles = set(database.iter_note_handles()) for note in database.db.iter_notes(): if note.handle not in proxy_handles: stab.row(note, note.gramps_id) matches += 1 elif (filter_name in ['all people', 'Person']): stab.columns(_("Person"), _("Gramps ID"), _("Birth Date")) for person in database.iter_people(): stab.row(person, person.gramps_id, sdb.birth_or_fallback(person)) matches += 1 elif (filter_name in ['all families', 'Family']): stab.columns(_("Family"), _("Gramps ID")) for family in database.iter_families(): stab.row(family, family.gramps_id) matches += 1 elif (filter_name in ['all events', 'Event']): stab.columns(_("Event"), _("Gramps ID")) for obj in database.iter_events(): stab.row(obj, obj.gramps_id) matches += 1 elif (filter_name in ['all places', 'Place']): stab.columns(_("Place"), _("Gramps ID")) for obj in database.iter_places(): stab.row(obj, obj.gramps_id) matches += 1 elif (filter_name in ['all sources', 'Source']): stab.columns(_("Source"), _("Gramps ID")) for obj in database.iter_sources(): stab.row(obj, obj.gramps_id) matches += 1 elif (filter_name in ['all repositories', 'Repository']): stab.columns(_("Repository"), _("Gramps ID")) for obj in database.iter_repositories(): stab.row(obj, obj.gramps_id) matches += 1 elif (filter_name in ['all media', 'MediaObject']): stab.columns(_("Media"), _("Gramps ID")) for obj in database.iter_media_objects(): stab.row(obj, obj.gramps_id) matches += 1 elif (filter_name in ['all notes', 'Note']): stab.columns(_("Note"), _("Gramps ID")) for obj in database.iter_notes(): stab.row(obj, obj.gramps_id) matches += 1 elif (filter_name == 'males'): stab.columns(_("Person"), _("Birth Date"), _("Name type")) for person in database.iter_people(): if person.gender == Person.MALE: stab.row(person, sdb.birth_or_fallback(person), str(person.get_primary_name().get_type())) matches += 1 elif (filter_name == 'females'): stab.columns(_("Person"), _("Birth Date"), _("Name type")) for person in database.iter_people(): if person.gender == Person.FEMALE: stab.row(person, sdb.birth_or_fallback(person), str(person.get_primary_name().get_type())) matches += 1 elif (filter_name == 'people with unknown gender'): stab.columns(_("Person"), _("Birth Date"), _("Name type")) for person in database.iter_people(): if person.gender not in [Person.FEMALE, Person.MALE]: stab.row(person, sdb.birth_or_fallback(person), str(person.get_primary_name().get_type())) matches += 1 elif (filter_name == 'incomplete names'): stab.columns(_("Name"), _("Birth Date"), _("Name type")) for person in database.iter_people(): for name in [person.get_primary_name()] + person.get_alternate_names(): if name.get_first_name().strip() == "": stab.row([name.get_name(), "Person", person.handle], sdb.birth_or_fallback(person), str(name.get_type())) matches += 1 else: if name.get_surname_list(): for surname in name.get_surname_list(): if surname.get_surname().strip() == "": stab.row([name.get_first_name(), "Person", person.handle], sdb.birth_or_fallback(person), str(name.get_type())) matches += 1 else: stab.row([name.get_first_name(), "Person", person.handle], sdb.birth_or_fallback(person), str(name.get_type())) matches += 1 elif (filter_name == 'people with missing birth dates'): stab.columns(_("Person"), _("Type")) for person in database.iter_people(): birth_ref = person.get_birth_ref() if birth_ref: birth = database.get_event_from_handle(birth_ref.ref) if not get_date(birth): stab.row(person, _("birth event but no date")) matches += 1 else: stab.row(person, _("missing birth event")) matches += 1 elif (filter_name == 'disconnected people'): stab.columns(_("Person"), _("Birth Date"), _("Name type")) for person in database.iter_people(): if ((not person.get_main_parents_family_handle()) and (not len(person.get_family_handle_list()))): stab.row(person, sdb.birth_or_fallback(person), str(person.get_primary_name().get_type())) matches += 1 elif (filter_name == 'unique surnames'): namelist = defaultdict(int) for person in database.iter_people(): names = [person.get_primary_name()] + person.get_alternate_names() surnames = list(set([name.get_group_name() for name in names])) for surname in surnames: namelist[surname] += 1 stab.columns(_("Surname"), _("Count")) for name in sorted(namelist): stab.row(name, namelist[name]) matches += 1 stab.set_callback("leftdouble", lambda name: run_quick_report_by_name_direct("samesurnames", database, document, name)) elif (filter_name == 'people with media'): stab.columns(_("Person"), _("Media count")) for person in database.iter_people(): length = len(person.get_media_list()) if length > 0: stab.row(person, str(length)) matches += 1 elif (filter_name == 'media references'): stab.columns(_("Person"), _("Reference")) for person in database.iter_people(): medialist = person.get_media_list() for item in medialist: stab.row(person, _("media")) matches += 1 elif (filter_name == 'unique media'): stab.columns(_("Unique Media")) for photo in database.iter_media_objects(): fullname = media_path_full(database, photo.get_path()) stab.row(fullname) matches += 1 elif (filter_name == 'missing media'): stab.columns(_("Missing Media")) for photo in database.iter_media_objects(): fullname = media_path_full(database, photo.get_path()) try: posixpath.getsize(fullname) except: stab.row(fullname) matches += 1 elif (filter_name == 'media by size'): stab.columns(_("Media"), _("Size in bytes")) for photo in database.iter_media_objects(): fullname = media_path_full(database, photo.get_path()) try: bytes = posixpath.getsize(fullname) stab.row(fullname, str(bytes)) matches += 1 except: pass elif (filter_name == 'list of people'): stab.columns(_("Person"), _("Birth Date"), _("Name type")) handles = kwargs["handles"] for person_handle in handles: person = database.get_person_from_handle(person_handle) stab.row(person, sdb.birth_or_fallback(person), str(person.get_primary_name().get_type())) matches += 1 else: raise AttributeError("invalid filter name: '%s'" % filter_name) # translators: leave all/any {...} untranslated sdoc.paragraph(ngettext("Filter matched {number_of} record.", "Filter matched {number_of} records.", matches ).format(number_of=matches) ) sdoc.paragraph("") document.has_data = matches > 0 if matches > 0: stab.write(sdoc)
def run(database, document, main_event): """ Displays events on a specific date of an event (or date) Takes an Event or Date object """ if isinstance(main_event, Date): main_date = main_event else: main_date = main_event.get_date_object() cal = main_date.get_calendar(); # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) stab.set_link_col(3) yeartab = QuickTable(sdb) yeartab.set_link_col(3) histab = QuickTable(sdb) histab.set_link_col(3) # display the title sdoc.title(_("Events of %(date)s") % {"date": sdb.date_string(main_date)}) sdoc.paragraph("") stab.columns(_("Date"), _("Type"), _("Place"), _("Reference")) yeartab.columns(_("Date"), _("Type"), _("Place"), _("Reference")) histab.columns(_("Date"), _("Type"), _("Place"), _("Reference")) for event in database.iter_events(): date = event.get_date_object() date.convert_calendar(cal) if date.get_year() == 0: continue if (date.get_year() == main_date.get_year() and date.get_month() == main_date.get_month() and date.get_day() == main_date.get_day()): for (objclass, handle) in database.find_backlink_handles(event.handle): ref = get_ref(database, objclass, handle) stab.row(date, sdb.event_type(event), sdb.event_place(event), ref) elif (date.get_month() == main_date.get_month() and date.get_day() == main_date.get_day() and date.get_month() != 0): for (objclass, handle) in database.find_backlink_handles(event.handle): ref = get_ref(database, objclass, handle) histab.row(date, sdb.event_type(event), sdb.event_place(event), ref) elif (date.get_year() == main_date.get_year()): for (objclass, handle) in database.find_backlink_handles(event.handle): ref = get_ref(database, objclass, handle) yeartab.row(date, sdb.event_type(event), sdb.event_place(event), ref) document.has_data = False if stab.get_row_count() > 0: document.has_data = True sdoc.paragraph(_("Events on this exact date")) stab.write(sdoc) else: sdoc.paragraph(_("No events on this exact date")) sdoc.paragraph("") sdoc.paragraph("") if histab.get_row_count() > 0: document.has_data = True sdoc.paragraph(_("Other events on this month/day in history")) histab.write(sdoc) else: sdoc.paragraph(_("No other events on this month/day in history")) sdoc.paragraph("") sdoc.paragraph("") if yeartab.get_row_count() > 0: document.has_data = True sdoc.paragraph(_("Other events in %(year)d") % {"year":main_date.get_year()}) yeartab.write(sdoc) else: sdoc.paragraph(_("No other events in %(year)d") % {"year":main_date.get_year()}) sdoc.paragraph("") sdoc.paragraph("")
def run(database, document, object, item, trans): """ Display back-references for this object. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # display the title sdoc.title(_("References for this %s") % trans) sdoc.paragraph("\n") stab.columns(_("Type"), _("Reference")) for (objclass, handle) in database.find_backlink_handles(object.handle): ref = get_ref(database, objclass, handle) stab.row(_(objclass), ref) # translation are explicit (above) if stab.get_row_count() > 0: document.has_data = True stab.write(sdoc) else: document.has_data = False sdoc.paragraph(_("No references for this %s") % trans) sdoc.paragraph("") sdoc.paragraph("")
def run_mother(database, document, person): """ Function writing the mother lineage quick report """ sa = SimpleAccess(database) sd = SimpleDoc(document) # display the results # feature request 2356: avoid genitive form sd.title(_("Mother lineage for %s") % sa.name(person)) sd.paragraph("") sd.paragraph( _("" "This report shows the mother lineage, also called matronymic lineage " "mtDNA lineage." " People in this lineage all share the same Mitochondrial DNA (mtDNA)." )) sd.paragraph("") stab = QuickTable(sa) stab.columns(_("Name Mother"), _("Birth"), _("Death Date"), _("Remark")) make_details(Person.FEMALE, person, sa, sd, database, stab) stab.write(sd) sd.paragraph("") if person.gender == Person.MALE: return sd.header2((_("Direct line female descendants"))) sd.paragraph("") make_details_child(Person.FEMALE, person, sa, sd, database)
def run_mother(database, document, person): """ Function writing the mother lineage quick report """ sa = SimpleAccess(database) sd = SimpleDoc(document) # display the results # feature request 2356: avoid genitive form sd.title(_("Mother lineage for %s") % sa.name(person)) sd.paragraph("") sd.paragraph(_("" "This report shows the mother lineage, also called matronymic lineage " "mtDNA lineage." " People in this lineage all share the same Mitochondrial DNA (mtDNA)." )) sd.paragraph("") stab = QuickTable(sa) stab.columns(_("Name Mother"), _("Birth"), _("Death Date"), _("Remark")) make_details(Person.FEMALE, person, sa, sd, database, stab) stab.write(sd) sd.paragraph("") if person.gender == Person.MALE : return sd.header2((_("Direct line female descendants"))) sd.paragraph("") make_details_child(Person.FEMALE, person, sa, sd, database)
def run(database, document, main_event): """ Displays events on a specific date of an event (or date) Takes an Event or Date object """ if isinstance(main_event, Date): main_date = main_event else: main_date = main_event.get_date_object() cal = main_date.get_calendar() # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) stab.set_link_col(3) yeartab = QuickTable(sdb) yeartab.set_link_col(3) histab = QuickTable(sdb) histab.set_link_col(3) # display the title sdoc.title(_("Events of %(date)s") % {"date": sdb.date_string(main_date)}) sdoc.paragraph("") stab.columns(_("Date"), _("Type"), _("Place"), _("Reference")) yeartab.columns(_("Date"), _("Type"), _("Place"), _("Reference")) histab.columns(_("Date"), _("Type"), _("Place"), _("Reference")) for event in database.iter_events(): date = event.get_date_object() date.convert_calendar(cal) if date.get_year() == 0: continue if (date.get_year() == main_date.get_year() and date.get_month() == main_date.get_month() and date.get_day() == main_date.get_day()): for (objclass, handle) in database.find_backlink_handles(event.handle): ref = get_ref(database, objclass, handle) stab.row(date, sdb.event_type(event), sdb.event_place(event), ref) elif (date.get_month() == main_date.get_month() and date.get_day() == main_date.get_day() and date.get_month() != 0): for (objclass, handle) in database.find_backlink_handles(event.handle): ref = get_ref(database, objclass, handle) histab.row(date, sdb.event_type(event), sdb.event_place(event), ref) elif (date.get_year() == main_date.get_year()): for (objclass, handle) in database.find_backlink_handles(event.handle): ref = get_ref(database, objclass, handle) yeartab.row(date, sdb.event_type(event), sdb.event_place(event), ref) document.has_data = False if stab.get_row_count() > 0: document.has_data = True sdoc.paragraph(_("Events on this exact date")) stab.write(sdoc) else: sdoc.paragraph(_("No events on this exact date")) sdoc.paragraph("") sdoc.paragraph("") if histab.get_row_count() > 0: document.has_data = True sdoc.paragraph(_("Other events on this month/day in history")) histab.write(sdoc) else: sdoc.paragraph(_("No other events on this month/day in history")) sdoc.paragraph("") sdoc.paragraph("") if yeartab.get_row_count() > 0: document.has_data = True sdoc.paragraph( _("Other events in %(year)d") % {"year": main_date.get_year()}) yeartab.write(sdoc) else: sdoc.paragraph( _("No other events in %(year)d") % {"year": main_date.get_year()}) sdoc.paragraph("") sdoc.paragraph("")
class DBI(object): """ The SQL-like interface to the database and document instances. """ def __init__(self, database, document=None): self.database = database self.document = document self.data = {} self.select = 0 self.flat = False self.raw = False if self.database: for name in self.database.get_table_names(): d = self.database._tables[name]["class_func"]().to_struct() self.data[name.lower()] = d.keys() # The macros: self.shortcuts = { "SURNAME": "primary_name.surname_list[0].surname", "GIVEN": "primary_name.first_name", } def parse(self, query): """ Parse the query. """ self.query_text = query.replace("\n", " ").strip() lexed = self.lexer(self.query_text) #print(lexed) self.parser(lexed) for col_name in self.columns[:]: # copy if col_name == "*": self.columns.remove('*') # this is useful to see what _class it is: self.columns.extend(self.get_columns(self.table)) # otherwise remove metadata: #self.columns.extend([col for col in self.get_columns(self.table) if not col.startswith("_")) def lexer(self, string): """ Given a string, break into a list of chunks. """ retval = [] state = None current = "" stack = [] i = 0 # Handle macros: for key in self.shortcuts.keys(): string = string.replace(key, self.shortcuts[key]) # (some "expression" in ok) # func(some "expression" in (ok)) # list[1][0] # [x for x in list] while i < len(string): ch = string[i] #print("lex:", i, ch, state, retval, current) if state == "in-double-quote": if ch == '"': state = stack.pop() current += ch elif state == "in-single-quote": if ch == "'": state = stack.pop() current += ch elif state == "in-expr": if ch == ")": state = stack.pop() elif ch == "(": stack.append("in-expr") current += ch elif state == "in-square-bracket": if ch == "]": state = stack.pop() elif ch == "[": stack.append("in-square-bracket") current += ch elif ch == '"': stack.append(state) state = "in-double-quote" current += ch elif ch == "'": stack.append(state) state = "in-single-quote" current += ch elif ch == "(": stack.append(state) state = "in-expr" current += "(" elif ch == "[": stack.append(state) state = "in-square-bracket" current += "[" elif ch == ",": if current: retval.append(current) retval.append(",") current = "" elif ch == "=": if current: retval.append(current) retval.append("=") current = "" elif ch in [' ', '\t', '\n', ";"]: # break if current: retval.append(current) if current.upper() == "WHERE": # HACK: get rest of string: if string[-1] == ";": retval.append(string[i + 1:-1]) i = len(string) - 2 else: retval.append(string[i + 1:]) i = len(string) - 1 current = "" else: pass # ignore whitespace else: current += ch i += 1 if current: retval.append(current) #print("lexed:", retval) return retval def parser(self, lex): """ Takes output of lexer, and sets the values. After parser, the DBI will be ready to process query. """ self.action = None self.table = None self.columns = [] self.setcolumns = [] self.values = [] self.aliases = {} self.limit = None self.where = None self.index = 0 while self.index < len(lex): symbol = lex[self.index] if symbol.upper() == "FROM": # from table select *; self.index += 1 if self.index < len(lex): self.table = lex[self.index] elif symbol.upper() == "SELECT": # select a, b from table; self.action = "SELECT" self.index += 1 self.columns.append(lex[self.index]) self.index += 1 while self.index < len(lex) and lex[self.index].upper() in [",", "AS"]: sep = lex[self.index] if sep == ",": self.index += 1 self.columns.append(lex[self.index]) self.index += 1 elif sep.upper() == "AS": self.index += 1 # alias self.aliases[self.columns[-1]] = lex[self.index] self.index += 1 self.index -= 1 elif symbol.upper() == "DELETE": # delete from table where item == 1; self.action = "DELETE" self.columns = ["gramps_id"] elif symbol.upper() == "SET": # SET x=1, y=2 self.index += 1 self.setcolumns.append(lex[self.index]) # first column self.index += 1 # equal sign # = self.index += 1 # value self.values.append(lex[self.index]) self.index += 1 # comma while self.index < len(lex) and lex[self.index] == ",": self.index += 1 # next column self.setcolumns.append(lex[self.index]) self.index += 1 # equal # = self.index += 1 # value self.values.append(lex[self.index]) self.index += 1 # comma? self.index -= 1 elif symbol.upper() == "LIMIT": self.index += 1 # after LIMIT number = lex[self.index] self.index += 1 # maybe a comma if self.index < len(lex) and lex[self.index] == ",": self.index += 1 # after "," stop = lex[self.index] self.limit = (int(number), int(stop)) else: self.limit = (0, int(number)) self.index -= 1 elif symbol.upper() == "WHERE": # how can we get all of Python expressions? # this assumes all by ; self.index += 1 self.where = lex[self.index] elif symbol.upper() == "UPDATE": # update table set x=1, y=2 where condition; # UPDATE gramps_id set tag_list = Tag("Betty") from person where "Betty" in primary_name.first_name self.columns = ["gramps_id"] self.action = "UPDATE" if self.index < len(lex): self.index += 1 self.table = lex[self.index] elif symbol.upper() == "FLAT": self.flat = True elif symbol.upper() == "EXPAND": self.flat = False elif symbol.upper() == "RAW": self.raw = True elif symbol.upper() == "NORAW": self.raw = False else: raise AttributeError("invalid SQL expression: '... %s ...'" % symbol) self.index += 1 def close(self): """ Close up any progress widgets or dialogs. """ #try: # self.progress.close() #except: pass def clean_titles(self, columns): """ Take the columns and turn them into strings for the table. """ retval = [] for column in columns: if column in self.aliases: column = self.aliases[column] retval.append(column.replace("_", "__")) return retval def query(self, query): self.parse(query) self.select = 0 start_time = time.time() class Table(): results = [] def row(self, *args, **kwargs): self.results.append([args, kwargs]) def get_rows(self): return [list(item[0]) for item in self.results] table = Table() self.sdb = SimpleAccess(self.database) self.process_table(table) # a class that has .row(1, 2, 3, ...) print(_("%d rows processed in %s seconds.\n") % (self.select, time.time() - start_time)) return table def eval(self): """ Execute the query. """ self.sdb = SimpleAccess(self.database) self.stab = QuickTable(self.sdb) self.select = 0 start_time = time.time() self.process_table(self.stab) # a class that has .row(1, 2, 3, ...) if self.select > 0: self.stab.columns(*self.clean_titles(self.columns)) self.sdoc = SimpleDoc(self.document) self.sdoc.title(self.query_text) self.sdoc.paragraph("\n") self.sdoc.paragraph("%d rows processed in %s seconds.\n" % (self.select, time.time() - start_time)) self.stab.write(self.sdoc) self.sdoc.paragraph("") return _("%d rows processed in %s seconds.\n") % (self.select, time.time() - start_time) def get_columns(self, table): """ Get the columns for the given table. """ if self.database: retval = self.data[table.lower()] return retval # [self.name] + retval else: return ["*"] def process_table(self, table): """ Given a table name, process the query on the elements of the table. """ # 'Person', 'Family', 'Source', 'Citation', 'Event', 'Media', # 'Place', 'Repository', 'Note', 'Tag' # table: a class that has .row(1, 2, 3, ...) if self.table == "person": self.do_query(self.sdb.all_people(), table) elif self.table == "family": self.do_query(self.sdb.all_families(), table) elif self.table == "event": self.do_query(self.sdb.all_events(), table) elif self.table == "source": self.do_query(self.sdb.all_sources(), table) elif self.table == "tag": self.do_query(self.sdb.all_tags(), table) elif self.table == "citation": self.do_query(self.sdb.all_citations(), table) elif self.table == "media": self.do_query(self.sdb.all_media(), table) elif self.table == "place": self.do_query(self.sdb.all_places(), table) elif self.table == "repository": self.do_query(self.sdb.all_repositories(), table) elif self.table == "note": self.do_query(self.sdb.all_notes(), table) else: raise AttributeError("no such table: '%s'" % self.table) def get_tag(self, name): tag = self.database.get_tag_from_name(name) if tag is None: tag = gramps.gen.lib.Tag() tag.set_name(name) trans_class = self.database.get_transaction_class() with trans_class("QueryQuickview new Tag", self.database, batch=False) as trans: self.database.add_tag(tag, trans) return Handle("Tag", tag.handle) def make_env(self, **kwargs): """ An environment with which to eval elements. """ retval= Environment({ _("Date"): gramps.gen.lib.date.Date, _("Today"): gramps.gen.lib.date.Today(), "random": random, "re": re, "db": self.database, "sdb": self.sdb, "lib": gramps.gen.lib, "_": _, "Tag": self.get_tag, }) retval.update(__builtins__) retval.update(kwargs) return retval def stringify(self, value): """ Turn the value into an appropriate string representation. """ if self.raw: return value if isinstance(value, Struct): return self.stringify(value.struct) elif isinstance(value, (list, tuple)): if len(value) == 0 and not self.flat: return "" elif len(value) == 1 and not self.flat: return self.stringify(value[0]) else: return "[%s]" % (", ".join(map(self.stringify, value))) elif isinstance(value, PrimaryObject): return value else: return str(value) def clean(self, values, names): """ Given the values and names of columns, change the values into string versions for the display table. """ if self.raw: return values retval = [] for i in range(len(values)): if names[i].endswith("handle"): retval.append(repr(values[i].struct["handle"])) else: retval.append(self.stringify(values[i])) return retval def do_query(self, items, table): """ Perform the query on the items in the named table. """ # table: a class that has .row(1, 2, 3, ...) with self.database.get_transaction_class()("QueryQuickview", self.database, batch=True) as trans: ROWNUM = 0 env = self.make_env() for item in items: if item is None: continue row = [] row_env = [] # "col[0]" in WHERE clause will return first column of selection: env["col"] = row_env env["ROWNUM"] = ROWNUM env["object"] = item struct = Struct(item.to_struct(), self.database) env.set_struct(struct) for col in self.columns: try: value = eval(col, env) except: value = None row.append(value) # allow col[#] reference: row_env.append(value) # an alias? if col in self.aliases: env[self.aliases[col]] = value # Should we include this row? if self.where: try: result = eval(self.where, env) except: continue else: if self.action in ["DELETE", "UPDATE"]: result = True else: result = any([col != None for col in row]) # are they all None? # If result, then append the row if result: if (self.limit is None) or (self.limit[0] <= ROWNUM < self.limit[1]): if self.action == "SELECT": if not self.flat: # Join by rows: products = [] columns = [] count = 0 for col in row: if ((isinstance(col, Struct) and isinstance(col.struct, list) and len(col.struct) > 0) or (isinstance(col, list) and len(col) > 0)): products.append(col) columns.append(count) count += 1 if len(products) > 0: current = self.clean(row, self.columns) for items in itertools.product(*products): for i in range(len(items)): current[columns[i]] = self.stringify(items[i]) table.row(*current, link=(item.__class__.__name__, item.handle)) self.select += 1 else: table.row(*self.clean(row, self.columns), link=(item.__class__.__name__, item.handle)) self.select += 1 else: table.row(*self.clean(row, self.columns), link=(item.__class__.__name__, item.handle)) self.select += 1 elif self.action == "UPDATE": # update table set col=val, col=val where expr; table.row(*self.clean(row, self.columns), link=(item.__class__.__name__, item.handle)) self.select += 1 for i in range(len(self.setcolumns)): struct.setitem(self.setcolumns[i], eval(self.values[i], env), trans=trans) elif self.action == "DELETE": table.row(*self.clean(row, self.columns)) self.select += 1 self.database.remove_instance(item, trans) else: raise AttributeError("unknown command: '%s'", self.action) ROWNUM += 1 if (self.limit is not None) and (ROWNUM >= self.limit[1]): break
def run(database, document, object, item='place', trans=_("Place")): """ Display back-references for this object. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # hold a person-event dictionary pedic = defaultdict(list) for pe in database.get_person_handles(): for eventref in database.get_person_from_handle(pe).event_ref_list: pedic[eventref.ref].append((eventref.get_role(), pe)) #for ev in pedic.keys(): # print(ev,pedic[ev]) # display the title sdoc.title(_("References for this %s") % trans) sdoc.paragraph("\n") stab.columns(_("Type"), _("Reference"), _("Date"), _("Persons")) # get the events event_handle_list = [handle for (objclass, handle) in database.find_backlink_handles(object.handle)] # ref = get_ref(database, objclass, handle) # #print(ref,pedic[handle]) # line='' # for i, (role, personhandle) in enumerate(pedic[handle]): # line = line + ' ' + ( # f'{i} {role} {_nd.display(database.get_person_from_handle(personhandle))} ' # f'[{database.get_person_from_handle(personhandle).get_gramps_id()}]' # ) # e_date = ref.get_date_object() # s_date = ref.get_date_object().get_sort_value() # event_list += [s_date, _(objclass), ref, e_date, line] # Sort the events by their date event_handle_list.sort(key=lambda x: database.get_event_from_handle(x).get_date_object().get_sort_value()) print(len(event_handle_list)) for handle in event_handle_list: print(database.get_event_from_handle(handle), pedic[handle], database.get_event_from_handle(handle).get_date_object()) line='' for i, (role, personhandle) in enumerate(pedic[handle]): line = line + ' ' + ( f'{i} {role} {_nd.display(database.get_person_from_handle(personhandle))} ' f'[{database.get_person_from_handle(personhandle).get_gramps_id()}]' ) stab.row(database.get_event_from_handle(handle).get_description(), database.get_event_from_handle(handle), database.get_event_from_handle(handle).get_date_object(), line) # translation are explicit (above) if stab.get_row_count() > 0: document.has_data = True # stab.sort(_("Date")) stab.write(sdoc) else: document.has_data = False sdoc.paragraph(_("No references for this %s") % trans) sdoc.paragraph("") sdoc.paragraph("")
def run(database, document, person): sdoc = SimpleDoc(document) name = gramps.gen.display.name.displayer.display(person) death_date = _get_date(database, person.get_death_ref()) sdoc.title(_("Number of %s's descendants") % name) sdoc.paragraph("") total = [] seen = [] outlived = [] alive = [] handles = [] _count_descendants(database, person, death_date, 0, total, seen, outlived, alive, handles) # Bring all lists to the same length. No list can be longer than "total". while len(seen) < len(total): seen.append(0) while len(outlived) < len(total): outlived.append(0) while len(alive) < len(total): alive.append(0) rel_calc = get_relationship_calculator() stab = QuickTable(document) if death_date: stab.columns( _("Generation"), _("Total"), _("Seen"), _("Outlived"), _("Now alive")) else: stab.columns( _("Generation"), _("Total"), _("Now alive")) n = 0 for (a, b, c, d, h) in zip(total, seen, outlived, alive, handles): n += 1 generation = rel_calc.get_plural_relationship_string(0, n) if death_date: # stab.row([generation, "PersonList"] + h, a, b, c, d) # Needs 3.2 stab.row(generation, a, b, c, d) else: # stab.row([generation, "PersonList"] + h, a, d) # Needs 3.2 stab.row(generation, a, d) stab.row_sort_val(0, n) if death_date: # stab.row([_("Total"), "PersonList"] + sum(handles, []), # Needs 3.2 stab.row(_("Total"), sum(total), sum(seen), sum(outlived), sum(alive)) else: # stab.row([_("Total"), "PersonList"] + sum(handles, []), # Needs 3.2 stab.row(_("Total"), sum(total), sum(alive)) stab.row_sort_val(0, n + 1) stab.write(sdoc) if death_date: sdoc.paragraph(_("Seen = number of descendants whose birth %s has " "lived to see") % name) sdoc.paragraph(_("Outlived = number of descendants who died while %s " "was still alive") % name)
def run(database, document, date): """ Display people probably alive and their ages on a particular date. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) if not date.get_valid(): sdoc.paragraph("Date is not a valid date.") return # display the title if date.get_day_valid(): sdoc.title(_("People and their ages the %s") % displayer.display(date)) else: sdoc.title(_("People and their ages on %s") % displayer.display(date)) stab.columns(_("Person"), _("Age"), _("Status")) # Actual Date makes column unicode alive_matches = 0 dead_matches = 0 for person in sdb.all_people(): alive, birth, death, explain, relative = \ probably_alive(person, database, date, return_range=True) # Doesn't show people probably alive but no way of figuring an age: if alive: if birth: diff_span = (date - birth) stab.row(person, str(diff_span), _("Alive: %s") % explain) stab.row_sort_val(1, int(diff_span)) else: stab.row(person, "", _("Alive: %s") % explain) stab.row_sort_val(1, 0) alive_matches += 1 else: # not alive if birth: diff_span = (date - birth) stab.row(person, str(diff_span), _("Deceased: %s") % explain) stab.row_sort_val(1, int(diff_span)) else: stab.row(person, "", _("Deceased: %s") % explain) stab.row_sort_val(1, 1) dead_matches += 1 document.has_data = (alive_matches + dead_matches) > 0 sdoc.paragraph(_("\nLiving matches: %(alive)d, " "Deceased matches: %(dead)d\n") % {'alive' : alive_matches, 'dead' : dead_matches}) if document.has_data: stab.write(sdoc) sdoc.paragraph("")
class DBI(object): """ The SQL-like interface to the database and document instances. """ def __init__(self, database, document=None): self.database = database self.document = document self.data = {} self.select = 0 self.flat = False self.raw = False if self.database: for name in ('Person', 'Family', 'Event', 'Place', 'Repository', 'Source', 'Citation', 'Media', 'Note', 'Tag'): d = self.database._tables[name]["class_func"]().to_struct() self.data[name.lower()] = d.keys() # The macros: self.shortcuts = { "SURNAME": "primary_name.surname_list[0].surname", "GIVEN": "primary_name.first_name", } def parse(self, query): """ Parse the query. """ self.query_text = query.replace("\n", " ").strip() lexed = self.lexer(self.query_text) #print(lexed) self.parser(lexed) for col_name in self.columns[:]: # copy if col_name == "*": self.columns.remove('*') # this is useful to see what _class it is: self.columns.extend(self.get_columns(self.table)) # otherwise remove metadata: #self.columns.extend([col for col in self.get_columns(self.table) if not col.startswith("_")) def lexer(self, string): """ Given a string, break into a list of chunks. """ retval = [] state = None current = "" stack = [] i = 0 # Handle macros: for key in self.shortcuts.keys(): string = string.replace(key, self.shortcuts[key]) # (some "expression" in ok) # func(some "expression" in (ok)) # list[1][0] # [x for x in list] while i < len(string): ch = string[i] #print("lex:", i, ch, state, retval, current) if state == "in-double-quote": if ch == '"': state = stack.pop() current += ch elif state == "in-single-quote": if ch == "'": state = stack.pop() current += ch elif state == "in-expr": if ch == ")": state = stack.pop() elif ch == "(": stack.append("in-expr") current += ch elif state == "in-square-bracket": if ch == "]": state = stack.pop() elif ch == "[": stack.append("in-square-bracket") current += ch elif ch == '"': stack.append(state) state = "in-double-quote" current += ch elif ch == "'": stack.append(state) state = "in-single-quote" current += ch elif ch == "(": stack.append(state) state = "in-expr" current += "(" elif ch == "[": stack.append(state) state = "in-square-bracket" current += "[" elif ch == ",": if current: retval.append(current) retval.append(",") current = "" elif ch == "=": if current: retval.append(current) retval.append("=") current = "" elif ch in [' ', '\t', '\n', ";"]: # break if current: retval.append(current) if current.upper() == "WHERE": # HACK: get rest of string: if string[-1] == ";": retval.append(string[i + 1:-1]) i = len(string) - 2 else: retval.append(string[i + 1:]) i = len(string) - 1 current = "" else: pass # ignore whitespace else: current += ch i += 1 if current: retval.append(current) #print("lexed:", retval) return retval def parser(self, lex): """ Takes output of lexer, and sets the values. After parser, the DBI will be ready to process query. """ self.action = None self.table = None self.columns = [] self.setcolumns = [] self.values = [] self.aliases = {} self.limit = None self.where = None self.index = 0 while self.index < len(lex): symbol = lex[self.index] if symbol.upper() == "FROM": # from table select *; self.index += 1 if self.index < len(lex): self.table = lex[self.index] elif symbol.upper() == "SELECT": # select a, b from table; self.action = "SELECT" self.index += 1 self.columns.append(lex[self.index]) self.index += 1 while self.index < len(lex) and lex[self.index].upper() in [ ",", "AS" ]: sep = lex[self.index] if sep == ",": self.index += 1 self.columns.append(lex[self.index]) self.index += 1 elif sep.upper() == "AS": self.index += 1 # alias self.aliases[self.columns[-1]] = lex[self.index] self.index += 1 self.index -= 1 elif symbol.upper() == "DELETE": # delete from table where item == 1; self.action = "DELETE" self.columns = ["gramps_id"] elif symbol.upper() == "SET": # SET x=1, y=2 self.index += 1 self.setcolumns.append(lex[self.index]) # first column self.index += 1 # equal sign # = self.index += 1 # value self.values.append(lex[self.index]) self.index += 1 # comma while self.index < len(lex) and lex[self.index] == ",": self.index += 1 # next column self.setcolumns.append(lex[self.index]) self.index += 1 # equal # = self.index += 1 # value self.values.append(lex[self.index]) self.index += 1 # comma? self.index -= 1 elif symbol.upper() == "LIMIT": self.index += 1 # after LIMIT number = lex[self.index] self.index += 1 # maybe a comma if self.index < len(lex) and lex[self.index] == ",": self.index += 1 # after "," stop = lex[self.index] self.limit = (int(number), int(stop)) else: self.limit = (0, int(number)) self.index -= 1 elif symbol.upper() == "WHERE": # how can we get all of Python expressions? # this assumes all by ; self.index += 1 self.where = lex[self.index] elif symbol.upper() == "UPDATE": # update table set x=1, y=2 where condition; # UPDATE gramps_id set tag_list = Tag("Betty") from person where "Betty" in primary_name.first_name self.columns = ["gramps_id"] self.action = "UPDATE" if self.index < len(lex): self.index += 1 self.table = lex[self.index] elif symbol.upper() == "FLAT": self.flat = True elif symbol.upper() == "EXPAND": self.flat = False elif symbol.upper() == "RAW": self.raw = True elif symbol.upper() == "NORAW": self.raw = False else: raise AttributeError("invalid SQL expression: '... %s ...'" % symbol) self.index += 1 def close(self): """ Close up any progress widgets or dialogs. """ #try: # self.progress.close() #except: pass def clean_titles(self, columns): """ Take the columns and turn them into strings for the table. """ retval = [] for column in columns: if column in self.aliases: column = self.aliases[column] retval.append(column.replace("_", "__")) return retval def query(self, query): self.parse(query) self.select = 0 start_time = time.time() class Table(): results = [] def row(self, *args, **kwargs): self.results.append([args, kwargs]) def get_rows(self): return [list(item[0]) for item in self.results] table = Table() self.sdb = SimpleAccess(self.database) self.process_table(table) # a class that has .row(1, 2, 3, ...) print( _("%d rows processed in %s seconds.\n") % (self.select, time.time() - start_time)) return table def eval(self): """ Execute the query. """ self.sdb = SimpleAccess(self.database) self.stab = QuickTable(self.sdb) self.select = 0 start_time = time.time() self.process_table(self.stab) # a class that has .row(1, 2, 3, ...) if self.select > 0: self.stab.columns(*self.clean_titles(self.columns)) self.sdoc = SimpleDoc(self.document) self.sdoc.title(self.query_text) self.sdoc.paragraph("\n") self.sdoc.paragraph("%d rows processed in %s seconds.\n" % (self.select, time.time() - start_time)) self.stab.write(self.sdoc) self.sdoc.paragraph("") return _("%d rows processed in %s seconds.\n") % ( self.select, time.time() - start_time) def get_columns(self, table): """ Get the columns for the given table. """ if self.database: retval = self.data[table.lower()] return retval # [self.name] + retval else: return ["*"] def process_table(self, table): """ Given a table name, process the query on the elements of the table. """ # 'Person', 'Family', 'Source', 'Citation', 'Event', 'Media', # 'Place', 'Repository', 'Note', 'Tag' # table: a class that has .row(1, 2, 3, ...) if self.table == "person": self.do_query(self.sdb.all_people(), table) elif self.table == "family": self.do_query(self.sdb.all_families(), table) elif self.table == "event": self.do_query(self.sdb.all_events(), table) elif self.table == "source": self.do_query(self.sdb.all_sources(), table) elif self.table == "tag": self.do_query(self.sdb.all_tags(), table) elif self.table == "citation": self.do_query(self.sdb.all_citations(), table) elif self.table == "media": self.do_query(self.sdb.all_media(), table) elif self.table == "place": self.do_query(self.sdb.all_places(), table) elif self.table == "repository": self.do_query(self.sdb.all_repositories(), table) elif self.table == "note": self.do_query(self.sdb.all_notes(), table) else: raise AttributeError("no such table: '%s'" % self.table) def get_tag(self, name): tag = self.database.get_tag_from_name(name) if tag is None: tag = gramps.gen.lib.Tag() tag.set_name(name) trans_class = self.database.get_transaction_class() with trans_class("QueryQuickview new Tag", self.database, batch=False) as trans: self.database.add_tag(tag, trans) return Handle("Tag", tag.handle) def make_env(self, **kwargs): """ An environment with which to eval elements. """ retval = Environment({ _("Date"): gramps.gen.lib.date.Date, _("Today"): gramps.gen.lib.date.Today(), "random": random, "re": re, "db": self.database, "sdb": self.sdb, "lib": gramps.gen.lib, "_": _, "Tag": self.get_tag, }) retval.update(__builtins__) retval.update(kwargs) return retval def stringify(self, value): """ Turn the value into an appropriate string representation. """ if self.raw: return value if isinstance(value, Struct): return self.stringify(value.struct) elif isinstance(value, (list, tuple)): if len(value) == 0 and not self.flat: return "" elif len(value) == 1 and not self.flat: return self.stringify(value[0]) else: return "[%s]" % (", ".join(map(self.stringify, value))) elif isinstance(value, PrimaryObject): return value else: return str(value) def clean(self, values, names): """ Given the values and names of columns, change the values into string versions for the display table. """ if self.raw: return values retval = [] for i in range(len(values)): if names[i].endswith("handle"): retval.append(repr(values[i].struct["handle"])) else: retval.append(self.stringify(values[i])) return retval def do_query(self, items, table): """ Perform the query on the items in the named table. """ # table: a class that has .row(1, 2, 3, ...) with self.database.get_transaction_class()("QueryQuickview", self.database, batch=True) as trans: ROWNUM = 0 env = self.make_env() for item in items: if item is None: continue row = [] row_env = [] # "col[0]" in WHERE clause will return first column of selection: env["col"] = row_env env["ROWNUM"] = ROWNUM env["object"] = item struct = Struct(item.to_struct(), self.database) env.set_struct(struct) for col in self.columns: try: value = eval(col, env) except: value = None row.append(value) # allow col[#] reference: row_env.append(value) # an alias? if col in self.aliases: env[self.aliases[col]] = value # Should we include this row? if self.where: try: result = eval(self.where, env) except: continue else: if self.action in ["DELETE", "UPDATE"]: result = True else: result = any([col != None for col in row]) # are they all None? # If result, then append the row if result: if (self.limit is None) or (self.limit[0] <= ROWNUM < self.limit[1]): if self.action == "SELECT": if not self.flat: # Join by rows: products = [] columns = [] count = 0 for col in row: if ((isinstance(col, Struct) and isinstance(col.struct, list) and len(col.struct) > 0) or (isinstance(col, list) and len(col) > 0)): products.append(col) columns.append(count) count += 1 if len(products) > 0: current = self.clean(row, self.columns) for items in itertools.product(*products): for i in range(len(items)): current[ columns[i]] = self.stringify( items[i]) table.row( *current, link=(item.__class__.__name__, item.handle)) self.select += 1 else: table.row(*self.clean(row, self.columns), link=(item.__class__.__name__, item.handle)) self.select += 1 else: table.row(*self.clean(row, self.columns), link=(item.__class__.__name__, item.handle)) self.select += 1 elif self.action == "UPDATE": # update table set col=val, col=val where expr; table.row(*self.clean(row, self.columns), link=(item.__class__.__name__, item.handle)) self.select += 1 for i in range(len(self.setcolumns)): struct.setitem(self.setcolumns[i], eval(self.values[i], env), trans=trans) elif self.action == "DELETE": table.row(*self.clean(row, self.columns)) self.select += 1 self.database.remove_instance(item, trans) else: raise AttributeError("unknown command: '%s'", self.action) ROWNUM += 1 if (self.limit is not None) and (ROWNUM >= self.limit[1]): break
def run(self): BUTTONS = ((_("Select All"), self.select_all), (_("Select None"), self.select_none), (_("Toggle Selection"), self.toggle_select), (_("Add Selected Events"), self.apply_selection), ) if hasattr(self, "table") and self.table: self.reselect = False if self.options.handler.options_dict['remove']: QuestionDialog(_("Remove Events, Notes, and Source and Reselect Data"), _("Are you sure you want to remove previous events, notes, and source and reselect data?"), _("Remove and Run Select Again"), self.set_reselect, self.window) else: QuestionDialog(_("Reselect Data"), _("Are you sure you want to reselect data?"), _("Run Select Again"), self.set_reselect, self.window) if not self.reselect: return current_date = Date() current_date.set_yr_mon_day(*time.localtime(time.time())[0:3]) self.action = {} widget = self.add_results_frame(_("Select")) document = TextBufDoc(make_basic_stylesheet(), None) document.dbstate = self.dbstate document.uistate = self.uistate document.open("", container=widget) self.sdb = SimpleAccess(self.db) sdoc = SimpleDoc(document) stab = QuickTable(self.sdb) self.table = stab stab.columns(_("Select"), _("Person"), _("Action"), _("Birth Date"), _("Death Date"), _("Evidence"), _("Relative")) self.results_write(_("Processing...\n")) self.filter_option = self.options.menu.get_option_by_name('filter') self.filter = self.filter_option.get_filter() # the actual filter people = self.filter.apply(self.db, self.db.iter_person_handles()) num_people = self.db.get_number_of_people() source_text = self.options.handler.options_dict['source_text'] source = None add_birth = self.options.handler.options_dict['add_birth'] add_death = self.options.handler.options_dict['add_death'] remove_old = self.options.handler.options_dict['remove'] self.MAX_SIB_AGE_DIFF = self.options.handler.options_dict['MAX_SIB_AGE_DIFF'] self.MAX_AGE_PROB_ALIVE = self.options.handler.options_dict['MAX_AGE_PROB_ALIVE'] self.AVG_GENERATION_GAP = self.options.handler.options_dict['AVG_GENERATION_GAP'] if remove_old: with DbTxn("", self.db, batch=True) as self.trans: self.db.disable_signals() self.results_write(_("Removing old estimations... ")) self.progress.set_pass((_("Removing '%s'...") % source_text), num_people) for person_handle in people: self.progress.step() pupdate = 0 person = self.db.get_person_from_handle(person_handle) birth_ref = person.get_birth_ref() if birth_ref: birth = self.db.get_event_from_handle(birth_ref.ref) for citation_handle in birth.get_citation_list(): citation = self.db.get_citation_from_handle(citation_handle) source_handle = citation.get_reference_handle() #print "birth handle:", source_handle source = self.db.get_source_from_handle(source_handle) if source: #print "birth source:", source, source.get_title() if source.get_title() == source_text: person.set_birth_ref(None) person.remove_handle_references('Event',[birth_ref.ref]) # remove note note_list = birth.get_referenced_note_handles() birth.remove_handle_references('Note', [note_handle for (obj_type, note_handle) in note_list]) for (obj_type, note_handle) in note_list: self.db.remove_note(note_handle, self.trans) self.db.remove_event(birth_ref.ref, self.trans) self.db.commit_source(source, self.trans) pupdate = 1 break death_ref = person.get_death_ref() if death_ref: death = self.db.get_event_from_handle(death_ref.ref) for citation_handle in death.get_citation_list(): citation = self.db.get_citation_from_handle(citation_handle) source_handle = citation.get_reference_handle() #print "death handle:", source_handle source = self.db.get_source_from_handle(source_handle) if source: #print "death source:", source, source.get_title() if source.get_title() == source_text: person.set_death_ref(None) person.remove_handle_references('Event',[death_ref.ref]) # remove note note_list = death.get_referenced_note_handles() birth.remove_handle_references('Note', [note_handle for (obj_type, note_handle) in note_list]) for (obj_type, note_handle) in note_list: self.db.remove_note(note_handle, self.trans) self.db.remove_event(death_ref.ref, self.trans) self.db.commit_source(source, self.trans) pupdate = 1 break if pupdate == 1: self.db.commit_person(person, self.trans) if source: self.db.remove_source(source.handle, self.trans) self.results_write(_("done!\n")) self.db.enable_signals() self.db.request_rebuild() if add_birth or add_death: self.results_write(_("Selecting... \n\n")) self.progress.set_pass(_('Selecting...'), num_people) row = 0 for person_handle in people: self.progress.step() person = self.db.get_person_from_handle(person_handle) birth_ref = person.get_birth_ref() death_ref = person.get_death_ref() add_birth_event, add_death_event = False, False if not birth_ref or not death_ref: date1, date2, explain, other = self.calc_estimates(person) if birth_ref: ev = self.db.get_event_from_handle(birth_ref.ref) date1 = ev.get_date_object() elif not birth_ref and add_birth and date1: if date1.match( current_date, "<"): add_birth_event = True date1.make_vague() else: date1 = Date() else: date1 = Date() if death_ref: ev = self.db.get_event_from_handle(death_ref.ref) date2 = ev.get_date_object() elif not death_ref and add_death and date2: if date2.match( current_date, "<"): add_death_event = True date2.make_vague() else: date2 = Date() else: date2 = Date() # Describe if add_birth_event and add_death_event: action = _("Add birth and death events") elif add_birth_event: action = _("Add birth event") elif add_death_event: action = _("Add death event") else: continue #stab.columns(_("Select"), _("Person"), _("Action"), # _("Birth Date"), _("Death Date"), _("Evidence"), _("Relative")) if add_birth == 1 and not birth_ref: # no date date1 = Date() if add_death == 1 and not death_ref: # no date date2 = Date() if person == other: other = None stab.row("checkbox", person, action, date1, date2, explain or "", other or "") if add_birth_event: stab.set_cell_markup(3, row, "<b>%s</b>" % date_displayer.display(date1)) if add_death_event: stab.set_cell_markup(4, row, "<b>%s</b>" % date_displayer.display(date2)) self.action[person.handle] = (add_birth_event, add_death_event) row += 1 if row > 0: self.results_write(" ") for text, function in BUTTONS: self.make_button(text, function, widget) self.results_write("\n") stab.write(sdoc) self.results_write(" ") for text, function in BUTTONS: self.make_button(text, function, widget) self.results_write("\n") else: self.results_write(_("No events to be added.")) self.results_write("\n") self.results_write("\n") self.progress.close() self.set_current_frame(_("Select"))
class AllRelReport: """ Obtains all relationships, displays the relations, and in details, the relation path """ def __init__(self, database, document, person): self.database = database self.person = person self.sdb = SimpleAccess(database) self.sdoc = SimpleDoc(document) self.rel_class = get_relationship_calculator(glocale) self.msg_list = [] def run(self): #get home_person self.home_person = self.database.get_default_person() if not self.home_person : self.sdoc.paragraph(_("Home person not set.")) return self.print_title() p2 = self.sdb.name(self.home_person) p1 = self.sdb.name(self.person) if self.person.handle == self.home_person.handle : self.sdoc.paragraph(_FMT_VOID % ( _("%(person)s and %(active_person)s are the same person.")) % { 'person' : p1, 'active_person' : p2 }) return #check if not a family too: is_spouse = self.rel_class.is_spouse(self.database, self.home_person, self.person) if is_spouse: rel_string = is_spouse rstr = _("%(person)s is the %(relationship)s of %(active_person)s." ) % {'person' : p1, 'relationship' : rel_string, 'active_person' : p2 } self.sdoc.paragraph(_FMT_VOID % (rstr)) self.sdoc.paragraph("") #obtain all relationships, assume home person has largest tree common, self.msg_list = self.rel_class.get_relationship_distance_new( self.database, self.person, self.home_person, all_families=True, all_dist=True, only_birth=False) #all relations if (not common or common[0][0]== -1 ) and not is_spouse: rstr = _("%(person)s and %(active_person)s are not " "directly related.") % {'person' : p2, 'active_person' : p1 } self.sdoc.paragraph(_FMT_VOID % (rstr)) self.sdoc.paragraph("") #collapse common so parents of same fam in common are one line commonnew = self.rel_class.collapse_relations(common) self.print_details_header(commonnew, self.home_person, self.person, skip_list_text=None) self.print_details_path(commonnew, self.home_person, self.person) self.print_details_path(commonnew, self.home_person, self.person, first=False) if not common or common[0][0]== -1 : self.remarks(self.msg_list) self.msg_list = [] #check inlaw relation next else: #stop return #we check the inlaw relationships if not partners. if is_spouse: return handles_done = [(self.person.handle, self.home_person.handle)] inlaws_pers = [self.person] + self.get_inlaws(self.person) inlaws_home = [self.home_person] + self.get_inlaws(self.home_person) #remove overlap: inlaws_home = [x for x in inlaws_home if x not in inlaws_pers] inlawwritten = False skiplist = [] commonnew = [] for inlawpers in inlaws_pers: for inlawhome in inlaws_home: if (inlawpers, inlawhome) in handles_done : continue else: handles_done.append((inlawpers, inlawhome)) common, msg = \ self.rel_class.get_relationship_distance_new( self.database, inlawpers, inlawhome, all_families=True, all_dist=True, only_birth=False) if msg: self.msg_list += msg if common and not common[0][0] == -1: if not inlawwritten: rstr = _("%(person)s and %(active_person)s have " "following in-law relations:" ) % {'person' : p2, 'active_person' : p1 } self.sdoc.paragraph(_FMT_VOID % (rstr)) self.sdoc.paragraph("") inlawwritten = True else: continue inlawb = not inlawpers.handle == self.person.handle inlawa = not inlawhome.handle == self.home_person.handle commonnew.append((inlawa, inlawb, inlawhome, inlawpers, self.rel_class.collapse_relations(common))) skip=[] skip_text = [] count = 1 for inlawa, inlawb, inlawhome, inlawpers, commonrel in commonnew: count = self.print_details_header(commonrel, inlawhome, inlawpers, inlawa = inlawa, inlawb = inlawb, count=count, skip_list=skip, skip_list_text = skip_text) count = 1 for inlawa, inlawb, inlawhome, inlawpers, commonrel in commonnew: self.print_details_path(commonrel, inlawhome, inlawpers, inlawa = inlawa, inlawb = inlawb, count = count, skip_list = skip) count = self.print_details_path(commonrel, inlawhome, inlawpers, inlawa = inlawa, inlawb = inlawb, count = count, skip_list = skip, first = False) self.remarks(self.msg_list, True) def get_inlaws(self, person): inlaws = [] family_handles = person.get_family_handle_list() for handle in family_handles: fam = self.database.get_family_from_handle(handle) if fam.father_handle and \ not fam.father_handle == person.handle: inlaws.append(self.database.get_person_from_handle( fam.father_handle)) elif fam.mother_handle and \ not fam.mother_handle == person.handle: inlaws.append(self.database.get_person_from_handle( fam.mother_handle)) return inlaws def print_title(self): """ print the title """ p2 = self.sdb.name(self.home_person) p1 = self.sdb.name(self.person) self.sdoc.title(_("Relationships of %(person)s to %(active_person)s") % { 'person' : p1 ,'active_person' : p2 }) self.sdoc.paragraph("") def print_details_header(self, relations, pers1, pers2, inlawa=False, inlawb=False, count=1, skip_list=[], skip_list_text = []): if not relations or relations[0][0] == -1: return count sdoc = self.sdoc rel_class = self.rel_class for relation in relations: birth = self.rel_class.only_birth(relation[2])\ and self.rel_class.only_birth(relation[4]) distorig = len(relation[4]) distother = len(relation[2]) if distorig == distother == 1 and not inlawa \ and not inlawb: rel_str = self.rel_class.get_sibling_relationship_string( self.rel_class.get_sibling_type( self.database, pers1, pers2), self.home_person.get_gender(), self.person.get_gender()) else: rel_str = self.rel_class.get_single_relationship_string( distorig, distother, self.home_person.get_gender(), self.person.get_gender(), relation[4], relation[2], only_birth = birth, in_law_a = inlawa, in_law_b = inlawb) if skip_list_text is not None: if rel_str in skip_list_text: skip_list.append(count) else: skip_list_text.append(rel_str) sdoc.paragraph(_FMT % (count-len(skip_list), rel_str)) else: sdoc.paragraph(_FMT % (count, rel_str)) count += 1 return count def print_details_path(self, relations, pers1, pers2, inlawa=False, inlawb=False, count = 1, skip_list = [], first=True): if not relations or relations[0][0] == -1: return count sdoc = self.sdoc rel_class = self.rel_class p2 = self.sdb.name(self.home_person) p1 = self.sdb.name(self.person) pers = p2 inlaw = inlawa if first: pers = p1 inlaw = inlawb if count == 1: sdoc.paragraph("") sdoc.header1(_("Detailed path from %(person)s to common ancestor" ) % {'person':pers}) sdoc.paragraph("") sdoc.header2(_FMT_DET1 % (' ', _('Name Common ancestor'))) sdoc.header2(_FMT_DET2 % (' ', _('Parent'), _('Birth'), _('Family'))) sdoc.paragraph("") for relation in relations: if count in skip_list: count += 1 continue counter = str(count - len([x for x in range(count) if x+1 in skip_list])) name = _('Unknown') if relation[1]: name = self.sdb.name(self.database.get_person_from_handle( relation[1][0])) for handle in relation[1][1:]: name += ' ' + _('and') + ' ' + self.sdb.name( self.database.get_person_from_handle(handle)) sdoc.paragraph(_FMT_DET1 % (counter, name)) if inlaw: sdoc.paragraph(_FMT_DET2 % (' ', _('Partner'), ' ', ' ')) if first: ind1 = 2 ind2 = 3 else: ind1 = 4 ind2 = 5 for rel,fam in zip(relation[ind1],relation[ind2]): par_str = _('Unknown') #when sibling, parent is unknown if rel == rel_class.REL_MOTHER \ or rel == rel_class.REL_MOTHER_NOTBIRTH: par_str = _('Mother') if rel == rel_class.REL_FATHER \ or rel == rel_class.REL_FATHER_NOTBIRTH: par_str = _('Father') if (rel == rel_class.REL_FAM_BIRTH or rel == rel_class.REL_FAM_NONBIRTH or rel == rel_class.REL_FAM_BIRTH_MOTH_ONLY or rel == rel_class.REL_FAM_BIRTH_FATH_ONLY): par_str = _('Parents') birth_str = _('Yes') if (rel == rel_class.REL_MOTHER_NOTBIRTH or rel == rel_class.REL_FATHER_NOTBIRTH or rel == rel_class.REL_FAM_NONBIRTH): birth_str = _('No') elif (rel == rel_class.REL_FAM_BIRTH_FATH_ONLY or rel == rel_class.REL_FAM_BIRTH_MOTH_ONLY): birth_str = _('Partial') famstr = '' if isinstance(fam, list): famstr = str(fam[0]+1) for val in fam[1:] : # TODO for Arabic, should the next comma be translated? famstr += ', ' + str(val+1) else: famstr = str(fam+1) sdoc.paragraph(_FMT_DET2 % (' ', par_str, birth_str, famstr)) counter='' name = '' count += 1 return count def remarks(self, msg_list, inlaw=False): if msg_list : sdoc = self.sdoc sdoc.paragraph("") if inlaw: sdoc.header1(_("Remarks with inlaw family")) else: sdoc.header1(_("Remarks")) sdoc.paragraph("") sdoc.paragraph(_("The following problems were encountered:")) list(map(sdoc.paragraph, msg_list)) sdoc.paragraph("") sdoc.paragraph("")
class AllRelReport: """ Obtains all relationships, displays the relations, and in details, the relation path """ def __init__(self, database, document, person): self.database = database self.person = person self.sdb = SimpleAccess(database) self.sdoc = SimpleDoc(document) self.rel_class = get_relationship_calculator(glocale) self.msg_list = [] def run(self): # get home_person self.home_person = self.database.get_default_person() if not self.home_person: self.sdoc.paragraph(_("Home person not set.")) return self.print_title() p2 = self.sdb.name(self.home_person) p1 = self.sdb.name(self.person) if self.person.handle == self.home_person.handle: self.sdoc.paragraph( _FMT_VOID % (_("%(person)s and %(active_person)s are the same person.")) % {"person": p1, "active_person": p2} ) return # check if not a family too: is_spouse = self.rel_class.is_spouse(self.database, self.home_person, self.person) if is_spouse: rel_string = is_spouse rstr = _("%(person)s is the %(relationship)s of %(active_person)s.") % { "person": p1, "relationship": rel_string, "active_person": p2, } self.sdoc.paragraph(_FMT_VOID % (rstr)) self.sdoc.paragraph("") # obtain all relationships, assume home person has largest tree common, self.msg_list = self.rel_class.get_relationship_distance_new( self.database, self.person, self.home_person, all_families=True, all_dist=True, only_birth=False ) # all relations if (not common or common[0][0] == -1) and not is_spouse: rstr = _("%(person)s and %(active_person)s are not " "directly related.") % { "person": p2, "active_person": p1, } self.sdoc.paragraph(_FMT_VOID % (rstr)) self.sdoc.paragraph("") # collapse common so parents of same fam in common are one line commonnew = self.rel_class.collapse_relations(common) self.print_details_header(commonnew, self.home_person, self.person, skip_list_text=None) self.print_details_path(commonnew, self.home_person, self.person) self.print_details_path(commonnew, self.home_person, self.person, first=False) if not common or common[0][0] == -1: self.remarks(self.msg_list) self.msg_list = [] # check inlaw relation next else: # stop return # we check the inlaw relationships if not partners. if is_spouse: return handles_done = [(self.person.handle, self.home_person.handle)] inlaws_pers = [self.person] + self.get_inlaws(self.person) inlaws_home = [self.home_person] + self.get_inlaws(self.home_person) # remove overlap: inlaws_home = [x for x in inlaws_home if x not in inlaws_pers] inlawwritten = False skiplist = [] commonnew = [] for inlawpers in inlaws_pers: for inlawhome in inlaws_home: if (inlawpers, inlawhome) in handles_done: continue else: handles_done.append((inlawpers, inlawhome)) common, msg = self.rel_class.get_relationship_distance_new( self.database, inlawpers, inlawhome, all_families=True, all_dist=True, only_birth=False ) if msg: self.msg_list += msg if common and not common[0][0] == -1: if not inlawwritten: rstr = _("%(person)s and %(active_person)s have " "following in-law relations:") % { "person": p2, "active_person": p1, } self.sdoc.paragraph(_FMT_VOID % (rstr)) self.sdoc.paragraph("") inlawwritten = True else: continue inlawb = not inlawpers.handle == self.person.handle inlawa = not inlawhome.handle == self.home_person.handle commonnew.append((inlawa, inlawb, inlawhome, inlawpers, self.rel_class.collapse_relations(common))) skip = [] skip_text = [] count = 1 for inlawa, inlawb, inlawhome, inlawpers, commonrel in commonnew: count = self.print_details_header( commonrel, inlawhome, inlawpers, inlawa=inlawa, inlawb=inlawb, count=count, skip_list=skip, skip_list_text=skip_text, ) count = 1 for inlawa, inlawb, inlawhome, inlawpers, commonrel in commonnew: self.print_details_path( commonrel, inlawhome, inlawpers, inlawa=inlawa, inlawb=inlawb, count=count, skip_list=skip ) count = self.print_details_path( commonrel, inlawhome, inlawpers, inlawa=inlawa, inlawb=inlawb, count=count, skip_list=skip, first=False ) self.remarks(self.msg_list, True) def get_inlaws(self, person): inlaws = [] family_handles = person.get_family_handle_list() for handle in family_handles: fam = self.database.get_family_from_handle(handle) if fam.father_handle and not fam.father_handle == person.handle: inlaws.append(self.database.get_person_from_handle(fam.father_handle)) elif fam.mother_handle and not fam.mother_handle == person.handle: inlaws.append(self.database.get_person_from_handle(fam.mother_handle)) return inlaws def print_title(self): """ print the title """ p2 = self.sdb.name(self.home_person) p1 = self.sdb.name(self.person) self.sdoc.title(_("Relationships of %(person)s to %(active_person)s") % {"person": p1, "active_person": p2}) self.sdoc.paragraph("") def print_details_header( self, relations, pers1, pers2, inlawa=False, inlawb=False, count=1, skip_list=[], skip_list_text=[] ): if not relations or relations[0][0] == -1: return count sdoc = self.sdoc rel_class = self.rel_class for relation in relations: birth = self.rel_class.only_birth(relation[2]) and self.rel_class.only_birth(relation[4]) distorig = len(relation[4]) distother = len(relation[2]) if distorig == distother == 1 and not inlawa and not inlawb: rel_str = self.rel_class.get_sibling_relationship_string( self.rel_class.get_sibling_type(self.database, pers1, pers2), self.home_person.get_gender(), self.person.get_gender(), ) else: rel_str = self.rel_class.get_single_relationship_string( distorig, distother, self.home_person.get_gender(), self.person.get_gender(), relation[4], relation[2], only_birth=birth, in_law_a=inlawa, in_law_b=inlawb, ) if not skip_list_text is None: if rel_str in skip_list_text: skip_list.append(count) else: skip_list_text.append(rel_str) sdoc.paragraph(_FMT % (count - len(skip_list), rel_str)) else: sdoc.paragraph(_FMT % (count, rel_str)) count += 1 return count def print_details_path( self, relations, pers1, pers2, inlawa=False, inlawb=False, count=1, skip_list=[], first=True ): if not relations or relations[0][0] == -1: return count sdoc = self.sdoc rel_class = self.rel_class p2 = self.sdb.name(self.home_person) p1 = self.sdb.name(self.person) pers = p2 inlaw = inlawa if first: pers = p1 inlaw = inlawb if count == 1: sdoc.paragraph("") sdoc.header1(_("Detailed path from %(person)s to common ancestor") % {"person": pers}) sdoc.paragraph("") sdoc.header2(_FMT_DET1 % (" ", _("Name Common ancestor"))) sdoc.header2(_FMT_DET2 % (" ", _("Parent"), _("Birth"), _("Family"))) sdoc.paragraph("") for relation in relations: if count in skip_list: count += 1 continue counter = str(count - len([x for x in range(count) if x + 1 in skip_list])) name = _("Unknown") if relation[1]: name = self.sdb.name(self.database.get_person_from_handle(relation[1][0])) for handle in relation[1][1:]: name += " " + _("and") + " " + self.sdb.name(self.database.get_person_from_handle(handle)) sdoc.paragraph(_FMT_DET1 % (counter, name)) if inlaw: sdoc.paragraph(_FMT_DET2 % (" ", _("Partner"), " ", " ")) if first: ind1 = 2 ind2 = 3 else: ind1 = 4 ind2 = 5 for rel, fam in zip(relation[ind1], relation[ind2]): par_str = _("Unknown") # when sibling, parent is unknown if rel == rel_class.REL_MOTHER or rel == rel_class.REL_MOTHER_NOTBIRTH: par_str = _("Mother") if rel == rel_class.REL_FATHER or rel == rel_class.REL_FATHER_NOTBIRTH: par_str = _("Father") if ( rel == rel_class.REL_FAM_BIRTH or rel == rel_class.REL_FAM_NONBIRTH or rel == rel_class.REL_FAM_BIRTH_MOTH_ONLY or rel == rel_class.REL_FAM_BIRTH_FATH_ONLY ): par_str = _("Parents") birth_str = _("Yes") if ( rel == rel_class.REL_MOTHER_NOTBIRTH or rel == rel_class.REL_FATHER_NOTBIRTH or rel == rel_class.REL_FAM_NONBIRTH ): birth_str = _("No") elif rel == rel_class.REL_FAM_BIRTH_FATH_ONLY or rel == rel_class.REL_FAM_BIRTH_MOTH_ONLY: birth_str = _("Partial") famstr = "" if isinstance(fam, list): famstr = str(fam[0] + 1) for val in fam[1:]: famstr += ", " + str(val + 1) else: famstr = str(fam + 1) sdoc.paragraph(_FMT_DET2 % (" ", par_str, birth_str, famstr)) counter = "" name = "" count += 1 return count def remarks(self, msg_list, inlaw=False): if msg_list: sdoc = self.sdoc sdoc.paragraph("") if inlaw: sdoc.header1(_("Remarks with inlaw family")) else: sdoc.header1(_("Remarks")) sdoc.paragraph("") sdoc.paragraph(_("The following problems were encountered:")) list(map(sdoc.paragraph, msg_list)) sdoc.paragraph("") sdoc.paragraph("")
def run(database, document, person): """ Output a text biography of active person """ sa = SimpleAccess(database) sd = SimpleDoc(document) sd.title(_("Biography for %s") % sa.name(person)) sd.paragraph('') narrator = Narrator(database, verbose=True, use_call_name=True, use_fulldate=True) narrator.set_subject(person) # Birth Details text = narrator.get_born_string() if text: sd.paragraph(text) text = narrator.get_baptised_string() if text: sd.paragraph(text) text = narrator.get_christened_string() if text: sd.paragraph(text) text = get_parents_desc(database, person) if text: sd.paragraph(text) sd.paragraph('') # Family Details for family in sa.parent_in(person): text = narrator.get_married_string(family) if text: sd.paragraph(text) sd.paragraph('') # Death Details text = narrator.get_died_string(True) if text: sd.paragraph(text) text = narrator.get_buried_string() if text: sd.paragraph(text) sd.paragraph('') # Sources sd.header1(_('Sources')) for source in get_sources(database, person): sd.paragraph(source)
def run(database, document, obj): """ Display link references for this note. """ # setup the simple access functions sdb = SimpleAccess(database) sdoc = SimpleDoc(document) stab = QuickTable(sdb) # display the title sdoc.title(_("Link References for this note")) sdoc.paragraph("\n") stab.columns(_("Type"), _("Reference"), _("Link check")) for (ldomain, ltype, lprop, lvalue) in obj.get_links(): if ldomain == "gramps": tagtype = _(ltype) ref_obj = sdb.get_link(ltype, lprop, lvalue) if ref_obj: tagvalue = ref_obj tagcheck = _("Ok") else: tagvalue = styledtext_tag.value tagcheck = _("Failed: missing object") else: tagtype = _("Internet") tagvalue = lvalue tagcheck = "" stab.row(tagtype, tagvalue, tagcheck) if stab.get_row_count() > 0: stab.write(sdoc) document.has_data = True else: sdoc.paragraph(_("No link references for this note")) sdoc.paragraph("") document.has_data = False sdoc.paragraph("")
def run(database, document, person): """ Output a text biography of active person """ sa = SimpleAccess(database) sd = SimpleDoc(document) sd.title("Biography for %s" % sa.name(person)) sd.paragraph('') narrator = Narrator(database, verbose=True, use_call_name=True, use_fulldate=True) narrator.set_subject(person) # Birth Details text = narrator.get_born_string() if text: sd.paragraph(text) text = narrator.get_baptised_string() if text: sd.paragraph(text) text = narrator.get_christened_string() if text: sd.paragraph(text) text = get_parents_desc(database, person) if text: sd.paragraph(text) sd.paragraph('') # Family Details for family in sa.parent_in(person): text = narrator.get_married_string(family) if text: sd.paragraph(text) sd.paragraph('') # Death Details text = narrator.get_died_string(True) if text: sd.paragraph(text) text = narrator.get_buried_string() if text: sd.paragraph(text) sd.paragraph('') # Sources sd.header1('Sources') for source in get_sources(database, person): sd.paragraph(source)