def instance_from_struct(cls, struct): """ Given a struct with metadata, create a Gramps object. self is class when called as a classmethod. """ from gramps.gen.lib import (Person, Family, Event, Source, Place, Citation, Repository, Media, Note, Tag, Date) if isinstance(struct, dict): if "_class" in struct.keys(): if struct["_class"] == "Person": return Person.create(Person.from_struct(struct)) elif struct["_class"] == "Family": return Family.create(Family.from_struct(struct)) elif struct["_class"] == "Event": return Event.create(Event.from_struct(struct)) elif struct["_class"] == "Source": return Source.create(Source.from_struct(struct)) elif struct["_class"] == "Place": return Place.create(Place.from_struct(struct)) elif struct["_class"] == "Citation": return Citation.create(Citation.from_struct(struct)) elif struct["_class"] == "Repository": return Repository.create(Repository.from_struct(struct)) elif struct["_class"] == "Media": return Media.create(Media.from_struct(struct)) elif struct["_class"] == "Note": return Note.create(Note.from_struct(struct)) elif struct["_class"] == "Tag": return Tag.create(Tag.from_struct(struct)) elif struct["_class"] == "Date": return Date().unserialize(Date.from_struct(struct, full=True)) raise AttributeError("invalid struct: %s" % struct)
def read_family_line(self, line, fields): self.current_husband_handle = None self.current_child_birthplace_handle = None self.current_child_source_handle = None self.current_family = Family() self.db.add_family(self.current_family, self.trans) #self.db.commit_family(self.current_family,self.trans) self.fkeys.append(self.current_family.get_handle()) idx = 1 LOG.debug("\nHusband:") (idx, husband) = self.parse_person(fields, idx, Person.MALE, None) if husband: self.current_husband_handle = husband.get_handle() self.current_family.set_father_handle(husband.get_handle()) self.db.commit_family(self.current_family, self.trans) husband.add_family_handle(self.current_family.get_handle()) self.db.commit_person(husband, self.trans) LOG.debug("Marriage:") idx = self.parse_marriage(fields, idx) LOG.debug("Wife:") (idx, wife) = self.parse_person(fields, idx, Person.FEMALE, None) if wife: self.current_family.set_mother_handle(wife.get_handle()) self.db.commit_family(self.current_family, self.trans) wife.add_family_handle(self.current_family.get_handle()) self.db.commit_person(wife, self.trans) return None
def instance_from_struct(cls, struct): """ Given a struct with metadata, create a Gramps object. self is class when called as a classmethod. """ from gramps.gen.lib import (Person, Family, Event, Source, Place, Citation, Repository, Media, Note, Tag, Date) if isinstance(struct, dict): if "_class" in struct.keys(): if struct["_class"] == "Person": return Person.create(Person.from_struct(struct)) elif struct["_class"] == "Family": return Family.create(Family.from_struct(struct)) elif struct["_class"] == "Event": return Event.create(Event.from_struct(struct)) elif struct["_class"] == "Source": return Source.create(Source.from_struct(struct)) elif struct["_class"] == "Place": return Place.create(Place.from_struct(struct)) elif struct["_class"] == "Citation": return Citation.create(Citation.from_struct(struct)) elif struct["_class"] == "Repository": return Repository.create(Repository.from_struct(struct)) elif struct["_class"] == "Media": return Media.create(Media.from_struct(struct)) elif struct["_class"] == "Note": return Note.create(Note.from_struct(struct)) elif struct["_class"] == "Tag": return Tag.create(Tag.from_struct(struct)) elif struct["_class"] == "Date": return Date().unserialize( Date.from_struct(struct, full=True)) raise AttributeError("invalid struct: %s" % struct)
def __init__(self, dbstate, uistate, clicked): self.clicked_func = clicked self.filter_id = widgets.BasicEntry() self.filter_father = widgets.BasicEntry() self.filter_mother = widgets.BasicEntry() self.filter_child = widgets.BasicEntry() self.filter_event = Event() self.filter_event.set_type((EventType.CUSTOM, '')) self.etype = Gtk.ComboBox(has_entry=True) self.family_stub = Family() self.family_stub.set_relationship((FamilyRelType.CUSTOM, '')) self.rtype = Gtk.ComboBox(has_entry=True) self.event_menu = widgets.MonitoredDataType(self.etype, self.filter_event.set_type, self.filter_event.get_type) self.rel_menu = widgets.MonitoredDataType( self.rtype, self.family_stub.set_relationship, self.family_stub.get_relationship) self.filter_note = widgets.BasicEntry() self.filter_regex = Gtk.CheckButton(label=_('Use regular expressions')) self.tag = Gtk.ComboBox() self.generic = Gtk.ComboBox() SidebarFilter.__init__(self, dbstate, uistate, "Family")
def from_struct(struct): """ Given a struct with metadata, create a Gramps object. """ from gramps.gen.lib import (Person, Family, Event, Source, Place, Citation, Repository, MediaObject, Note, Tag) if isinstance(struct, dict): if "_class" in struct.keys(): if struct["_class"] == "Person": return Person.create(Person.from_struct(struct)) elif struct["_class"] == "Family": return Family.create(Family.from_struct(struct)) elif struct["_class"] == "Event": return Event.create(Event.from_struct(struct)) elif struct["_class"] == "Source": return Source.create(Source.from_struct(struct)) elif struct["_class"] == "Place": return Place.create(Place.from_struct(struct)) elif struct["_class"] == "Citation": return Citation.create(Citation.from_struct(struct)) elif struct["_class"] == "Repository": return Repository.create(Repository.from_struct(struct)) elif struct["_class"] == "MediaObject": return MediaObject.create(MediaObject.from_struct(struct)) elif struct["_class"] == "Note": return Note.create(Note.from_struct(struct)) elif struct["_class"] == "Tag": return Tag.create(Tag.from_struct(struct)) raise AttributeError("invalid struct: %s" % struct)
def __add_family(self, father, mother, trans): family = Family() family.set_father_handle(father.handle) family.set_mother_handle(mother.handle) fam_handle = self.db.add_family(family, trans) father.add_family_handle(fam_handle) mother.add_family_handle(fam_handle) self.db.commit_person(father, trans) self.db.commit_person(mother, trans) return family
def add_parent_family(self, obj, event, handle): if button_activated(event, _LEFT_BUTTON): family = Family() person = self.dbstate.db.get_person_from_handle(self.get_handle()) ref = ChildRef() ref.ref = person.handle family.add_child_ref(ref) try: EditFamily(self.dbstate, self.uistate, [], family) except WindowActiveError: pass
def log(self, ltype, action, handles): for handle in set(handles): if self.last_log == (ltype, action, handle): continue self.last_log = (ltype, action, handle) self.timestamp() # Translators: needed for French, ignore otherwise self.append_text(_("%s: ") % _(action)) if action == 'Deleted': transaction = self.dbstate.db.transaction if ltype == 'Person': name = 'a person' if transaction is not None: for i in transaction.get_recnos(reverse=True): (obj_type, trans_type, hndl, old_data, dummy) = \ transaction.get_record(i) if isinstance(hndl, bytes): hndl = str(hndl, "utf-8") if (obj_type == PERSON_KEY and trans_type == TXNDEL and hndl == handle): person = Person() person.unserialize(old_data) name = name_displayer.display(person) break elif ltype == 'Family': name = 'a family' if transaction is not None: for i in transaction.get_recnos(reverse=True): (obj_type, trans_type, hndl, old_data, dummy) = \ transaction.get_record(i) if isinstance(hndl, bytes): hndl = str(hndl, "utf-8") if (obj_type == FAMILY_KEY and trans_type == TXNDEL and hndl == handle): family = Family() family.unserialize(old_data) name = family_name(family, self.dbstate.db, name) break self.append_text(name) else: if ltype == 'Person': person = self.dbstate.db.get_person_from_handle(handle) name = name_displayer.display(person) elif ltype == 'Family': family = self.dbstate.db.get_family_from_handle(handle) name = family_name(family, self.dbstate.db, 'a family') self.link(name, ltype, handle) self.append_text("\n")
def add_parents(self, *obj): family = Family() person = self.dbstate.db.get_person_from_handle(self.handle) if not person: return ref = ChildRef() ref.ref = person.handle family.add_child_ref(ref) try: EditFamily(self.dbstate, self.uistate, [], family) except WindowActiveError: pass
def log(self, ltype, action, handles): for handle in set(handles): if self.last_log == (ltype, action, handle): continue self.last_log = (ltype, action, handle) self.timestamp() # translators: needed for French, ignore otherwise self.append_text(_("%s: ") % _(action)) if action == 'Deleted': transaction = self.dbstate.db.transaction if ltype == 'Person': name = 'a person' if transaction is not None: for i in transaction.get_recnos(reverse=True): (obj_type, trans_type, hndl, old_data, dummy) = \ transaction.get_record(i) if isinstance(hndl, bytes): hndl = str(hndl, "utf-8") if (obj_type == PERSON_KEY and trans_type == TXNDEL and hndl == handle): person = Person() person.unserialize(old_data) name = name_displayer.display(person) break elif ltype == 'Family': name = 'a family' if transaction is not None: for i in transaction.get_recnos(reverse=True): (obj_type, trans_type, hndl, old_data, dummy) = \ transaction.get_record(i) if isinstance(hndl, bytes): hndl = str(hndl, "utf-8") if (obj_type == FAMILY_KEY and trans_type == TXNDEL and hndl == handle): family = Family() family.unserialize(old_data) name = family_name(family, self.dbstate.db, name) break self.append_text(name) else: if ltype == 'Person': person = self.dbstate.db.get_person_from_handle(handle) name = name_displayer.display(person) elif ltype == 'Family': family = self.dbstate.db.get_family_from_handle(handle) name = family_name(family, self.dbstate.db, 'a family') self.link(name, ltype, handle) self.append_text("\n")
def __init__(self, dbstate, uistate, clicked): self.clicked_func = clicked self.filter_id = widgets.BasicEntry() self.filter_father = widgets.BasicEntry() self.filter_mother = widgets.BasicEntry() self.filter_child = widgets.BasicEntry() self.filter_event = Event() self.filter_event.set_type((EventType.CUSTOM, '')) self.etype = Gtk.ComboBox(has_entry=True) self.family_stub = Family() self.family_stub.set_relationship((FamilyRelType.CUSTOM, '')) self.rtype = Gtk.ComboBox(has_entry=True) self.event_menu = widgets.MonitoredDataType( self.etype, self.filter_event.set_type, self.filter_event.get_type) self.rel_menu = widgets.MonitoredDataType( self.rtype, self.family_stub.set_relationship, self.family_stub.get_relationship) self.filter_note = widgets.BasicEntry() self.filter_regex = Gtk.CheckButton(label=_('Use regular expressions')) self.tag = Gtk.ComboBox() self.generic = Gtk.ComboBox() SidebarFilter.__init__(self, dbstate, uistate, "Family")
def read_family_line(self,line,fields): self.current_husband_handle = None self.current_child_birthplace_handle = None self.current_child_source_handle = None self.current_family = Family() self.db.add_family(self.current_family,self.trans) #self.db.commit_family(self.current_family,self.trans) self.fkeys.append(self.current_family.get_handle()) idx = 1; LOG.debug("\nHusband:") (idx, husband) = self.parse_person(fields,idx,Person.MALE,None) if husband: self.current_husband_handle = husband.get_handle() self.current_family.set_father_handle(husband.get_handle()) self.db.commit_family(self.current_family,self.trans) husband.add_family_handle(self.current_family.get_handle()) self.db.commit_person(husband,self.trans) LOG.debug("Marriage:") idx = self.parse_marriage(fields,idx) LOG.debug("Wife:") (idx,wife) = self.parse_person(fields,idx,Person.FEMALE,None) if wife: self.current_family.set_mother_handle(wife.get_handle()) self.db.commit_family(self.current_family,self.trans) wife.add_family_handle(self.current_family.get_handle()) self.db.commit_person(wife,self.trans) return None
def importData(db, filename, user): """Function called by Gramps to import data on persons in CSV format.""" db.disable_signals() try: with DbTxn(_("JSON import"), db, batch=True) as trans: with OpenFileOrStdin(filename, encoding="utf-8") as fp: line = fp.readline() while line: data = json.loads(line) if data["_class"] == "Person": obj = Person.create(Person.from_struct(data)) db.add_person(obj, trans) elif data["_class"] == "Family": obj = Family.create(Family.from_struct(data)) db.add_family(obj, trans) elif data["_class"] == "Event": obj = Event.create(Event.from_struct(data)) db.add_event(obj, trans) elif data["_class"] == "Media": obj = Media.create(Media.from_struct(data)) db.add_media(obj, trans) elif data["_class"] == "Repository": obj = Repository.create(Repository.from_struct(data)) db.add_repository(obj, trans) elif data["_class"] == "Tag": obj = Tag.create(Tag.from_struct(data)) db.add_tag(obj, trans) elif data["_class"] == "Source": obj = Source.create(Source.from_struct(data)) db.add_source(obj, trans) elif data["_class"] == "Citation": obj = Citation.create(Citation.from_struct(data)) db.add_citation(obj, trans) elif data["_class"] == "Note": obj = Note.create(Note.from_struct(data)) db.add_note(obj, trans) elif data["_class"] == "Place": obj = Place.create(Place.from_struct(data)) db.add_place(obj, trans) else: LOG.warn("ignored: " + data) line = fp.readline() except EnvironmentError as err: user.notify_error(_("%s could not be opened\n") % filename, str(err)) db.enable_signals() db.request_rebuild()
def _get_parent(self, person, father): """ Get the father of the family if father == True, otherwise mother """ if person: parent_handle_list = person.get_parent_family_handle_list() if parent_handle_list: family_id = parent_handle_list[0] family = self.dbstate.db.get_family_from_handle(family_id) if family: if father: person_handle = Family.get_father_handle(family) else: person_handle = Family.get_mother_handle(family) if person_handle: fct = self.dbstate.db.get_person_from_handle return fct(person_handle) return None
def add_family_update_refs( db_handle: DbWriteBase, obj: Family, trans: DbTxn, ) -> None: """Update the `family_list` and `parent_family_list` of family members. Case where the family is new. """ # add family handle to parents for handle in [obj.get_father_handle(), obj.get_mother_handle()]: if handle: parent = db_handle.get_person_from_handle(handle) parent.add_family_handle(obj.handle) db_handle.commit_person(parent, trans) # for each child, add the family handle to the child for ref in obj.get_child_ref_list(): child = db_handle.get_person_from_handle(ref.ref) child.add_parent_family_handle(obj.handle) db_handle.commit_person(child, trans)
def object_extend(self, obj: Family, args: Dict, locale: GrampsLocale = glocale) -> Family: """Extend family attributes as needed.""" db_handle = self.db_handle if "profile" in args: obj.profile = get_family_profile_for_object(db_handle, obj, args["profile"], locale=locale) if "extend" in args: obj.extended = get_extended_attributes(db_handle, obj, args) if "all" in args["extend"] or "father_handle" in args["extend"]: obj.extended["father"] = get_person_by_handle( db_handle, obj.father_handle) if "all" in args["extend"] or "mother_handle" in args["extend"]: obj.extended["mother"] = get_person_by_handle( db_handle, obj.mother_handle) return obj
def update_family_update_refs( db_handle: DbWriteBase, obj_old: Family, obj: Family, trans: DbTxn, ) -> None: """Update the `family_list` and `parent_family_list` of family members. Case where the family was modified. """ _fix_parent_handles( db_handle, obj, obj_old.get_father_handle(), obj.get_father_handle(), trans ) _fix_parent_handles( db_handle, obj, obj_old.get_mother_handle(), obj.get_mother_handle(), trans ) # fix child handles orig_set = set(r.ref for r in obj_old.get_child_ref_list()) new_set = set(r.ref for r in obj.get_child_ref_list()) # remove the family from children which have been removed for ref in orig_set - new_set: person = db_handle.get_person_from_handle(ref) person.remove_parent_family_handle(obj.handle) db_handle.commit_person(person, trans) # add the family to children which have been added for ref in new_set - orig_set: person = db_handle.get_person_from_handle(ref) person.add_parent_family_handle(obj.handle) db_handle.commit_person(person, trans)
def post(self, path): if "/" in path: handle, action = path.split("/") else: handle, action = path, "view" if handle == "add": family = Family() family.handle = handle = create_id() else: family = self.database.get_family_from_handle(handle) form = FamilyForm(self.database, _, instance=family) form.save(handler=self) self.redirect("/family/%(handle)s" % {"handle": handle})
def get(self, path=""): """ HANDLE HANDLE/edit|delete /add b2cfa6ca1e174b1f63d/remove/eventref/1 """ page = int(self.get_argument("page", 1)) search = self.get_argument("search", "") if "/" in path: handle, action = path.split("/", 1) else: handle, action = path, "view" if handle: if handle == "add": family = Family() action = "edit" else: family = self.database.get_family_from_handle(handle) if family: self.render( "family.html", **self.get_template_dict(tview=_("family detail"), page=page, action=action, form=FamilyForm(self.database, _, instance=family), logform=None)) return else: self.clear() self.set_status(404) self.finish("<html><body>No such family</body></html>") return self.render( "page_view.html", **self.get_template_dict( tview=_("family view"), page=page, search=search, form=FamilyForm(self.database, _, table="Family"), ))
def add_spouse(self, *obj): family = Family() person = self.dbstate.db.get_person_from_handle(self.handle) if not person: return if person.gender == Person.MALE: family.set_father_handle(person.handle) else: family.set_mother_handle(person.handle) try: EditFamily(self.dbstate, self.uistate, [], family) except WindowActiveError: pass
def add_family(self, obj, event, handle): if button_activated(event, _LEFT_BUTTON): family = Family() person = self.dbstate.db.get_person_from_handle(self.get_handle()) if not person: return if person.gender == Person.MALE: family.set_father_handle(person.handle) else: family.set_mother_handle(person.handle) try: EditFamily(self.dbstate, self.uistate, [], family) except WindowActiveError: pass
def exportData(database, filename, error_dialog=None, option_box=None, callback=None): if not callable(callback): callback = lambda percent: None # dummy with OpenFileOrStdout(filename) as fp: total = (len(database.note_map) + len(database.person_map) + len(database.event_map) + len(database.family_map) + len(database.repository_map) + len(database.place_map) + len(database.media_map) + len(database.source_map)) count = 0.0 # GProlog ISO directives: # /number must match the number of arguments to functions: fp.write(":- discontiguous(data/2).\n") fp.write(":- discontiguous(is_alive/2).\n") fp.write(":- discontiguous(parent/2).\n") # Rules: fp.write("grandparent(X, Y) :- parent(X, Z), parent(Z, Y).\n") fp.write("ancestor(X, Y) :- parent(X, Y).\n") fp.write("ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).\n") fp.write("sibling(X, Y) :- parent(Z, X), parent(Z, Y), X \= Y.\n") # --------------------------------- # Notes # --------------------------------- for note_handle in database.note_map.keys(): note = database.note_map[note_handle] #write_line(fp, "note_details(%s, %s)" % (note_handle, note)) count += 1 callback(100 * count / total) # --------------------------------- # Event # --------------------------------- for event_handle in database.event_map.keys(): event = database.event_map[event_handle] #write_line(fp, "event:", event_handle, event) count += 1 callback(100 * count / total) # --------------------------------- # Person # --------------------------------- for person_handle in database.person_map.keys(): data = database.person_map[person_handle] person = Person.create(data) gid = person.gramps_id.lower() fp.write("data(%s, '%s').\n" % (gid, escape(name_displayer.display(person)))) fp.write("is_alive(%s, '%s').\n" % (gid, probably_alive(person, database))) count += 1 callback(100 * count / total) # --------------------------------- # Family # --------------------------------- for family_handle in database.family_map.keys(): data = database.family_map[family_handle] family = Family.create(data) father_handle = family.get_father_handle() mother_handle = family.get_mother_handle() parents = [] if mother_handle: mother = database.get_person_from_handle(mother_handle) if mother: parents.append(mother.gramps_id.lower()) if father_handle: father = database.get_person_from_handle(father_handle) if father: parents.append(father.gramps_id.lower()) children = [] for child_ref in family.get_child_ref_list(): child_handle = child_ref.ref child = database.get_person_from_handle(child_handle) if child: children.append(child.gramps_id.lower()) for pid in parents: for cid in children: fp.write("parent(%s, %s).\n" % (pid, cid)) count += 1 callback(100 * count / total) # --------------------------------- # Repository # --------------------------------- for repository_handle in database.repository_map.keys(): repository = database.repository_map[repository_handle] #write_line(fp, "repository:", repository_handle, repository) count += 1 callback(100 * count / total) # --------------------------------- # Place # --------------------------------- for place_handle in database.place_map.keys(): place = database.place_map[place_handle] #write_line(fp, "place:", place_handle, place) count += 1 callback(100 * count / total) # --------------------------------- # Source # --------------------------------- for source_handle in database.source_map.keys(): source = database.source_map[source_handle] #write_line(fp, "source:", source_handle, source) count += 1 callback(100 * count / total) # --------------------------------- # Media # --------------------------------- for media_handle in database.media_map.keys(): media = database.media_map[media_handle] #write_line(fp, "media:", media_handle, media) count += 1 callback(100 * count / total) return True
class FamilySidebarFilter(SidebarFilter): def __init__(self, dbstate, uistate, clicked): self.clicked_func = clicked self.filter_id = widgets.BasicEntry() self.filter_father = widgets.BasicEntry() self.filter_mother = widgets.BasicEntry() self.filter_child = widgets.BasicEntry() self.filter_event = Event() self.filter_event.set_type((EventType.CUSTOM, '')) self.etype = Gtk.ComboBox(has_entry=True) self.family_stub = Family() self.family_stub.set_relationship((FamilyRelType.CUSTOM, '')) self.rtype = Gtk.ComboBox(has_entry=True) self.event_menu = widgets.MonitoredDataType( self.etype, self.filter_event.set_type, self.filter_event.get_type) self.rel_menu = widgets.MonitoredDataType( self.rtype, self.family_stub.set_relationship, self.family_stub.get_relationship) self.filter_note = widgets.BasicEntry() self.filter_regex = Gtk.CheckButton(label=_('Use regular expressions')) self.tag = Gtk.ComboBox() self.generic = Gtk.ComboBox() SidebarFilter.__init__(self, dbstate, uistate, "Family") def create_widget(self): cell = Gtk.CellRendererText() cell.set_property('width', self._FILTER_WIDTH) cell.set_property('ellipsize', self._FILTER_ELLIPSIZE) self.generic.pack_start(cell, True) self.generic.add_attribute(cell, 'text', 0) self.on_filters_changed('Family') cell = Gtk.CellRendererText() cell.set_property('width', self._FILTER_WIDTH) cell.set_property('ellipsize', self._FILTER_ELLIPSIZE) self.tag.pack_start(cell, True) self.tag.add_attribute(cell, 'text', 0) self.etype.get_child().set_width_chars(5) self.rtype.get_child().set_width_chars(5) self.add_text_entry(_('ID'), self.filter_id) self.add_text_entry(_('Father'), self.filter_father) self.add_text_entry(_('Mother'), self.filter_mother) self.add_text_entry(_('Child'), self.filter_child) self.add_entry(_('Relationship'), self.rtype) self.add_entry(_('Family Event'), self.etype) self.add_text_entry(_('Family Note'), self.filter_note) self.add_entry(_('Tag'), self.tag) self.add_filter_entry(_('Custom filter'), self.generic) self.add_regex_entry(self.filter_regex) def clear(self, obj): self.filter_id.set_text('') self.filter_father.set_text('') self.filter_mother.set_text('') self.filter_child.set_text('') self.filter_note.set_text('') self.etype.get_child().set_text('') self.rtype.get_child().set_text('') self.tag.set_active(0) self.generic.set_active(0) def get_filter(self): gid = str(self.filter_id.get_text()).strip() father = str(self.filter_father.get_text()).strip() mother = str(self.filter_mother.get_text()).strip() child = str(self.filter_child.get_text()).strip() note = str(self.filter_note.get_text()).strip() etype = self.filter_event.get_type().xml_str() rtype = self.family_stub.get_relationship().xml_str() regex = self.filter_regex.get_active() tag = self.tag.get_active() > 0 generic = self.generic.get_active() > 0 empty = not (gid or father or mother or child or note or regex or etype or rtype or tag or generic) if empty: generic_filter = None else: generic_filter = GenericFamilyFilter() if gid: rule = RegExpIdOf([gid], use_regex=regex) generic_filter.add_rule(rule) if father: rule = RegExpFatherName([father], use_regex=regex) generic_filter.add_rule(rule) if mother: rule = RegExpMotherName([mother], use_regex=regex) generic_filter.add_rule(rule) if child: rule = RegExpChildName([child], use_regex=regex) generic_filter.add_rule(rule) if etype: rule = HasEvent([etype, '', '', '', ''], use_regex=regex) generic_filter.add_rule(rule) if rtype: rule = HasRelType([rtype], use_regex=regex) generic_filter.add_rule(rule) if note: rule = HasNoteRegexp([note], use_regex=regex) generic_filter.add_rule(rule) # check the Tag if tag: model = self.tag.get_model() node = self.tag.get_active_iter() attr = model.get_value(node, 0) rule = HasTag([attr]) generic_filter.add_rule(rule) if self.generic.get_active() != 0: model = self.generic.get_model() node = self.generic.get_active_iter() obj = str(model.get_value(node, 0)) rule = MatchesFilter([obj]) generic_filter.add_rule(rule) return generic_filter def on_filters_changed(self, name_space): if name_space == 'Family': all_filter = GenericFamilyFilter() all_filter.set_name(_("None")) all_filter.add_rule(rules.family.AllFamilies([])) self.generic.set_model(build_filter_model('Family', [all_filter])) self.generic.set_active(0) def on_tags_changed(self, tag_list): """ Update the list of tags in the tag filter. """ model = Gtk.ListStore(str) model.append(('',)) for tag_name in tag_list: model.append((tag_name,)) self.tag.set_model(model) self.tag.set_active(0)
def make_family(self, family): if self.use_db_cache and family.cache: data = family.from_cache() else: data = self.dji.get_family(family) return Family.create(data)
class GeneWebParser: def __init__(self, dbase, file): self.db = dbase if file: # Unit tests can create the parser w/o underlying file self.f = open(file, "rUb") self.filename = file self.encoding = 'iso-8859-1' self.gwplus = False def get_next_line(self): self.lineno += 1 line = self.f.readline() try: line = line.decode('utf-8') except GrampsImportError as err: self.errmsg(str(err)) if line: try: line = str(line.strip()) except UnicodeDecodeError: line = line.decode(self.encoding).strip() else: line = None return line def parse_geneweb_file(self): with DbTxn(_("GeneWeb import"), self.db, batch=True) as self.trans: self.db.disable_signals() t = time.time() self.lineno = 0 self.index = 0 self.fam_count = 0 self.indi_count = 0 self.fkeys = [] self.ikeys = {} self.pkeys = {} self.skeys = {} self.current_mode = None self.current_family = None self.current_husband_handle = None self.current_child_birthplace_handle = None self.current_child_source_handle = None try: while 1: line = self.get_next_line() if line is None: break if line == "": continue fields = line.split(" ") LOG.debug("LINE: %s" %line) if fields[0] == "gwplus": self.gwplus = True self.encoding = 'utf-8' elif fields[0] == "encoding:": self.encoding = fields[1] elif fields[0] == "fam": self.current_mode = "fam" self.read_family_line(line,fields) elif fields[0] == "rel": self.current_mode = "rel" self.read_relationship_person(line,fields) elif fields[0] == "src": self.read_source_line(line,fields) elif fields[0] in ("wit", "wit:"): self.read_witness_line(line,fields) elif fields[0] == "cbp": self.read_children_birthplace_line(line,fields) elif fields[0] == "csrc": self.read_children_source_line(line,fields) elif fields[0] == "beg" and self.current_mode == "fam": self.read_children_lines() elif fields[0] == "beg" and self.current_mode == "rel": self.read_relation_lines() elif fields[0] == "comm": self.read_family_comment(line,fields) elif fields[0] == "notes": self.read_person_notes_lines(line,fields) elif fields[0] == "fevt" and self.current_mode == "fam": #self.read_fevent_line(self.get_next_line()) pass elif fields[0] == "pevt": #self.read_pevent_line(self.get_next_line(), fields) pass elif fields[0] == "notes-db": self.read_database_notes_lines(line,fields) elif fields[0] == "pages-ext" or "wizard-note": pass elif fields[0] == "end": self.current_mode = None else: LOG.warning("parse_geneweb_file(): Token >%s< unknown. line %d skipped: %s" % (fields[0],self.lineno,line)) except GedcomError as err: self.errmsg(str(err)) t = time.time() - t # translators: leave all/any {...} untranslated msg = ngettext('Import Complete: {number_of} second', 'Import Complete: {number_of} seconds', t ).format(number_of=t) self.db.enable_signals() self.db.request_rebuild() LOG.debug(msg) LOG.debug("Families: %d" % len(self.fkeys)) LOG.debug("Individuals: %d" % len(self.ikeys)) return None def read_family_line(self,line,fields): self.current_husband_handle = None self.current_child_birthplace_handle = None self.current_child_source_handle = None self.current_family = Family() self.db.add_family(self.current_family,self.trans) #self.db.commit_family(self.current_family,self.trans) self.fkeys.append(self.current_family.get_handle()) idx = 1; LOG.debug("\nHusband:") (idx, husband) = self.parse_person(fields,idx,Person.MALE,None) if husband: self.current_husband_handle = husband.get_handle() self.current_family.set_father_handle(husband.get_handle()) self.db.commit_family(self.current_family,self.trans) husband.add_family_handle(self.current_family.get_handle()) self.db.commit_person(husband,self.trans) LOG.debug("Marriage:") idx = self.parse_marriage(fields,idx) LOG.debug("Wife:") (idx,wife) = self.parse_person(fields,idx,Person.FEMALE,None) if wife: self.current_family.set_mother_handle(wife.get_handle()) self.db.commit_family(self.current_family,self.trans) wife.add_family_handle(self.current_family.get_handle()) self.db.commit_person(wife,self.trans) return None def read_relationship_person(self,line,fields): LOG.debug("\Relationships:") (idx,person) = self.parse_person(fields,1,Person.UNKNOWN,None) if person: self.current_relationship_person_handle = person.get_handle() def read_relation_lines(self): if not self.current_relationship_person_handle: LOG.warning("Unknown person for relationship in line %d!" % self.lineno) return None rel_person = self.db.get_person_from_handle(self.current_relationship_person_handle) while 1: line = self.get_next_line() if line is None or line == "end": break if line == "": continue # match relationship type and related person line_re = re.compile("^- ([^:]+): (.*)$") matches = line_re.match(line) if matches: #split related person into fields fields = matches.groups()[1].split(" ") if fields: (idx,asso_p) = self.parse_person(fields,0,Person.UNKNOWN,None) pref = PersonRef() pref.set_relation(matches.groups()[0]) LOG.warning("TODO: Handle association types properly") pref.set_reference_handle(asso_p.get_handle()) rel_person.add_person_ref(pref) self.db.commit_person(rel_person,self.trans) else: LOG.warning("Invalid name of person in line %d" % self.lineno) else: LOG.warning("Invalid relationship in line %d" % self.lineno) break self.current_mode = None return None def read_source_line(self,line,fields): if not self.current_family: LOG.warning("Unknown family of child in line %d!" % self.lineno) return None source = self.get_or_create_source(self.decode(fields[1])) self.current_family.add_citation(source.get_handle()) self.db.commit_family(self.current_family,self.trans) return None def read_witness_line(self,line,fields): LOG.debug("Witness:") if fields[1] == "m:": (idx,wit_p) = self.parse_person(fields,2,Person.MALE,None) elif fields[1] == "f:": (idx,wit_p) = self.parse_person(fields,2,Person.FEMALE,None) else: (idx,wit_p) = self.parse_person(fields,1,None,None) if wit_p: mev = None # search marriage event for evr in self.current_family.get_event_ref_list(): ev = self.db.get_event_from_handle(evr.get_reference_handle()) if ev.get_type() == EventType.MARRIAGE: mev = ev # found. if not mev: # No marriage event found create a new one mev = self.create_event(EventType.MARRIAGE, None, None, None, None) mar_ref = EventRef() mar_ref.set_reference_handle(mev.get_handle()) self.current_family.add_event_ref(mar_ref) wit_ref = EventRef() wit_ref.set_role(EventRoleType(EventRoleType.WITNESS)) wit_ref.set_reference_handle(mev.get_handle()) wit_p.add_event_ref(wit_ref) self.db.commit_person(wit_p,self.trans) return None def read_children_lines(self): father_surname = "Dummy" if not self.current_husband_handle: LOG.warning("Unknown father for child in line %d!" % self.lineno) return None husb = self.db.get_person_from_handle(self.current_husband_handle) father_surname = husb.get_primary_name().get_surname() if not self.current_family: LOG.warning("Unknown family of child in line %d!" % self.lineno) return None while 1: line = self.get_next_line() if line is None: break if line == "": continue fields = line.split(" ") if fields[0] == "-": LOG.debug("Child:") child = None if fields[1] == "h": (idx,child) = self.parse_person(fields,2,Person.MALE,father_surname) elif fields[1] == "f": (idx,child) = self.parse_person(fields,2,Person.FEMALE,father_surname) else: (idx,child) = self.parse_person(fields,1,Person.UNKNOWN,father_surname) if child: childref = ChildRef() childref.set_reference_handle(child.get_handle()) self.current_family.add_child_ref( childref) self.db.commit_family(self.current_family,self.trans) child.add_parent_family_handle( self.current_family.get_handle()) if self.current_child_birthplace_handle: birth = None birth_ref = child.get_birth_ref() if birth_ref: birth = self.db.get_event_from_handle(birth_ref.ref) if not birth: birth = self.create_event(EventType.BIRTH) birth_ref = EventRef() birth_ref.set_reference_handle(birth.get_handle()) child.set_birth_ref(birth_ref) birth.set_place_handle(self.current_child_birthplace_handle) self.db.commit_event(birth,self.trans) if self.current_child_source_handle: child.add_citation(self.current_child_source_handle) self.db.commit_person(child,self.trans) else: break self.current_mode = None return None def read_children_birthplace_line(self,line,fields): cbp = self.get_or_create_place(self.decode(fields[1])) if cbp: self.current_child_birthplace_handle = cbp.get_handle() return None def read_children_source_line(self,line,fields): csrc = self.get_or_create_source(self.decode(fields[1])) self.current_child_source_handle = csrc.handle return None def read_family_comment(self,line,fields): if not self.current_family: LOG.warning("Unknown family of child in line %d!" % self.lineno) return None n = Note() n.set(line) self.db.add_note(n,self.trans) self.current_family.add_note(n.handle) self.db.commit_family(self.current_family,self.trans) return None def _read_notes_lines(self, note_tag): note_txt = "" while True: line = self.get_next_line() if line is None: break fields = line.split(" ") if fields[0] == "end" and fields[1] == note_tag: break elif fields[0] == "beg": continue else: if note_txt: note_txt = note_txt + "\n" + line else: note_txt = note_txt + line if note_txt: n = Note() n.set(note_txt) self.db.add_note(n,self.trans) return n.handle return None def read_person_notes_lines(self,line,fields): (idx,person) = self.parse_person(fields,1,None,None) note_handle = self._read_notes_lines( fields[0]) if note_handle: person.add_note(note_handle) self.db.commit_person(person,self.trans) def read_database_notes_lines(self,line,fields): note_handle = self._read_notes_lines( fields[0]) def parse_marriage(self,fields,idx): mariageDataRe = re.compile("^[+#-0-9].*$") mar_date = None mar_place = None mar_source = None sep_date = None div_date = None married = 1 engaged = 0 # skip to marriage date in case person contained unmatches tokens #Alex: this failed when fields[idx] was an empty line. Fixed. #while idx < len(fields) and not fields[idx][0] == "+": while idx < len(fields) and not (fields[idx] and fields[idx][0] == "+"): if fields[idx]: LOG.warning(("parse_marriage(): Unknown field: " + "'%s' in line %d!") % (fields[idx], self.lineno)) idx += 1 while idx < len(fields) and mariageDataRe.match(fields[idx]): field = fields[idx] idx += 1 if field.startswith("+"): field = field[1:] mar_date = self.parse_date(self.decode(field)) LOG.debug(" Married at: %s" % field) elif field.startswith("-"): field = field[1:] div_date = self.parse_date(self.decode(field)) LOG.debug(" Div at: %s" % field) elif field == "#mp" and idx < len(fields): mar_place = self.get_or_create_place(self.decode(fields[idx])) LOG.debug(" Marriage place: %s" % fields[idx]) idx += 1 elif field == "#ms" and idx < len(fields): mar_source = self.get_or_create_source(self.decode(fields[idx])) LOG.debug(" Marriage source: %s" % fields[idx]) idx += 1 elif field == "#sep" and idx < len(fields): sep_date = self.parse_date(self.decode(fields[idx])) LOG.debug(" Seperated since: %s" % fields[idx]) idx += 1 elif field == "#nm": LOG.debug(" Are not married.") married = 0 elif field == "#noment": LOG.debug(" Not mentioned.") elif field == "#eng": LOG.debug(" Are engaged.") engaged = 1 else: LOG.warning(("parse_marriage(): Unknown field " + "'%s'for mariage in line %d!") % (field, self.lineno)) if mar_date or mar_place or mar_source: mar = self.create_event( EventType.MARRIAGE, None, mar_date, mar_place, mar_source) mar_ref = EventRef() mar_ref.set_reference_handle(mar.get_handle()) mar_ref.set_role(EventRoleType.FAMILY) self.current_family.add_event_ref(mar_ref) self.current_family.set_relationship( FamilyRelType(FamilyRelType.MARRIED)) if div_date: div = self.create_event( EventType.DIVORCE, None, div_date, None, None) div_ref = EventRef() div_ref.set_reference_handle(div.get_handle()) div_ref.set_role(EventRoleType.FAMILY) self.current_family.add_event_ref(div_ref) if sep_date or engaged: sep = self.create_event( EventType.ENGAGEMENT, None, sep_date, None, None) sep_ref = EventRef() sep_ref.set_reference_handle(sep.get_handle()) sep_ref.set_role(EventRoleType.FAMILY) self.current_family.add_event_ref(sep_ref) if not married: self.current_family.set_relationship( FamilyRelType(FamilyRelType.UNMARRIED)) self.db.commit_family(self.current_family,self.trans) return idx def parse_person(self,fields,idx,gender,father_surname): if not father_surname: if not idx < len(fields): LOG.warning("Missing surname of person in line %d!" % self.lineno) surname ="" else: surname = self.decode(fields[idx]) idx += 1 else: surname = father_surname if not idx < len(fields): LOG.warning("Missing firstname of person in line %d!" % self.lineno) firstname = "" else: firstname = self.decode(fields[idx]) idx += 1 if idx < len(fields) and father_surname: noSurnameRe = re.compile("^[({\[~><?0-9#].*$") if not noSurnameRe.match(fields[idx]): surname = self.decode(fields[idx]) idx += 1 LOG.debug("Person: %s %s" % (firstname, surname)) person = self.get_or_create_person(firstname,surname) name = Name() name.set_type( NameType(NameType.BIRTH)) name.set_first_name(firstname) surname_obj = name.get_primary_surname() surname_obj.set_surname(surname) person.set_primary_name(name) if person.get_gender() == Person.UNKNOWN and gender is not None: person.set_gender(gender) self.db.commit_person(person,self.trans) personDataRe = re.compile("^[kmes0-9<>~#\[({!].*$") dateRe = re.compile("^[kmes0-9~<>?]+.*$") source = None birth_parsed = False birth_date = None birth_place = None birth_source = None bapt_date = None bapt_place = None bapt_source = None death_date = None death_place = None death_source = None death_cause = None crem_date = None bur_date = None bur_place = None bur_source = None public_name = None firstname_aliases = [] nick_names = [] name_aliases = [] surname_aliases = [] while idx < len(fields) and personDataRe.match(fields[idx]): field = fields[idx] idx += 1 if field.startswith('('): LOG.debug("Public Name: %s" % field) public_name = self.decode(field[1:-1]) elif field.startswith('{'): LOG.debug("Firstsname Alias: %s" % field) firstname_aliases.append(self.decode(field[1:-1])) elif field.startswith('['): LOG.debug("Title: %s" % field) titleparts = self.decode(field[1:-1]).split(":") tname = ttitle = tplace = tstart = tend = tnth = None try: tname = titleparts[0] ttitle = titleparts[1] if titleparts[2]: tplace = self.get_or_create_place(titleparts[2]) tstart = self.parse_date(titleparts[3]) tend = self.parse_date(titleparts[4]) tnth = titleparts[5] except IndexError: # not all parts are written all the time pass if tnth: # Append title numer to title ttitle += ", " + tnth title = self.create_event( EventType.NOB_TITLE, ttitle, tstart, tplace) # TODO: Geneweb has a start date and an end date, and therefore # supports stuff like: FROM about 1955 TO between 1998 and 1999 # gramps only supports one single date or range. if tname and tname != "*": n = Note() n.set(tname) self.db.add_note(n,self.trans) title.add_note( n.handle) title_ref = EventRef() title_ref.set_reference_handle(title.get_handle()) person.add_event_ref(title_ref) elif field == '#nick' and idx < len(fields): LOG.debug("Nick Name: %s" % fields[idx]) nick_names.append(self.decode(fields[idx])) idx += 1 elif field == '#occu' and idx < len(fields): LOG.debug("Occupation: %s" % fields[idx]) occu = self.create_event( EventType.OCCUPATION, self.decode(fields[idx])) occu_ref = EventRef() occu_ref.set_reference_handle(occu.get_handle()) person.add_event_ref(occu_ref) idx += 1 elif field == '#alias' and idx < len(fields): LOG.debug("Name Alias: %s" % fields[idx]) name_aliases.append(self.decode(fields[idx])) idx += 1 elif field == '#salias' and idx < len(fields): LOG.debug("Surname Alias: %s" % fields[idx]) surname_aliases.append(self.decode(fields[idx])) idx += 1 elif field == '#image' and idx < len(fields): LOG.debug("Image: %s" % fields[idx]) idx += 1 elif field == '#src' and idx < len(fields): LOG.debug("Source: %s" % fields[idx]) source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 elif field == '#bs' and idx < len(fields): LOG.debug("Birth Source: %s" % fields[idx]) birth_source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 elif field[0] == '!': LOG.debug("Baptize at: %s" % field[1:]) bapt_date = self.parse_date(self.decode(field[1:])) elif field == '#bp' and idx < len(fields): LOG.debug("Birth Place: %s" % fields[idx]) birth_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 elif field == '#pp' and idx < len(fields): LOG.debug("Baptize Place: %s" % fields[idx]) bapt_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 elif field == '#ps' and idx < len(fields): LOG.debug("Baptize Source: %s" % fields[idx]) bapt_source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 elif field == '#dp' and idx < len(fields): LOG.debug("Death Place: %s" % fields[idx]) death_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 elif field == '#ds' and idx < len(fields): LOG.debug("Death Source: %s" % fields[idx]) death_source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 elif field == '#buri' and idx < len(fields): if fields[idx][0]!='#': # bug in GeneWeb: empty #buri fields LOG.debug("Burial Date: %s" % fields[idx]) bur_date = self.parse_date(self.decode(fields[idx])) idx += 1 elif field == '#crem' and idx < len(fields): LOG.debug("Cremention Date: %s" % fields[idx]) crem_date = self.parse_date(self.decode(fields[idx])) idx += 1 elif field == '#rp' and idx < len(fields): LOG.debug("Burial Place: %s" % fields[idx]) bur_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 elif field == '#rs' and idx < len(fields): LOG.debug("Burial Source: %s" % fields[idx]) bur_source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 elif field == '#apubl': LOG.debug("This is a public record") elif field == '#apriv': LOG.debug("This is a private record") person.set_privacy(True) elif field == '#h': LOG.debug("This is a restricted record") #TODO: Gramps does currently not feature this level person.set_privacy(True) elif dateRe.match(field): if not birth_parsed: LOG.debug("Birth Date: %s" % field) birth_date = self.parse_date(self.decode(field)) birth_parsed = True else: LOG.debug("Death Date: %s" % field) death_date = self.parse_date(self.decode(field)) if field == "mj": death_cause = "Died joung" elif field.startswith("k"): death_cause = "Killed" elif field.startswith("m"): death_cause = "Murdered" elif field.startswith("e"): death_cause = "Executed" elif field.startswith("d"): death_cause = "Disappeared" #TODO: Set special death types more properly else: LOG.warning(("parse_person(): Unknown field " + "'%s' for person in line %d!") % (field, self.lineno)) if public_name: name = person.get_primary_name() name.set_type(NameType(NameType.BIRTH)) person.add_alternate_name(name) name = Name() name.set_type(NameType(NameType.AKA)) name.set_first_name(public_name) surname_obj = name.get_primary_surname() surname_obj.set_surname(surname) person.set_primary_name(name) for aka in nick_names: name = Attribute() name.set_type(AttributeType(AttributeType.NICKNAME)) name.set_value(aka) person.add_attribute(name) for aka in firstname_aliases: name = Name() name.set_type(NameType(NameType.AKA)) name.set_first_name(aka) surname_obj = name.get_primary_surname() surname_obj.set_surname(surname) person.add_alternate_name(name) for aka in name_aliases: name = Name() name.set_type(NameType(NameType.AKA)) name.set_first_name(aka) surname_obj = name.get_primary_surname() surname_obj.set_surname(surname) person.add_alternate_name(name) for aka in surname_aliases: name = Name() name.set_type(NameType(NameType.AKA)) if public_name: name.set_first_name(public_name) else: name.set_first_name(firstname) surname_obj = name.get_primary_surname() surname_obj.set_surname(aka) person.add_alternate_name(name) if source: person.add_citation(source.get_handle()) if birth_date or birth_place or birth_source: birth = self.create_event(EventType.BIRTH, None, birth_date, birth_place, birth_source) birth_ref = EventRef() birth_ref.set_reference_handle( birth.get_handle()) person.set_birth_ref( birth_ref) if bapt_date or bapt_place or bapt_source: babt = self.create_event(EventType.BAPTISM, None, bapt_date, bapt_place, bapt_source) babt_ref = EventRef() babt_ref.set_reference_handle( babt.get_handle()) person.add_event_ref( babt_ref) if death_date or death_place or death_source or death_cause: death = self.create_event(EventType.DEATH, None, death_date, death_place, death_source) if death_cause: death.set_description(death_cause) self.db.commit_event(death,self.trans) death_ref = EventRef() death_ref.set_reference_handle( death.get_handle()) person.set_death_ref( death_ref) if bur_date: bur = self.create_event(EventType.BURIAL, None, bur_date, bur_place, bur_source) bur_ref = EventRef() bur_ref.set_reference_handle( bur.get_handle()) person.add_event_ref( bur_ref) if crem_date: crem = self.create_event(EventType.CREMATION, None, crem_date, bur_place, bur_source) crem_ref = EventRef() crem_ref.set_reference_handle( crem.get_handle()) person.add_event_ref(crem_ref) self.db.commit_person(person,self.trans) return (idx,person) def parse_date(self,field): if field == "0": return None date = Date() matches = _text_parse.match(field) if matches: groups = matches.groups() date.set_as_text(groups[0]) date.set_modifier(Date.MOD_TEXTONLY) return date matches = _date_parse.match(field) if matches: groups = matches.groups() mod = _mod_map.get(groups[0],Date.MOD_NONE) if groups[3] == "..": mod = Date.MOD_SPAN cal2 = _cal_map.get(groups[5],Date.CAL_GREGORIAN) sub2 = self.sub_date(groups[4]) else: sub2 = (0,0,0) cal1 = _cal_map.get(groups[2],Date.CAL_GREGORIAN) sub1 = self.sub_date(groups[1]) try: date.set(Date.QUAL_NONE,mod, cal1, (sub1[0],sub1[1],sub1[2],0,sub2[0],sub2[1],sub2[2],0)) except DateError as e: # TRANSLATORS: leave the {date} and {gw_snippet} untranslated # in the format string, but you may re-order them if needed. LOG.warning(_( "Invalid date {date} in {gw_snippet}, " "preserving date as text." ).format(date=e.date.to_struct(), gw_snippet=field)) date.set(modifier=Date.MOD_TEXTONLY, text=field) return date else: return None def sub_date(self,data): vals = data.split('/') if len(vals) == 1: return (0,0,int(vals[0])) elif len(vals) == 2: return (0,int(vals[0]),int(vals[1])) else: return (int(vals[0]),int(vals[1]),int(vals[2])) def create_event(self,type,desc=None,date=None,place=None,source=None): event = Event() if type: event.set_type(EventType(type)) if desc: event.set_description(desc) if date: event.set_date_object(date) if place: event.set_place_handle(place.get_handle()) if source: event.add_citation(source.get_handle()) self.db.add_event(event,self.trans) self.db.commit_event(event,self.trans) return event def get_or_create_person(self,firstname,lastname): person = None mykey = firstname+lastname if mykey in self.ikeys and firstname != "?" and lastname != "?": person = self.db.get_person_from_handle(self.ikeys[mykey]) else: person = Person() self.db.add_person(person,self.trans) self.db.commit_person(person,self.trans) self.ikeys[mykey] = person.get_handle() return person def get_or_create_place(self,place_name): place = None if place_name in self.pkeys: place = self.db.get_place_from_handle(self.pkeys[place_name]) else: place = Place() place.set_title(place_name) self.db.add_place(place,self.trans) self.db.commit_place(place,self.trans) self.pkeys[place_name] = place.get_handle() return place def get_or_create_source(self,source_name): source = None if source_name in self.skeys: source = self.db.get_source_from_handle(self.skeys[source_name]) else: source = Source() source.set_title(source_name) self.db.add_source(source,self.trans) self.db.commit_source(source,self.trans) self.skeys[source_name] = source.get_handle() citation = Citation() citation.set_reference_handle(source.get_handle()) self.db.add_citation(citation, self.trans) self.db.commit_citation(citation, self.trans) return citation def read_fevent_line(self, event): if fevents_map.get(event[0:5]) == None: return #need to fix custom event types not in the map fev = None # get events for the current family for evr in self.current_family.get_event_ref_list(): ev = self.db.get_event_from_handle(evr.get_reference_handle()) if ev.get_type() == fevents_map.get(event[0:5]): fev = ev # found. Need to also check EventRef role return if not fev: # No event found create a new one if evr.get_role() != EventRoleType(EventRoleType.FAMILY): continue else: LOG.info((ev.get_type(), self.current_family.handle)) self.new_gwplus_fevent(event) while True: line = self.get_next_line() if line and line[0:5] in fevents_map: self.new_gwplus_fevent(line) elif line and line[0:4] == "wit:": continue else: self.current_mode = None #self.db.commit_family(self.current_family,self.trans) break def read_pevent_line(self, event, fields): name = fields[2] + fields[1] try: self.person = self.ikeys[name] # check key on {ikey} except: self.person = "(TO_CHECK: %s)" % fields[1:] #GrampsImportError() lastname = fields[1] firstname = fields[2] self.current_person = self.get_or_create_person(firstname, lastname) #name = Name() #name.set_type(NameType(NameType.BIRTH)) #name.set_first_name(firstname) #surname_obj = name.get_primary_surname() #surname_obj.set_surname(surname) #self.current_person.set_primary_name(name) if pevents_map.get(event[0:5]) == None: return #need to fix custom event types not in the map self.current_event = None # get events for the current person for evr in self.current_person.get_event_ref_list(): ev = self.db.get_event_from_handle(evr.get_reference_handle()) if ev.get_type() == pevents_map.get(event[0:5]): self.current_event = ev # found. Need to also check EventRef role if not self.current_event: # No event found create a new one self.current_event = self.new_gwplus_pevent(event) while True: line = self.get_next_line() if line and line[0:5] in pevents_map: self.current_mode = "person_event" self.current_event = self.new_gwplus_pevent(line) elif line and line[0:4] == "note": n = Note() n.set(line[5:]) self.db.add_note(n, self.trans) if self.current_event: self.current_event.add_note(n.handle) self.db.commit_event(self.current_event, self.trans) else: print('note', n.handle) else: self.current_mode = None #self.db.commit_person(self.current_person,self.trans) break def new_gwplus_fevent(self, line): source = place = note = type = None date = self.parse_date(self.decode(line[6:])) idx = 0 LOG.info((line, fevents_map.get(line[0:5]))) type = fevents_map.get(line[0:5]) data = line.split() date = self.parse_date(self.decode(line[6:])) for part in data: idx += 1 if part == "#p": place = self.get_or_create_place(self.decode(data[idx])) if part == "#s": source = self.get_or_create_source(self.decode(data[idx])) self.current_event = self.create_event(type, None, None, None, None) print('new event', self.current_event.handle) if date: print(date) self.current_event.set_date_object(date) if place: print('place', place.handle) self.current_event.set_place_handle(place.get_handle()) if source: print('source', source.handle) self.current_event.add_citation(source.get_handle()) self.db.commit_event(self.current_event, self.trans) nev_ref = EventRef() nev_ref.set_reference_handle(self.current_event.get_handle()) self.current_family.add_event_ref(nev_ref) self.db.commit_family(self.current_family, self.trans) return self.current_event def new_gwplus_pevent(self, line): source = place = note = type = None date = self.parse_date(self.decode(line[6:])) idx = 0 LOG.info((self.person, line, pevents_map.get(line[0:5]))) type = pevents_map.get(line[0:5]) data = line.split() date = self.parse_date(self.decode(line[6:])) for part in data: idx += 1 if part == "#p": place = self.get_or_create_place(self.decode(data[idx])) if part == "#s": source = self.get_or_create_source(self.decode(data[idx])) self.current_event = self.create_event(type, None, None, None, None) print('new event', self.current_event.handle) if date: print(date) self.current_event.set_date_object(date) if place: print('place', place.handle) self.current_event.set_place_handle(place.get_handle()) if source: print('source', source.handle) self.current_event.add_citation(source.get_handle()) self.db.commit_event(self.current_event, self.trans) nev_ref = EventRef() nev_ref.set_reference_handle(self.current_event.get_handle()) self.current_person.add_event_ref(nev_ref) self.db.commit_person(self.current_person, self.trans) return self.current_event def decode(self,s): s = s.replace('_',' ') charref_re = re.compile('(&#)(x?)([0-9a-zA-Z]+)(;)') for match in charref_re.finditer(s): try: if match.group(2): # HEX nchar = chr(int(match.group(3),16)) else: # Decimal nchar = chr(int(match.group(3))) s = s.replace(match.group(0), nchar) except UnicodeDecodeError: pass # replace named entities entref_re = re.compile('(&)([a-zA-Z]+)(;)') for match in entref_re.finditer(s): try: if match.group(2) in name2codepoint: nchar = chr(name2codepoint[match.group(2)]) s = s.replace(match.group(0), nchar) except UnicodeDecodeError: pass return(s) def debug(self, txt): LOG.debug(txt)
def get_or_create_family(self, family_ref, husband, wife): "Return the family object for the give family ID." # if a gramps_id and exists: LOG.debug("get_or_create_family") if family_ref.startswith("[") and family_ref.endswith("]"): id_ = self.db.fid2user_format(family_ref[1:-1]) family = self.db.get_family_from_gramps_id(id_) if family: # don't delete, only add fam_husband_handle = family.get_father_handle() fam_wife_handle = family.get_mother_handle() if husband: if husband.get_handle() != fam_husband_handle: # this husband is not the same old one! Add him! family.set_father_handle(husband.get_handle()) if wife: if wife.get_handle() != fam_wife_handle: # this wife is not the same old one! Add her! family.set_mother_handle(wife.get_handle()) LOG.debug(" returning existing family") return family # if not, create one: family = Family() # was marked with a gramps_id, but didn't exist, so we'll use it: if family_ref.startswith("[") and family_ref.endswith("]"): id_ = self.db.fid2user_format(family_ref[1:-1]) family.set_gramps_id(id_) # add it: family.set_handle(create_id()) if self.default_tag: family.add_tag(self.default_tag.handle) if husband: family.set_father_handle(husband.get_handle()) husband.add_family_handle(family.get_handle()) if wife: family.set_mother_handle(wife.get_handle()) wife.add_family_handle(family.get_handle()) if husband and wife: family.set_relationship(FamilyRelType.MARRIED) self.db.add_family(family, self.trans) if husband: self.db.commit_person(husband, self.trans) if wife: self.db.commit_person(wife, self.trans) self.fam_count += 1 return family
class GeneWebParser(object): def __init__(self, dbase, file): self.db = dbase if file: # Unit tests can create the parser w/o underlying file self.f = open(file, "rUb") self.filename = file self.encoding = 'iso-8859-1' self.gwplus = False def get_next_line(self): self.lineno += 1 line = self.f.readline() try: line = conv_to_unicode(line) except GrampsImportError as err: self.errmsg(str(err)) if line: try: line = str(line.strip()) except UnicodeDecodeError: line = conv_to_unicode(line.strip(), self.encoding) else: line = None return line def parse_geneweb_file(self): with DbTxn(_("GeneWeb import"), self.db, batch=True) as self.trans: self.db.disable_signals() t = time.time() self.lineno = 0 self.index = 0 self.fam_count = 0 self.indi_count = 0 self.fkeys = [] self.ikeys = {} self.pkeys = {} self.skeys = {} self.current_mode = None self.current_family = None self.current_husband_handle = None self.current_child_birthplace_handle = None self.current_child_source_handle = None try: while 1: line = self.get_next_line() if line is None: break if line == "": continue fields = line.split(" ") LOG.debug("LINE: %s" % line) if fields[0] == "gwplus": self.gwplus = True self.encoding = 'utf-8' elif fields[0] == "encoding:": self.encoding = fields[1] elif fields[0] == "fam": self.current_mode = "fam" self.read_family_line(line, fields) elif fields[0] == "rel": self.current_mode = "rel" self.read_relationship_person(line, fields) elif fields[0] == "src": self.read_source_line(line, fields) elif fields[0] in ("wit", "wit:"): self.read_witness_line(line, fields) elif fields[0] == "cbp": self.read_children_birthplace_line(line, fields) elif fields[0] == "csrc": self.read_children_source_line(line, fields) elif fields[0] == "beg" and self.current_mode == "fam": self.read_children_lines() elif fields[0] == "beg" and self.current_mode == "rel": self.read_relation_lines() elif fields[0] == "comm": self.read_family_comment(line, fields) elif fields[0] == "notes": self.read_person_notes_lines(line, fields) elif fields[0] == "fevt" and self.current_mode == "fam": #self.read_fevent_line(self.get_next_line()) pass elif fields[0] == "pevt": #self.read_pevent_line(self.get_next_line(), fields) pass elif fields[0] == "notes-db": self.read_database_notes_lines(line, fields) elif fields[0] == "pages-ext" or "wizard-note": pass elif fields[0] == "end": self.current_mode = None else: LOG.warning( "parse_geneweb_file(): Token >%s< unknown. line %d skipped: %s" % (fields[0], self.lineno, line)) except GedcomError as err: self.errmsg(str(err)) t = time.time() - t # translators: leave all/any {...} untranslated msg = ngettext('Import Complete: {number_of} second', 'Import Complete: {number_of} seconds', t).format(number_of=t) self.db.enable_signals() self.db.request_rebuild() LOG.debug(msg) LOG.debug("Families: %d" % len(self.fkeys)) LOG.debug("Individuals: %d" % len(self.ikeys)) return None def read_family_line(self, line, fields): self.current_husband_handle = None self.current_child_birthplace_handle = None self.current_child_source_handle = None self.current_family = Family() self.db.add_family(self.current_family, self.trans) #self.db.commit_family(self.current_family,self.trans) self.fkeys.append(self.current_family.get_handle()) idx = 1 LOG.debug("\nHusband:") (idx, husband) = self.parse_person(fields, idx, Person.MALE, None) if husband: self.current_husband_handle = husband.get_handle() self.current_family.set_father_handle(husband.get_handle()) self.db.commit_family(self.current_family, self.trans) husband.add_family_handle(self.current_family.get_handle()) self.db.commit_person(husband, self.trans) LOG.debug("Marriage:") idx = self.parse_marriage(fields, idx) LOG.debug("Wife:") (idx, wife) = self.parse_person(fields, idx, Person.FEMALE, None) if wife: self.current_family.set_mother_handle(wife.get_handle()) self.db.commit_family(self.current_family, self.trans) wife.add_family_handle(self.current_family.get_handle()) self.db.commit_person(wife, self.trans) return None def read_relationship_person(self, line, fields): LOG.debug("\Relationships:") (idx, person) = self.parse_person(fields, 1, Person.UNKNOWN, None) if person: self.current_relationship_person_handle = person.get_handle() def read_relation_lines(self): if not self.current_relationship_person_handle: LOG.warning("Unknown person for relationship in line %d!" % self.lineno) return None rel_person = self.db.get_person_from_handle( self.current_relationship_person_handle) while 1: line = self.get_next_line() if line is None or line == "end": break if line == "": continue # match relationship type and related person line_re = re.compile("^- ([^:]+): (.*)$") matches = line_re.match(line) if matches: #split related person into fields fields = matches.groups()[1].split(" ") if fields: (idx, asso_p) = self.parse_person(fields, 0, Person.UNKNOWN, None) pref = PersonRef() pref.set_relation(matches.groups()[0]) LOG.warning("TODO: Handle association types properly") pref.set_reference_handle(asso_p.get_handle()) rel_person.add_person_ref(pref) self.db.commit_person(rel_person, self.trans) else: LOG.warning("Invalid name of person in line %d" % self.lineno) else: LOG.warning("Invalid relationship in line %d" % self.lineno) break self.current_mode = None return None def read_source_line(self, line, fields): if not self.current_family: LOG.warning("Unknown family of child in line %d!" % self.lineno) return None source = self.get_or_create_source(self.decode(fields[1])) self.current_family.add_citation(source.get_handle()) self.db.commit_family(self.current_family, self.trans) return None def read_witness_line(self, line, fields): LOG.debug("Witness:") if fields[1] == "m:": (idx, wit_p) = self.parse_person(fields, 2, Person.MALE, None) elif fields[1] == "f:": (idx, wit_p) = self.parse_person(fields, 2, Person.FEMALE, None) else: (idx, wit_p) = self.parse_person(fields, 1, None, None) if wit_p: mev = None # search marriage event for evr in self.current_family.get_event_ref_list(): ev = self.db.get_event_from_handle(evr.get_reference_handle()) if ev.get_type() == EventType.MARRIAGE: mev = ev # found. if not mev: # No marriage event found create a new one mev = self.create_event(EventType.MARRIAGE, None, None, None, None) mar_ref = EventRef() mar_ref.set_reference_handle(mev.get_handle()) self.current_family.add_event_ref(mar_ref) wit_ref = EventRef() wit_ref.set_role(EventRoleType(EventRoleType.WITNESS)) wit_ref.set_reference_handle(mev.get_handle()) wit_p.add_event_ref(wit_ref) self.db.commit_person(wit_p, self.trans) return None def read_children_lines(self): father_surname = "Dummy" if not self.current_husband_handle: LOG.warning("Unknown father for child in line %d!" % self.lineno) return None husb = self.db.get_person_from_handle(self.current_husband_handle) father_surname = husb.get_primary_name().get_surname() if not self.current_family: LOG.warning("Unknown family of child in line %d!" % self.lineno) return None while 1: line = self.get_next_line() if line is None: break if line == "": continue fields = line.split(" ") if fields[0] == "-": LOG.debug("Child:") child = None if fields[1] == "h": (idx, child) = self.parse_person(fields, 2, Person.MALE, father_surname) elif fields[1] == "f": (idx, child) = self.parse_person(fields, 2, Person.FEMALE, father_surname) else: (idx, child) = self.parse_person(fields, 1, Person.UNKNOWN, father_surname) if child: childref = ChildRef() childref.set_reference_handle(child.get_handle()) self.current_family.add_child_ref(childref) self.db.commit_family(self.current_family, self.trans) child.add_parent_family_handle( self.current_family.get_handle()) if self.current_child_birthplace_handle: birth = None birth_ref = child.get_birth_ref() if birth_ref: birth = self.db.get_event_from_handle( birth_ref.ref) if not birth: birth = self.create_event(EventType.BIRTH) birth_ref = EventRef() birth_ref.set_reference_handle(birth.get_handle()) child.set_birth_ref(birth_ref) birth.set_place_handle( self.current_child_birthplace_handle) self.db.commit_event(birth, self.trans) if self.current_child_source_handle: child.add_citation(self.current_child_source_handle) self.db.commit_person(child, self.trans) else: break self.current_mode = None return None def read_children_birthplace_line(self, line, fields): cbp = self.get_or_create_place(self.decode(fields[1])) if cbp: self.current_child_birthplace_handle = cbp.get_handle() return None def read_children_source_line(self, line, fields): csrc = self.get_or_create_source(self.decode(fields[1])) self.current_child_source_handle = csrc.handle return None def read_family_comment(self, line, fields): if not self.current_family: LOG.warning("Unknown family of child in line %d!" % self.lineno) return None n = Note() n.set(line) self.db.add_note(n, self.trans) self.current_family.add_note(n.handle) self.db.commit_family(self.current_family, self.trans) return None def _read_notes_lines(self, note_tag): note_txt = "" while True: line = self.get_next_line() if line is None: break fields = line.split(" ") if fields[0] == "end" and fields[1] == note_tag: break elif fields[0] == "beg": continue else: if note_txt: note_txt = note_txt + "\n" + line else: note_txt = note_txt + line if note_txt: n = Note() n.set(note_txt) self.db.add_note(n, self.trans) return n.handle return None def read_person_notes_lines(self, line, fields): (idx, person) = self.parse_person(fields, 1, None, None) note_handle = self._read_notes_lines(fields[0]) if note_handle: person.add_note(note_handle) self.db.commit_person(person, self.trans) def read_database_notes_lines(self, line, fields): note_handle = self._read_notes_lines(fields[0]) def parse_marriage(self, fields, idx): mariageDataRe = re.compile("^[+#-0-9].*$") mar_date = None mar_place = None mar_source = None sep_date = None div_date = None married = 1 engaged = 0 # skip to marriage date in case person contained unmatches tokens #Alex: this failed when fields[idx] was an empty line. Fixed. #while idx < len(fields) and not fields[idx][0] == "+": while idx < len(fields) and not (fields[idx] and fields[idx][0] == "+"): if fields[idx]: LOG.warning( ("parse_marriage(): Unknown field: " + "'%s' in line %d!") % (fields[idx], self.lineno)) idx += 1 while idx < len(fields) and mariageDataRe.match(fields[idx]): field = fields[idx] idx += 1 if field.startswith("+"): field = field[1:] mar_date = self.parse_date(self.decode(field)) LOG.debug(" Married at: %s" % field) elif field.startswith("-"): field = field[1:] div_date = self.parse_date(self.decode(field)) LOG.debug(" Div at: %s" % field) elif field == "#mp" and idx < len(fields): mar_place = self.get_or_create_place(self.decode(fields[idx])) LOG.debug(" Marriage place: %s" % fields[idx]) idx += 1 elif field == "#ms" and idx < len(fields): mar_source = self.get_or_create_source(self.decode( fields[idx])) LOG.debug(" Marriage source: %s" % fields[idx]) idx += 1 elif field == "#sep" and idx < len(fields): sep_date = self.parse_date(self.decode(fields[idx])) LOG.debug(" Seperated since: %s" % fields[idx]) idx += 1 elif field == "#nm": LOG.debug(" Are not married.") married = 0 elif field == "#noment": LOG.debug(" Not mentioned.") elif field == "#eng": LOG.debug(" Are engaged.") engaged = 1 else: LOG.warning( ("parse_marriage(): Unknown field " + "'%s'for mariage in line %d!") % (field, self.lineno)) if mar_date or mar_place or mar_source: mar = self.create_event(EventType.MARRIAGE, None, mar_date, mar_place, mar_source) mar_ref = EventRef() mar_ref.set_reference_handle(mar.get_handle()) mar_ref.set_role(EventRoleType.FAMILY) self.current_family.add_event_ref(mar_ref) self.current_family.set_relationship( FamilyRelType(FamilyRelType.MARRIED)) if div_date: div = self.create_event(EventType.DIVORCE, None, div_date, None, None) div_ref = EventRef() div_ref.set_reference_handle(div.get_handle()) div_ref.set_role(EventRoleType.FAMILY) self.current_family.add_event_ref(div_ref) if sep_date or engaged: sep = self.create_event(EventType.ENGAGEMENT, None, sep_date, None, None) sep_ref = EventRef() sep_ref.set_reference_handle(sep.get_handle()) sep_ref.set_role(EventRoleType.FAMILY) self.current_family.add_event_ref(sep_ref) if not married: self.current_family.set_relationship( FamilyRelType(FamilyRelType.UNMARRIED)) self.db.commit_family(self.current_family, self.trans) return idx def parse_person(self, fields, idx, gender, father_surname): if not father_surname: if not idx < len(fields): LOG.warning("Missing surname of person in line %d!" % self.lineno) surname = "" else: surname = self.decode(fields[idx]) idx += 1 else: surname = father_surname if not idx < len(fields): LOG.warning("Missing firstname of person in line %d!" % self.lineno) firstname = "" else: firstname = self.decode(fields[idx]) idx += 1 if idx < len(fields) and father_surname: noSurnameRe = re.compile("^[({\[~><?0-9#].*$") if not noSurnameRe.match(fields[idx]): surname = self.decode(fields[idx]) idx += 1 LOG.debug("Person: %s %s" % (firstname, surname)) person = self.get_or_create_person(firstname, surname) name = Name() name.set_type(NameType(NameType.BIRTH)) name.set_first_name(firstname) surname_obj = name.get_primary_surname() surname_obj.set_surname(surname) person.set_primary_name(name) if person.get_gender() == Person.UNKNOWN and gender is not None: person.set_gender(gender) self.db.commit_person(person, self.trans) personDataRe = re.compile("^[kmes0-9<>~#\[({!].*$") dateRe = re.compile("^[kmes0-9~<>?]+.*$") source = None birth_parsed = False birth_date = None birth_place = None birth_source = None bapt_date = None bapt_place = None bapt_source = None death_date = None death_place = None death_source = None death_cause = None crem_date = None bur_date = None bur_place = None bur_source = None public_name = None firstname_aliases = [] nick_names = [] name_aliases = [] surname_aliases = [] while idx < len(fields) and personDataRe.match(fields[idx]): field = fields[idx] idx += 1 if field.startswith('('): LOG.debug("Public Name: %s" % field) public_name = self.decode(field[1:-1]) elif field.startswith('{'): LOG.debug("Firstsname Alias: %s" % field) firstname_aliases.append(self.decode(field[1:-1])) elif field.startswith('['): LOG.debug("Title: %s" % field) titleparts = self.decode(field[1:-1]).split(":") tname = ttitle = tplace = tstart = tend = tnth = None try: tname = titleparts[0] ttitle = titleparts[1] if titleparts[2]: tplace = self.get_or_create_place(titleparts[2]) tstart = self.parse_date(titleparts[3]) tend = self.parse_date(titleparts[4]) tnth = titleparts[5] except IndexError: # not all parts are written all the time pass if tnth: # Append title numer to title ttitle += ", " + tnth title = self.create_event(EventType.NOB_TITLE, ttitle, tstart, tplace) # TODO: Geneweb has a start date and an end date, and therefore # supports stuff like: FROM about 1955 TO between 1998 and 1999 # gramps only supports one single date or range. if tname and tname != "*": n = Note() n.set(tname) self.db.add_note(n, self.trans) title.add_note(n.handle) title_ref = EventRef() title_ref.set_reference_handle(title.get_handle()) person.add_event_ref(title_ref) elif field == '#nick' and idx < len(fields): LOG.debug("Nick Name: %s" % fields[idx]) nick_names.append(self.decode(fields[idx])) idx += 1 elif field == '#occu' and idx < len(fields): LOG.debug("Occupation: %s" % fields[idx]) occu = self.create_event(EventType.OCCUPATION, self.decode(fields[idx])) occu_ref = EventRef() occu_ref.set_reference_handle(occu.get_handle()) person.add_event_ref(occu_ref) idx += 1 elif field == '#alias' and idx < len(fields): LOG.debug("Name Alias: %s" % fields[idx]) name_aliases.append(self.decode(fields[idx])) idx += 1 elif field == '#salias' and idx < len(fields): LOG.debug("Surname Alias: %s" % fields[idx]) surname_aliases.append(self.decode(fields[idx])) idx += 1 elif field == '#image' and idx < len(fields): LOG.debug("Image: %s" % fields[idx]) idx += 1 elif field == '#src' and idx < len(fields): LOG.debug("Source: %s" % fields[idx]) source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 elif field == '#bs' and idx < len(fields): LOG.debug("Birth Source: %s" % fields[idx]) birth_source = self.get_or_create_source( self.decode(fields[idx])) idx += 1 elif field[0] == '!': LOG.debug("Baptize at: %s" % field[1:]) bapt_date = self.parse_date(self.decode(field[1:])) elif field == '#bp' and idx < len(fields): LOG.debug("Birth Place: %s" % fields[idx]) birth_place = self.get_or_create_place(self.decode( fields[idx])) idx += 1 elif field == '#pp' and idx < len(fields): LOG.debug("Baptize Place: %s" % fields[idx]) bapt_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 elif field == '#ps' and idx < len(fields): LOG.debug("Baptize Source: %s" % fields[idx]) bapt_source = self.get_or_create_source( self.decode(fields[idx])) idx += 1 elif field == '#dp' and idx < len(fields): LOG.debug("Death Place: %s" % fields[idx]) death_place = self.get_or_create_place(self.decode( fields[idx])) idx += 1 elif field == '#ds' and idx < len(fields): LOG.debug("Death Source: %s" % fields[idx]) death_source = self.get_or_create_source( self.decode(fields[idx])) idx += 1 elif field == '#buri' and idx < len(fields): if fields[idx][0] != '#': # bug in GeneWeb: empty #buri fields LOG.debug("Burial Date: %s" % fields[idx]) bur_date = self.parse_date(self.decode(fields[idx])) idx += 1 elif field == '#crem' and idx < len(fields): LOG.debug("Cremention Date: %s" % fields[idx]) crem_date = self.parse_date(self.decode(fields[idx])) idx += 1 elif field == '#rp' and idx < len(fields): LOG.debug("Burial Place: %s" % fields[idx]) bur_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 elif field == '#rs' and idx < len(fields): LOG.debug("Burial Source: %s" % fields[idx]) bur_source = self.get_or_create_source(self.decode( fields[idx])) idx += 1 elif field == '#apubl': LOG.debug("This is a public record") elif field == '#apriv': LOG.debug("This is a private record") person.set_privacy(True) elif field == '#h': LOG.debug("This is a restricted record") #TODO: Gramps does currently not feature this level person.set_privacy(True) elif dateRe.match(field): if not birth_parsed: LOG.debug("Birth Date: %s" % field) birth_date = self.parse_date(self.decode(field)) birth_parsed = True else: LOG.debug("Death Date: %s" % field) death_date = self.parse_date(self.decode(field)) if field == "mj": death_cause = "Died joung" elif field.startswith("k"): death_cause = "Killed" elif field.startswith("m"): death_cause = "Murdered" elif field.startswith("e"): death_cause = "Executed" elif field.startswith("d"): death_cause = "Disappeared" #TODO: Set special death types more properly else: LOG.warning( ("parse_person(): Unknown field " + "'%s' for person in line %d!") % (field, self.lineno)) if public_name: name = person.get_primary_name() name.set_type(NameType(NameType.BIRTH)) person.add_alternate_name(name) name = Name() name.set_type(NameType(NameType.AKA)) name.set_first_name(public_name) surname_obj = name.get_primary_surname() surname_obj.set_surname(surname) person.set_primary_name(name) for aka in nick_names: name = Attribute() name.set_type(AttributeType(AttributeType.NICKNAME)) name.set_value(aka) person.add_attribute(name) for aka in firstname_aliases: name = Name() name.set_type(NameType(NameType.AKA)) name.set_first_name(aka) surname_obj = name.get_primary_surname() surname_obj.set_surname(surname) person.add_alternate_name(name) for aka in name_aliases: name = Name() name.set_type(NameType(NameType.AKA)) name.set_first_name(aka) surname_obj = name.get_primary_surname() surname_obj.set_surname(surname) person.add_alternate_name(name) for aka in surname_aliases: name = Name() name.set_type(NameType(NameType.AKA)) if public_name: name.set_first_name(public_name) else: name.set_first_name(firstname) surname_obj = name.get_primary_surname() surname_obj.set_surname(aka) person.add_alternate_name(name) if source: person.add_citation(source.get_handle()) if birth_date or birth_place or birth_source: birth = self.create_event(EventType.BIRTH, None, birth_date, birth_place, birth_source) birth_ref = EventRef() birth_ref.set_reference_handle(birth.get_handle()) person.set_birth_ref(birth_ref) if bapt_date or bapt_place or bapt_source: babt = self.create_event(EventType.BAPTISM, None, bapt_date, bapt_place, bapt_source) babt_ref = EventRef() babt_ref.set_reference_handle(babt.get_handle()) person.add_event_ref(babt_ref) if death_date or death_place or death_source or death_cause: death = self.create_event(EventType.DEATH, None, death_date, death_place, death_source) if death_cause: death.set_description(death_cause) self.db.commit_event(death, self.trans) death_ref = EventRef() death_ref.set_reference_handle(death.get_handle()) person.set_death_ref(death_ref) if bur_date: bur = self.create_event(EventType.BURIAL, None, bur_date, bur_place, bur_source) bur_ref = EventRef() bur_ref.set_reference_handle(bur.get_handle()) person.add_event_ref(bur_ref) if crem_date: crem = self.create_event(EventType.CREMATION, None, crem_date, bur_place, bur_source) crem_ref = EventRef() crem_ref.set_reference_handle(crem.get_handle()) person.add_event_ref(crem_ref) self.db.commit_person(person, self.trans) return (idx, person) def parse_date(self, field): if field == "0": return None date = Date() matches = _text_parse.match(field) if matches: groups = matches.groups() date.set_as_text(groups[0]) date.set_modifier(Date.MOD_TEXTONLY) return date matches = _date_parse.match(field) if matches: groups = matches.groups() mod = _mod_map.get(groups[0], Date.MOD_NONE) if groups[3] == "..": mod = Date.MOD_SPAN cal2 = _cal_map.get(groups[5], Date.CAL_GREGORIAN) sub2 = self.sub_date(groups[4]) else: sub2 = (0, 0, 0) cal1 = _cal_map.get(groups[2], Date.CAL_GREGORIAN) sub1 = self.sub_date(groups[1]) try: date.set(Date.QUAL_NONE, mod, cal1, (sub1[0], sub1[1], sub1[2], 0, sub2[0], sub2[1], sub2[2], 0)) except DateError as e: # TRANSLATORS: leave the {date} and {gw_snippet} untranslated # in the format string, but you may re-order them if needed. LOG.warning( _("Invalid date {date} in {gw_snippet}, " "preserving date as text.").format( date=e.date.to_struct(), gw_snippet=field)) date.set(modifier=Date.MOD_TEXTONLY, text=field) return date else: return None def sub_date(self, data): vals = data.split('/') if len(vals) == 1: return (0, 0, int(vals[0])) elif len(vals) == 2: return (0, int(vals[0]), int(vals[1])) else: return (int(vals[0]), int(vals[1]), int(vals[2])) def create_event(self, type, desc=None, date=None, place=None, source=None): event = Event() if type: event.set_type(EventType(type)) if desc: event.set_description(desc) if date: event.set_date_object(date) if place: event.set_place_handle(place.get_handle()) if source: event.add_citation(source.get_handle()) self.db.add_event(event, self.trans) self.db.commit_event(event, self.trans) return event def get_or_create_person(self, firstname, lastname): person = None mykey = firstname + lastname if mykey in self.ikeys and firstname != "?" and lastname != "?": person = self.db.get_person_from_handle(self.ikeys[mykey]) else: person = Person() self.db.add_person(person, self.trans) self.db.commit_person(person, self.trans) self.ikeys[mykey] = person.get_handle() return person def get_or_create_place(self, place_name): place = None if place_name in self.pkeys: place = self.db.get_place_from_handle(self.pkeys[place_name]) else: place = Place() place.set_title(place_name) self.db.add_place(place, self.trans) self.db.commit_place(place, self.trans) self.pkeys[place_name] = place.get_handle() return place def get_or_create_source(self, source_name): source = None if source_name in self.skeys: source = self.db.get_source_from_handle(self.skeys[source_name]) else: source = Source() source.set_title(source_name) self.db.add_source(source, self.trans) self.db.commit_source(source, self.trans) self.skeys[source_name] = source.get_handle() citation = Citation() citation.set_reference_handle(source.get_handle()) self.db.add_citation(citation, self.trans) self.db.commit_citation(citation, self.trans) return citation def read_fevent_line(self, event): if fevents_map.get(event[0:5]) == None: return #need to fix custom event types not in the map fev = None # get events for the current family for evr in self.current_family.get_event_ref_list(): ev = self.db.get_event_from_handle(evr.get_reference_handle()) if ev.get_type() == fevents_map.get(event[0:5]): fev = ev # found. Need to also check EventRef role return if not fev: # No event found create a new one if evr.get_role() != EventRoleType(EventRoleType.FAMILY): continue else: LOG.info((ev.get_type(), self.current_family.handle)) self.new_gwplus_fevent(event) while True: line = self.get_next_line() if line and line[0:5] in fevents_map: self.new_gwplus_fevent(line) elif line and line[0:4] == "wit:": continue else: self.current_mode = None #self.db.commit_family(self.current_family,self.trans) break def read_pevent_line(self, event, fields): name = fields[2] + fields[1] try: self.person = self.ikeys[name] # check key on {ikey} except: self.person = "(TO_CHECK: %s)" % fields[1:] #GrampsImportError() lastname = fields[1] firstname = fields[2] self.current_person = self.get_or_create_person(firstname, lastname) #name = Name() #name.set_type(NameType(NameType.BIRTH)) #name.set_first_name(firstname) #surname_obj = name.get_primary_surname() #surname_obj.set_surname(surname) #self.current_person.set_primary_name(name) if pevents_map.get(event[0:5]) == None: return #need to fix custom event types not in the map self.current_event = None # get events for the current person for evr in self.current_person.get_event_ref_list(): ev = self.db.get_event_from_handle(evr.get_reference_handle()) if ev.get_type() == pevents_map.get(event[0:5]): self.current_event = ev # found. Need to also check EventRef role if not self.current_event: # No event found create a new one self.current_event = self.new_gwplus_pevent(event) while True: line = self.get_next_line() if line and line[0:5] in pevents_map: self.current_mode = "person_event" self.current_event = self.new_gwplus_pevent(line) elif line and line[0:4] == "note": n = Note() n.set(line[5:]) self.db.add_note(n, self.trans) if self.current_event: self.current_event.add_note(n.handle) self.db.commit_event(self.current_event, self.trans) else: print('note', n.handle) else: self.current_mode = None #self.db.commit_person(self.current_person,self.trans) break def new_gwplus_fevent(self, line): source = place = note = type = None date = self.parse_date(self.decode(line[6:])) idx = 0 LOG.info((line, fevents_map.get(line[0:5]))) type = fevents_map.get(line[0:5]) data = line.split() date = self.parse_date(self.decode(line[6:])) for part in data: idx += 1 if part == "#p": place = self.get_or_create_place(self.decode(data[idx])) if part == "#s": source = self.get_or_create_source(self.decode(data[idx])) self.current_event = self.create_event(type, None, None, None, None) print('new event', self.current_event.handle) if date: print(date) self.current_event.set_date_object(date) if place: print('place', place.handle) self.current_event.set_place_handle(place.get_handle()) if source: print('source', source.handle) self.current_event.add_citation(source.get_handle()) self.db.commit_event(self.current_event, self.trans) nev_ref = EventRef() nev_ref.set_reference_handle(self.current_event.get_handle()) self.current_family.add_event_ref(nev_ref) self.db.commit_family(self.current_family, self.trans) return self.current_event def new_gwplus_pevent(self, line): source = place = note = type = None date = self.parse_date(self.decode(line[6:])) idx = 0 LOG.info((self.person, line, pevents_map.get(line[0:5]))) type = pevents_map.get(line[0:5]) data = line.split() date = self.parse_date(self.decode(line[6:])) for part in data: idx += 1 if part == "#p": place = self.get_or_create_place(self.decode(data[idx])) if part == "#s": source = self.get_or_create_source(self.decode(data[idx])) self.current_event = self.create_event(type, None, None, None, None) print('new event', self.current_event.handle) if date: print(date) self.current_event.set_date_object(date) if place: print('place', place.handle) self.current_event.set_place_handle(place.get_handle()) if source: print('source', source.handle) self.current_event.add_citation(source.get_handle()) self.db.commit_event(self.current_event, self.trans) nev_ref = EventRef() nev_ref.set_reference_handle(self.current_event.get_handle()) self.current_person.add_event_ref(nev_ref) self.db.commit_person(self.current_person, self.trans) return self.current_event def decode(self, s): s = s.replace('_', ' ') charref_re = re.compile('(&#)(x?)([0-9a-zA-Z]+)(;)') for match in charref_re.finditer(s): try: if match.group(2): # HEX nchar = chr(int(match.group(3), 16)) else: # Decimal nchar = chr(int(match.group(3))) s = s.replace(match.group(0), nchar) except UnicodeDecodeError: pass # replace named entities entref_re = re.compile('(&)([a-zA-Z]+)(;)') for match in entref_re.finditer(s): try: if match.group(2) in name2codepoint: nchar = chr(name2codepoint[match.group(2)]) s = s.replace(match.group(0), nchar) except UnicodeDecodeError: pass return (s) def debug(self, txt): if enable_debug: print(txt)
def empty_object(self): return Family()
def __add_clicked(self, obj): family = Family() EditFamily(self.dbstate, self.uistate, self.track, family, self.__added)
def exportData(database, filename, error_dialog=None, option_box=None, callback=None): if not callable(callback): callback = lambda percent: None # dummy with OpenFileOrStdout(filename, encoding="utf-8") as fp: total = (len(database.note_map) + len(database.person_map) + len(database.event_map) + len(database.family_map) + len(database.repository_map) + len(database.place_map) + len(database.media_map) + len(database.citation_map) + len(database.source_map) + len(database.tag_map)) count = 0.0 # --------------------------------- # Notes # --------------------------------- for handle in database.note_map.keys(): serial = database.note_map[handle] write_line(fp, Note.create(serial)) count += 1 callback(100 * count/total) # --------------------------------- # Event # --------------------------------- for handle in database.event_map.keys(): serial = database.event_map[handle] write_line(fp, Event.create(serial)) count += 1 callback(100 * count/total) # --------------------------------- # Person # --------------------------------- for handle in database.person_map.keys(): serial = database.person_map[handle] write_line(fp, Person.create(serial)) count += 1 callback(100 * count/total) # --------------------------------- # Family # --------------------------------- for handle in database.family_map.keys(): serial = database.family_map[handle] write_line(fp, Family.create(serial)) count += 1 callback(100 * count/total) # --------------------------------- # Repository # --------------------------------- for handle in database.repository_map.keys(): serial = database.repository_map[handle] write_line(fp, Repository.create(serial)) count += 1 callback(100 * count/total) # --------------------------------- # Place # --------------------------------- for handle in database.place_map.keys(): serial = database.place_map[handle] write_line(fp, Place.create(serial)) count += 1 callback(100 * count/total) # --------------------------------- # Source # --------------------------------- for handle in database.source_map.keys(): serial = database.source_map[handle] write_line(fp, Source.create(serial)) count += 1 callback(100 * count/total) # --------------------------------- # Citation # --------------------------------- for handle in database.citation_map.keys(): serial = database.citation_map[handle] write_line(fp, Citation.create(serial)) count += 1 callback(100 * count/total) # --------------------------------- # Media # --------------------------------- for handle in database.media_map.keys(): serial = database.media_map[handle] write_line(fp, Media.create(serial)) count += 1 callback(100 * count/total) # --------------------------------- # Tag # --------------------------------- for handle in database.tag_map.keys(): serial = database.tag_map[handle] write_line(fp, Tag.create(serial)) count += 1 callback(100 * count/total) return True
def _process(self, count, total, sql): # --------------------------------- # Process note # --------------------------------- notes = sql.query("""select * from note;""") for note in notes: (handle, gid, text, _format, note_type1, note_type2, change, private) = note styled_text = [text, []] markups = sql.query( """select * from link where from_handle = ? """ """and to_type = 'markup';""", handle) for markup_link in markups: _from_type, _from_handle, _to_type, to_handle = markup_link markup_detail = sql.query( """select * from markup where handle = ?;""", to_handle) for markup in markup_detail: (_mhandle, markup0, markup1, value, start_stop_list) = markup ss_list = eval(start_stop_list) styled_text[1] += [((markup0, markup1), value, ss_list)] tags = self.get_links(sql, "note", handle, "tag") g_note = Note() g_note.unserialize( (handle, gid, styled_text, _format, (note_type1, note_type2), change, tags, bool(private))) self.db.add_note(g_note, self.trans) count += 1 self.callback(100 * count / total) # --------------------------------- # Process event # --------------------------------- events = sql.query("""select * from event;""") for event in events: (handle, gid, the_type0, the_type1, description, change, private) = event note_list = self.get_note_list(sql, "event", handle) citation_list = self.get_citation_list(sql, "event", handle) media_list = self.get_media_list(sql, "event", handle) attribute_list = self.get_attribute_list(sql, "event", handle) date_handle = self.get_link(sql, "event", handle, "date") date = self.get_date(sql, date_handle) place_handle = self.get_link(sql, "event", handle, "place") place = self.get_place_from_handle(sql, place_handle) tags = self.get_links(sql, "event", handle, "tag") data = (handle, gid, (the_type0, the_type1), date, description, place, citation_list, note_list, media_list, attribute_list, change, tags, bool(private)) g_event = Event() g_event.unserialize(data) self.db.add_event(g_event, self.trans) count += 1 self.callback(100 * count / total) # --------------------------------- # Process person # --------------------------------- people = sql.query("""select * from person;""") for person in people: if person is None: continue ( handle, # 0 gid, # 1 gender, # 2 death_ref_handle, # 5 birth_ref_handle, # 6 change, # 17 private, # 19 ) = person primary_name = self.get_names(sql, "person", handle, True) # one alternate_names = self.get_names(sql, "person", handle, False) event_ref_list = self.get_event_ref_list(sql, "person", handle) family_list = self.get_family_list(sql, "person", handle) parent_family_list = self.get_parent_family_list( sql, "person", handle) media_list = self.get_media_list(sql, "person", handle) address_list = self.get_address_list(sql, "person", handle, with_parish=False) attribute_list = self.get_attribute_list(sql, "person", handle) urls = self.get_url_list(sql, "person", handle) lds_ord_list = self.get_lds_list(sql, "person", handle) pcitation_list = self.get_citation_list(sql, "person", handle) pnote_list = self.get_note_list(sql, "person", handle) person_ref_list = self.get_person_ref_list(sql, "person", handle) death_ref_index = lookup(death_ref_handle, event_ref_list) birth_ref_index = lookup(birth_ref_handle, event_ref_list) tags = self.get_links(sql, "person", handle, "tag") data = ( handle, # 0 gid, # 1 gender, # 2 primary_name, # 3 alternate_names, # 4 death_ref_index, # 5 birth_ref_index, # 6 event_ref_list, # 7 family_list, # 8 parent_family_list, # 9 media_list, # 10 address_list, # 11 attribute_list, # 12 urls, # 13 lds_ord_list, # 14 pcitation_list, # 15 pnote_list, # 16 change, # 17 tags, bool(private), # 19 person_ref_list, ) # 20 g_pers = Person() g_pers.unserialize(data) self.db.add_person(g_pers, self.trans) count += 1 self.callback(100 * count / total) # --------------------------------- # Process family # --------------------------------- families = sql.query("""select * from family;""") for family in families: (handle, gid, father_handle, mother_handle, the_type0, the_type1, change, private) = family child_ref_list = self.get_child_ref_list(sql, "family", handle) event_ref_list = self.get_event_ref_list(sql, "family", handle) media_list = self.get_media_list(sql, "family", handle) attribute_list = self.get_attribute_list(sql, "family", handle) lds_seal_list = self.get_lds_list(sql, "family", handle) citation_list = self.get_citation_list(sql, "family", handle) note_list = self.get_note_list(sql, "family", handle) tags = self.get_links(sql, "family", handle, "tag") data = (handle, gid, father_handle, mother_handle, child_ref_list, (the_type0, the_type1), event_ref_list, media_list, attribute_list, lds_seal_list, citation_list, note_list, change, tags, private) g_fam = Family() g_fam.unserialize(data) self.db.add_family(g_fam, self.trans) count += 1 self.callback(100 * count / total) # --------------------------------- # Process repository # --------------------------------- repositories = sql.query("""select * from repository;""") for repo in repositories: (handle, gid, the_type0, the_type1, name, change, private) = repo note_list = self.get_note_list(sql, "repository", handle) address_list = self.get_address_list(sql, "repository", handle, with_parish=False) urls = self.get_url_list(sql, "repository", handle) tags = self.get_links(sql, "repository", handle, "tag") data = (handle, gid, (the_type0, the_type1), name, note_list, address_list, urls, change, tags, private) g_rep = Repository() g_rep.unserialize(data) self.db.add_repository(g_rep, self.trans) count += 1 self.callback(100 * count / total) # --------------------------------- # Process place # --------------------------------- places = sql.query("""select * from place;""") for place in places: count += 1 (handle, gid, title, value, the_type0, the_type1, code, long, lat, lang, change, private) = place # We could look this up by "place_main", but we have the handle: #main_loc = self.get_main_location(sql, handle, with_parish=True) alt_loc_list = self.get_location_list(sql, "place_alt", handle, with_parish=True) urls = self.get_url_list(sql, "place", handle) media_list = self.get_media_list(sql, "place", handle) citation_list = self.get_citation_list(sql, "place", handle) note_list = self.get_note_list(sql, "place", handle) tags = self.get_links(sql, "place", handle, "tag") place_type = (the_type0, the_type1) alt_place_name_list = self.get_alt_place_name_list(sql, handle) place_ref_list = self.get_place_ref_list(sql, handle) data = (handle, gid, title, long, lat, place_ref_list, PlaceName(value=value, lang=lang).serialize(), alt_place_name_list, place_type, code, alt_loc_list, urls, media_list, citation_list, note_list, change, tags, private) g_plac = Place() g_plac.unserialize(data) self.db.commit_place(g_plac, self.trans) self.callback(100 * count / total) # --------------------------------- # Process citation # --------------------------------- citations = sql.query("""select * from citation;""") for citation in citations: (handle, gid, confidence, page, source_handle, change, private) = citation date_handle = self.get_link(sql, "citation", handle, "date") date = self.get_date(sql, date_handle) note_list = self.get_note_list(sql, "citation", handle) media_list = self.get_media_list(sql, "citation", handle) datamap = self.get_datamap_list(sql, "citation", handle) tags = self.get_links(sql, "citation", handle, "tag") data = (handle, gid, date, page, confidence, source_handle, note_list, media_list, datamap, change, tags, private) g_cit = Citation() g_cit.unserialize(data) self.db.commit_citation(g_cit, self.trans) count += 1 self.callback(100 * count / total) # --------------------------------- # Process source # --------------------------------- sources = sql.query("""select * from source;""") for source in sources: (handle, gid, title, author, pubinfo, abbrev, change, private) = source note_list = self.get_note_list(sql, "source", handle) media_list = self.get_media_list(sql, "source", handle) datamap = self.get_datamap_list(sql, "source", handle) reporef_list = self.get_repository_ref_list(sql, "source", handle) tags = self.get_links(sql, "source", handle, "tag") data = (handle, gid, title, author, pubinfo, note_list, media_list, abbrev, change, datamap, reporef_list, tags, private) g_src = Source() g_src.unserialize(data) self.db.commit_source(g_src, self.trans) count += 1 self.callback(100 * count / total) # --------------------------------- # Process media # --------------------------------- media = sql.query("""select * from media;""") for med in media: (handle, gid, path, mime, desc, checksum, change, private) = med attribute_list = self.get_attribute_list(sql, "media", handle) citation_list = self.get_citation_list(sql, "media", handle) note_list = self.get_note_list(sql, "media", handle) date_handle = self.get_link(sql, "media", handle, "date") date = self.get_date(sql, date_handle) tags = self.get_links(sql, "media", handle, "tag") data = (handle, gid, path, mime, desc, checksum, attribute_list, citation_list, note_list, change, date, tags, private) g_med = Media() g_med.unserialize(data) self.db.commit_media(g_med, self.trans) count += 1 self.callback(100 * count / total) # --------------------------------- # Process tag # --------------------------------- tags = sql.query("""select * from tag;""") for tag in tags: (handle, name, color, priority, change) = tag data = (handle, name, color, priority, change) g_tag = Tag() g_tag.unserialize(data) self.db.commit_tag(g_tag, self.trans) count += 1 self.callback(100 * count / total)
def add(self, *obj): family = Family() try: EditFamily(self.dbstate, self.uistate, [], family) except WindowActiveError: pass
def exportData(database, filename, error_dialog=None, option_box=None, callback=None): if not callable(callback): callback = lambda percent: None # dummy with OpenFileOrStdout(filename, encoding="utf-8") as fp: total = (len(database.note_map) + len(database.person_map) + len(database.event_map) + len(database.family_map) + len(database.repository_map) + len(database.place_map) + len(database.media_map) + len(database.citation_map) + len(database.source_map) + len(database.tag_map)) count = 0.0 # --------------------------------- # Notes # --------------------------------- for handle in database.note_map.keys(): serial = database.note_map[handle] write_line(fp, Note.create(serial)) count += 1 callback(100 * count / total) # --------------------------------- # Event # --------------------------------- for handle in database.event_map.keys(): serial = database.event_map[handle] write_line(fp, Event.create(serial)) count += 1 callback(100 * count / total) # --------------------------------- # Person # --------------------------------- for handle in database.person_map.keys(): serial = database.person_map[handle] write_line(fp, Person.create(serial)) count += 1 callback(100 * count / total) # --------------------------------- # Family # --------------------------------- for handle in database.family_map.keys(): serial = database.family_map[handle] write_line(fp, Family.create(serial)) count += 1 callback(100 * count / total) # --------------------------------- # Repository # --------------------------------- for handle in database.repository_map.keys(): serial = database.repository_map[handle] write_line(fp, Repository.create(serial)) count += 1 callback(100 * count / total) # --------------------------------- # Place # --------------------------------- for handle in database.place_map.keys(): serial = database.place_map[handle] write_line(fp, Place.create(serial)) count += 1 callback(100 * count / total) # --------------------------------- # Source # --------------------------------- for handle in database.source_map.keys(): serial = database.source_map[handle] write_line(fp, Source.create(serial)) count += 1 callback(100 * count / total) # --------------------------------- # Citation # --------------------------------- for handle in database.citation_map.keys(): serial = database.citation_map[handle] write_line(fp, Citation.create(serial)) count += 1 callback(100 * count / total) # --------------------------------- # Media # --------------------------------- for handle in database.media_map.keys(): serial = database.media_map[handle] write_line(fp, MediaObject.create(serial)) count += 1 callback(100 * count / total) # --------------------------------- # Tag # --------------------------------- for handle in database.tag_map.keys(): serial = database.tag_map[handle] write_line(fp, Tag.create(serial)) count += 1 callback(100 * count / total) return True
class FamilySidebarFilter(SidebarFilter): def __init__(self, dbstate, uistate, clicked): self.clicked_func = clicked self.filter_id = widgets.BasicEntry() self.filter_father = widgets.BasicEntry() self.filter_mother = widgets.BasicEntry() self.filter_child = widgets.BasicEntry() self.filter_event = Event() self.filter_event.set_type((EventType.CUSTOM, '')) self.etype = Gtk.ComboBox(has_entry=True) if dbstate.is_open(): self.custom_types = dbstate.db.get_event_types() else: self.custom_types = [] self.event_menu = widgets.MonitoredDataType( self.etype, self.filter_event.set_type, self.filter_event.get_type, custom_values=self.custom_types) self.filter_family = Family() self.filter_family.set_relationship((FamilyRelType.CUSTOM, '')) self.rtype = Gtk.ComboBox(has_entry=True) if dbstate.is_open(): self.custom_types = dbstate.db.get_family_relation_types() else: self.custom_types = [] self.rel_menu = widgets.MonitoredDataType( self.rtype, self.filter_family.set_relationship, self.filter_family.get_relationship, custom_values=self.custom_types) self.filter_note = widgets.BasicEntry() self.filter_regex = Gtk.CheckButton(label=_('Use regular expressions')) self.tag = Gtk.ComboBox() self.generic = Gtk.ComboBox() SidebarFilter.__init__(self, dbstate, uistate, "Family") def create_widget(self): cell = Gtk.CellRendererText() cell.set_property('width', self._FILTER_WIDTH) cell.set_property('ellipsize', self._FILTER_ELLIPSIZE) self.generic.pack_start(cell, True) self.generic.add_attribute(cell, 'text', 0) self.on_filters_changed('Family') cell = Gtk.CellRendererText() cell.set_property('width', self._FILTER_WIDTH) cell.set_property('ellipsize', self._FILTER_ELLIPSIZE) self.tag.pack_start(cell, True) self.tag.add_attribute(cell, 'text', 0) self.etype.get_child().set_width_chars(5) self.rtype.get_child().set_width_chars(5) self.add_text_entry(_('ID'), self.filter_id) self.add_text_entry(_('Father'), self.filter_father) self.add_text_entry(_('Mother'), self.filter_mother) self.add_text_entry(_('Child'), self.filter_child) self.add_entry(_('Relationship'), self.rtype) self.add_entry(_('Family Event'), self.etype) self.add_text_entry(_('Family Note'), self.filter_note) self.add_entry(_('Tag'), self.tag) self.add_filter_entry(_('Custom filter'), self.generic) self.add_regex_entry(self.filter_regex) def clear(self, obj): self.filter_id.set_text('') self.filter_father.set_text('') self.filter_mother.set_text('') self.filter_child.set_text('') self.filter_note.set_text('') self.etype.get_child().set_text('') self.rtype.get_child().set_text('') self.tag.set_active(0) self.generic.set_active(0) def get_filter(self): gid = str(self.filter_id.get_text()).strip() father = str(self.filter_father.get_text()).strip() mother = str(self.filter_mother.get_text()).strip() child = str(self.filter_child.get_text()).strip() note = str(self.filter_note.get_text()).strip() etype = self.filter_event.get_type().xml_str() rtype = self.filter_family.get_relationship().xml_str() regex = self.filter_regex.get_active() tag = self.tag.get_active() > 0 generic = self.generic.get_active() > 0 empty = not (gid or father or mother or child or note or regex or etype or rtype or tag or generic) if empty: generic_filter = None else: generic_filter = GenericFamilyFilter() if gid: rule = RegExpIdOf([gid], use_regex=regex) generic_filter.add_rule(rule) if father: rule = RegExpFatherName([father], use_regex=regex) generic_filter.add_rule(rule) if mother: rule = RegExpMotherName([mother], use_regex=regex) generic_filter.add_rule(rule) if child: rule = RegExpChildName([child], use_regex=regex) generic_filter.add_rule(rule) if etype: rule = HasEvent([etype, '', '', '', ''], use_regex=regex) generic_filter.add_rule(rule) if rtype: rule = HasRelType([rtype], use_regex=regex) generic_filter.add_rule(rule) if note: rule = HasNoteRegexp([note], use_regex=regex) generic_filter.add_rule(rule) # check the Tag if tag: model = self.tag.get_model() node = self.tag.get_active_iter() attr = model.get_value(node, 0) rule = HasTag([attr]) generic_filter.add_rule(rule) if self.generic.get_active() != 0: model = self.generic.get_model() node = self.generic.get_active_iter() obj = str(model.get_value(node, 0)) rule = MatchesFilter([obj]) generic_filter.add_rule(rule) return generic_filter def on_filters_changed(self, name_space): if name_space == 'Family': all_filter = GenericFamilyFilter() all_filter.set_name(_("None")) all_filter.add_rule(rules.family.AllFamilies([])) self.generic.set_model(build_filter_model('Family', [all_filter])) self.generic.set_active(0) def on_tags_changed(self, tag_list): """ Update the list of tags in the tag filter. """ model = Gtk.ListStore(str) model.append(('', )) for tag_name in tag_list: model.append((tag_name, )) self.tag.set_model(model) self.tag.set_active(0)
def exportData(database, filename, error_dialog=None, option_box=None, callback=None): if not callable(callback): callback = lambda percent: None # dummy with OpenFileOrStdout(filename) as fp: total = (len(database.note_map) + len(database.person_map) + len(database.event_map) + len(database.family_map) + len(database.repository_map) + len(database.place_map) + len(database.media_map) + len(database.source_map)) count = 0.0 # GProlog ISO directives: # /number must match the number of arguments to functions: fp.write(":- discontiguous(data/2).\n") fp.write(":- discontiguous(is_alive/2).\n") fp.write(":- discontiguous(parent/2).\n") # Rules: fp.write("grandparent(X, Y) :- parent(X, Z), parent(Z, Y).\n") fp.write("ancestor(X, Y) :- parent(X, Y).\n") fp.write("ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).\n") fp.write("sibling(X, Y) :- parent(Z, X), parent(Z, Y), X \= Y.\n") # --------------------------------- # Notes # --------------------------------- for note_handle in database.note_map.keys(): note = database.note_map[note_handle] #write_line(fp, "note_details(%s, %s)" % (note_handle, note)) count += 1 callback(100 * count/total) # --------------------------------- # Event # --------------------------------- for event_handle in database.event_map.keys(): event = database.event_map[event_handle] #write_line(fp, "event:", event_handle, event) count += 1 callback(100 * count/total) # --------------------------------- # Person # --------------------------------- for person_handle in database.person_map.keys(): data = database.person_map[person_handle] person = Person.create(data) gid = person.gramps_id.lower() fp.write("data(%s, '%s').\n" % (gid, escape(name_displayer.display(person)))) fp.write("is_alive(%s, '%s').\n" % (gid, probably_alive(person, database))) count += 1 callback(100 * count/total) # --------------------------------- # Family # --------------------------------- for family_handle in database.family_map.keys(): data = database.family_map[family_handle] family = Family.create(data) father_handle = family.get_father_handle() mother_handle = family.get_mother_handle() parents = [] if mother_handle: mother = database.get_person_from_handle(mother_handle) if mother: parents.append(mother.gramps_id.lower()) if father_handle: father = database.get_person_from_handle(father_handle) if father: parents.append(father.gramps_id.lower()) children = [] for child_ref in family.get_child_ref_list(): child_handle = child_ref.ref child = database.get_person_from_handle(child_handle) if child: children.append(child.gramps_id.lower()) for pid in parents: for cid in children: fp.write("parent(%s, %s).\n" % (pid, cid)) count += 1 callback(100 * count/total) # --------------------------------- # Repository # --------------------------------- for repository_handle in database.repository_map.keys(): repository = database.repository_map[repository_handle] #write_line(fp, "repository:", repository_handle, repository) count += 1 callback(100 * count/total) # --------------------------------- # Place # --------------------------------- for place_handle in database.place_map.keys(): place = database.place_map[place_handle] #write_line(fp, "place:", place_handle, place) count += 1 callback(100 * count/total) # --------------------------------- # Source # --------------------------------- for source_handle in database.source_map.keys(): source = database.source_map[source_handle] #write_line(fp, "source:", source_handle, source) count += 1 callback(100 * count/total) # --------------------------------- # Media # --------------------------------- for media_handle in database.media_map.keys(): media = database.media_map[media_handle] #write_line(fp, "media:", media_handle, media) count += 1 callback(100 * count/total) return True