From 6bca4083cbd8b168c1a602090ec57cbe557a3edd Mon Sep 17 00:00:00 2001 From: matt Date: Sun, 14 Apr 2019 00:56:44 +0200 Subject: [PATCH] Add occupation and residence events and attributes in the import User can now add the following columns in the csv import file for a person: - Occupation description - Occupation date - Occupation place - Occupation source - Residence date - Residence place - Residence source - Attribute type - Attribute value - Attribute source the corresponding events will be added to the person. The user can put several lines for the same person if two occupations are known, one event per line will be created. --- gramps/plugins/importer/importcsv.py | 143 +++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 18 deletions(-) diff --git a/gramps/plugins/importer/importcsv.py b/gramps/plugins/importer/importcsv.py index ce758f3fe..c83ed7fdb 100644 --- a/gramps/plugins/importer/importcsv.py +++ b/gramps/plugins/importer/importcsv.py @@ -53,7 +53,8 @@ ngettext = glocale.translation.ngettext # else "nearby" comments are ignored from gramps.gen.lib import (ChildRef, Citation, Event, EventRef, EventType, Family, FamilyRelType, Name, NameType, Note, NoteType, Person, Place, Source, Surname, Tag, - PlaceName, PlaceType, PlaceRef) + PlaceName, PlaceType, PlaceRef, + Attribute, AttributeType) from gramps.gen.db import DbTxn from gramps.gen.datehandler import parser as _dp from gramps.gen.utils.string import gender as gender_map @@ -206,6 +207,21 @@ class CSVParser: "grampsid": (_("Gramps ID"), "grampsid", "id", "gramps_id", "gramps id"), "person": ("person", _("person"), _("Person")), + "occupationdescr": ("occupationdescr", _("occupationdescr"), _("Occupation description")), + "occupationdate": ("occupationdate", _("occupationdate"), _("Occupation date")), + "occupationplace": ("occupationplace", _("occupationplace"), _("Occupation place")), + "occupationplace_id": ("occupationplace_id", _("occupationplace_id"), _("Occupation place id")), + "occupationsource": ("occupationsource", _("occupationsource"), _("Occupation source")), + + "residencedate": ("residencedate", _("residencedate"), _("residence date")), + "residenceplace": ("residenceplace", _("residenceplace"), _("residence place")), + "residenceplace_id": ("residenceplace_id", _("residenceplace_id"), _("residence place id")), + "residencesource": ("residencesource", _("residencesource"), _("residence source")), + + "attributetype": ("attributetype", _("attributetype"), _("attribute type")), + "attributevalue": ("attributevalue", _("attributevalue"), _("attribute value")), + "attributesource": ("attributesource", _("attributesource"), _("attribute source")), + # ---------------------------------- "child": ("child", _("child"), _("Child")), "family": ("family", _("family"), _("Family")), @@ -588,6 +604,19 @@ class CSVParser: deathcause = rd(line_number, row, col, "deathcause") grampsid = rd(line_number, row, col, "grampsid") person_ref = rd(line_number, row, col, "person") + occupationdescr = rd(line_number, row, col, "occupationdescr") + occupationplace = rd(line_number, row, col, "occupationplace") + occupationplace_id = rd(line_number, row, col, "occupationplace_id") + occupationsource = rd(line_number, row, col, "occupationsource") + occupationdate = rd(line_number, row, col, "occupationdate") + residencedate = rd(line_number, row, col, "residencedate") + residenceplace = rd(line_number, row, col, "residenceplace") + residenceplace_id = rd(line_number, row, col, "residenceplace_id") + residencesource = rd(line_number, row, col, "residencesource") + attributetype = rd(line_number, row, col, "attributetype") + attributevalue = rd(line_number, row, col, "attributevalue") + attributesource = rd(line_number, row, col, "attributesource") + ######################################################### # if this person already exists, don't create them person = self.lookup("person", person_ref) @@ -762,6 +791,54 @@ class CSVParser: # add, if new new, source = self.get_or_create_source(source) self.find_and_set_citation(person, source) + + # Attribute + # update existing custom attribute or create it + if attributevalue is not None: + new, attr = self.get_or_create_attribute(person, attributetype, + attributevalue, attributesource) + + # Occupation: + # Contrary to the fields above, + # each line in the csv will add a new occupation event + if occupationdescr is not None: # if no description we have no info to add + if occupationdate is not None: + occupationdate = _dp.parse(occupationdate) + # occupation place takes precedence over place id if both are set + if occupationplace is not None: + new, occupationplace = self.get_or_create_place(occupationplace) + elif occupationplace_id: + occupationplace = self.lookup("place", occupationplace_id) + if occupationsource is not None: + new, occupationsource = self.get_or_create_source(occupationsource) + new, occupation = self.get_or_create_event(person, + EventType.OCCUPATION, occupationdate, + occupationplace, occupationsource, occupationdescr, True) + occupation_ref = EventRef() + occupation_ref.set_reference_handle( occupation.get_handle()) + person.add_event_ref( occupation_ref) + + # Residence: + # Contrary to the fields above occupation, + # each line in the csv will add a new residence event + if residencedate is not None: + residencedate = _dp.parse(residencedate) + # residence place takes precedence over place id if both are set + if residenceplace is not None: + new, residenceplace = self.get_or_create_place(residenceplace) + elif residenceplace_id: + residenceplace = self.lookup("place", residenceplace_id) + if residencesource is not None: + new, residencesource = self.get_or_create_source(residencesource) + if residencedate or residenceplace or residencesource: + new, residence = self.get_or_create_event(person, + EventType.RESIDENCE, residencedate, + residenceplace, residencesource, None, True) + residence_ref = EventRef() + residence_ref.set_reference_handle( residence.get_handle()) + person.add_event_ref( residence_ref) + + self.db.commit_person(person, self.trans) def _parse_place(self, line_number, row, col): @@ -865,28 +942,32 @@ class CSVParser: return family def get_or_create_event(self, object_, type_, date=None, place=None, - source=None): - """ Add or find a type event on object """ + source=None, descr=None, create_only=False): # first, see if it exists LOG.debug("get_or_create_event") ref_list = object_.get_event_ref_list() LOG.debug("refs: %s", ref_list) # look for a match, and possible correction - for ref in ref_list: - event = self.db.get_event_from_handle(ref.ref) - LOG.debug(" compare event type %s == %s", int(event.get_type()), - type_) - if int(event.get_type()) == type_: - # Match! Let's update - if date: - event.set_date_object(date) - if place: - event.set_place_handle(place.get_handle()) - if source: - self.find_and_set_citation(event, source) - self.db.commit_event(event, self.trans) - LOG.debug(" returning existing event") - return (0, event) + # except if create_only is true (for events that + # can have several occurrences like occupations, residences) + if not create_only : + for ref in ref_list: + event = self.db.get_event_from_handle(ref.ref) + LOG.debug(" compare event type %s == %s", int(event.get_type()), + type_) + if int(event.get_type()) == type_: + # Match! Let's update + if date: + event.set_date_object(date) + if place: + event.set_place_handle(place.get_handle()) + if source: + self.find_and_set_citation(event, source) + if descr: + event.set_description(descr) + self.db.commit_event(event, self.trans) + LOG.debug(" returning existing event") + return (0, event) # else create it: LOG.debug(" creating event") event = Event() @@ -898,9 +979,35 @@ class CSVParser: event.set_place_handle(place.get_handle()) if source: self.find_and_set_citation(event, source) + if descr: + event.set_description(descr) + if self.default_tag: + event.add_tag(self.default_tag.handle) self.db.add_event(event, self.trans) return (1, event) + def get_or_create_attribute(self, object_, type_, value_, source=None): + "Replaces existing attribute or create it" + LOG.debug("get_or_create_attribute") + attr_list = object_.get_attribute_list() + LOG.debug("refs: %s", attr_list) + # remove attributes if it already exists + if type_ is None: + type_ = "UNKNOWN" + for attr in attr_list: + if attr.get_type() == type_: + object_.remove_attribute(attr) + # then add it + LOG.debug("adding attribute") + attr = Attribute() + attr.set_type(type_) + attr.set_value(value_) + if source is not None: + new, source = self.get_or_create_source(source) + self.find_and_set_citation(attr, source) + object_.add_attribute(attr) + return (1, attr) + def create_person(self): """ Used to create a new person we know doesn't exist """ person = Person()