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.
This commit is contained in:
matt 2019-04-14 00:56:44 +02:00 committed by Nick Hall
parent 3ba2253ac0
commit 6bca4083cb

View File

@ -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()