Start of a new (unsupported) plugin to import from Pro-Gen.

* src/plugins/ImportProGen.py


svn: r10639
This commit is contained in:
Kees Bakker 2008-04-25 14:37:20 +00:00
parent 141c38cde3
commit 09246035b3

887
src/plugins/ImportProGen.py Normal file
View File

@ -0,0 +1,887 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008-2008 Kees Bakker
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id:$
"Import from Pro-Gen"
#-------------------------------------------------------------------------
#
# standard python modules
#
#-------------------------------------------------------------------------
import re
from gettext import gettext as _
import os
import struct
import time
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
log = logging.getLogger('.ImportProGen')
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import Errors
import Utils
import gen.lib
import const
from QuestionDialog import ErrorDialog
from PluginUtils import register_import
class ProgenError(Exception):
"""Error used to report Progen errors."""
def __init__(self, value=""):
Exception.__init__(self)
self.value = value
def __str__(self):
return self.value
def _importData(database, filename, cb=None):
try:
g = ProgenParser(database, filename)
except IOError, msg:
ErrorDialog(_("%s could not be opened") % filename, str(msg))
return
try:
status = g.parse_progen_file()
except ProgenError, msg:
ErrorDialog(_("Pro-Gen data error"), str(msg))
return
except IOError, msg:
ErrorDialog(_("%s could not be opened") % filename, str(msg))
return
def _find_from_handle(gramps_id, table):
"""
Find a handle corresponding to the specified GRAMPS ID.
The passed table contains the mapping. If the value is found, we return
it, otherwise we create a new handle, store it, and return it.
"""
intid = table.get(gramps_id)
if not intid:
intid = Utils.create_id()
table[gramps_id] = intid
return intid
def _read_mem(bname):
'''
Each record is 32 bytes. First a 4 byte reference to the next record
followed by 28 bytes of text.
The information forms a chain of records, that stops when a reference is 0
or smaller.
There are two special sequences:
<ESC> <CR> hard return
<ESC> <^Z> end of the memo field
'''
f = open(bname + '.mem')
recfmt = "i28s"
reclen = struct.calcsize( recfmt )
#print "# reclen = %d" % reclen
mems = []
while 1:
buf = f.read(reclen)
if not buf:
break
(recno, text) = struct.unpack(recfmt, buf)
mems.append([recno, text])
return mems
def _read_recs(table, bname):
'Read records from .PER or .REL file.'
f = open(bname + table.fileext)
recfmt = table.recfmt
log.info("# %s - recfmt = %s" % (table['name1'], recfmt))
reclen = struct.calcsize( recfmt )
log.info("# %s - reclen = %d" % (table['name1'], reclen))
recs = []
while 1:
buf = f.read(reclen)
if not buf:
break
tups = struct.unpack(recfmt, buf)
recs.append(tups)
log.info("# length %s.recs[] = %d" % (table['name1'], len(recs)))
return recs
def _get_defname(fname):
'''
Get the name of the PG30 DEF file by looking at the user DEF file. And return
the name of the DEF file. fname is expected to be somewhere in the PG30 tree.
Contents of <fname> is something like:
=> \0
=> C:\PG30\NL\PG30-1.DEF
We will strip the C: and convert the rest to a native pathname. Next, this pathname
is compared with <fname>.
'''
lines = open( fname ).readlines()
if not lines[0].startswith(r'\0') or len(lines) < 2:
raise ProgenError(_("Not a Pro-Gen file"))
return None, '?'
defname = lines[1].lower()
defname = defname.strip()
# Strip drive, if any
defname = re.sub( r'^\w:', '', defname )
defname = defname.replace('\\', os.sep)
# Strip leading slash, if any.
if defname.startswith(os.sep):
defname = defname[1:]
# Using the directory of <fname>, go to the parent directory until
# the DEF is found.
dir_, f = os.path.split(os.path.abspath(fname))
while dir_:
newdefname = os.path.join(dir_, defname)
if os.path.exists(newdefname):
return newdefname, defname
dir_, f = os.path.split(dir_)
return None, defname
esc_ctrlz_pat = re.compile(r'\033\032.*')
def _get_mem_text(mems, i):
'Notice that Pro-Gen starts the mem numbering at 1.'
if i <= 0:
return ''
i = i - 1
recno = mems[i][0]
text = mems[i][1].decode('cp850')
if recno != 0:
text += _get_mem_text(mems, recno)
# ESC-^M is newline
text = text.replace('\033\r', '\n')
# ESC-^Z is end of string
text = esc_ctrlz_pat.sub('', text)
# TODO. Strip trailing empty lines.
#print text.encode('utf-8')
return text
# Example field:
# ['Voornaam', '47', '64', '4', '2', '15', '""', '""']
# item 0
# item 1 is a number indicating the fieldtype
# item 2
# item 3 is the size of the field
class PG30_Def_Table_Field:
'This class represents a field in one of the tables in the DEF file.'
def __init__(self, name, value):
self.fieldname = name
self.fields = value.split(',')
self.fields = [p.strip() for p in self.fields]
self.name = self.fields[0]
self.type_ = int(self.fields[1])
self.size = int(self.fields[3])
def __repr__(self):
return self.fieldname + ' -> ' + ', '.join(self.fields)
class PG30_Def_Table:
'This class represents a table in the DEF file.'
def __init__(self, name, lines):
self.name = name
self.parms = {}
self.recfmt = None
# Example line:
#f02=Persoon gewijzigd ,32,10,10, 1,68,"","INDI CHAN DATE"
line_pat = re.compile(r'(\w+) = (.*)', re.VERBOSE)
for l in lines:
#print l
m = line_pat.match(l)
if m:
# TODO. Catch duplicates?
self.parms[m.group(1)] = m.group(2)
self.fileext = self.parms.get('fileext', None)
if self.fileext:
self.fileext = self.fileext.lower()
#self.name1 = self.parms.get('name1', None)
# If there is a n_fields entry then this is a table that
# has details about the record format of another file (PER or REL).
if self.parms.has_key('n_fields'):
self.get_fields()
self.recfmt = self.get_recfmt()
self.nam2fld = {}
self.nam2idx = {}
self.recflds = [] # list of fields that use up space in a record
j = 0
for i, f in enumerate(self.flds):
#print "# field %s" % f
nam = f.name
self.nam2fld[nam] = f
if f.size != 0:
self.nam2idx[nam] = j
#print "# %s <= %d" % (f[0], j)
self.recflds.append(f)
j = j + 1
def __getitem__(self, i):
return self.parms.get(i, None)
def get_recfmt(self):
'Get the record format for struct.unpack'
# Example field:
# ['Voornaam', '47', '64', '4', '2', '15', '""', '""']
# item 0
# item 1 is a number indicating the fieldtype
# item 2
# item 3 is the size of the field
# ...
flds = self.flds
fmt = '='
for f in flds:
fldtyp = f.type_
if fldtyp == 2 or fldtyp == 3 or fldtyp == 22 or fldtyp == 23:
fmt += 'i'
elif fldtyp == 31:
pass
elif fldtyp == 32 or fldtyp == 44 or fldtyp == 45:
fmt += '%ds' % f.size
elif fldtyp == 41:
fmt += 'h'
elif fldtyp == 42 or fldtyp == 43 or fldtyp == 46 or fldtyp == 47:
fmt += 'i'
else:
pass # ???? Do we want to know?
return fmt
def get_fields(self):
# For example from pg30-1.def
#n_fields=58
#f01=Persoon record ,31, 6, 0, 1,17,"","INDI RFN"
#f02=Persoon gewijzigd ,32,10,10, 1,68,"","INDI CHAN DATE"
#f03=Voornaam ,47,64, 4, 2,15,"",""
n_fields = int(self.parms['n_fields'])
flds = []
for i in range(n_fields):
fld_name = 'f%02d' % (i+1)
fld = self.parms.get(fld_name, None)
flds.append(PG30_Def_Table_Field(fld_name, fld))
self.flds = flds
def get_record_field_index(self, fldname):
'Return the index number in the record tuple, based on the name.'
if not fldname in self.nam2idx:
raise ProgenError(_("Field '%(fldname)s' not found") % locals())
return self.nam2idx[fldname]
def convert_record_to_list(self, rec, mems):
flds = []
for i in range(len(rec)):
if self.field_ix_is_record_number(i):
flds.append("%d" % rec[i])
elif self.field_ix_is_mem_type(i):
flds.append(_get_mem_text(mems, rec[i]))
else:
# Not a record number, not a mem number. It must be just text.
fld = rec[i].strip()
# Convert to unicode
fld = fld.decode('cp850')
flds.append(fld)
#print ', '.join([f.encode('utf-8') for f in flds])
return flds
def get_field_names(self):
ret = []
for f in self.flds:
if f.size != 0:
ret.append(f.name)
return ret
def field_is_mem_type(self, fldname):
if not fldname in self.nam2fld:
return None
typ = self.nam2fld[fldname].type_
if typ == 46 or typ == 47:
return True
return False
# TODO. Integrate this into field_is_mem_type()
def field_ix_is_mem_type(self, ix):
typ = self.recflds[ix].type_
if typ == 46 or typ == 47:
return True
return False
def field_ix_is_record_number(self, ix):
typ = self.recflds[ix].type_
if typ == 2 or typ == 3 or typ == 22 or typ == 23:
return True
return False
def diag(self):
txt = self.name + '\n'
if self.parms.has_key('n_fields'):
txt += 'n_fields = %s\n' % self.parms['n_fields']
# Just grab a field
f = self.flds[1]
txt += '"%s"\n' % f
txt += 'recfmt = %s (length=%d)' % (self.recfmt, struct.calcsize(self.recfmt))
return txt
class PG30_Def:
'''
Utility class to read PG30-1.DEF and to get certain information
from it.
The contents of the DEF file is separated in sections that start
with [<section name>]. For example:
[general]
dateformat=DD-MM-YYYY
pointerlength=4
tables=2
'''
def __init__(self, fname):
#print fname
fname, deffname = _get_defname(fname)
if not fname:
raise ProgenError(_("Cannot find DEF file: %(deffname)s") % locals())
# This can throw a IOError
lines = open(fname).readlines()
lines = [l.strip() for l in lines]
content = '\n'.join(lines)
parts = re.split(r'\n(?=\[)', content)
self.parts = {}
self.tables = {}
for p in parts:
lines = p.splitlines()
# Get section name
k = re.sub(r'\[(.*)\]', r'\1', lines[0])
# Store section contents in a hashtable using that section name
self.parts[k] = lines[1:]
self.tables[k] = PG30_Def_Table(k, self.parts[k])
# Some sections are special: Table_1 and Table_2
def __getitem__(self, i):
return self.tables.get(i, None)
# TODO. Maybe rename to __repr__
def diag(self):
return '\n\n'.join([self.tables[t].diag() for t in self.tables])
class ProgenParser:
def __init__(self, dbase, file_):
self.bname, ext = os.path.splitext(file_)
if ext.lower() != '.def':
raise ProgenError(_("Expecting a file with .def extension"))
self.db = dbase
self.fname = file_
self.gid2id = {} # Maps person id
self.fid2id = {} # Maps family id
self.pkeys = {} # Caching place handles
def parse_progen_file(self):
self.progress = Utils.ProgressMeter(_("Import from Pro-Gen"), '')
self.def_ = PG30_Def(self.fname)
#print self.def_.diag()
self.mems = _read_mem(self.bname)
self.pers = _read_recs(self.def_['Table_1'], self.bname)
self.rels = _read_recs(self.def_['Table_2'], self.bname)
self.trans = self.db.transaction_begin('', batch=True)
self.db.disable_signals()
self.create_persons()
self.create_families()
#self.add_children()
self.db.transaction_commit(self.trans, _("Pro-Gen import"))
self.db.enable_signals()
self.db.request_rebuild()
self.progress.close()
def __find_person_handle(self, gramps_id):
"""
Return the database handle associated with the person's GRAMPS ID
"""
return _find_from_handle(gramps_id, self.gid2id)
def __find_family_handle(self, gramps_id):
"""
Return the database handle associated with the family's GRAMPS ID
"""
return _find_from_handle(gramps_id, self.fid2id)
def __find_or_create_person(self, gramps_id):
"""
Finds or creates a person based on the GRAMPS ID. If the ID is
already used (is in the db), we return the item in the db. Otherwise,
we create a new person, assign the handle and GRAMPS ID.
"""
person = gen.lib.Person()
intid = self.gid2id.get(gramps_id)
if self.db.has_person_handle(intid):
person.unserialize(self.db.get_raw_person_data(intid))
else:
intid = _find_from_handle(gramps_id, self.gid2id)
person.set_handle(intid)
person.set_gramps_id(gramps_id)
return person
def __find_or_create_family(self, gramps_id):
"""
Finds or creates a family based on the GRAMPS ID. If the ID is
already used (is in the db), we return the item in the db. Otherwise,
we create a new family, assign the handle and GRAMPS ID.
"""
family = gen.lib.Family()
intid = self.fid2id.get(gramps_id)
if self.db.has_family_handle(intid):
family.unserialize(self.db.get_raw_family_data(intid))
else:
intid = _find_from_handle(gramps_id, self.fid2id)
family.set_handle(intid)
family.set_gramps_id(gramps_id)
return family
def __get_or_create_place(self, place_name):
if not place_name:
return None
place = None
if place_name in self.pkeys:
place = self.db.get_place_from_handle(self.pkeys[place_name])
else:
# Create a new Place
place = gen.lib.Place()
place.set_title(place_name)
self.db.add_place(place, self.trans)
self.db.commit_place(place, self.trans)
self.pkeys[place_name] = place.get_handle()
return place
def __create_event_and_ref(self, type_, desc=None, date=None, place=None, source=None):
event = gen.lib.Event()
event.set_type(gen.lib.EventType(type_))
if desc:
event.set_description(desc)
if date:
event.set_date_object(date)
if place:
event.set_place_handle(place.get_handle())
if source:
event.add_source_reference(source)
self.db.add_event(event,self.trans)
self.db.commit_event(event,self.trans)
event_ref = gen.lib.EventRef()
event_ref.set_reference_handle(event.get_handle())
return event, event_ref
__date_pat1 = re.compile(r'(?P<day>\d{1,2}) (-|=) (?P<month>\d{1,2}) (-|=) (?P<year>\d{2,4})', re.VERBOSE)
__date_pat2 = re.compile(r'(?P<month>\d{1,2}) (-|=) (?P<year>\d{4})', re.VERBOSE)
__date_pat3 = re.compile(r'(?P<year>\d{4})', re.VERBOSE)
__date_pat4 = re.compile(ur'(v|vóór|voor|na|circa|ca|rond) \s* (?P<year>\d{4})', re.VERBOSE)
__date_pat5 = re.compile(r'(oo) (-|=) (oo) (-|=) (?P<year>\d{2,4})', re.VERBOSE)
def __create_date_from_text(self, txt, diag_msg=None):
'''
Pro-Gen has a text field for the date. It can be anything. Mostly it will be dd-mm-yyyy,
but we have seen:
yyyy
mm-yyyy
voor yyyy
dd=mm-yyyy (typo I guess)
00-00-yyyy
oo-oo-yyyy
dd-mm-00 (does this mean we do not know about the year?)
This function tries to parse the text and create a proper Gramps Date() object.
If all else fails we create a MOD_TEXTONLY Date() object.
'''
date = gen.lib.Date()
# dd-mm-yyyy
m = self.__date_pat1.match(txt)
if m:
day = int(m.group('day'))
month = int(m.group('month'))
year = int(m.group('year'))
if day and month and year:
date.set_yr_mon_day(year, month, day)
else:
date.set(gen.lib.Date.QUAL_NONE, gen.lib.Date.MOD_ABOUT, gen.lib.Date.CAL_GREGORIAN, (day, month, year, None))
return date
# mm-yyyy
m = self.__date_pat2.match(txt)
if m:
month = int(m.group('month'))
year = int(m.group('year'))
date.set(gen.lib.Date.QUAL_NONE, gen.lib.Date.MOD_ABOUT, gen.lib.Date.CAL_GREGORIAN, (0, month, year, None))
return date
# yyyy
m = self.__date_pat3.match(txt)
if m:
year = int(m.group('year'))
date.set(gen.lib.Date.QUAL_NONE, gen.lib.Date.MOD_ABOUT, gen.lib.Date.CAL_GREGORIAN, (0, 0, year, None))
return date
# voor|na|... yyyy
m = self.__date_pat4.match(txt)
if m:
year = int(m.group('year'))
if m.group(1) == 'voor' or m.group(1) == 'v' or m.group(1) == u'vóór':
date.set(gen.lib.Date.QUAL_NONE, gen.lib.Date.MOD_BEFORE, gen.lib.Date.CAL_GREGORIAN, (0, 0, year, None))
elif m.group(1) == 'na':
date.set(gen.lib.Date.QUAL_NONE, gen.lib.Date.MOD_AFTER, gen.lib.Date.CAL_GREGORIAN, (0, 0, year, None))
else:
date.set(gen.lib.Date.QUAL_NONE, gen.lib.Date.MOD_ABOUT, gen.lib.Date.CAL_GREGORIAN, (0, 0, year, None))
return date
# oo-oo-yyyy
m = self.__date_pat5.match(txt)
if m:
year = int(m.group('year'))
date.set(gen.lib.Date.QUAL_NONE, gen.lib.Date.MOD_ABOUT, gen.lib.Date.CAL_GREGORIAN, (0, 0, year, None))
return date
log.warning(_("date did not match: '%s' (%s)") % (txt.encode('utf-8'), diag_msg or ''))
# Hmmm. Just use the plain text.
date.set_as_text(txt)
return date
def create_persons(self):
self.progress.set_pass(_('Importing individuals'), len(self.pers))
table = self.def_['Table_1']
# Records in the PER file using PG30-1.DEF contain the following fields:
# (Note. We want this to be computed just once.
#log.info(table.get_field_names())
# I'm sure I can find a better way to do this through the local() dict)
first_name_ix = table.get_record_field_index('Voornaam')
surname_ix = table.get_record_field_index('Achternaam')
gender_ix = table.get_record_field_index('Geslacht')
patron_ix = table.get_record_field_index('Patroniem')
call_name_ix = table.get_record_field_index('Roepnaam')
alias_ix = table.get_record_field_index('Alias')
percode_ix = table.get_record_field_index('Persoon code')
title1_ix = table.get_record_field_index('Titel1')
title2_ix = table.get_record_field_index('Titel2')
title3_ix = table.get_record_field_index('Titel3')
father_ix = table.get_record_field_index('Vader')
mother_ix = table.get_record_field_index('Moeder')
occu_ix = table.get_record_field_index('Beroep')
per_klad_ix = table.get_record_field_index('Persoon klad')
per_info_ix = table.get_record_field_index('Persoon info')
addr_date_ix = table.get_record_field_index('Adres datum')
addr_street_ix = table.get_record_field_index('Adres straat')
addr_postal_ix = table.get_record_field_index('Adres postcode')
addr_place_ix = table.get_record_field_index('Adres plaats')
addr_country_ix = table.get_record_field_index('Adres land')
addr_tel_ix = table.get_record_field_index('Adres telefoon')
addr_info_ix = table.get_record_field_index('Adres info')
birth_date_ix = table.get_record_field_index('Geboorte datum')
birth_place_ix = table.get_record_field_index('Geboorte plaats')
birth_time_ix = table.get_record_field_index('Geboorte tijd')
birth_source_ix = table.get_record_field_index('Geboorte bron')
birth_cert_ix = table.get_record_field_index('Geboorte akte')
birth_source_text_ix = table.get_record_field_index('Geboorte brontekst')
birth_info_ix = table.get_record_field_index('Geboorte info')
bapt_date_ix = table.get_record_field_index('Doop datum')
bapt_place_ix = table.get_record_field_index('Doop plaats')
bapt_reli_ix = table.get_record_field_index('Gezindte')
bapt_wit_ix = table.get_record_field_index('Doop getuigen')
bapt_source_ix = table.get_record_field_index('Doop bron')
bapt_cert_ix = table.get_record_field_index('Doop akte')
bapt_source_text_ix = table.get_record_field_index('Doop brontekst')
bapt_info_ix = table.get_record_field_index('Doop info')
death_date_ix = table.get_record_field_index('Overlijden datum')
death_place_ix = table.get_record_field_index('Overlijden plaats')
death_time_ix = table.get_record_field_index('Overlijden tijd')
death_source_ix = table.get_record_field_index('Overlijden bron')
death_cert_ix = table.get_record_field_index('Overlijden akte')
death_source_text_ix = table.get_record_field_index('Overlijden brontekst')
death_info_ix = table.get_record_field_index('Overlijden info')
crem_date_ix = table.get_record_field_index('Crematie datum')
crem_place_ix = table.get_record_field_index('Crematie plaats')
crem_source_ix = table.get_record_field_index('Crematie bron')
crem_cert_ix = table.get_record_field_index('Crematie akte')
crem_source_text_ix = table.get_record_field_index('Crematie brontekst')
crem_info_ix = table.get_record_field_index('Crematie info')
bur_date_ix = table.get_record_field_index('Begrafenis datum')
bur_place_ix = table.get_record_field_index('Begrafenis plaats')
bur_source_ix = table.get_record_field_index('Begrafenis bron')
bur_cert_ix = table.get_record_field_index('Begrafenis akte')
bur_source_text_ix = table.get_record_field_index('Begrafenis brontekst')
bur_info_ix = table.get_record_field_index('Begrafenis info')
# The records are numbered 1..N
for i, rec in enumerate(self.pers):
pers_id = i + 1
father = rec[father_ix]
mother = rec[mother_ix]
if father >= 0 and mother >= 0:
recflds = table.convert_record_to_list(rec, self.mems)
first_name = recflds[first_name_ix]
surname = recflds[surname_ix]
gender = recflds[gender_ix]
if gender == 'M':
gender = gen.lib.Person.MALE
elif gender == 'V':
gender = gen.lib.Person.FEMALE
else:
gender = gen.lib.Person.UNKNOWN
person = self.__find_or_create_person("I%d" % pers_id)
diag_msg = "I%d: %s %s" % (pers_id, first_name.encode('utf-8'), surname.encode('utf-8'))
#log.info(diag_msg)
name = gen.lib.Name()
name.set_type(gen.lib.NameType.BIRTH)
name.set_surname(surname)
name.set_first_name(first_name)
if recflds[call_name_ix]:
name.set_call_name(recflds[call_name_ix])
person.set_primary_name(name)
person.set_gender(gender)
if recflds[alias_ix]:
# Alias skipped. Not sure if it is used.
# TODO. Log it
pass
if recflds[patron_ix]:
# Patronym skipped. Not sure if it is used.
# TODO. Log it
pass
if recflds[percode_ix]:
# Person code skipped. Not sure if it is used.
# TODO. Log it
pass
if recflds[occu_ix]:
event, event_ref = self.__create_event_and_ref(gen.lib.EventType.OCCUPATION, recflds[occu_ix])
person.add_event_ref(event_ref)
if recflds[birth_date_ix]:
place = self.__get_or_create_place(recflds[birth_place_ix])
time = recflds[birth_time_ix]
source = recflds[birth_source_ix]
cert = recflds[birth_cert_ix]
source_text = recflds[birth_source_text_ix]
info = recflds[birth_info_ix]
date = self.__create_date_from_text(recflds[birth_date_ix], diag_msg)
event, birth_ref = self.__create_event_and_ref(gen.lib.EventType.BIRTH, info, date, place)
person.set_birth_ref(birth_ref)
if recflds[bapt_date_ix]:
place = self.__get_or_create_place(recflds[bapt_place_ix])
reli = recflds[bapt_reli_ix]
witness = recflds[bapt_wit_ix]
source = recflds[bapt_source_ix]
cert = recflds[bapt_cert_ix]
source_text = recflds[bapt_source_text_ix]
info = recflds[bapt_info_ix]
date = self.__create_date_from_text(recflds[bapt_date_ix], diag_msg)
event, bapt_ref = self.__create_event_and_ref(gen.lib.EventType.BAPTISM, info, date, place)
# ???? reli
# ???? witness
person.add_event_ref(bapt_ref)
if recflds[death_date_ix]:
place = self.__get_or_create_place(recflds[death_place_ix])
time = recflds[death_time_ix]
source = recflds[death_source_ix]
cert = recflds[death_cert_ix]
source_text = recflds[death_source_text_ix]
info = recflds[death_info_ix]
date = self.__create_date_from_text(recflds[death_date_ix], diag_msg)
event, death_ref = self.__create_event_and_ref(gen.lib.EventType.DEATH, info, date, place)
person.set_death_ref(death_ref)
if recflds[bur_date_ix]:
place = self.__get_or_create_place(recflds[bur_place_ix])
source = recflds[bur_source_ix]
cert = recflds[bur_cert_ix]
source_text = recflds[bur_source_text_ix]
info = recflds[bur_info_ix]
date = self.__create_date_from_text(recflds[bur_date_ix], diag_msg)
event, burial_ref = self.__create_event_and_ref(gen.lib.EventType.BURIAL, info, date, place)
person.add_event_ref(burial_ref)
elif recflds[crem_date_ix]:
place = self.__get_or_create_place(recflds[crem_place_ix])
source = recflds[crem_source_ix]
cert = recflds[crem_cert_ix]
source_text = recflds[crem_source_text_ix]
info = recflds[crem_info_ix]
date = self.__create_date_from_text(recflds[crem_date_ix], diag_msg)
event, cremation_ref = self.__create_event_and_ref(gen.lib.EventType.CREMATION, info, date, place)
person.add_event_ref(cremation_ref)
self.db.commit_person(person, self.trans)
self.progress.step()
def create_families(self):
self.progress.set_pass(_('Importing families'), len(self.rels))
table = self.def_['Table_2']
# Records in the REL file using PG30-1.DEF contain the following fields:
# (Note. We want this to be computed just once.
#log.info(table.get_field_names())
man_ix = table.get_record_field_index('Man')
vrouw_ix = table.get_record_field_index('Vrouw')
f05 = table.get_record_field_index('Relatie code')
f06 = table.get_record_field_index('Relatie klad')
f07 = table.get_record_field_index('Relatie info')
f08 = table.get_record_field_index('Samenwonen datum')
f09 = table.get_record_field_index('Samenwonen plaats')
f10 = table.get_record_field_index('Samenwonen bron')
f11 = table.get_record_field_index('Samenwonen akte')
f12 = table.get_record_field_index('Samenwonen brontekst')
f13 = table.get_record_field_index('Samenwonen info')
f14 = table.get_record_field_index('Ondertrouw datum')
f15 = table.get_record_field_index('Ondertrouw plaats')
f16 = table.get_record_field_index('Ondertrouw getuigen')
f17 = table.get_record_field_index('Ondertrouw bron')
f18 = table.get_record_field_index('Ondertrouw akte')
f19 = table.get_record_field_index('Ondertrouw brontekst')
f20 = table.get_record_field_index('Ondertrouw info')
f21 = table.get_record_field_index('Wettelijk datum')
f22 = table.get_record_field_index('Wettelijk plaats')
f23 = table.get_record_field_index('Wettelijk getuigen')
f24 = table.get_record_field_index('Wettelijk bron')
f25 = table.get_record_field_index('Wettelijk akte')
f26 = table.get_record_field_index('Wettelijk brontekst')
f27 = table.get_record_field_index('Wettelijk info')
f28 = table.get_record_field_index('Kerkelijk datum')
f29 = table.get_record_field_index('Kerkelijk plaats')
f30 = table.get_record_field_index('Kerk')
f31 = table.get_record_field_index('Kerkelijk getuigen')
f32 = table.get_record_field_index('Kerkelijk bron')
f33 = table.get_record_field_index('Kerkelijk akte')
f34 = table.get_record_field_index('Kerkelijk brontekst')
f35 = table.get_record_field_index('Kerkelijk info')
f36 = table.get_record_field_index('Scheiding datum')
f37 = table.get_record_field_index('Scheiding plaats')
f38 = table.get_record_field_index('Scheiding bron')
f39 = table.get_record_field_index('Scheiding akte')
f40 = table.get_record_field_index('Scheiding brontekst')
f41 = table.get_record_field_index('Scheiding info')
# The records are numbered 1..N
self.progress.set_pass(_('Adding families'), len(self.rels))
for i, rec in enumerate(self.rels):
fam_id = i + 1
husband = rec[man_ix]
wife = rec[vrouw_ix]
if husband > 0 or wife > 0:
fam = self.__find_or_create_family("F%d" % fam_id)
if husband > 0:
husband_handle = self.__find_person_handle("I%d" % husband)
fam.set_father_handle(husband_handle)
husband_person = self.db.get_person_from_handle(husband_handle)
husband_person.add_family_handle(fam.get_handle())
self.db.commit_person(husband_person,self.trans)
if wife > 0:
wife_handle = self.__find_person_handle("I%d" % wife)
fam.set_mother_handle(wife_handle)
wife_person = self.db.get_person_from_handle(wife_handle)
wife_person.add_family_handle(fam.get_handle())
self.db.commit_person(wife_person,self.trans)
self.db.commit_family(fam, self.trans)
self.progress.step()
def add_children():
# Once more to record the father and mother
# The records are numbered 1..N
self.progress.set_pass(_('Adding children'), len(self.pers))
for i, rec in enumerate(self.pers):
pers_id = i + 1
father = rec[father_ix]
mother = rec[mother_ix]
if father > 0 or mother > 0:
person = self.__find_or_create_person("I%d" % pers_id)
if father > 0:
father_handle = self.__find_person("I%d" % father)
if mother > 0:
mother_handle = self.__find_person("I%d" % mother)
self.progress.step()
_mime_type = "application/x-progen"
import gtk
_filter = gtk.FileFilter()
_filter.set_name(_('Pro-Gen files'))
_filter.add_mime_type(_mime_type)
_format_name = _('Pro-Gen')
register_import(_importData, _filter, [_mime_type], 0, _format_name)