Files
gramps/gramps/gen/display/place.py
Paul Franklin e6ddedf6c6 fix typo
in cbac98894b
2018-10-04 17:49:35 -07:00

197 lines
6.7 KiB
Python

#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2014-2017 Nick Hall
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
"""
Class handling displaying of places.
"""
#---------------------------------------------------------------
#
# Python imports
#
#---------------------------------------------------------------
import os
import xml.dom.minidom
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from ..const import PLACE_FORMATS, GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from ..config import config
from ..utils.location import get_location_list
from ..lib import PlaceType
#-------------------------------------------------------------------------
#
# PlaceFormat class
#
#-------------------------------------------------------------------------
class PlaceFormat:
def __init__(self, name, levels, language, street, reverse):
self.name = name
self.levels = levels
self.language = language
self.street = street
self.reverse = reverse
def to_xml(self):
return (' <format name="%s" levels="%s" language="%s" '
'street="%s" reverse="%s"/>\n' %
(self.name, self.levels, self.language,
self.street, self.reverse))
#-------------------------------------------------------------------------
#
# PlaceDisplay class
#
#-------------------------------------------------------------------------
class PlaceDisplay:
def __init__(self):
self.place_formats = []
self.default_format = config.get('preferences.place-format')
if os.path.exists(PLACE_FORMATS):
self.load_formats()
else:
pf = PlaceFormat(_('Full'), ':', '', 0, False)
self.place_formats.append(pf)
def display_event(self, db, event, fmt=-1):
if not event:
return ""
place_handle = event.get_place_handle()
if place_handle:
place = db.get_place_from_handle(place_handle)
return self.display(db, place, event.get_date_object(), fmt)
else:
return ""
def display(self, db, place, date=None, fmt=-1):
if not place:
return ""
if not config.get('preferences.place-auto'):
return place.title
else:
if fmt == -1:
fmt = config.get('preferences.place-format')
pf = self.place_formats[fmt]
lang = pf.language
all_places = get_location_list(db, place, date, lang)
# Apply format string to place list
index = _find_populated_place(all_places)
places = []
for slice in pf.levels.split(','):
parts = slice.split(':')
if len(parts) == 1:
offset = _get_offset(parts[0], index)
if offset is not None:
try:
places.append(all_places[offset])
except IndexError:
pass
elif len(parts) == 2:
start = _get_offset(parts[0], index)
end = _get_offset(parts[1], index)
if start is None:
places.extend(all_places[:end])
elif end is None:
places.extend(all_places[start:])
else:
places.extend(all_places[start:end])
if pf.street:
types = [item[1] for item in places]
try:
idx = types.index(PlaceType.NUMBER)
except ValueError:
idx = None
if idx is not None and len(places) > idx+1:
if pf.street == 1:
combined = (places[idx][0] + ' ' + places[idx+1][0],
places[idx+1][1])
else:
combined = (places[idx+1][0] + ' ' + places[idx][0],
places[idx+1][1])
places = places[:idx] + [combined] + places[idx+2:]
names = [item[0] for item in places]
if pf.reverse:
names.reverse()
# TODO for Arabic, should the next line's comma be translated?
return ", ".join(names)
def get_formats(self):
return self.place_formats
def set_formats(self, formats):
self.place_formats = formats
def load_formats(self):
dom = xml.dom.minidom.parse(PLACE_FORMATS)
top = dom.getElementsByTagName('place_formats')
for fmt in top[0].getElementsByTagName('format'):
name = fmt.attributes['name'].value
levels = fmt.attributes['levels'].value
language = fmt.attributes['language'].value
street = int(fmt.attributes['street'].value)
reverse = fmt.attributes['reverse'].value == 'True'
pf = PlaceFormat(name, levels, language, street, reverse)
self.place_formats.append(pf)
dom.unlink()
def save_formats(self):
with open(PLACE_FORMATS, 'w') as fd:
fd.write('<?xml version="1.0" encoding="utf-8"?>\n')
fd.write('<place_formats>\n')
for fmt in self.place_formats:
fd.write(fmt.to_xml())
fd.write('</place_formats>\n')
def _get_offset(value, index):
if index is not None and value.startswith('p'):
try:
offset = int(value[1:])
except ValueError:
offset = 0
offset += index
else:
try:
offset = int(value)
except ValueError:
offset = None
return offset
def _find_populated_place(places):
populated_place = None
for index, item in enumerate(places):
if int(item[1]) in [PlaceType.HAMLET, PlaceType.VILLAGE,
PlaceType.TOWN, PlaceType.CITY]:
populated_place = index
return populated_place
displayer = PlaceDisplay()