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):
|
||||
WriterOptionBox.__init__(self, person, dbstate, uistate)
|
||||
## TODO: add place filter selection
|
||||
self.include_individuals = 1
|
||||
self.include_marriages = 1
|
||||
self.include_children = 1
|
||||
self.include_places = 1
|
||||
self.translate_headers = 1
|
||||
self.include_individuals_check = None
|
||||
self.include_marriages_check = None
|
||||
self.include_children_check = None
|
||||
self.include_places_check = None
|
||||
self.translate_headers_check = None
|
||||
|
||||
def get_option_box(self):
|
||||
@ -197,16 +200,19 @@ class CSVWriterOptionBox(WriterOptionBox):
|
||||
self.include_individuals_check = Gtk.CheckButton(label=_("Include people"))
|
||||
self.include_marriages_check = Gtk.CheckButton(label=_("Include marriages"))
|
||||
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.include_individuals_check.set_active(1)
|
||||
self.include_marriages_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)
|
||||
|
||||
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_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)
|
||||
|
||||
return option_box
|
||||
@ -217,6 +223,7 @@ class CSVWriterOptionBox(WriterOptionBox):
|
||||
self.include_individuals = self.include_individuals_check.get_active()
|
||||
self.include_marriages = self.include_marriages_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()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -237,6 +244,7 @@ class CSVWriter(object):
|
||||
|
||||
self.plist = {}
|
||||
self.flist = {}
|
||||
self.place_list = {}
|
||||
|
||||
self.persons_details_done = []
|
||||
self.persons_notes_done = []
|
||||
@ -246,6 +254,7 @@ class CSVWriter(object):
|
||||
self.include_individuals = 1
|
||||
self.include_marriages = 1
|
||||
self.include_children = 1
|
||||
self.include_places = 1
|
||||
self.translate_headers = 1
|
||||
else:
|
||||
self.option_box.parse_options()
|
||||
@ -254,9 +263,24 @@ class CSVWriter(object):
|
||||
self.include_individuals = self.option_box.include_individuals
|
||||
self.include_marriages = self.option_box.include_marriages
|
||||
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.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:
|
||||
self.flist = {}
|
||||
for key in self.plist:
|
||||
@ -313,9 +337,12 @@ class CSVWriter(object):
|
||||
self.total += len(self.flist)
|
||||
if self.include_children:
|
||||
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 families to export: %s", len(self.flist))
|
||||
LOG.debug("Possible places to export: %s", len(self.place_list))
|
||||
########################### sort:
|
||||
sortorder = []
|
||||
dropped_surnames = set()
|
||||
@ -530,6 +557,43 @@ class CSVWriter(object):
|
||||
self.write_csv(family_id, grampsid_ref)
|
||||
self.update()
|
||||
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()
|
||||
return True
|
||||
|
||||
|
@ -49,11 +49,15 @@ LOG = logging.getLogger(".ImportCSV")
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.sgettext
|
||||
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.datehandler import parser as _dp
|
||||
from gramps.gen.utils.string import gender as gender_map
|
||||
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.constfunc import conv_to_unicode
|
||||
from gramps.gen.config import config
|
||||
@ -125,8 +129,19 @@ class CSVParser(object):
|
||||
self.index = 0
|
||||
self.fam_count = 0
|
||||
self.indi_count = 0
|
||||
self.place_count = 0
|
||||
self.pref = {} # person 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 = {
|
||||
"surname": ("Lastname", "Surname", _("Surname"), "lastname",
|
||||
"last_name", "surname", _("surname")),
|
||||
@ -189,6 +204,14 @@ class CSVParser(object):
|
||||
"marriage": ("Marriage", _("Marriage"), "marriage", _("marriage")),
|
||||
"date": ("Date", _("Date"), "date", _("date")),
|
||||
"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 = []
|
||||
for key in list(column2label.keys()):
|
||||
@ -251,6 +274,18 @@ class CSVParser(object):
|
||||
return self.pref[id_.lower()]
|
||||
else:
|
||||
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:
|
||||
LOG.warn("invalid lookup type in CSV import: '%s'" % type_)
|
||||
return None
|
||||
@ -266,6 +301,9 @@ class CSVParser(object):
|
||||
elif type_ == "family":
|
||||
id_ = self.db.fid2user_format(id_)
|
||||
self.fref[id_.lower()] = object_
|
||||
elif type_ == "place":
|
||||
id_ = self.db.pid2user_format(id_)
|
||||
self.placeref[id_.lower()] = object_
|
||||
else:
|
||||
LOG.warn("invalid storeup type in CSV import: '%s'" % type_)
|
||||
|
||||
@ -305,8 +343,10 @@ class CSVParser(object):
|
||||
self.index = 0
|
||||
self.fam_count = 0
|
||||
self.indi_count = 0
|
||||
self.place_count = 0
|
||||
self.pref = {} # person ref, internal to this sheet
|
||||
self.fref = {} # family ref, internal to this sheet
|
||||
self.placeref = {}
|
||||
header = None
|
||||
line_number = 0
|
||||
for row in data:
|
||||
@ -324,7 +364,7 @@ class CSVParser(object):
|
||||
col[key] = count
|
||||
count += 1
|
||||
continue
|
||||
# three different kinds of data: person, family, and marriage
|
||||
# four different kinds of data: person, family, and marriage
|
||||
if (("marriage" in header) or
|
||||
("husband" in header) or
|
||||
("wife" in header)):
|
||||
@ -333,6 +373,8 @@ class CSVParser(object):
|
||||
self._parse_family(line_number, row, col)
|
||||
elif "surname" in header:
|
||||
self._parse_person(line_number, row, col)
|
||||
elif "place" in header:
|
||||
self._parse_place(line_number, row, col)
|
||||
else:
|
||||
LOG.warn("ignoring line %d" % line_number)
|
||||
return None
|
||||
@ -670,6 +712,56 @@ class CSVParser(object):
|
||||
self.find_and_set_citation(person, source)
|
||||
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):
|
||||
"Return the family object for the give family ID."
|
||||
# if a gramps_id and exists:
|
||||
@ -763,6 +855,15 @@ class CSVParser(object):
|
||||
self.indi_count += 1
|
||||
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):
|
||||
"Return the requested place object tuple-packed with a new indicator."
|
||||
LOG.debug("get_or_create_place: looking for: %s", place_name)
|
||||
@ -773,6 +874,7 @@ class CSVParser(object):
|
||||
return (0, place)
|
||||
place = Place()
|
||||
place.set_title(place_name)
|
||||
place.name = PlaceName(value=place_name)
|
||||
self.db.add_place(place, self.trans)
|
||||
return (1, place)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user