Example #1
0
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)
Example #2
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)
Example #3
0
    def add(self, obj):
        person = Person()

        # attempt to get the current surname
        (model, pathlist) = self.selection.get_selected_rows()
        name = Name()
        #the editor requires a surname
        name.add_surname(Surname())
        name.set_primary_surname(0)
        basepers = None
        if len(pathlist) == 1:
            path = pathlist[0]
            pathids = path.get_indices()
            if len(pathids) == 1:
                path = Gtk.TreePath((pathids[0], 0))
            iter_ = model.get_iter(path)
            handle = model.get_handle_from_iter(iter_)
            basepers = self.dbstate.db.get_person_from_handle(handle)
        if basepers:
            preset_name(basepers, name)
        person.set_primary_name(name)
        try:
            EditPerson(self.dbstate, self.uistate, [], person)
        except WindowActiveError:
            pass
Example #4
0
    def add(self, *obj):
        person = Person()

        # attempt to get the current surname
        (model, pathlist) = self.selection.get_selected_rows()
        name = Name()
        #the editor requires a surname
        name.add_surname(Surname())
        name.set_primary_surname(0)
        basepers = None
        if len(pathlist) == 1:
            path = pathlist[0]
            pathids = path.get_indices()
            if len(pathids) == 1:
                path = Gtk.TreePath((pathids[0], 0))
            iter_ = model.get_iter(path)
            handle = model.get_handle_from_iter(iter_)
            basepers = self.dbstate.db.get_person_from_handle(handle)
        if basepers:
            preset_name(basepers, name)
        person.set_primary_name(name)
        try:
            EditPerson(self.dbstate, self.uistate, [], person)
        except WindowActiveError:
            pass
Example #5
0
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)
Example #6
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)
Example #7
0
 def create_person(self):
     """ Used to create a new person we know doesn't exist """
     person = Person()
     if self.default_tag:
         person.add_tag(self.default_tag.handle)
     self.db.add_person(person, self.trans)
     self.indi_count += 1
     return person
Example #8
0
 def create_person(self):
     """ Used to create a new person we know doesn't exist """
     person = Person()
     if self.default_tag:
         person.add_tag(self.default_tag.handle)
     self.db.add_person(person, self.trans)
     self.indi_count += 1
     return person
Example #9
0
 def next_person(self):
     """A VCard for another person is started."""
     if self.person is not None:
         self.finish_person()
         LOG.warn("BEGIN property not properly closed by END property, "
                  "Gramps can't cope with nested VCards.")
     self.person = Person()
     self.formatted_name = ''
     self.name_parts = ''
Example #10
0
    def add_participant(self, *obj):
        person = Person()
        ref = EventRef()
        ref.ref = self.handle
        person.add_event_ref(ref)

        try:
            EditPerson(self.dbstate, self.uistate, [], person)
        except WindowActiveError:
            pass
Example #11
0
 def __add_person(self, gender, first_name, surname, trans):
     person = Person()
     person.gender = gender
     name = person.primary_name
     name.first_name = first_name
     surname1 = Surname()
     surname1.surname = surname
     name.set_surname_list([surname1])
     self.all_surnames.append(surname)
     self.db.add_person(person, trans)
Example #12
0
 def __add_person(self, gender, first_name, surname, trans):
     person = Person()
     person.gender = gender
     name = person.primary_name
     name.first_name = first_name
     surname1 = Surname()
     surname1.surname = surname
     name.set_surname_list([surname1])
     self.all_surnames.append(surname)
     self.db.add_person(person, trans)
Example #13
0
def _add_person(gender, first_name, surname, trans, db):
    person = Person()
    person.gender = gender
    _name = person.primary_name
    _name.first_name = first_name
    surname1 = Surname()
    surname1.surname = surname
    _name.set_surname_list([surname1])
    person.gramps_id = "person001"
    db.add_person(person, trans)
 def next_person(self):
     """A VCard for another person is started."""
     if self.person is not None:
         self.finish_person()
         self.__add_msg(_("BEGIN property not properly closed by END "
                        "property, Gramps can't cope with nested VCards."),
                        self.line_num - 1)
     self.person = Person()
     self.formatted_name = ''
     self.name_parts = ''
Example #15
0
 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
Example #16
0
 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
Example #17
0
 def add_mother_clicked(self, obj):
     person = Person()
     person.set_gender(Person.FEMALE)
     autoname = config.get("behavior.surname-guessing")
     # _("Father's surname"),
     # _("None"),
     # _("Combination of mother's and father's surname"),
     # _("Icelandic style"),
     if autoname == 2:
         name = self.latin_american_child("mother")
     else:
         name = self.no_name()
     person.set_primary_name(name)
     EditPerson(self.dbstate, self.uistate, self.track, person, self.new_mother_added)
Example #18
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")
Example #19
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")
Example #20
0
 def __add_person(self, button):
     """
     Create a new person and add them to the form.
     """
     person = Person()
     EditPerson(self.dbstate, self.uistate, self.track, person,
                self.__person_added)
Example #21
0
def get_person_profile_for_object(
    db_handle: DbReadBase,
    person: Person,
    with_family: bool = True,
    with_events: bool = True,
) -> Person:
    """Get person profile given a Person."""
    profile = {
        "handle": person.handle,
        "sex": get_sex_profile(person),
        "birth": get_birth_profile(db_handle, person),
        "death": get_death_profile(db_handle, person),
        "name_given": nd.display_given(person),
        "name_surname": person.primary_name.get_surname(),
    }
    if with_family:
        primary_parent_family_handle = person.get_main_parents_family_handle()
        profile["primary_parent_family"] = get_family_profile_for_handle(
            db_handle, primary_parent_family_handle)
        profile["other_parent_families"] = []
        for handle in person.parent_family_list:
            if handle != primary_parent_family_handle:
                profile["other_parent_families"].append(
                    get_family_profile_for_handle(db_handle, handle))
        profile["families"] = [
            get_family_profile_for_handle(db_handle, handle)
            for handle in person.family_list
        ]
    if with_events:
        profile["events"] = [
            get_event_profile_for_handle(db_handle, event_ref.ref)
            for event_ref in person.event_ref_list
        ]
    return profile
Example #22
0
    def add_button_clicked(self, obj=None):
        person = Person()
        autoname = config.get("behavior.surname-guessing")
        # _("Father's surname"),
        # _("None"),
        # _("Combination of mother's and father's surname"),
        # _("Icelandic style"),
        if autoname == 0:
            name = self.north_american()
        elif autoname == 2:
            name = self.latin_american()
        else:
            name = self.no_name()
        person.set_primary_name(name)

        EditPerson(self.dbstate, self.uistate, self.track, person, self.new_child_added)
Example #23
0
def get_deathdate(db: DbReadBase, person: Person) -> Optional[str]:
    """Return the formatted death date."""
    death_ref = person.get_death_ref()
    try:
        return get_event_date_from_handle(db, death_ref.ref)
    except (AttributeError, HandleError):
        return None
Example #24
0
def get_birthdate(db: DbReadBase, person: Person) -> Optional[str]:
    """Return the formatted birth date of a person."""
    birth_handle = person.get_birth_ref()
    try:
        return get_event_date_from_handle(db, birth_handle.ref)
    except (AttributeError, HandleError):
        return None
Example #25
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()
Example #26
0
def get_deathplace_grampsid(db: DbReadBase,
                            person: Person) -> Optional[GrampsId]:
    """Return the name of the death place."""
    death_ref = person.get_death_ref()
    try:
        return get_event_place_from_handle(db, death_ref.ref)
    except (AttributeError, HandleError):
        return None
Example #27
0
    def add_button_clicked(self, obj=None):
        person = Person()
        autoname = config.get('behavior.surname-guessing')
        #_("Father's surname"),
        #_("None"),
        #_("Combination of mother's and father's surname"),
        #_("Icelandic style"),
        if autoname == 0:
            name = self.north_american()
        elif autoname == 2:
            name = self.latin_american()
        else:
            name = self.no_name()
        person.set_primary_name(name)

        EditPerson(self.dbstate, self.uistate, self.track, person,
                   self.new_child_added)
Example #28
0
def get_parents_grampsids(db: DbReadBase,
                          person: Person) -> Optional[GrampsId]:
    """Get the Gramps IDs of the family's parents."""
    handle = person.get_main_parents_family_handle()
    try:
        return db.get_family_from_handle(handle).gramps_id
    except HandleError:
        return None
 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":
             person = Person()
             person.primary_name.surname_list.append(Surname())
             action = "edit"
         else:
             person = self.database.get_person_from_handle(handle)
         if person:
             person.probably_alive = True
             self.render(
                 "person.html",
                 **self.get_template_dict(tview=_("person detail"),
                                          action=action,
                                          page=page,
                                          search=search,
                                          form=PersonForm(self.database,
                                                          _,
                                                          instance=person),
                                          logform=None))
             return
         else:
             self.clear()
             self.set_status(404)
             self.finish("<html><body>No such person</body></html>")
             return
     self.render(
         "page_view.html",
         **self.get_template_dict(
             tview=_("person view"),
             page=page,
             search=search,
             form=PersonForm(self.database, _, table="Person"),
         ))
Example #30
0
 def next_person(self):
     """A VCard for another person is started."""
     if self.person is not None:
         self.finish_person()
         LOG.warning("BEGIN property not properly closed by END property, "
                     "Gramps can't cope with nested VCards.")
     self.person = Person()
     self.formatted_name = ''
     self.name_parts = ''
Example #31
0
 def next_person(self):
     """A VCard for another person is started."""
     if self.person is not None:
         self.finish_person()
         self.__add_msg(_("BEGIN property not properly closed by END "
                        "property, Gramps can't cope with nested VCards."),
                        self.line_num - 1)
     self.person = Person()
     self.formatted_name = ''
     self.name_parts = ''
Example #32
0
 def add_child_to_fam(self, obj, event, handle):
     if button_activated(event, _LEFT_BUTTON):
         callback = lambda x: self.callback_add_child(x, handle)
         person = Person()
         name = Name()
         #the editor requires a surname
         name.add_surname(Surname())
         name.set_primary_surname(0)
         family = self.dbstate.db.get_family_from_handle(handle)
         father = self.dbstate.db.get_person_from_handle(
                                     family.get_father_handle())
         if father:
             preset_name(father, name)
         person.set_primary_name(name)
         try:
             EditPerson(self.dbstate, self.uistate, [], person,
                        callback=callback)
         except WindowActiveError:
             pass
Example #33
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":
             person = Person()
             person.primary_name.surname_list.append(Surname())
             action = "edit"
         else:
             person = self.database.get_person_from_handle(handle)
         if person:
             person.probably_alive = True
             self.render("person.html",
                         **self.get_template_dict(tview=_("person detail"),
                                                  action=action,
                                                  page=page,
                                                  search=search,
                                                  form=PersonForm(self.database, _, instance=person),
                                                  logform=None))
             return
         else:
             self.clear()
             self.set_status(404)
             self.finish("<html><body>No such person</body></html>")
             return
     self.render("page_view.html",
                 **self.get_template_dict(tview=_("person view"),
                                          page=page,
                                          search=search,
                                          form=PersonForm(self.database, _, table="Person"),
                                      )
             )
Example #34
0
    def empty_object(self):
        """
        Return an empty Person object for comparison for changes.

        This is used by the base class (EditPrimary).

        """
        person = Person()
        #the editor requires a surname
        person.primary_name.add_surname(Surname())
        person.primary_name.set_primary_surname(0)
        return person
Example #35
0
 def object_extend(self, obj: Person, args: Dict) -> Person:
     """Extend person attributes as needed."""
     db_handle = self.db_handle
     if "profile" in args:
         obj.profile = get_person_profile_for_object(db_handle,
                                                     obj,
                                                     with_family=True,
                                                     with_events=True)
     if "extend" in args:
         obj.extended = get_extended_attributes(db_handle, obj, args)
         if "all" in args["extend"] or "families" in args["extend"]:
             obj.extended["families"] = [
                 get_family_by_handle(db_handle, handle)
                 for handle in obj.family_list
             ]
         if "all" in args["extend"] or "parent_families" in args["extend"]:
             obj.extended["parent_families"] = [
                 get_family_by_handle(db_handle, handle)
                 for handle in obj.parent_family_list
             ]
         if "all" in args["extend"] or "primary_parent_family" in args[
                 "extend"]:
             obj.extended["primary_parent_family"] = get_family_by_handle(
                 db_handle, obj.get_main_parents_family_handle())
     return obj
Example #36
0
    def add(self, obj):
        """
        Add a new person to the database.
        """
        person = Person()
        #the editor requires a surname
        person.primary_name.add_surname(Surname())
        person.primary_name.set_primary_surname(0)

        try:
            EditPerson(self.dbstate, self.uistate, [], person)
        except WindowActiveError:
            pass
 def post(self, path):
     if "/" in path:
         handle, action = path.split("/")
     else:
         handle, action = path, "view"
     if handle == "add":
         person = Person()
         person.primary_name.surname_list.append(Surname())
         person.handle = handle = create_id()
     else:
         person = self.database.get_person_from_handle(handle)
     form = PersonForm(self.database, _, instance=person)
     form.save(handler=self)
     self.redirect("/person/%(handle)s" % {"handle": handle})
Example #38
0
 def add_mother_clicked(self, obj):
     person = Person()
     person.set_gender(Person.FEMALE)
     autoname = config.get('behavior.surname-guessing')
     #_("Father's surname"),
     #_("None"),
     #_("Combination of mother's and father's surname"),
     #_("Icelandic style"),
     if autoname == 2:
         name = self.latin_american_child("mother")
     else:
         name = self.no_name()
     person.set_primary_name(name)
     EditPerson(self.dbstate, self.uistate, self.track, person,
                self.new_mother_added)
Example #39
0
    def run_tool(self):
        self.progress = ProgressMeter(_('Running Date Test'),'',
                                        parent=self.parent_window)
        self.progress.set_pass(_('Generating dates'),
                               4)
        dates = []
        # first some valid dates
        calendar = Date.CAL_GREGORIAN
        for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED,
                        Date.QUAL_CALCULATED):
            for modifier in (Date.MOD_NONE, Date.MOD_BEFORE,
                             Date.MOD_AFTER, Date.MOD_ABOUT):
                for slash1 in (False,True):
                    for month in range(0,13):
                        for day in (0,5,27):
                            if not month and day:
                                continue
                            d = Date()
                            d.set(quality,modifier,calendar,(day,month,1789,slash1),"Text comment")
                            dates.append( d)
            for modifier in (Date.MOD_RANGE, Date.MOD_SPAN):
                for slash1 in (False,True):
                    for slash2 in (False,True):
                        for month in range(0,13):
                            for day in (0,5,27):
                                if not month and day:
                                    continue

                                d = Date()
                                d.set(quality,modifier,calendar,(day,month,1789,slash1,day,month,1876,slash2),"Text comment")
                                dates.append( d)

                                if not month:
                                    continue

                                d = Date()
                                d.set(quality,modifier,calendar,(day,month,1789,slash1,day,13-month,1876,slash2),"Text comment")
                                dates.append( d)

                                if not day:
                                    continue

                                d = Date()
                                d.set(quality,modifier,calendar,(day,month,1789,slash1,32-day,month,1876,slash2),"Text comment")
                                dates.append( d)
                                d = Date()
                                d.set(quality,modifier,calendar,(day,month,1789,slash1,32-day,13-month,1876,slash2),"Text comment")
                                dates.append( d)
            modifier = Date.MOD_TEXTONLY
            d = Date()
            d.set(quality,modifier,calendar,Date.EMPTY,
                  "This is a textual date")
            dates.append( d)
            self.progress.step()
        
        # test invalid dates
        #dateval = (4,7,1789,False,5,8,1876,False)
        #for l in range(1,len(dateval)):
        #    d = Date()
        #    try:
        #        d.set(Date.QUAL_NONE,Date.MOD_NONE,
        #              Date.CAL_GREGORIAN,dateval[:l],"Text comment")
        #        dates.append( d)
        #    except DateError, e:
        #        d.set_as_text("Date identified value correctly as invalid.\n%s" % e)
        #        dates.append( d)
        #    except:
        #        d = Date()
        #        d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
        #        dates.append( d)
        #for l in range(1,len(dateval)):
        #    d = Date()
        #    try:
        #        d.set(Date.QUAL_NONE,Date.MOD_SPAN,Date.CAL_GREGORIAN,dateval[:l],"Text comment")
        #        dates.append( d)
        #    except DateError, e:
        #        d.set_as_text("Date identified value correctly as invalid.\n%s" % e)
        #        dates.append( d)
        #    except:
        #        d = Date()
        #        d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
        #        dates.append( d)
        #self.progress.step()
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_NONE,
        #      Date.CAL_GREGORIAN,(44,7,1789,False),"Text comment")
        #dates.append( d)
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_NONE,
        #      Date.CAL_GREGORIAN,(4,77,1789,False),"Text comment")
        #dates.append( d)
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_SPAN,
        #      Date.CAL_GREGORIAN,
        #      (4,7,1789,False,55,8,1876,False),"Text comment")
        #dates.append( d)
        #d = Date()
        #d.set(Date.QUAL_NONE,Date.MOD_SPAN,
        #      Date.CAL_GREGORIAN,
        #      (4,7,1789,False,5,88,1876,False),"Text comment")
        #dates.append( d)
        
        with DbTxn(_("Date Test Plugin"), self.db, batch=True) as self.trans:
            self.db.disable_signals()
            self.progress.set_pass(_('Generating dates'),
                                   len(dates))

            # create pass and fail tags
            pass_handle = self.create_tag(_('Pass'), '#0000FFFF0000')
            fail_handle = self.create_tag(_('Fail'), '#FFFF00000000')

            # now add them as birth to new persons
            i = 1
            for dateval in dates:
                person = Person()
                surname = Surname()
                surname.set_surname("DateTest")
                name = Name()
                name.add_surname(surname)
                name.set_first_name("Test %d" % i)
                person.set_primary_name(name)
                self.db.add_person(person, self.trans)
                bevent = Event()
                bevent.set_type(EventType.BIRTH)
                bevent.set_date_object(dateval)
                bevent.set_description("Date Test %d (source)" % i)
                bevent_h = self.db.add_event(bevent, self.trans)
                bevent_ref = EventRef()
                bevent_ref.set_reference_handle(bevent_h)
                # for the death event display the date as text and parse it back to a new date
                ndate = None
                try:
                    datestr = _dd.display( dateval)
                    try:
                        ndate = _dp.parse( datestr)
                        if not ndate:
                            ndate = Date()
                            ndate.set_as_text("DateParser None")
                            person.add_tag(fail_handle)
                        else:
                            person.add_tag(pass_handle)
                    except:
                        ndate = Date()
                        ndate.set_as_text("DateParser Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
                        person.add_tag(fail_handle)
                    else:
                        person.add_tag(pass_handle)
                except:
                    ndate = Date()
                    ndate.set_as_text("DateDisplay Exception: %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
                    person.add_tag(fail_handle)
                
                if dateval.get_modifier() != Date.MOD_TEXTONLY \
                       and ndate.get_modifier() == Date.MOD_TEXTONLY:
                    # parser was unable to correctly parse the string
                    ndate.set_as_text( "TEXTONLY: "+ndate.get_text())
                    person.add_tag(fail_handle)
                if dateval.get_modifier() == Date.MOD_TEXTONLY \
                        and dateval.get_text().count("Traceback") \
                        and pass_handle in person.get_tag_list():
                    person.add_tag(fail_handle)
                
                devent = Event()
                devent.set_type(EventType.DEATH)
                devent.set_date_object(ndate)
                devent.set_description("Date Test %d (result)" % i)
                devent_h = self.db.add_event(devent, self.trans)
                devent_ref = EventRef()
                devent_ref.set_reference_handle(devent_h)
                person.set_birth_ref(bevent_ref)
                person.set_death_ref(devent_ref)
                self.db.commit_person(person, self.trans)
                i = i + 1
                self.progress.step()
        self.db.enable_signals()
        self.db.request_rebuild()
        self.progress.close()
Example #40
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
Example #41
0
def get_families_grampsids(db: DbReadBase, person: Person) -> List[GrampsId]:
    """Get the Gramps IDs of all the person's families."""
    handles = person.get_family_handle_list() or []
    return [db.get_family_from_handle(handle).gramps_id for handle in handles]
Example #42
0
    def dump_parent(self,title,person_handle):

        if not person_handle and not self.missingInfo:
            return
        elif not person_handle:
            person = Person()
        else:
            person = self.database.get_person_from_handle(person_handle)
        name = self._name_display.display(person)

        self.doc.start_table(title,'FGR-ParentTable')
        self.doc.start_row()
        self.doc.start_cell('FGR-ParentHead',3)
        self.doc.start_paragraph('FGR-ParentName')
        mark = ReportUtils.get_person_mark(self.database,person)
        # translators: needed for French, ignore otherwise
        self.doc.write_text(self._("%(str1)s: %(str2)s") % {
                                          'str1' : title,
                                          'str2' : name }, mark)
        if self.gramps_ids:
            gid = person.get_gramps_id()
            if gid:
                self.doc.write_text(" (%s)" % gid)
        self.doc.end_paragraph()
        self.doc.end_cell()
        self.doc.end_row()

        birth_ref = person.get_birth_ref()
        birth = None
        evtName = self._("Birth")
        if birth_ref:
            birth = self.database.get_event_from_handle(birth_ref.ref)
        if birth or self.missingInfo:
            self.dump_parent_event(evtName,birth)

        death_ref = person.get_death_ref()
        death = None
        evtName = self._("Death")
        if death_ref:
            death = self.database.get_event_from_handle(death_ref.ref)
        if death or self.missingInfo:
            self.dump_parent_event(evtName,death)

        self.dump_parent_parents(person)

        if self.incParEvents:
            for event_ref in person.get_primary_event_ref_list():
                if event_ref != birth_ref and event_ref != death_ref:
                    event = self.database.get_event_from_handle(event_ref.ref)
                    event_type = self._get_type(event.get_type())
                    self.dump_parent_event(self._(event_type),event)

        if self.incParAddr:
            addrlist = person.get_address_list()[:]
            for addr in addrlist:
                location = ReportUtils.get_address_str(addr)
                date = self._get_date(addr.get_date_object())

                self.doc.start_row()
                self.doc.start_cell("FGR-TextContents")
                self.doc.start_paragraph('FGR-Normal')
                self.doc.write_text(self._("Address"))
                self.doc.end_paragraph()
                self.doc.end_cell()
                self.doc.start_cell("FGR-TextContents")
                self.doc.start_paragraph('FGR-Normal')
                self.doc.write_text(date)
                self.doc.end_paragraph()
                self.doc.end_cell()
                self.doc.start_cell("FGR-TextContentsEnd")
                self.doc.start_paragraph('FGR-Normal')
                self.doc.write_text(location)
                self.doc.end_paragraph()
                self.doc.end_cell()
                self.doc.end_row()

        if self.incParNotes:
            for notehandle in person.get_note_list():
                note = self.database.get_note_from_handle(notehandle)
                self.dump_parent_noteline(self._("Note"), note)

        if self.includeAttrs:
            for attr in person.get_attribute_list():
                attr_type = self._get_type(attr.get_type())
                self.dump_parent_line(self._(attr_type),attr.get_value())

        if self.incParNames:
            for alt_name in person.get_alternate_names():
                name_type = self._get_type(alt_name.get_type())
                name = self._name_display.display_name(alt_name)
                self.dump_parent_line(self._(name_type), name)

        self.doc.end_table()
Example #43
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
Example #44
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
 def add_person_clicked(self, event):
     if self.selection_widget.get_current():
         person = Person()
         EditPerson(self.dbstate, self.uistate, self.track, person,
                    self.new_person_added)
Example #46
0
    def dump_parent(self, title, person_handle):

        if not person_handle and not self.missingInfo:
            return
        elif not person_handle:
            person = Person()
        else:
            person = self.database.get_person_from_handle(person_handle)
        name = self._name_display.display(person)

        self.doc.start_table(title, 'FGR-ParentTable')
        self.doc.start_row()
        self.doc.start_cell('FGR-ParentHead', 3)
        self.doc.start_paragraph('FGR-ParentName')
        self.doc.write_text(title + ': ')
        mark = ReportUtils.get_person_mark(self.database, person)
        self.doc.write_text(name, mark)
        self.doc.end_paragraph()
        self.doc.end_cell()
        self.doc.end_row()

        birth_ref = person.get_birth_ref()
        birth = None
        evtName = self._("Birth")
        if birth_ref:
            birth = self.database.get_event_from_handle(birth_ref.ref)
        if birth or self.missingInfo:
            self.dump_parent_event(evtName, birth)

        death_ref = person.get_death_ref()
        death = None
        evtName = self._("Death")
        if death_ref:
            death = self.database.get_event_from_handle(death_ref.ref)
        if death or self.missingInfo:
            self.dump_parent_event(evtName, death)

        self.dump_parent_parents(person)

        if self.incParEvents:
            for event_ref in person.get_primary_event_ref_list():
                if event_ref != birth_ref and event_ref != death_ref:
                    event = self.database.get_event_from_handle(event_ref.ref)
                    event_type = self._get_type(event.get_type())
                    self.dump_parent_event(self._(event_type), event)

        if self.incParAddr:
            addrlist = person.get_address_list()[:]
            for addr in addrlist:
                location = ReportUtils.get_address_str(addr)
                date = self._get_date(addr.get_date_object())

                self.doc.start_row()
                self.doc.start_cell("FGR-TextContents")
                self.doc.start_paragraph('FGR-Normal')
                self.doc.write_text(self._("Address"))
                self.doc.end_paragraph()
                self.doc.end_cell()
                self.doc.start_cell("FGR-TextContents")
                self.doc.start_paragraph('FGR-Normal')
                self.doc.write_text(date)
                self.doc.end_paragraph()
                self.doc.end_cell()
                self.doc.start_cell("FGR-TextContentsEnd")
                self.doc.start_paragraph('FGR-Normal')
                self.doc.write_text(location)
                self.doc.end_paragraph()
                self.doc.end_cell()
                self.doc.end_row()

        if self.incParNotes:
            for notehandle in person.get_note_list():
                note = self.database.get_note_from_handle(notehandle)
                self.dump_parent_noteline(self._("Note"), note)

        if self.includeAttrs:
            for attr in person.get_attribute_list():
                attr_type = self._get_type(attr.get_type())
                self.dump_parent_line(self._(attr_type), attr.get_value())

        if self.incParNames:
            for alt_name in person.get_alternate_names():
                name_type = self._get_type(alt_name.get_type())
                name = self._name_display.display_name(alt_name)
                self.dump_parent_line(self._(name_type), name)

        self.doc.end_table()
Example #47
0
class VCardParser:
    """Class to read data in VCard format from a file."""
    DATE_RE = re.compile(r'^(\d{4}-\d{1,2}-\d{1,2})|(?:(\d{4})-?(\d\d)-?(\d\d))')
    GROUP_RE = re.compile(r'^(?:[-0-9A-Za-z]+\.)?(.+)$')  # see RFC 2425 sec5.8.2
    ESCAPE_CHAR = '\\'
    TOBE_ESCAPED = ['\\', ',', ';']  # order is important
    LINE_CONTINUATION = [' ', '\t']

    @staticmethod
    def name_value_split(data):
        """Property group.name:value split is on first unquoted colon."""
        colon_idx = data.find(':')
        if colon_idx < 1:
            return ()
        quote_count = data.count('"', 0, colon_idx)
        while quote_count % 2 == 1:
            colon_idx = data.find(':', colon_idx + 1)
            quote_count = data.count('"', 0, colon_idx)
        group_name, value = data[:colon_idx], data[colon_idx + 1:]
        name_parts = VCardParser.GROUP_RE.match(group_name)
        return (name_parts.group(1), value)

    @staticmethod
    def unesc(data):
        """Remove VCard escape sequences."""
        if type(data) == type('string'):
            for char in reversed(VCardParser.TOBE_ESCAPED):
                data = data.replace(VCardParser.ESCAPE_CHAR + char, char)
            return data
        elif type(data) == type([]):
            return list(map(VCardParser.unesc, data))
        else:
            raise TypeError("VCard unescaping is not implemented for "
                              "data type %s." % str(type(data)))

    @staticmethod
    def count_escapes(strng):
        """Count the number of escape characters at the end of a string."""
        count = 0
        for char in reversed(strng):
            if char != VCardParser.ESCAPE_CHAR:
                return count
            count += 1
        return count

    @staticmethod
    def split_unescaped(strng, sep):
        """Split on sep if sep is unescaped."""
        strng_parts = strng.split(sep)
        for i in reversed(range(len(strng_parts[:]))):
            if VCardParser.count_escapes(strng_parts[i]) % 2 == 1:
                # the sep was escaped so undo split
                appendix = strng_parts.pop(i + 1)
                strng_parts[i] += sep + appendix
        return strng_parts

    def __init__(self, dbase):
        self.database = dbase
        self.formatted_name = ''
        self.name_parts = ''
        self.next_line = None
        self.trans = None
        self.version = None
        self.person = None
        self.errors = []
        self.number_of_errors = 0

    def __get_next_line(self, filehandle):
        """
        Read and return the line with the next property of the VCard.

        Also if it spans multiple lines (RFC 2425 sec.5.8.1).
        """
        line = self.next_line
        self.next_line = filehandle.readline()
        self.line_num = self.line_num + 1
        while self.next_line and self.next_line[0] in self.LINE_CONTINUATION:
            line = line.rstrip("\n")
            # TODO perhaps next lines superflous because of rU open parameter?
            if len(line) > 0 and line[-1] == "\r":
                line = line[:-1]
            line += self.next_line[1:]
            self.next_line = filehandle.readline()
            self.line_num = self.line_num + 1
        if line:
            line = line.strip()
        else:
            line = None
        return line

    def __add_msg(self, problem, line=None):
        if problem != "":
            self.number_of_errors += 1
        if line:
            message = _("Line %(line)5d: %(prob)s\n") % {"line": line,
                                                         "prob": problem}
        else:
            message = problem + "\n"
        self.errors.append(message)

    def parse(self, filehandle, user):
        """
        Prepare the database and parse the input file.

        :param filehandle: open file handle positioned at start of the file
        """
        tym = time.time()
        self.person = None
        self.database.disable_signals()
        with DbTxn(_("vCard import"), self.database, batch=True) as self.trans:
            self._parse_vCard_file(filehandle)
        self.database.enable_signals()
        self.database.request_rebuild()
        tym = time.time() - tym
        # translators: leave all/any {...} untranslated
        msg = ngettext('Import Complete: {number_of} second',
                       'Import Complete: {number_of} seconds', tym
                      ).format(number_of=tym)
        LOG.debug(msg)
        if self.number_of_errors == 0:
            message = _("VCARD import report: No errors detected")
        else:
            message = _("VCARD import report: %s errors detected\n") % \
                self.number_of_errors
        if hasattr(user.uistate, 'window'):
            parent_window = user.uistate.window
        else:
            parent_window = None
        user.info(message, "".join(self.errors),
                  parent=parent_window, monospaced=True)

    def _parse_vCard_file(self, filehandle):
        """Read each line of the input file and act accordingly."""
        self.next_line = filehandle.readline()
        self.line_num = 1

        while True:
            line = self.__get_next_line(filehandle)
            if line is None:
                break
            if line == "":
                continue

            if line.find(":") == -1:
                continue
            line_parts = self.name_value_split(line)
            if not line_parts:
                continue

            # No check for escaped ; because only fields[0] is used.
            fields = line_parts[0].split(";")

            property_name = fields[0].upper()
            if property_name == "BEGIN":
                self.next_person()
            elif property_name == "END":
                self.finish_person()
            elif property_name == "VERSION":
                self.check_version(fields, line_parts[1])
            elif property_name == "FN":
                self.add_formatted_name(fields, line_parts[1])
            elif property_name == "N":
                self.add_name_parts(fields, line_parts[1])
            elif property_name == "NICKNAME":
                self.add_nicknames(fields, line_parts[1])
            elif property_name == "SORT-STRING":
                self.add_sortas(fields, line_parts[1])
            elif property_name == "ADR":
                self.add_address(fields, line_parts[1])
            elif property_name == "TEL":
                self.add_phone(fields, line_parts[1])
            elif property_name == "BDAY":
                self.add_birthday(fields, line_parts[1])
            elif property_name == "ROLE":
                self.add_occupation(fields, line_parts[1])
            elif property_name == "URL":
                self.add_url(fields, line_parts[1])
            elif property_name == "EMAIL":
                self.add_email(fields, line_parts[1])
            elif property_name == "X-GENDER" or property_name == "GENDER":
                # VCard 3.0 only has X-GENDER, GENDER is 4.0 syntax,
                # but we want to be robust here.
                self.add_gender(fields, line_parts[1])
            elif property_name == "PRODID":
                # Included cause VCards made by Gramps have this prop.
                pass
            else:
                self.__add_msg(_("Token >%(token)s< unknown. line skipped: %(line)s") %
                               {"token": (fields[0], line), "line": self.line_num - 1})

    def finish_person(self):
        """All info has been collected, write to database."""
        if self.person is not None:
            if self.add_name():
                self.database.add_person(self.person, self.trans)
        self.person = None

    def next_person(self):
        """A VCard for another person is started."""
        if self.person is not None:
            self.finish_person()
            self.__add_msg(_("BEGIN property not properly closed by END "
                           "property, Gramps can't cope with nested VCards."),
                           self.line_num - 1)
        self.person = Person()
        self.formatted_name = ''
        self.name_parts = ''

    def check_version(self, fields, data):
        """Check the version of the VCard, only version 3.0 is supported."""
        self.version = data
        if self.version != "3.0":
            raise GrampsImportError(_("Import of VCards version %s is "
                    "not supported by Gramps.") % self.version)

    def add_formatted_name(self, fields, data):
        """Read the FN property of a VCard."""
        if not self.formatted_name:
            self.formatted_name = self.unesc(str(data)).strip()

    def add_name_parts(self, fields, data):
        """Read the N property of a VCard."""
        if not self.name_parts:
            self.name_parts = data.strip()

    def add_name(self):
        """
        Add the name to the person.

        Returns True on success, False on failure.
        """
        if not self.name_parts.strip():
            self.__add_msg(_("VCard is malformed missing the compulsory N "
                           "property, so there is no name; skip it."),
                           self.line_num - 1)
            return False
        if not self.formatted_name:
            self.__add_msg(_("VCard is malformed missing the compulsory FN "
                           "property, get name from N alone."), self.line_num - 1)
        data_fields = self.split_unescaped(self.name_parts, ';')
        if len(data_fields) != 5:
            self.__add_msg(_("VCard is malformed wrong number of name "
                           "components."), self.line_num - 1)

        name = Name()
        name.set_type(NameType(NameType.BIRTH))

        if data_fields[0].strip():
            # assume first surname is primary
            for surname_str in self.split_unescaped(data_fields[0], ','):
                surname = Surname()
                prefix, sname = splitof_nameprefix(self.unesc(surname_str))
                surname.set_surname(sname.strip())
                surname.set_prefix(prefix.strip())
                name.add_surname(surname)
            name.set_primary_surname()

        if len(data_fields) > 1 and data_fields[1].strip():
            given_name = ' '.join(self.unesc(
                                  self.split_unescaped(data_fields[1], ',')))
        else:
            given_name = ''
        if len(data_fields) > 2 and data_fields[2].strip():
            additional_names = ' '.join(self.unesc(
                                     self.split_unescaped(data_fields[2], ',')))
        else:
            additional_names = ''
        self.add_firstname(given_name.strip(), additional_names.strip(), name)

        if len(data_fields) > 3 and data_fields[3].strip():
            name.set_title(' '.join(self.unesc(
                            self.split_unescaped(data_fields[3], ','))))
        if len(data_fields) > 4 and data_fields[4].strip():
            name.set_suffix(' '.join(self.unesc(
                             self.split_unescaped(data_fields[4], ','))))

        self.person.set_primary_name(name)
        return True

    def add_firstname(self, given_name, additional_names, name):
        """
        Combine given_name and additional_names and add as firstname to name.

        If possible try to add given_name as call name.
        """
        default = "%s %s" % (given_name, additional_names)
        if self.formatted_name:
            if given_name:
                if additional_names:
                    given_name_pos = self.formatted_name.find(given_name)
                    if given_name_pos != -1:
                        add_names_pos = self.formatted_name.find(additional_names)
                        if add_names_pos != -1:
                            if given_name_pos <= add_names_pos:
                                firstname = default
                                # Uncertain if given name is used as callname
                            else:
                                firstname = "%s %s" % (additional_names,
                                                       given_name)
                                name.set_call_name(given_name)
                        else:
                            idx = fitin(self.formatted_name, additional_names,
                                        given_name)
                            if idx == -1:
                                # Additional names is not in formatted name
                                firstname = default
                            else:  # Given name in middle of additional names
                                firstname = "%s%s %s" % (additional_names[:idx],
                                             given_name, additional_names[idx:])
                                name.set_call_name(given_name)
                    else:  # Given name is not in formatted name
                        firstname = default
                else:  # There are no additional_names
                    firstname = given_name
            else:  # There is no given_name
                firstname = additional_names
        else:  # There is no formatted name
            firstname = default
        name.set_first_name(firstname.strip())
        return

    def add_nicknames(self, fields, data):
        """Read the NICKNAME property of a VCard."""
        for nick in self.split_unescaped(data, ','):
            nickname = nick.strip()
            if nickname:
                name = Name()
                name.set_nick_name(self.unesc(nickname))
                self.person.add_alternate_name(name)

    def add_sortas(self, fields, data):
        """Read the SORT-STRING property of a VCard."""
        # TODO
        pass

    def add_address(self, fields, data):
        """Read the ADR property of a VCard."""
        data_fields = self.split_unescaped(data, ';')
        data_fields = [x.strip() for x in self.unesc(data_fields)]
        if ''.join(data_fields):
            addr = Address()
            def add_street(strng):
                if strng:
                    already = addr.get_street()
                    if already:
                        addr.set_street("%s %s" % (already, strng))
                    else:
                        addr.set_street(strng)
            addr.add_street = add_street
            set_func = ['add_street', 'add_street', 'add_street', 'set_city',
                        'set_state', 'set_postal_code', 'set_country']
            for i, data in enumerate(data_fields):
                if i >= len(set_func):
                    break
                getattr(addr, set_func[i])(data)
            self.person.add_address(addr)

    def add_phone(self, fields, data):
        """Read the TEL property of a VCard."""
        tel = data.strip()
        if tel:
            addr = Address()
            addr.set_phone(self.unesc(tel))
            self.person.add_address(addr)

    def add_birthday(self, fields, data):
        """Read the BDAY property of a VCard."""
        date_str = data.strip()
        date_match = VCardParser.DATE_RE.match(date_str)
        date = Date()
        if date_match:
            if date_match.group(2):
                date_str = "%s-%s-%s" % (date_match.group(2),
                                       date_match.group(3), date_match.group(4))
            else:
                date_str = date_match.group(1)
            y, m, d = [int(x, 10) for x in date_str.split('-')]
            try:
                date.set(value=(d, m, y, False))
            except DateError:
                # TRANSLATORS: leave the {vcard_snippet} untranslated
                # in the format string, but you may re-order it if needed.
                self.__add_msg(_(
                    "Invalid date in BDAY {vcard_snippet}, "
                    "preserving date as text."
                    ).format(vcard_snippet=data), self.line_num - 1)
                date.set(modifier=Date.MOD_TEXTONLY, text=data)
        else:
            if date_str:
                # TRANSLATORS: leave the {vcard_snippet} untranslated.
                self.__add_msg(_(
                    "Date {vcard_snippet} not in appropriate format "
                    "yyyy-mm-dd, preserving date as text."
                    ).format(vcard_snippet=date_str), self.line_num - 1)
                date.set(modifier=Date.MOD_TEXTONLY, text=date_str)
            else:  # silently ignore an empty BDAY record
                return
        event = Event()
        event.set_type(EventType(EventType.BIRTH))
        event.set_date_object(date)
        self.database.add_event(event, self.trans)

        event_ref = EventRef()
        event_ref.set_reference_handle(event.get_handle())
        self.person.set_birth_ref(event_ref)

    def add_occupation(self, fields, data):
        """Read the ROLE property of a VCard."""
        occupation = data.strip()
        if occupation:
            event = Event()
            event.set_type(EventType(EventType.OCCUPATION))
            event.set_description(self.unesc(occupation))
            self.database.add_event(event, self.trans)

            event_ref = EventRef()
            event_ref.set_reference_handle(event.get_handle())
            self.person.add_event_ref(event_ref)

    def add_url(self, fields, data):
        """Read the URL property of a VCard."""
        href = data.strip()
        if href:
            url = Url()
            url.set_path(self.unesc(href))
            self.person.add_url(url)

    def add_email(self, fields, data):
        """Read the EMAIL property of a VCard."""
        email = data.strip()
        if email:
            url = Url()
            url.set_type(UrlType(UrlType.EMAIL))
            url.set_path(self.unesc(email))
            self.person.add_url(url)

    def add_gender(self, fields, data):
        """Read the GENDER property of a VCard."""
        gender_value = data.strip()
        if gender_value:
            gender_value = gender_value.upper()
            gender_value = gender_value[0]
            if gender_value == 'M':
                gender = Person.MALE
            elif gender_value == 'F':
                gender = Person.FEMALE
            else:
                return
            self.person.set_gender(gender)
Example #48
0
 def __add_clicked(self, obj):
     person = Person()
     EditPerson(self.dbstate, self.uistate, self.track, person,
                self.__added)