Added Places to CSV import/export
This commit is contained in:
parent
58d7cbe99d
commit
3df700b22a
@ -181,13 +181,16 @@ class CSVWriterOptionBox(WriterOptionBox):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, person, dbstate, uistate):
|
def __init__(self, person, dbstate, uistate):
|
||||||
WriterOptionBox.__init__(self, person, dbstate, uistate)
|
WriterOptionBox.__init__(self, person, dbstate, uistate)
|
||||||
|
## TODO: add place filter selection
|
||||||
self.include_individuals = 1
|
self.include_individuals = 1
|
||||||
self.include_marriages = 1
|
self.include_marriages = 1
|
||||||
self.include_children = 1
|
self.include_children = 1
|
||||||
|
self.include_places = 1
|
||||||
self.translate_headers = 1
|
self.translate_headers = 1
|
||||||
self.include_individuals_check = None
|
self.include_individuals_check = None
|
||||||
self.include_marriages_check = None
|
self.include_marriages_check = None
|
||||||
self.include_children_check = None
|
self.include_children_check = None
|
||||||
|
self.include_places_check = None
|
||||||
self.translate_headers_check = None
|
self.translate_headers_check = None
|
||||||
|
|
||||||
def get_option_box(self):
|
def get_option_box(self):
|
||||||
@ -197,16 +200,19 @@ class CSVWriterOptionBox(WriterOptionBox):
|
|||||||
self.include_individuals_check = Gtk.CheckButton(label=_("Include people"))
|
self.include_individuals_check = Gtk.CheckButton(label=_("Include people"))
|
||||||
self.include_marriages_check = Gtk.CheckButton(label=_("Include marriages"))
|
self.include_marriages_check = Gtk.CheckButton(label=_("Include marriages"))
|
||||||
self.include_children_check = Gtk.CheckButton(label=_("Include children"))
|
self.include_children_check = Gtk.CheckButton(label=_("Include children"))
|
||||||
|
self.include_places_check = Gtk.CheckButton(label=_("Include places"))
|
||||||
self.translate_headers_check = Gtk.CheckButton(label=_("Translate headers"))
|
self.translate_headers_check = Gtk.CheckButton(label=_("Translate headers"))
|
||||||
|
|
||||||
self.include_individuals_check.set_active(1)
|
self.include_individuals_check.set_active(1)
|
||||||
self.include_marriages_check.set_active(1)
|
self.include_marriages_check.set_active(1)
|
||||||
self.include_children_check.set_active(1)
|
self.include_children_check.set_active(1)
|
||||||
|
self.include_places_check.set_active(1)
|
||||||
self.translate_headers_check.set_active(1)
|
self.translate_headers_check.set_active(1)
|
||||||
|
|
||||||
option_box.pack_start(self.include_individuals_check, False, True, 0)
|
option_box.pack_start(self.include_individuals_check, False, True, 0)
|
||||||
option_box.pack_start(self.include_marriages_check, False, True, 0)
|
option_box.pack_start(self.include_marriages_check, False, True, 0)
|
||||||
option_box.pack_start(self.include_children_check, False, True, 0)
|
option_box.pack_start(self.include_children_check, False, True, 0)
|
||||||
|
option_box.pack_start(self.include_places_check, False, True, 0)
|
||||||
option_box.pack_start(self.translate_headers_check, False, True, 0)
|
option_box.pack_start(self.translate_headers_check, False, True, 0)
|
||||||
|
|
||||||
return option_box
|
return option_box
|
||||||
@ -217,6 +223,7 @@ class CSVWriterOptionBox(WriterOptionBox):
|
|||||||
self.include_individuals = self.include_individuals_check.get_active()
|
self.include_individuals = self.include_individuals_check.get_active()
|
||||||
self.include_marriages = self.include_marriages_check.get_active()
|
self.include_marriages = self.include_marriages_check.get_active()
|
||||||
self.include_children = self.include_children_check.get_active()
|
self.include_children = self.include_children_check.get_active()
|
||||||
|
self.include_places = self.include_places_check.get_active()
|
||||||
self.translate_headers = self.translate_headers_check.get_active()
|
self.translate_headers = self.translate_headers_check.get_active()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
@ -237,6 +244,7 @@ class CSVWriter(object):
|
|||||||
|
|
||||||
self.plist = {}
|
self.plist = {}
|
||||||
self.flist = {}
|
self.flist = {}
|
||||||
|
self.place_list = {}
|
||||||
|
|
||||||
self.persons_details_done = []
|
self.persons_details_done = []
|
||||||
self.persons_notes_done = []
|
self.persons_notes_done = []
|
||||||
@ -246,6 +254,7 @@ class CSVWriter(object):
|
|||||||
self.include_individuals = 1
|
self.include_individuals = 1
|
||||||
self.include_marriages = 1
|
self.include_marriages = 1
|
||||||
self.include_children = 1
|
self.include_children = 1
|
||||||
|
self.include_places = 1
|
||||||
self.translate_headers = 1
|
self.translate_headers = 1
|
||||||
else:
|
else:
|
||||||
self.option_box.parse_options()
|
self.option_box.parse_options()
|
||||||
@ -254,9 +263,24 @@ class CSVWriter(object):
|
|||||||
self.include_individuals = self.option_box.include_individuals
|
self.include_individuals = self.option_box.include_individuals
|
||||||
self.include_marriages = self.option_box.include_marriages
|
self.include_marriages = self.option_box.include_marriages
|
||||||
self.include_children = self.option_box.include_children
|
self.include_children = self.option_box.include_children
|
||||||
|
self.include_places = self.option_box.include_places
|
||||||
self.translate_headers = self.option_box.translate_headers
|
self.translate_headers = self.option_box.translate_headers
|
||||||
|
|
||||||
self.plist = [x for x in self.db.iter_person_handles()]
|
self.plist = [x for x in self.db.iter_person_handles()]
|
||||||
|
|
||||||
|
# make place list so that dependencies are first:
|
||||||
|
self.place_list = []
|
||||||
|
place_list = [x for x in self.db.iter_place_handles()]
|
||||||
|
while place_list:
|
||||||
|
handle = place_list[0]
|
||||||
|
place = self.db.get_place_from_handle(handle)
|
||||||
|
if place:
|
||||||
|
if all([(x.ref in self.place_list) for x in place.placeref_list]):
|
||||||
|
self.place_list.append(place_list.pop(0))
|
||||||
|
else: # put at the back of the line:
|
||||||
|
place_list.append(place_list.pop(0))
|
||||||
|
else:
|
||||||
|
place_list.pop(0)
|
||||||
# get the families for which these people are spouses:
|
# get the families for which these people are spouses:
|
||||||
self.flist = {}
|
self.flist = {}
|
||||||
for key in self.plist:
|
for key in self.plist:
|
||||||
@ -313,9 +337,12 @@ class CSVWriter(object):
|
|||||||
self.total += len(self.flist)
|
self.total += len(self.flist)
|
||||||
if self.include_children:
|
if self.include_children:
|
||||||
self.total += len(self.flist)
|
self.total += len(self.flist)
|
||||||
|
if self.include_places:
|
||||||
|
self.total += len(self.place_list)
|
||||||
########################
|
########################
|
||||||
LOG.debug("Possible people to export: %s", len(self.plist))
|
LOG.debug("Possible people to export: %s", len(self.plist))
|
||||||
LOG.debug("Possible families to export: %s", len(self.flist))
|
LOG.debug("Possible families to export: %s", len(self.flist))
|
||||||
|
LOG.debug("Possible places to export: %s", len(self.place_list))
|
||||||
########################### sort:
|
########################### sort:
|
||||||
sortorder = []
|
sortorder = []
|
||||||
dropped_surnames = set()
|
dropped_surnames = set()
|
||||||
@ -530,6 +557,43 @@ class CSVWriter(object):
|
|||||||
self.write_csv(family_id, grampsid_ref)
|
self.write_csv(family_id, grampsid_ref)
|
||||||
self.update()
|
self.update()
|
||||||
self.writeln()
|
self.writeln()
|
||||||
|
###########################
|
||||||
|
if self.include_places:
|
||||||
|
if self.translate_headers:
|
||||||
|
self.write_csv(_("Place"), _("Title"), _("Name"),
|
||||||
|
_("Type"), _("Latitude"), _("Longitude"),
|
||||||
|
_("Code"), _("Enclosed_by"), _("Date"))
|
||||||
|
else:
|
||||||
|
self.write_csv("Place", "Title", "Name",
|
||||||
|
"Type", "Latitude", "Longitude",
|
||||||
|
"Code", "Enclosed_by", "Date")
|
||||||
|
for key in self.place_list:
|
||||||
|
place = self.db.get_place_from_handle(key)
|
||||||
|
if place:
|
||||||
|
place_id = place.gramps_id
|
||||||
|
place_title = place.title
|
||||||
|
place_name = place.name.value
|
||||||
|
place_type = str(place.place_type)
|
||||||
|
place_latitude = place.lat
|
||||||
|
place_longitude = place.long
|
||||||
|
place_code = place.code
|
||||||
|
if place.placeref_list:
|
||||||
|
for placeref in place.placeref_list:
|
||||||
|
placeref_obj = self.db.get_place_from_handle(placeref.ref)
|
||||||
|
placeref_date = ""
|
||||||
|
if not placeref.date.is_empty():
|
||||||
|
placeref_date = placeref.date
|
||||||
|
placeref_id = ""
|
||||||
|
if placeref_obj:
|
||||||
|
placeref_id = "[%s]" % placeref_obj.gramps_id
|
||||||
|
self.write_csv("[%s]" % place_id, place_title, place_name, place_type,
|
||||||
|
place_latitude, place_longitude, place_code, placeref_id,
|
||||||
|
placeref_date)
|
||||||
|
else:
|
||||||
|
self.write_csv("[%s]" % place_id, place_title, place_name, place_type,
|
||||||
|
place_latitude, place_longitude, place_code, "",
|
||||||
|
"")
|
||||||
|
self.writeln()
|
||||||
self.g.close()
|
self.g.close()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -49,11 +49,15 @@ LOG = logging.getLogger(".ImportCSV")
|
|||||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||||
_ = glocale.translation.sgettext
|
_ = glocale.translation.sgettext
|
||||||
ngettext = glocale.translation.ngettext # else "nearby" comments are ignored
|
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
|
from gramps.gen.lib import (ChildRef, Citation, Event, EventRef, EventType,
|
||||||
|
Family, FamilyRelType, Name, NameType, Note,
|
||||||
|
NoteType, Person, Place, Source, Surname, Tag,
|
||||||
|
PlaceName, PlaceType, PlaceRef)
|
||||||
from gramps.gen.db import DbTxn
|
from gramps.gen.db import DbTxn
|
||||||
from gramps.gen.datehandler import parser as _dp
|
from gramps.gen.datehandler import parser as _dp
|
||||||
from gramps.gen.utils.string import gender as gender_map
|
from gramps.gen.utils.string import gender as gender_map
|
||||||
from gramps.gen.utils.id import create_id
|
from gramps.gen.utils.id import create_id
|
||||||
|
from gramps.gen.utils.location import located_in
|
||||||
from gramps.gen.lib.eventroletype import EventRoleType
|
from gramps.gen.lib.eventroletype import EventRoleType
|
||||||
from gramps.gen.constfunc import conv_to_unicode
|
from gramps.gen.constfunc import conv_to_unicode
|
||||||
from gramps.gen.config import config
|
from gramps.gen.config import config
|
||||||
@ -125,8 +129,19 @@ class CSVParser(object):
|
|||||||
self.index = 0
|
self.index = 0
|
||||||
self.fam_count = 0
|
self.fam_count = 0
|
||||||
self.indi_count = 0
|
self.indi_count = 0
|
||||||
|
self.place_count = 0
|
||||||
self.pref = {} # person ref, internal to this sheet
|
self.pref = {} # person ref, internal to this sheet
|
||||||
self.fref = {} # family ref, internal to this sheet
|
self.fref = {} # family ref, internal to this sheet
|
||||||
|
self.placeref = {}
|
||||||
|
self.place_types = {}
|
||||||
|
# Build reverse dictionary, name to type number
|
||||||
|
for items in PlaceType().get_map().items(): # (0, 'Custom')
|
||||||
|
self.place_types[items[1]] = items[0]
|
||||||
|
if _(items[1]) != items[1]:
|
||||||
|
self.place_types[_(items[1])] = items[0]
|
||||||
|
# Add custom types:
|
||||||
|
for custom_type in self.db.get_place_types():
|
||||||
|
self.place_types[custom_type] = 0
|
||||||
column2label = {
|
column2label = {
|
||||||
"surname": ("Lastname", "Surname", _("Surname"), "lastname",
|
"surname": ("Lastname", "Surname", _("Surname"), "lastname",
|
||||||
"last_name", "surname", _("surname")),
|
"last_name", "surname", _("surname")),
|
||||||
@ -189,6 +204,14 @@ class CSVParser(object):
|
|||||||
"marriage": ("Marriage", _("Marriage"), "marriage", _("marriage")),
|
"marriage": ("Marriage", _("Marriage"), "marriage", _("marriage")),
|
||||||
"date": ("Date", _("Date"), "date", _("date")),
|
"date": ("Date", _("Date"), "date", _("date")),
|
||||||
"place": ("Place", _("Place"), "place", _("place")),
|
"place": ("Place", _("Place"), "place", _("place")),
|
||||||
|
"title": ("Title", _("Title"), "title", _("title")),
|
||||||
|
"name": ("Name", _("Name"), "name", _("name")),
|
||||||
|
"type": ("Type", _("Type"), "type", _("type")),
|
||||||
|
"latitude": ("Latitude", _("latitude"), "latitude", _("latitude")),
|
||||||
|
"longitude": ("Longitude", _("Longitude"), "longitude", _("longitude")),
|
||||||
|
"code": ("Code", _("Code"), "code", _("code")),
|
||||||
|
"enclosed_by": ("Enclosed by", _("Enclosed by"), "enclosed by", _("enclosed by"),
|
||||||
|
"enclosed_by", _("enclosed_by"), "Enclosed_by", _("Enclosed_by"))
|
||||||
}
|
}
|
||||||
lab2col_dict = []
|
lab2col_dict = []
|
||||||
for key in list(column2label.keys()):
|
for key in list(column2label.keys()):
|
||||||
@ -251,6 +274,18 @@ class CSVParser(object):
|
|||||||
return self.pref[id_.lower()]
|
return self.pref[id_.lower()]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
elif type_ == "place":
|
||||||
|
if id_.startswith("[") and id_.endswith("]"):
|
||||||
|
id_ = self.db.id2user_format(id_[1:-1])
|
||||||
|
db_lookup = self.db.get_place_from_gramps_id(id_)
|
||||||
|
if db_lookup is None:
|
||||||
|
return self.lookup(type_, id_)
|
||||||
|
else:
|
||||||
|
return db_lookup
|
||||||
|
elif id_.lower() in self.placeref:
|
||||||
|
return self.placeref[id_.lower()]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
else:
|
else:
|
||||||
LOG.warn("invalid lookup type in CSV import: '%s'" % type_)
|
LOG.warn("invalid lookup type in CSV import: '%s'" % type_)
|
||||||
return None
|
return None
|
||||||
@ -266,6 +301,9 @@ class CSVParser(object):
|
|||||||
elif type_ == "family":
|
elif type_ == "family":
|
||||||
id_ = self.db.fid2user_format(id_)
|
id_ = self.db.fid2user_format(id_)
|
||||||
self.fref[id_.lower()] = object_
|
self.fref[id_.lower()] = object_
|
||||||
|
elif type_ == "place":
|
||||||
|
id_ = self.db.pid2user_format(id_)
|
||||||
|
self.placeref[id_.lower()] = object_
|
||||||
else:
|
else:
|
||||||
LOG.warn("invalid storeup type in CSV import: '%s'" % type_)
|
LOG.warn("invalid storeup type in CSV import: '%s'" % type_)
|
||||||
|
|
||||||
@ -305,8 +343,10 @@ class CSVParser(object):
|
|||||||
self.index = 0
|
self.index = 0
|
||||||
self.fam_count = 0
|
self.fam_count = 0
|
||||||
self.indi_count = 0
|
self.indi_count = 0
|
||||||
|
self.place_count = 0
|
||||||
self.pref = {} # person ref, internal to this sheet
|
self.pref = {} # person ref, internal to this sheet
|
||||||
self.fref = {} # family ref, internal to this sheet
|
self.fref = {} # family ref, internal to this sheet
|
||||||
|
self.placeref = {}
|
||||||
header = None
|
header = None
|
||||||
line_number = 0
|
line_number = 0
|
||||||
for row in data:
|
for row in data:
|
||||||
@ -324,7 +364,7 @@ class CSVParser(object):
|
|||||||
col[key] = count
|
col[key] = count
|
||||||
count += 1
|
count += 1
|
||||||
continue
|
continue
|
||||||
# three different kinds of data: person, family, and marriage
|
# four different kinds of data: person, family, and marriage
|
||||||
if (("marriage" in header) or
|
if (("marriage" in header) or
|
||||||
("husband" in header) or
|
("husband" in header) or
|
||||||
("wife" in header)):
|
("wife" in header)):
|
||||||
@ -333,6 +373,8 @@ class CSVParser(object):
|
|||||||
self._parse_family(line_number, row, col)
|
self._parse_family(line_number, row, col)
|
||||||
elif "surname" in header:
|
elif "surname" in header:
|
||||||
self._parse_person(line_number, row, col)
|
self._parse_person(line_number, row, col)
|
||||||
|
elif "place" in header:
|
||||||
|
self._parse_place(line_number, row, col)
|
||||||
else:
|
else:
|
||||||
LOG.warn("ignoring line %d" % line_number)
|
LOG.warn("ignoring line %d" % line_number)
|
||||||
return None
|
return None
|
||||||
@ -670,6 +712,56 @@ class CSVParser(object):
|
|||||||
self.find_and_set_citation(person, source)
|
self.find_and_set_citation(person, source)
|
||||||
self.db.commit_person(person, self.trans)
|
self.db.commit_person(person, self.trans)
|
||||||
|
|
||||||
|
def _parse_place(self, line_number, row, col):
|
||||||
|
"Parse the content of a Place line."
|
||||||
|
place_id = rd(line_number, row, col, "place")
|
||||||
|
place_title = rd(line_number, row, col, "title")
|
||||||
|
place_name = rd(line_number, row, col, "name")
|
||||||
|
place_type_str = rd(line_number, row, col, "type")
|
||||||
|
place_latitude = rd(line_number, row, col, "latitude")
|
||||||
|
place_longitude = rd(line_number, row, col, "longitude")
|
||||||
|
place_code = rd(line_number, row, col, "code")
|
||||||
|
place_enclosed_by_id = rd(line_number, row, col, "enclosed_by")
|
||||||
|
place_date = rd(line_number, row, col, "date")
|
||||||
|
#########################################################
|
||||||
|
# if this place already exists, don't create it
|
||||||
|
place = self.lookup("place", place_id)
|
||||||
|
if place is None:
|
||||||
|
# new place
|
||||||
|
place = self.create_place()
|
||||||
|
self.storeup("place", place_id.lower(), place)
|
||||||
|
if place_title is not None:
|
||||||
|
place.title = place_title
|
||||||
|
if place_name is not None:
|
||||||
|
place.name = PlaceName(value=place_name)
|
||||||
|
if place_type_str is not None:
|
||||||
|
place.place_type = self.get_place_type(place_type_str)
|
||||||
|
if place_latitude is not None:
|
||||||
|
place.lat = place_latitude
|
||||||
|
if place_longitude is not None:
|
||||||
|
place.long = place_longitude
|
||||||
|
if place_code is not None:
|
||||||
|
place.code = place_code
|
||||||
|
if place_enclosed_by_id is not None:
|
||||||
|
place_enclosed_by = self.lookup("place", place_enclosed_by_id)
|
||||||
|
if place_enclosed_by is None:
|
||||||
|
raise Exception("cannot enclose %s in %s as it doesn't exist" % (place.gramps_id, place_enclosed_by_id))
|
||||||
|
if not place_enclosed_by.handle in place.placeref_list:
|
||||||
|
placeref = PlaceRef()
|
||||||
|
placeref.ref = place_enclosed_by.handle
|
||||||
|
if place_date:
|
||||||
|
placeref.date = _dp.parse(place_date)
|
||||||
|
place.placeref_list.append(placeref)
|
||||||
|
#########################################################
|
||||||
|
self.db.commit_place(place, self.trans)
|
||||||
|
|
||||||
|
def get_place_type(self, place_type_str):
|
||||||
|
if place_type_str in self.place_types:
|
||||||
|
return PlaceType((self.place_types[place_type_str], place_type_str))
|
||||||
|
else:
|
||||||
|
# New custom type:
|
||||||
|
return PlaceType((0, place_type_str))
|
||||||
|
|
||||||
def get_or_create_family(self, family_ref, husband, wife):
|
def get_or_create_family(self, family_ref, husband, wife):
|
||||||
"Return the family object for the give family ID."
|
"Return the family object for the give family ID."
|
||||||
# if a gramps_id and exists:
|
# if a gramps_id and exists:
|
||||||
@ -763,6 +855,15 @@ class CSVParser(object):
|
|||||||
self.indi_count += 1
|
self.indi_count += 1
|
||||||
return person
|
return person
|
||||||
|
|
||||||
|
def create_place(self):
|
||||||
|
""" Used to create a new person we know doesn't exist """
|
||||||
|
place = Place()
|
||||||
|
if self.default_tag:
|
||||||
|
place.add_tag(self.default_tag.handle)
|
||||||
|
self.db.add_place(place, self.trans)
|
||||||
|
self.place_count += 1
|
||||||
|
return place
|
||||||
|
|
||||||
def get_or_create_place(self, place_name):
|
def get_or_create_place(self, place_name):
|
||||||
"Return the requested place object tuple-packed with a new indicator."
|
"Return the requested place object tuple-packed with a new indicator."
|
||||||
LOG.debug("get_or_create_place: looking for: %s", place_name)
|
LOG.debug("get_or_create_place: looking for: %s", place_name)
|
||||||
@ -773,6 +874,7 @@ class CSVParser(object):
|
|||||||
return (0, place)
|
return (0, place)
|
||||||
place = Place()
|
place = Place()
|
||||||
place.set_title(place_name)
|
place.set_title(place_name)
|
||||||
|
place.name = PlaceName(value=place_name)
|
||||||
self.db.add_place(place, self.trans)
|
self.db.add_place(place, self.trans)
|
||||||
return (1, place)
|
return (1, place)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user