예제 #1
0
파일: struct.py 프로젝트: belissent/gramps
    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)
예제 #2
0
    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
예제 #3
0
    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)
예제 #4
0
    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")
예제 #5
0
파일: diff.py 프로젝트: cicl06/gramps
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)
예제 #6
0
파일: diff.py 프로젝트: cicl06/gramps
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)
예제 #7
0
 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
예제 #8
0
    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
예제 #9
0
 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")
예제 #10
0
    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
예제 #11
0
 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")
예제 #12
0
    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")
예제 #13
0
    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
예제 #14
0
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()
예제 #15
0
 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
예제 #16
0
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)
예제 #17
0
 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
예제 #18
0
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)
예제 #19
0
 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})
예제 #20
0
 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
예제 #21
0
 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"),
         ))
예제 #22
0
    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
예제 #23
0
    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
예제 #24
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
예제 #25
0
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)
예제 #26
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)
예제 #27
0
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)
예제 #28
0
 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
예제 #29
0
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)
예제 #30
0
 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
예제 #31
0
 def empty_object(self):
     return Family()
예제 #32
0
 def __add_clicked(self, obj):
     family = Family()
     EditFamily(self.dbstate, self.uistate, self.track, family,
                self.__added)
예제 #33
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, 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
예제 #34
0
    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)
예제 #35
0
 def add(self, *obj):
     family = Family()
     try:
         EditFamily(self.dbstate, self.uistate, [], family)
     except WindowActiveError:
         pass
예제 #36
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, 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
예제 #37
0
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)
예제 #38
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