GEPS 6: Implement place hierarchy

svn: r23444
This commit is contained in:
Nick Hall 2013-11-01 19:13:16 +00:00
parent 8e123f8695
commit d6ae8cffb4
44 changed files with 2208 additions and 1272 deletions

View File

@ -245,6 +245,8 @@ register('interface.person-sel-height', 450)
register('interface.person-sel-width', 600)
register('interface.person-width', 750)
register('interface.place-height', 450)
register('interface.place-ref-height', 450)
register('interface.place-ref-width', 600)
register('interface.place-sel-height', 450)
register('interface.place-sel-width', 600)
register('interface.place-width', 650)

View File

@ -199,6 +199,32 @@ class DbReadCursor(BsddbBaseCursor):
self.cursor = source.db.cursor(txn)
self.source = source
#-------------------------------------------------------------------------
#
# DbBsddbTreeCursor
#
#-------------------------------------------------------------------------
class DbBsddbTreeCursor(BsddbBaseCursor):
def __init__(self, source, txn=None, **kwargs):
BsddbBaseCursor.__init__(self, txn=txn, **kwargs)
self.cursor = source.cursor(txn)
self.source = source
def __iter__(self):
"""
Iterator
"""
to_do = ['']
while to_do:
data = self.set(str(to_do.pop()))
_n = self.next_dup
while data:
payload = pickle.loads(data[1])
yield (payload[0], payload)
to_do.append(payload[0])
data = _n()
class DbBsddbRead(DbReadBase, Callback):
"""
Read class for the GRAMPS databases. Implements methods necessary to read
@ -488,6 +514,9 @@ class DbBsddbRead(DbReadBase, Callback):
def get_place_cursor(self, *args, **kwargs):
return self.get_cursor(self.place_map, *args, **kwargs)
def get_place_tree_cursor(self, *args, **kwargs):
return DbBsddbTreeCursor(self.parents, self.txn)
def get_source_cursor(self, *args, **kwargs):
return self.get_cursor(self.source_map, *args, **kwargs)

View File

@ -25,8 +25,12 @@ from __future__ import with_statement, unicode_literals
import sys
import os
import re
from ..lib.markertype import MarkerType
from ..lib.tag import Tag
from ..lib.place import Place
from ..lib.placeref import PlaceRef
from ..lib.placetype import PlaceType
from ..utils.file import create_checksum
import time
import logging
@ -81,11 +85,65 @@ def gramps_upgrade_17(self):
# ---------------------------------
# Modify Place
# ---------------------------------
# Add new tag_list field.
# Convert to hierarchical structure and add new tag_list field.
locations = {}
self.max_id = 0
index = re.compile('[0-9]+')
for handle in self.place_map.keys():
place = self.place_map[handle]
match = index.search(place[1])
if match:
if self.max_id <= int(match.group(0)):
self.max_id = int(match.group(0))
if place[5] is not None:
locations[get_location(place[5])] = handle
for handle in list(self.place_map.keys()):
place = self.place_map[handle]
new_place = list(place)
new_place = new_place[:12] + [[]] + new_place[12:]
zip_code = ''
if new_place[5]:
zip_code = new_place[5][0][6]
# find title and type
main_loc = get_location(new_place[5])
for type_num, name in enumerate(main_loc):
if name:
break
loc = list(main_loc[:])
loc[type_num] = ''
# find top parent
parent_handle = None
for n in range(7):
if loc[n]:
tup = tuple([''] * n + loc[n:])
parent_handle = locations.get(tup, None)
if parent_handle:
break
# create nodes
if parent_handle:
n -= 1
while n > type_num:
if loc[n]:
title = ', '.join([item for item in loc[n:] if item])
parent_handle = add_place(self, loc[n], n, parent_handle, title)
locations[tuple([''] * n + loc[n:])] = parent_handle
n -= 1
if parent_handle is not None:
placeref = PlaceRef()
placeref.ref = parent_handle
placeref_list = [placeref.serialize()]
else:
placeref_list = []
new_place = new_place[:5] + [placeref_list, name,
PlaceType(7-type_num).serialize(), zip_code] + \
new_place[6:12] + [[]] + new_place[12:]
new_place = tuple(new_place)
with BSDDBTxn(self.env, self.place_map) as txn:
if isinstance(handle, UNITYPE):
@ -194,6 +252,33 @@ def gramps_upgrade_17(self):
with BSDDBTxn(self.env, self.metadata) as txn:
txn.put(b'version', 17)
def get_location(loc):
# (street, locality, parish, city, county, state, country)
if loc is None:
location = ('',) * 7
else:
location = loc[0][:2] + (loc[1],) + loc[0][2:6]
return location
def add_place(self, name, type_num, parent, title):
handle = self.create_id()
place = Place()
place.handle = handle
self.max_id += 1
place.gramps_id = self.place_prefix % self.max_id
place.name = name
place.title = title
place.place_type = PlaceType(7-type_num)
if parent is not None:
placeref = PlaceRef()
placeref.ref = parent
place.set_placeref_list([placeref])
with BSDDBTxn(self.env, self.place_map) as txn:
if isinstance(handle, UNITYPE):
handle = handle.encode('utf-8')
txn.put(handle, place.serialize())
return handle
def upgrade_datamap_17(datamap):
"""
In version 16 key value pairs are stored in source and citation. These become

View File

@ -110,6 +110,7 @@ TAGTRANS = "tag_name"
SURNAMES = "surnames"
NAME_GROUP = "name_group"
META = "meta_data"
PPARENT = "place_parent"
FAMILY_TBL = "family"
PLACES_TBL = "place"
@ -183,6 +184,15 @@ def find_idmap(key, data):
val = val.encode('utf-8')
return val
def find_parent(key, data):
if len(data[5]) > 0:
val = data[5][0][0]
else:
val = ''
if isinstance(val, UNITYPE):
val = val.encode('utf-8')
return val
# Secondary database key lookups for reference_map table
# reference_map data values are of the form:
# ((primary_object_class_name, primary_object_handle),
@ -374,6 +384,13 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
return DbBsddbAssocCursor(self.reference_map_referenced_map,
self.txn)
@catch_db_error
def get_place_parent_cursor(self):
"""
Returns a reference to a cursor over the place parents
"""
return DbBsddbAssocCursor(self.parents, self.txn)
# These are overriding the DbBsddbRead's methods of saving metadata
# because we now have txn-capable metadata table
@ -870,6 +887,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
("rid_trans", RIDTRANS, db.DB_HASH, 0),
("nid_trans", NIDTRANS, db.DB_HASH, 0),
("tag_trans", TAGTRANS, db.DB_HASH, 0),
("parents", PPARENT, db.DB_HASH, 0),
("reference_map_primary_map", REF_PRI, db.DB_BTREE, 0),
("reference_map_referenced_map", REF_REF, db.DB_BTREE, db.DB_DUPSORT),
]
@ -887,6 +905,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
(self.family_map, self.fid_trans, find_idmap),
(self.event_map, self.eid_trans, find_idmap),
(self.place_map, self.pid_trans, find_idmap),
(self.place_map, self.parents, find_parent),
(self.source_map, self.sid_trans, find_idmap),
(self.citation_map, self.cid_trans, find_idmap),
(self.media_map, self.oid_trans, find_idmap),
@ -934,6 +953,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
( self.nid_trans, NIDTRANS ),
( self.cid_trans, CIDTRANS ),
( self.tag_trans, TAGTRANS ),
( self.parents, PPARENT ),
( self.reference_map_primary_map, REF_PRI),
( self.reference_map_referenced_map, REF_REF),
]
@ -960,6 +980,36 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
if callback:
callback(12)
@catch_db_error
def find_place_child_handles(self, handle):
"""
Find all child places having the given place as the primary parent.
"""
handle = str(handle)
parent_cur = self.get_place_parent_cursor()
try:
ret = parent_cur.set(handle)
except:
ret = None
while (ret is not None):
(key, data) = ret
### FIXME: this is a dirty hack that works without no
### sensible explanation. For some reason, for a readonly
### database, secondary index returns a primary table key
### corresponding to the data, not the data.
if self.readonly:
data = self.place_map.get(data)
else:
data = pickle.loads(data)
yield data[0]
ret = parent_cur.next_dup()
parent_cur.close()
@catch_db_error
def find_backlink_handles(self, handle, include_classes=None):
"""
@ -1303,6 +1353,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.__close_metadata()
self.name_group.close()
self.surnames.close()
self.parents.close()
self.id_trans.close()
self.fid_trans.close()
self.eid_trans.close()

View File

@ -36,7 +36,8 @@ _ = glocale.translation.gettext
#
#-------------------------------------------------------------------------
from .. import Rule
from ....lib import Location
from ....lib import PlaceType
from ....utils.location import get_locations
#-------------------------------------------------------------------------
#
@ -46,7 +47,6 @@ from ....lib import Location
class HasPlace(Rule):
"""Rule that checks for a place with a particular value"""
labels = [ _('Name:'),
_('Street:'),
_('Locality:'),
@ -62,50 +62,37 @@ class HasPlace(Rule):
category = _('General filters')
allow_regex = True
TYPE2FIELD = {PlaceType.STREET: 1,
PlaceType.LOCALITY: 2,
PlaceType.CITY: 3,
PlaceType.COUNTY: 4,
PlaceType.STATE: 5,
PlaceType.COUNTRY: 6,
PlaceType.PARISH: 8}
def apply(self, db, place):
if not self.match_substring(0, place.get_title()):
return False
if not self.match_substring(7, place.get_code()):
return False
# If no location data was given then we're done: match
if not any(self.list[1:]):
if not any(self.list[1:7] + [self.list[8]]):
return True
# Something was given, so checking for location until we match
for loc in [place.main_loc] + place.alt_loc:
if self.apply_location(loc):
for location in get_locations(db, place):
if self.check(location):
return True
# Nothing matched
return False
def apply_location(self, loc):
if not loc:
# Allow regular expressions to match empty fields
loc = Location()
if not self.match_substring(1, loc.get_street()):
return False
if not self.match_substring(2, loc.get_locality()):
return False
if not self.match_substring(3, loc.get_city()):
return False
if not self.match_substring(4, loc.get_county()):
return False
if not self.match_substring(5, loc.get_state()):
return False
if not self.match_substring(6, loc.get_country()):
return False
if not self.match_substring(7, loc.get_postal_code()):
return False
if not self.match_substring(8, loc.get_parish()):
return False
# Nothing contradicted, so we're matching this location
def check(self, location):
"""
Check each location for a match.
"""
for place_type, field in self.TYPE2FIELD.iteritems():
name = location.get(place_type, '')
if not self.match_substring(field, name):
return False
return True

View File

@ -36,6 +36,7 @@ from .eventref import EventRef
from .ldsord import LdsOrd
from .mediaref import MediaRef
from .name import Name
from .placeref import PlaceRef
from .reporef import RepoRef
from .surname import Surname
from .url import Url
@ -78,6 +79,7 @@ from .markertype import MarkerType
from .nameorigintype import NameOriginType
from .notetype import NoteType
from .styledtexttagtype import StyledTextTagType
from .placetype import PlaceType
# Text
from .styledtexttag import StyledTextTag

View File

@ -33,6 +33,8 @@ from __future__ import unicode_literals
#
#-------------------------------------------------------------------------
from .primaryobj import PrimaryObject
from .placeref import PlaceRef
from .placetype import PlaceType
from .citationbase import CitationBase
from .notebase import NoteBase
from .mediabase import MediaBase
@ -41,8 +43,6 @@ from .tagbase import TagBase
from .location import Location
from .handle import Handle
_EMPTY_LOC = Location().serialize()
#-------------------------------------------------------------------------
#
# Place class
@ -71,13 +71,19 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
self.long = source.long
self.lat = source.lat
self.title = source.title
self.main_loc = Location(source.main_loc)
self.name = source.name
self.placeref_list = list(map(PlaceRef, source.placeref_list))
self.place_type = source.place_type
self.code = source.code
self.alt_loc = list(map(Location, source.alt_loc))
else:
self.long = ""
self.lat = ""
self.title = ""
self.main_loc = None
self.name = ""
self.placeref_list = []
self.place_type = PlaceType()
self.code = ""
self.alt_loc = []
def serialize(self):
@ -98,14 +104,10 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
be considered persistent.
:rtype: tuple
"""
if self.main_loc is None or self.main_loc.serialize() == _EMPTY_LOC:
main_loc = None
else:
main_loc = self.main_loc.serialize()
return (self.handle, self.gramps_id, self.title, self.long, self.lat,
main_loc, [al.serialize() for al in self.alt_loc],
[pr.serialize() for pr in self.placeref_list],
self.name, self.place_type.serialize(), self.code,
[al.serialize() for al in self.alt_loc],
UrlBase.serialize(self),
MediaBase.serialize(self),
CitationBase.serialize(self),
@ -132,17 +134,15 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
:returns: Returns a struct containing the data of the object.
:rtype: dict
"""
if self.main_loc is None or self.main_loc.serialize() == _EMPTY_LOC:
main_loc = None
else:
main_loc = self.main_loc.to_struct()
return {"handle": Handle("Place", self.handle),
"gramps_id": self.gramps_id,
"title": self.title,
"long": self.long,
"lat": self.lat,
"main_loc": main_loc,
"placeref_list": [pr.to_struct() for pr in self.placeref_list],
"name": self.name,
"place_type": self.place_type.to_struct(),
"code": self.code,
"alt_loc": [al.to_struct() for al in self.alt_loc],
"urls": UrlBase.to_struct(self),
"media_list": MediaBase.to_struct(self),
@ -162,14 +162,14 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
:type data: tuple
"""
(self.handle, self.gramps_id, self.title, self.long, self.lat,
main_loc, alt_loc, urls, media_list, citation_list, note_list,
placeref_list, self.name, the_type, self.code,
alt_loc, urls, media_list, citation_list, note_list,
self.change, tag_list, self.private) = data
if main_loc is None:
self.main_loc = None
else:
self.main_loc = Location().unserialize(main_loc)
self.place_type = PlaceType()
self.place_type.unserialize(the_type)
self.alt_loc = [Location().unserialize(al) for al in alt_loc]
self.placeref_list = [PlaceRef().unserialize(pr) for pr in placeref_list]
UrlBase.unserialize(self, urls)
MediaBase.unserialize(self, media_list)
CitationBase.unserialize(self, citation_list)
@ -184,7 +184,7 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
:returns: Returns the list of all textual attributes of the object.
:rtype: list
"""
return [self.long, self.lat, self.title, self.gramps_id]
return [self.long, self.lat, self.title, self.name, self.gramps_id]
def get_text_data_child_list(self):
"""
@ -195,8 +195,6 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
"""
ret = self.media_list + self.alt_loc + self.urls
if self.main_loc:
ret.append(self.main_loc)
return ret
def get_citation_child_list(self):
@ -226,7 +224,7 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
:returns: Returns the list of objects referencing primary objects.
:rtype: list
"""
return self.get_citation_child_list()
return self.get_citation_child_list() + self.placeref_list
def get_referenced_handles(self):
"""
@ -253,6 +251,7 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
self._merge_note_list(acquisition)
self._merge_citation_list(acquisition)
self._merge_tag_list(acquisition)
self._merge_placeref_list(acquisition)
def set_title(self, title):
"""
@ -272,6 +271,24 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
"""
return self.title
def set_name(self, name):
"""
Set the name of the Place object.
:param title: name to assign to the Place
:type title: str
"""
self.name = name
def get_name(self):
"""
Return the name of the Place object.
:returns: Returns the name of the Place
:rtype: str
"""
return self.name
def set_longitude(self, longitude):
"""
Set the longitude of the Place object.
@ -308,31 +325,120 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
"""
return self.lat
def get_main_location(self):
def set_type(self, place_type):
"""
Return the :class:`~gen.lib.location.Location` object representing the primary information for
the Place instance.
Set the type of the Place object.
:param type: type to assign to the Place
:type type: PlaceType
"""
self.place_type.set(place_type)
def get_type(self):
"""
Return the type of the Place object.
:returns: Returns the type of the Place
:rtype: PlaceType
"""
return self.place_type
def set_code(self, code):
"""
Set the code of the Place object.
:param code: code to assign to the Place
:type code: str
"""
self.code = code
def get_code(self):
"""
Return the code of the Place object.
:returns: Returns the code of the Place
:rtype: str
"""
return self.code
def add_placeref(self, placeref):
"""
Add a place reference to the list of place references.
:param code: place reference to append to the list
:type code: PlaceRef
"""
self.placeref_list.append(placeref)
def get_placeref_list(self):
"""
Return the place reference list for the Place object.
:returns: Returns the place reference list for the Place
:rtype: list
"""
return self.placeref_list
def set_placeref_list(self, placeref_list):
"""
Set the place reference list for the Place object.
:param code: place reference list to assign to the Place
:type code: list
"""
self.placeref_list = placeref_list
def _merge_placeref_list(self, acquisition):
"""
Add the main and alternate locations of acquisition to the alternate
location list.
:param acquisition: instance to merge
:type acquisition: :class:'~gen.lib.place.Place
"""
placeref_list = self.placeref_list[:]
add_list = acquisition.placeref_list
for addendum in add_list:
for placeref in placeref_list:
if placeref.is_equal(addendum):
break
else:
self.placeref_list.append(addendum)
def _has_handle_reference(self, classname, handle):
"""
Return True if the object has reference to a given handle of given
primary object type.
If a :class:`~gen.lib.location.Location` hasn't been assigned yet, an empty one is created.
:returns: Returns the :class:`~gen.lib.location.Location` instance representing the primary
location information about the Place.
:rtype: :class:`~gen.lib.location.Location`
:param classname: The name of the primary object class.
:type classname: str
:param handle: The handle to be checked.
:type handle: str
:returns: Returns whether the object has reference to this handle of
this object type.
:rtype: bool
"""
if not self.main_loc:
self.main_loc = Location()
return self.main_loc
if classname == 'Place':
for placeref in self.placeref_list:
if placeref.ref == handle:
return True
return False
def set_main_location(self, location):
def _replace_handle_reference(self, classname, old_handle, new_handle):
"""
Assign the main location information about the Place to the :class:`~gen.lib.location.Location`
object passed.
Replace all references to old handle with those to the new handle.
:param location: :class:`~gen.lib.location.Location` instance to assign to as the main
information for the Place.
:type location: :class:`~gen.lib.location.Location`
:param classname: The name of the primary object class.
:type classname: str
:param old_handle: The handle to be replaced.
:type old_handle: str
:param new_handle: The handle to replace the old one with.
:type new_handle: str
"""
self.main_loc = location
if classname == 'Place':
for placeref in self.placeref_list:
if placeref.ref == old_handle:
placeref.ref = new_handle
def get_alternate_locations(self):
"""
@ -376,40 +482,10 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
:type acquisition: :class:'~gen.lib.place.Place
"""
altloc_list = self.alt_loc[:]
if self.main_loc and not self.main_loc.is_empty():
altloc_list.insert(0, self.main_loc)
add_list = acquisition.get_alternate_locations()
acq_main_loc = acquisition.get_main_location()
if acq_main_loc and not acq_main_loc.is_empty():
add_list.insert(0, acquisition.get_main_location())
for addendum in add_list:
for altloc in altloc_list:
if altloc.is_equal(addendum):
break
else:
self.alt_loc.append(addendum)
def get_display_info(self):
"""
Get the display information associated with the object.
This includes the information that is used for display and for sorting.
Returns a list consisting of 13 strings. These are:
Place Title, Place ID, Main Location Parish, Main Location County,
Main Location City, Main Location State/Province,
Main Location Country, upper case Place Title, upper case Parish,
upper case city, upper case county, upper case state,
upper case country.
"""
if self.main_loc:
return [self.title, self.gramps_id, self.main_loc.parish,
self.main_loc.city, self.main_loc.county,
self.main_loc.state, self.main_loc.country,
self.title.upper(), self.main_loc.parish.upper(),
self.main_loc.city.upper(), self.main_loc.county.upper(),
self.main_loc.state.upper(), self.main_loc.country.upper()]
else:
return [self.title, self.gramps_id, '', '', '', '', '',
self.title.upper(), '', '', '', '', '']

176
gramps/gen/lib/placeref.py Normal file
View File

@ -0,0 +1,176 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Place Reference class for Gramps
"""
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from .secondaryobj import SecondaryObject
from .refbase import RefBase
from .datebase import DateBase
from .const import IDENTICAL, EQUAL, DIFFERENT
#-------------------------------------------------------------------------
#
# Place References
#
#-------------------------------------------------------------------------
class PlaceRef(RefBase, DateBase, SecondaryObject):
"""
Place reference class.
This class is for keeping information about how places link to other places
in the place hierarchy.
"""
def __init__(self, source=None):
"""
Create a new PlaceRef instance, copying from the source if present.
"""
RefBase.__init__(self, source)
DateBase.__init__(self, source)
def serialize(self):
"""
Convert the object to a serialized tuple of data.
"""
return (
RefBase.serialize(self),
DateBase.serialize(self)
)
def to_struct(self):
"""
Convert the data held in this object to a structure (eg,
struct) that represents all the data elements.
This method is used to recursively convert the object into a
self-documenting form that can easily be used for various
purposes, including diffs and queries.
These structures may be primitive Python types (string,
integer, boolean, etc.) or complex Python types (lists,
tuples, or dicts). If the return type is a dict, then the keys
of the dict match the fieldname of the object. If the return
struct (or value of a dict key) is a list, then it is a list
of structs. Otherwise, the struct is just the value of the
attribute.
:returns: Returns a struct containing the data of the object.
:rtype: dict
"""
return {
"ref": RefBase.to_struct(self),
"date": DateBase.to_struct(self)
}
def unserialize(self, data):
"""
Convert a serialized tuple of data to an object.
"""
(ref, date) = data
RefBase.unserialize(self, ref)
DateBase.unserialize(self, date)
return self
def get_text_data_list(self):
"""
Return the list of all textual attributes of the object.
:returns: Returns the list of all textual attributes of the object.
:rtype: list
"""
return []
def get_text_data_child_list(self):
"""
Return the list of child objects that may carry textual data.
:returns: Returns the list of child objects that may carry textual data.
:rtype: list
"""
return []
def get_citation_child_list(self):
"""
Return the list of child secondary objects that may refer citations.
:returns: Returns the list of child secondary child objects that may
refer citations.
:rtype: list
"""
return []
def get_note_child_list(self):
"""
Return the list of child secondary objects that may refer notes.
:returns: Returns the list of child secondary child objects that may
refer notes.
:rtype: list
"""
return []
def get_referenced_handles(self):
"""
Return the list of (classname, handle) tuples for all directly
referenced primary objects.
:returns: Returns the list of (classname, handle) tuples for referenced
objects.
:rtype: list
"""
return [('Place', self.ref)]
def get_handle_referents(self):
"""
Return the list of child objects which may, directly or through their
children, reference primary objects..
:returns: Returns the list of objects referencing primary objects.
:rtype: list
"""
return []
def is_equivalent(self, other):
"""
Return if this eventref is equivalent, that is agrees in handle and
role, to other.
:param other: The eventref to compare this one to.
:rtype other: EventRef
:returns: Constant indicating degree of equivalence.
:rtype: int
"""
if self.ref != other.ref or self.date != other.date:
return DIFFERENT
else:
if self.is_equal(other):
return IDENTICAL
else:
return EQUAL

View File

@ -0,0 +1,68 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
#
# 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$
"""
Provide the different place types.
"""
#------------------------------------------------------------------------
#
# Python modules
#
#------------------------------------------------------------------------
from ..const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from .grampstype import GrampsType
class PlaceType(GrampsType):
UNKNOWN = -1
CUSTOM = 0
COUNTRY = 1
STATE = 2
COUNTY = 3
CITY = 4
PARISH = 5
LOCALITY = 6
STREET = 7
_CUSTOM = CUSTOM
_DEFAULT = COUNTRY
_DATAMAP = [
(UNKNOWN, _("Unknown"), "Unknown"),
(CUSTOM, _("Custom"), "Custom"),
(COUNTRY, _("Country"), "Country"),
(STATE, _("State"), "State"),
(COUNTY, _("County"), "County"),
(CITY, _("City"), "City"),
(PARISH, _("Parish"), "Parish"),
(LOCALITY, _("Locality"), "Locality"),
(STREET, _("Street"), "Street"),
]
def __init__(self, value=None):
GrampsType.__init__(self, value)

View File

@ -30,7 +30,7 @@ Provide merge capabilities for places.
# Gramps modules
#
#-------------------------------------------------------------------------
from ..lib import Person, Family, Event
from ..lib import Person, Family, Event, Place
from ..db import DbTxn
from ..const import GRAMPS_LOCALE as glocale
_ = glocale.translation.sgettext
@ -81,6 +81,12 @@ class MergePlaceQuery(object):
event.replace_handle_reference('Place', old_handle,
new_handle)
self.database.commit_event(event, trans)
elif class_name == Place.__name__:
place = self.database.get_place_from_handle(handle)
assert(place.has_handle_reference('Place', old_handle))
place.replace_handle_reference('Place', old_handle,
new_handle)
self.database.commit_place(place, trans)
else:
raise MergeError("Encounter an object of type %s that has "
"a place reference." % class_name)

View File

@ -980,8 +980,11 @@ def sanitize_place(db, place):
new_place.set_change_time(place.get_change_time())
new_place.set_longitude(place.get_longitude())
new_place.set_latitude(place.get_latitude())
new_place.set_main_location(place.get_main_location())
new_place.set_alternate_locations(place.get_alternate_locations())
new_place.set_name(place.get_name())
new_place.set_type(place.get_type())
new_place.set_code(place.get_code())
new_place.set_placeref_list(place.get_placeref_list())
copy_citation_ref_list(db, place, new_place)
copy_notes(db, place, new_place)

View File

@ -0,0 +1,80 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Location utility functions
"""
#-------------------------------------------------------------------------
#
# get_location_list
#
#-------------------------------------------------------------------------
def get_location_list(db, place):
"""
Return a list of place names for display.
"""
lines = [place.name]
while len(place.get_placeref_list()) > 0:
place = db.get_place_from_handle(place.get_placeref_list()[0].ref)
lines.append(place.name)
return lines
#-------------------------------------------------------------------------
#
# get_main_location
#
#-------------------------------------------------------------------------
def get_main_location(db, place):
"""
Find all places in the hierarchy above the given place, and return the
result as a dictionary of place types and names.
"""
items = {int(place.get_type()): place.name}
while len(place.get_placeref_list()) > 0:
place = db.get_place_from_handle(place.get_placeref_list()[0].ref)
items[int(place.get_type())] = place.name
return items
#-------------------------------------------------------------------------
#
# get_locations
#
#-------------------------------------------------------------------------
def get_locations(db, place):
"""
Determine each possible route up the place hierarchy, and return a list
containing dictionaries of place types and names.
"""
locations = []
todo = [(place, [(int(place.get_type()), place.get_name())])]
while len(todo):
place, tree = todo.pop()
if len(place.get_placeref_list()):
for parent in place.get_placeref_list():
parent_place = db.get_place_from_handle(parent.ref)
parent_tree = tree + [(int(parent_place.get_type()),
parent_place.get_name())]
todo.append((parent_place, parent_tree))
else:
locations.append(dict(tree))
return locations

View File

@ -121,6 +121,7 @@ def map2class(target):
'mediaobj': ClipMediaObj,
'mediaref': ClipMediaRef,
'place-link': ClipPlace,
'placeref': ClipPlaceRef,
'note-link': ClipNote,
}
return d[target] if target in d else None
@ -568,6 +569,24 @@ class ClipEventRef(ClipObjWrapper):
self._title = base.gramps_id
self._value = str(base.get_type())
class ClipPlaceRef(ClipObjWrapper):
DROP_TARGETS = [DdTargets.PLACEREF]
DRAG_TARGET = DdTargets.PLACEREF
ICON = LINK_PIC
def __init__(self, dbstate, obj):
super(ClipPlaceRef, self).__init__(dbstate, obj)
self._type = _("Place ref")
self.refresh()
def refresh(self):
if self._obj:
base = self._db.get_place_from_handle(self._obj.ref)
if base:
self._title = base.gramps_id
self._value = str(base.get_name())
class ClipName(ClipObjWrapper):
DROP_TARGETS = [DdTargets.NAME]
@ -1082,6 +1101,7 @@ class ClipboardListView(object):
self.register_wrapper_class(ClipEvent)
self.register_wrapper_class(ClipPlace)
self.register_wrapper_class(ClipEventRef)
self.register_wrapper_class(ClipPlaceRef)
self.register_wrapper_class(ClipRepoRef)
self.register_wrapper_class(ClipFamilyEvent)
self.register_wrapper_class(ClipUrl)

View File

@ -142,6 +142,7 @@ class _DdTargets(object):
self.NAME = _DdType(self, 'name')
self.NOTE_LINK = _DdType(self, 'note-link')
self.PLACE_LINK = _DdType(self, 'place-link')
self.PLACEREF = _DdType(self, 'placeref')
self.REPO_LINK = _DdType(self, 'repo-link')
self.REPOREF = _DdType(self, 'reporef')
self.PERSON_LINK = _DdType(self, 'person-link')
@ -172,6 +173,7 @@ class _DdTargets(object):
self.NAME,
self.NOTE_LINK,
self.PLACE_LINK,
self.PLACEREF,
self.PERSON_LINK,
self.FAMILY_LINK,
self.LINK_LIST,

View File

@ -39,6 +39,7 @@ from .editnote import EditNote, DeleteNoteQuery
from .editperson import EditPerson
from .editpersonref import EditPersonRef
from .editplace import EditPlace, DeletePlaceQuery
from .editplaceref import EditPlaceRef
from .editrepository import EditRepository, DeleteRepositoryQuery
from .editreporef import EditRepoRef
from .editsource import EditSource, DeleteSrcQuery

View File

@ -56,6 +56,7 @@ from .personeventembedlist import PersonEventEmbedList
from .personrefembedlist import PersonRefEmbedList
from .personbackreflist import PersonBackRefList
from .placebackreflist import PlaceBackRefList
from .placerefembedlist import PlaceRefEmbedList
from .repoembedlist import RepoEmbedList
from .surnametab import SurnameTab
from .sourcebackreflist import SourceBackRefList

View File

@ -0,0 +1,101 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
#
# 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$
#-------------------------------------------------------------------------
#
# Python classes
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from gi.repository import GObject
#-------------------------------------------------------------------------
#
# GRAMPS classes
#
#-------------------------------------------------------------------------
from gramps.gen.lib import PlaceRef
from gramps.gen.errors import WindowActiveError
from ...ddtargets import DdTargets
from .placerefmodel import PlaceRefModel
from .embeddedlist import EmbeddedList, TEXT_COL
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class PlaceRefEmbedList(EmbeddedList):
_HANDLE_COL = 4
#_DND_TYPE = DdTargets.PLACEREF
#index = column in model. Value =
# (name, sortcol in model, width, markup/text, weigth_col
_column_names = [
(_('ID'), 0, 75, TEXT_COL, -1, None),
(_('Name'), 1, 250, TEXT_COL, -1, None),
(_('Type'), 2, 100, TEXT_COL, -1, None),
(_('Date'), 3, 150, TEXT_COL, -1, None),
]
def __init__(self, dbstate, uistate, track, data, handle):
self.data = data
self.handle = handle
EmbeddedList.__init__(self, dbstate, uistate, track,
_('Parents'), PlaceRefModel,
move_buttons=True)
def get_data(self):
return self.data
def column_order(self):
return ((1, 0), (1, 1), (1, 2), (1, 3))
def add_button_clicked(self, obj):
placeref = PlaceRef()
try:
from .. import EditPlaceRef
EditPlaceRef(self.dbstate, self.uistate, self.track,
placeref, self.handle, self.add_callback)
except WindowActiveError:
pass
def add_callback(self, name):
data = self.get_data()
data.append(name)
self.rebuild()
GObject.idle_add(self.tree.scroll_to_cell, len(data) - 1)
def edit_button_clicked(self, obj):
placeref = self.get_selected()
if placeref:
try:
from .. import EditPlaceRef
EditPlaceRef(self.dbstate, self.uistate, self.track,
placeref, self.handle, self.edit_callback)
except WindowActiveError:
pass
def edit_callback(self, name):
self.rebuild()

View File

@ -0,0 +1,53 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
#
# 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$
#-------------------------------------------------------------------------
#
# GTK libraries
#
#-------------------------------------------------------------------------
from gi.repository import Gtk
#-------------------------------------------------------------------------
#
# Gramps classes
#
#-------------------------------------------------------------------------
from gramps.gen.datehandler import displayer
#-------------------------------------------------------------------------
#
# PlaceRefModel
#
#-------------------------------------------------------------------------
class PlaceRefModel(Gtk.ListStore):
def __init__(self, obj_list, db):
Gtk.ListStore.__init__(self, str, str, str, str, object)
self.db = db
for obj in obj_list:
place = self.db.get_place_from_handle(obj.ref)
self.append(row=[place.get_gramps_id(),
place.get_name(),
str(place.get_type()),
displayer.display(obj.date),
obj, ])

View File

@ -50,57 +50,15 @@ from gi.repository import Gtk
from gramps.gen.lib import NoteType, Place
from gramps.gen.db import DbTxn
from .editprimary import EditPrimary
from .displaytabs import (GrampsTab, LocationEmbedList, CitationEmbedList,
from .displaytabs import (PlaceRefEmbedList, LocationEmbedList, CitationEmbedList,
GalleryTab, NoteTab, WebEmbedList, PlaceBackRefList)
from ..widgets import MonitoredEntry, PrivacyButton, MonitoredTagList
from ..widgets import (MonitoredEntry, PrivacyButton, MonitoredTagList,
MonitoredDataType)
from gramps.gen.errors import ValidationError
from gramps.gen.utils.place import conv_lat_lon
from ..dialog import ErrorDialog
from ..glade import Glade
#-------------------------------------------------------------------------
#
# Classes
#
#-------------------------------------------------------------------------
class MainLocTab(GrampsTab):
"""
This class provides the tabpage of the main location tab
"""
def __init__(self, dbstate, uistate, track, name, widget):
"""
@param dbstate: The database state. Contains a reference to
the database, along with other state information. The GrampsTab
uses this to access the database and to pass to and created
child windows (such as edit dialogs).
@type dbstate: DbState
@param uistate: The UI state. Used primarily to pass to any created
subwindows.
@type uistate: DisplayState
@param track: The window tracking mechanism used to manage windows.
This is only used to pass to generted child windows.
@type track: list
@param name: Notebook label name
@type name: str/unicode
@param widget: widget to be shown in the tab
@type widge: gtk widget
"""
GrampsTab.__init__(self, dbstate, uistate, track, name)
eventbox = Gtk.EventBox()
eventbox.add(widget)
self.pack_start(eventbox, True, True, 0)
self._set_label(show_image=False)
eventbox.connect('key_press_event', self.key_pressed)
self.show_all()
def is_empty(self):
"""
Override base class
"""
return False
#-------------------------------------------------------------------------
#
# EditPlace
@ -121,17 +79,7 @@ class EditPlace(EditPrimary):
self.height_key = 'interface.place-height'
self.top = Glade()
self.set_window(self.top.toplevel, None,
self.get_menu_title())
tblmloc = self.top.get_object('table19')
notebook = self.top.get_object('notebook3')
#recreate start page as GrampsTab
notebook.remove_page(0)
self.mloc = MainLocTab(self.dbstate, self.uistate, self.track,
_('_Location'), tblmloc)
self.track_ref_for_deletion("mloc")
self.set_window(self.top.toplevel, None, self.get_menu_title())
def get_menu_title(self):
if self.obj and self.obj.get_handle():
@ -155,23 +103,14 @@ class EditPlace(EditPrimary):
self._add_db_signal('place-delete', self.check_for_close)
def _setup_fields(self):
mloc = self.obj.get_main_location()
self.title = MonitoredEntry(self.top.get_object("place_title"),
self.obj.set_title, self.obj.get_title,
self.db.readonly)
self.street = MonitoredEntry(self.top.get_object("street"),
mloc.set_street, mloc.get_street,
self.db.readonly)
self.locality = MonitoredEntry(self.top.get_object("locality"),
mloc.set_locality, mloc.get_locality,
self.db.readonly)
self.city = MonitoredEntry(self.top.get_object("city"),
mloc.set_city, mloc.get_city,
self.db.readonly)
self.name = MonitoredEntry(self.top.get_object("name_entry"),
self.obj.set_name, self.obj.get_name,
self.db.readonly)
self.gid = MonitoredEntry(self.top.get_object("gid"),
self.obj.set_gramps_id,
@ -188,29 +127,14 @@ class EditPlace(EditPrimary):
self.privacy = PrivacyButton(self.top.get_object("private"), self.obj,
self.db.readonly)
self.parish = MonitoredEntry(self.top.get_object("parish"),
mloc.set_parish, mloc.get_parish,
self.db.readonly)
self.county = MonitoredEntry(self.top.get_object("county"),
mloc.set_county, mloc.get_county,
self.db.readonly)
self.state = MonitoredEntry(self.top.get_object("state"),
mloc.set_state, mloc.get_state,
self.db.readonly)
self.place_type = MonitoredDataType(self.top.get_object("place_type"),
self.obj.set_type,
self.obj.get_type)
self.phone = MonitoredEntry(self.top.get_object("phone"),
mloc.set_phone, mloc.get_phone,
self.db.readonly)
self.postal = MonitoredEntry(self.top.get_object("postal"),
mloc.set_postal_code,
mloc.get_postal_code, self.db.readonly)
self.country = MonitoredEntry(self.top.get_object("country"),
mloc.set_country, mloc.get_country,
self.db.readonly)
self.code = MonitoredEntry(
self.top.get_object("code_entry"),
self.obj.set_code, self.obj.get_code,
self.db.readonly)
self.longitude = MonitoredEntry(
self.top.get_object("lon_entry"),
@ -247,8 +171,14 @@ class EditPlace(EditPrimary):
"""
notebook = self.top.get_object('notebook3')
self._add_tab(notebook, self.mloc)
self.placeref_list = PlaceRefEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_placeref_list(),
self.obj.handle)
self._add_tab(notebook, self.placeref_list)
self.track_ref_for_deletion("placeref_list")
self.loc_list = LocationEmbedList(self.dbstate,
self.uistate,
self.track,
@ -306,6 +236,20 @@ class EditPlace(EditPrimary):
self.ok_button.set_sensitive(True)
return
if self.obj.get_title().strip() == '':
msg1 = _("Cannot save location. Title not entered.")
msg2 = _("You must enter a title before saving.'")
ErrorDialog(msg1, msg2)
self.ok_button.set_sensitive(True)
return
if self.obj.get_name().strip() == '':
msg1 = _("Cannot save location. Name not entered.")
msg2 = _("You must enter a name before saving.'")
ErrorDialog(msg1, msg2)
self.ok_button.set_sensitive(True)
return
(uses_dupe_id, id) = self._uses_duplicate_id()
if uses_dupe_id:
prim_object = self.get_from_gramps_id(id)

View File

@ -0,0 +1,100 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from .editsecondary import EditSecondary
from ..glade import Glade
from ..widgets import MonitoredDate
from ..selectors import SelectorFactory
from ..dialog import ErrorDialog
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
SelectPlace = SelectorFactory('Place')
#-------------------------------------------------------------------------
#
# EditPlaceRef class
#
#-------------------------------------------------------------------------
class EditPlaceRef(EditSecondary):
def __init__(self, dbstate, uistate, track, placeref, handle, callback):
self.handle = handle
EditSecondary.__init__(self, dbstate, uistate, track,
placeref, callback)
def _local_init(self):
self.width_key = 'interface.place-ref-width'
self.height_key = 'interface.place-ref-height'
self.top = Glade()
self.set_window(self.top.toplevel, None, _('Place Reference Editor'))
def _setup_fields(self):
self.date_field = MonitoredDate(self.top.get_object("date_entry"),
self.top.get_object("date_stat"),
self.obj.get_date_object(),
self.uistate, self.track,
self.db.readonly)
self.parent = self.top.get_object('place_label')
if self.obj.ref is not None:
place = self.db.get_place_from_handle(self.obj.ref)
self.parent.set_text(place.get_name())
else:
self.parent.set_text(_('Top level place'))
button = self.top.get_object('place_button')
button.connect('clicked', self.select_parent)
def get_skip_list(self, handle):
todo = [handle]
skip = [handle]
while todo:
handle = todo.pop()
for child in self.dbstate.db.find_place_child_handles(handle):
todo.append(child)
skip.append(child)
return skip
def select_parent(self, button):
skip = self.get_skip_list(self.handle)
sel = SelectPlace(self.dbstate, self.uistate, self.track, skip=skip)
parent = sel.run()
if parent:
self.parent.set_text(parent.get_name())
self.obj.ref = parent.get_handle()
def _connect_signals(self):
self.define_cancel_button(self.top.get_object('cancel_button'))
self.define_ok_button(self.top.get_object('ok_button'), self.save)
self.define_help_button(self.top.get_object('help_button'))
def save(self, *obj):
if self.callback:
self.callback(self.obj)
self.close()

View File

@ -16,12 +16,10 @@
<child>
<object class="GtkButton" id="cancel">
<property name="label">gtk-cancel</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -33,13 +31,11 @@
<child>
<object class="GtkButton" id="ok">
<property name="label">gtk-ok</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -51,12 +47,10 @@
<child>
<object class="GtkButton" id="help">
<property name="label">gtk-help</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -82,23 +76,26 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="n_rows">3</property>
<property name="n_rows">4</property>
<property name="n_columns">5</property>
<property name="column_spacing">6</property>
<property name="row_spacing">4</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkLabel" id="label244">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Place Name:</property>
<property name="label" translatable="yes">_Place Title:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">place_title</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -112,10 +109,10 @@
<property name="mnemonic_widget">lat_entry</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -131,23 +128,23 @@
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="UndoableEntry" id="place_title">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Full name of this place.</property>
<property name="tooltip_text" translatable="yes">Full title of this place.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">5</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -160,10 +157,10 @@
<property name="mnemonic_widget">gid</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -178,9 +175,9 @@ You can set these values via the Geography View by searching the place, or via a
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -195,9 +192,9 @@ You can set these values via the Geography View by searching the place, or via a
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -221,11 +218,12 @@ You can set these values via the Geography View by searching the place, or via a
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Tags:</property>
<property name="label" translatable="yes">Code:</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
@ -234,10 +232,12 @@ You can set these values via the Geography View by searching the place, or via a
</packing>
</child>
<child>
<object class="GtkLabel" id="tag_label">
<object class="UndoableEntry" id="code_entry">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Code associated with this place. Eg Country Code or Postal Code.</property>
<property name="invisible_char">●</property>
<property name="width_chars">8</property>
</object>
<packing>
<property name="expand">True</property>
@ -248,19 +248,17 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="private">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="accessible">
@ -284,28 +282,121 @@ You can set these values via the Geography View by searching the place, or via a
<packing>
<property name="left_attach">4</property>
<property name="right_attach">5</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"></property>
<property name="y_options"></property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"/>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkButton" id="tag_button">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="left_attach">4</property>
<property name="right_attach">5</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"></property>
<property name="y_options"></property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options"/>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Name:</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Type:</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="UndoableEntry" id="name_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">The name of this place.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkComboBox" id="place_type">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">What type of place this is. Eg 'Country', 'City', ... .</property>
<property name="has_entry">True</property>
<child internal-child="entry">
<object class="GtkEntry" id="combobox-entry2">
<property name="can_focus">False</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Tags:</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="tag_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"/>
</packing>
</child>
</object>
@ -320,345 +411,10 @@ You can set these values via the Geography View by searching the place, or via a
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkTable" id="table19">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="n_rows">5</property>
<property name="n_columns">4</property>
<property name="column_spacing">12</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkLabel" id="label245">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">C_ity:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">city</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label664">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">S_treet:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">street</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="UndoableEntry" id="street">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Lowest level of a place division: eg the street name.
Use Alternate Locations tab to store the current name.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="UndoableEntry" id="city">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">The town or city where the place is.
Use Alternate Locations tab to store the current name.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="UndoableEntry" id="parish">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Lowest clergical division of this place. Typically used for church sources that only mention the parish.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label279">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Ch_urch parish:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">parish</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label247">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Co_unty:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">county</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="UndoableEntry" id="county">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Third level of place division. Eg., in the USA a county.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label246">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_State:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">state</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="UndoableEntry" id="state">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Second level of place division, eg., in the USA a state, in Germany a Bundesland.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label248">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Count_ry:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">country</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="UndoableEntry" id="country">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">The country where the place is.
</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label290">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_ZIP/Postal code:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">postal</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="UndoableEntry" id="postal">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label291">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Phon_e:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">phone</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="UndoableEntry" id="phone">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Locality:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">locality</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkEntry" id="locality">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">A district within, or a settlement near to, a town or city.
Use Alternate Locations tab to store the current name.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
</object>
<placeholder/>
</child>
<child type="tab">
<object class="GtkHBox" id="hbox107">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="image2598">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-file</property>
<property name="icon-size">1</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label252">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Location</property>
<property name="justify">center</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
<placeholder/>
</child>
</object>
<packing>

View File

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkDialog" id="editplaceref">
<property name="can_focus">False</property>
<property name="default_width">550</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="cancel_button">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ok_button">
<property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="help_button">
<property name="label">gtk-help</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTable" id="table">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="n_rows">2</property>
<property name="n_columns">3</property>
<property name="column_spacing">12</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Parent Place:</property>
<property name="use_underline">True</property>
<property name="justify">right</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Date:</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkButton" id="place_button">
<property name="label" translatable="yes">...</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkButton" id="date_stat">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="has_tooltip">True</property>
<property name="tooltip_text" translatable="yes">Invoke date editor</property>
<property name="relief">none</property>
<accelerator key="d" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="accessible">
<object class="AtkObject" id="date_stat-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">Date</property>
</object>
</child>
<child>
<object class="GtkImage" id="date_stat_child">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="has_tooltip">True</property>
<property name="tooltip_text" translatable="yes">Show Date Editor</property>
<property name="icon_name">gramps-date</property>
<child internal-child="accessible">
<object class="AtkObject" id="date_stat_child-atkobject">
<property name="AtkObject::accessible-description" translatable="yes">Date</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="place_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="ValidatableMaskedEntry" id="date_entry">
<property name="height_request">27</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Date range for which the parent is valid.</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"/>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-6">cancel_button</action-widget>
<action-widget response="-5">ok_button</action-widget>
<action-widget response="-11">help_button</action-widget>
</action-widgets>
</object>
</interface>

View File

@ -19,12 +19,10 @@
<child>
<object class="GtkButton" id="place_cancel">
<property name="label">gtk-cancel</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -36,12 +34,10 @@
<child>
<object class="GtkButton" id="place_ok">
<property name="label">gtk-ok</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -53,12 +49,10 @@
<child>
<object class="GtkButton" id="place_help">
<property name="label">gtk-help</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
@ -111,11 +105,9 @@ primary data for the merged place.</property>
<property name="can_focus">False</property>
<child>
<object class="GtkRadioButton" id="handle_btn1">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<child>
@ -135,11 +127,9 @@ primary data for the merged place.</property>
</child>
<child>
<object class="GtkRadioButton" id="handle_btn2">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<property name="group">handle_btn1</property>
@ -179,7 +169,7 @@ primary data for the merged place.</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="n_rows">6</property>
<property name="n_rows">8</property>
<property name="n_columns">4</property>
<property name="column_spacing">6</property>
<property name="row_spacing">6</property>
@ -194,7 +184,7 @@ primary data for the merged place.</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -210,17 +200,15 @@ primary data for the merged place.</property>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="title_btn1">
<property name="label" translatable="yes">Title:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -229,17 +217,15 @@ primary data for the merged place.</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="title_btn2">
<property name="label" translatable="yes">Title:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -251,36 +237,32 @@ primary data for the merged place.</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="lat_btn1">
<property name="label" translatable="yes">Latitude:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="lat_btn2">
<property name="label" translatable="yes">Latitude:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -289,39 +271,35 @@ primary data for the merged place.</property>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="long_btn1">
<property name="label" translatable="yes">Longitude:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="long_btn2">
<property name="label" translatable="yes">Longitude:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -330,80 +308,35 @@ primary data for the merged place.</property>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="loc_btn1">
<property name="label" translatable="yes">Location:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="loc_btn2">
<property name="label" translatable="yes">Location:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<property name="group">loc_btn1</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="gramps_btn1">
<property name="label" translatable="yes">Gramps ID:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="gramps_btn2">
<property name="label" translatable="yes">Gramps ID:</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
@ -412,10 +345,10 @@ primary data for the merged place.</property>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -429,7 +362,7 @@ primary data for the merged place.</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -443,7 +376,7 @@ primary data for the merged place.</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -455,9 +388,9 @@ primary data for the merged place.</property>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -469,9 +402,9 @@ primary data for the merged place.</property>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -483,9 +416,9 @@ primary data for the merged place.</property>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -497,49 +430,9 @@ primary data for the merged place.</property>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkViewport" id="viewport1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTextView" id="loc1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkViewport" id="viewport2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTextView" id="loc2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -551,9 +444,9 @@ primary data for the merged place.</property>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="y_options"/>
</packing>
</child>
<child>
@ -568,14 +461,229 @@ primary data for the merged place.</property>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="y_options"/>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkRadioButton" id="name_btn1">
<property name="label" translatable="yes">Name:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="relief">half</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="name_btn2">
<property name="label" translatable="yes">Name:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="relief">half</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<property name="group">name_btn1</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="name1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="name2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="type_btn1">
<property name="label" translatable="yes">Type:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="relief">half</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="type_btn2">
<property name="label" translatable="yes">Type:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="relief">half</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<property name="group">type_btn1</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="type1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="type2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="code_btn1">
<property name="label" translatable="yes">Code:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="relief">half</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="code_btn2">
<property name="label" translatable="yes">Code:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<property name="group">code_btn1</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="code1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="code2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"/>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>

View File

@ -63,10 +63,11 @@ class MergePlace(ManagedWindow):
"""
Displays a dialog box that allows the places to be combined into one.
"""
def __init__(self, dbstate, uistate, handle1, handle2):
def __init__(self, dbstate, uistate, handle1, handle2, callback=None):
ManagedWindow.__init__(self, uistate, [], self.__class__)
self.dbstate = dbstate
database = dbstate.db
self.callback = callback
self.pl1 = database.get_place_from_handle(handle1)
self.pl2 = database.get_place_from_handle(handle2)
@ -86,6 +87,30 @@ class MergePlace(ManagedWindow):
for widget_name in ('title1', 'title2', 'title_btn1', 'title_btn2'):
self.get_widget(widget_name).set_sensitive(False)
entry1 = self.get_widget("name1")
entry2 = self.get_widget("name2")
entry1.set_text(self.pl1.get_name())
entry2.set_text(self.pl2.get_name())
if entry1.get_text() == entry2.get_text():
for widget_name in ('name1', 'name2', 'name_btn1', 'name_btn2'):
self.get_widget(widget_name).set_sensitive(False)
entry1 = self.get_widget("type1")
entry2 = self.get_widget("type2")
entry1.set_text(str(self.pl1.get_type()))
entry2.set_text(str(self.pl2.get_type()))
if entry1.get_text() == entry2.get_text():
for widget_name in ('type1', 'type2', 'type_btn1', 'type_btn2'):
self.get_widget(widget_name).set_sensitive(False)
entry1 = self.get_widget("code1")
entry2 = self.get_widget("code2")
entry1.set_text(self.pl1.get_code())
entry2.set_text(self.pl2.get_code())
if entry1.get_text() == entry2.get_text():
for widget_name in ('code1', 'code2', 'code_btn1', 'code_btn2'):
self.get_widget(widget_name).set_sensitive(False)
entry1 = self.get_widget("lat1")
entry2 = self.get_widget("lat2")
entry1.set_text(self.pl1.get_latitude())
@ -102,20 +127,6 @@ class MergePlace(ManagedWindow):
for widget_name in ('long1', 'long2', 'long_btn1', 'long_btn2'):
self.get_widget(widget_name).set_sensitive(False)
loc1 = self.pl1.get_main_location().get_text_data_list()
loc2 = self.pl2.get_main_location().get_text_data_list()
tv1 = self.get_widget("loc1")
tv2 = self.get_widget("loc2")
tb1 = Gtk.TextBuffer()
tb2 = Gtk.TextBuffer()
tv1.set_buffer(tb1)
tv2.set_buffer(tb2)
tb1.set_text("\n".join(loc1))
tb2.set_text("\n".join(loc2))
if loc1 == loc2:
for widget_name in ('loc1', 'loc2', 'loc_btn1', 'loc_btn2'):
self.get_widget(widget_name).set_sensitive(False)
gramps1 = self.pl1.get_gramps_id()
gramps2 = self.pl2.get_gramps_id()
entry1 = self.get_widget("gramps1")
@ -144,12 +155,18 @@ class MergePlace(ManagedWindow):
"""first chosen place changes"""
if obj.get_active():
self.get_widget("title_btn1").set_active(True)
self.get_widget("name_btn1").set_active(True)
self.get_widget("type_btn1").set_active(True)
self.get_widget("code_btn1").set_active(True)
self.get_widget("lat_btn1").set_active(True)
self.get_widget("long_btn1").set_active(True)
self.get_widget("loc_btn1").set_active(True)
self.get_widget("gramps_btn1").set_active(True)
else:
self.get_widget("title_btn2").set_active(True)
self.get_widget("name_btn2").set_active(True)
self.get_widget("type_btn2").set_active(True)
self.get_widget("code_btn2").set_active(True)
self.get_widget("lat_btn2").set_active(True)
self.get_widget("long_btn2").set_active(True)
self.get_widget("loc_btn2").set_active(True)
@ -179,18 +196,23 @@ class MergePlace(ManagedWindow):
if self.get_widget("title_btn1").get_active() ^ use_handle1:
phoenix.set_title(titanic.get_title())
if self.get_widget("name_btn1").get_active() ^ use_handle1:
phoenix.set_name(titanic.get_name())
if self.get_widget("type_btn1").get_active() ^ use_handle1:
phoenix.set_type(titanic.get_type())
if self.get_widget("code_btn1").get_active() ^ use_handle1:
phoenix.set_code(titanic.get_code())
if self.get_widget("lat_btn1").get_active() ^ use_handle1:
phoenix.set_latitude(titanic.get_latitude())
if self.get_widget("long_btn1").get_active() ^ use_handle1:
phoenix.set_longitude(titanic.get_longitude())
if self.get_widget("loc_btn1").get_active() ^ use_handle1:
swaploc = phoenix.get_main_location()
phoenix.set_main_location(titanic.get_main_location())
titanic.set_main_location(swaploc)
if self.get_widget("gramps_btn1").get_active() ^ use_handle1:
phoenix.set_gramps_id(titanic.get_gramps_id())
query = MergePlaceQuery(self.dbstate, phoenix, titanic)
query.execute()
if self.callback:
self.callback()
self.uistate.set_busy_cursor(False)
self.close()

View File

@ -35,7 +35,7 @@ _ = glocale.translation.gettext
# gramps modules
#
#-------------------------------------------------------------------------
from ..views.treemodels.placemodel import PlaceListModel
from ..views.treemodels.placemodel import PlaceTreeModel
from .baseselector import BaseSelector
#-------------------------------------------------------------------------
@ -56,19 +56,14 @@ class SelectPlace(BaseSelector):
return _("Select Place")
def get_model_class(self):
return PlaceListModel
return PlaceTreeModel
def get_column_titles(self):
return [
(_('Title'), 350, BaseSelector.TEXT, 0),
(_('ID'), 75, BaseSelector.TEXT, 1),
(_('Street'), 75, BaseSelector.TEXT, 2),
(_('Locality'), 75, BaseSelector.TEXT, 3),
(_('City'), 75, BaseSelector.TEXT, 4),
(_('County'), 75, BaseSelector.TEXT, 5),
(_('State'), 75, BaseSelector.TEXT, 6),
(_('Country'), 75, BaseSelector.TEXT, 7),
(_('Parish'), 75, BaseSelector.TEXT, 9),
(_('Name'), 200, BaseSelector.TEXT, 0),
(_('ID'), 75, BaseSelector.TEXT, 1),
(_('Type'), 100, BaseSelector.TEXT, 3),
(_('Title'), 300, BaseSelector.TEXT, 2),
]
def get_from_handle_func(self):

View File

@ -424,11 +424,12 @@ class ListView(NavigationView):
parent_iter = self.model.iter_parent(iter_)
if parent_iter:
parent_path = self.model.get_path(parent_iter)
parent_path_list = parent_path.get_indices()
for i in range(len(parent_path_list)):
expand_path = Gtk.TreePath(
tuple([x for x in parent_path_list[:i+1]]))
self.list.expand_row(expand_path, False)
if parent_path:
parent_path_list = parent_path.get_indices()
for i in range(len(parent_path_list)):
expand_path = Gtk.TreePath(
tuple([x for x in parent_path_list[:i+1]]))
self.list.expand_row(expand_path, False)
# Select active object
path = self.model.get_path(iter_)

View File

@ -30,7 +30,6 @@ Place Model.
# python modules
#
#-------------------------------------------------------------------------
import cgi
import logging
_LOG = logging.getLogger(".gui.views.treemodels.placemodel")
@ -46,6 +45,7 @@ from gi.repository import Gtk
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gramps.gen.lib.placetype import PlaceType
from gramps.gen.datehandler import format_time
from gramps.gen.utils.place import conv_lat_lon
from gramps.gen.constfunc import cuni
@ -60,16 +60,6 @@ from .treebasemodel import TreeBaseModel
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
COUNTRYLEVELS = {
'default': [_('<Countries>'), _('<States>'), _('<Counties>'),
_('<Places>')]
}
#-------------------------------------------------------------------------
#
# PlaceBaseModel
@ -83,39 +73,27 @@ class PlaceBaseModel(object):
self.fmap = [
self.column_name,
self.column_id,
self.column_street,
self.column_locality,
self.column_city,
self.column_county,
self.column_state,
self.column_country,
self.column_postal_code,
self.column_parish,
self.column_title,
self.column_type,
self.column_code,
self.column_latitude,
self.column_longitude,
self.column_private,
self.column_tags,
self.column_change,
self.column_place_name,
self.column_tag_color
]
self.smap = [
self.column_name,
self.column_id,
self.column_street,
self.column_locality,
self.column_city,
self.column_county,
self.column_state,
self.column_country,
self.column_postal_code,
self.column_parish,
self.column_title,
self.column_type,
self.column_code,
self.sort_latitude,
self.sort_longitude,
self.column_private,
self.column_tags,
self.sort_change,
self.column_place_name,
self.column_tag_color
]
@ -133,14 +111,17 @@ class PlaceBaseModel(object):
"""
Return the color column.
"""
return 16
return 10
def on_get_n_columns(self):
return len(self.fmap)+1
def column_place_name(self, data):
def column_title(self, data):
return cuni(data[2])
def column_name(self, data):
return cuni(data[6])
def column_longitude(self, data):
if not data[3]:
return ''
@ -176,66 +157,24 @@ class PlaceBaseModel(object):
def column_id(self, data):
return cuni(data[1])
def column_parish(self, data):
try:
return data[5][1]
except:
return ''
def column_type(self, data):
return str(PlaceType(data[7]))
def column_street(self, data):
try:
return data[5][0][0]
except:
return ''
def column_locality(self, data):
try:
return data[5][0][1]
except:
return ''
def column_city(self, data):
try:
return data[5][0][2]
except:
return ''
def column_county(self, data):
try:
return data[5][0][3]
except:
return ''
def column_state(self, data):
try:
return data[5][0][4]
except:
return ''
def column_country(self, data):
try:
return data[5][0][5]
except:
return ''
def column_postal_code(self, data):
try:
return data[5][0][6]
except:
return ''
def column_code(self, data):
return cuni(data[8])
def column_private(self, data):
if data[13]:
if data[16]:
return 'gramps-lock'
else:
# There is a problem returning None here.
return ''
def sort_change(self, data):
return "%012x" % data[11]
return "%012x" % data[14]
def column_change(self, data):
return format_time(data[11])
return format_time(data[14])
def get_tag_name(self, tag_handle):
"""
@ -249,7 +188,7 @@ class PlaceBaseModel(object):
"""
tag_color = "#000000000000"
tag_priority = None
for handle in data[12]:
for handle in data[15]:
tag = self.db.get_tag_from_handle(handle)
if tag:
this_priority = tag.get_priority()
@ -262,7 +201,7 @@ class PlaceBaseModel(object):
"""
Return the sorted list of tags.
"""
tag_list = list(map(self.get_tag_name, data[12]))
tag_list = list(map(self.get_tag_name, data[15]))
return ', '.join(sorted(tag_list, key=glocale.sort_key))
#-------------------------------------------------------------------------
@ -288,9 +227,6 @@ class PlaceListModel(PlaceBaseModel, FlatBaseModel):
PlaceBaseModel.destroy(self)
FlatBaseModel.destroy(self)
def column_name(self, data):
return cgi.escape(cuni(data[2]))
#-------------------------------------------------------------------------
#
# PlaceTreeModel
@ -322,6 +258,7 @@ class PlaceTreeModel(PlaceBaseModel, TreeBaseModel):
PlaceBaseModel
"""
self.number_items = self.db.get_number_of_places
self.gen_cursor = self.db.get_place_tree_cursor
def get_tree_levels(self):
"""
@ -336,68 +273,19 @@ class PlaceTreeModel(PlaceBaseModel, TreeBaseModel):
handle The handle of the gramps object.
data The object data.
"""
if data[5] is None:
# No primary location
level = [''] * 6
else:
#country, state, county, city, locality, street
level = [data[5][0][i] for i in range(5,-1,-1)]
node1 = (level[0], )
node2 = (level[1], level[0])
node3 = (level[2], level[1], level[0])
sort_key = self.sort_func(data)
if not (level[3] or level[4] or level[5]):
if level[2]:
self.add_node(None, node1, level[0], None, add_parent=False)
self.add_node(node1, node2, level[1], None, add_parent=False)
self.add_node(node2, node3, level[2], None, add_parent=False)
self.add_node(node3, handle, sort_key, handle, add_parent=False)
elif level[1]:
self.add_node(None, node1, level[0], None, add_parent=False)
self.add_node(node1, node2, level[1], None, add_parent=False)
self.add_node(node2, handle, level[1], handle, add_parent=False)
elif level[0]:
self.add_node(None, node1, level[0], None, add_parent=False)
self.add_node(node1, handle, level[0], handle, add_parent=False)
else:
self.add_node(None, node1, level[0], None, add_parent=False)
self.add_node(node1, node2, level[1], None, add_parent=False)
self.add_node(node2, node3, level[2], None, add_parent=False)
self.add_node(node3, handle, sort_key, handle, add_parent=False)
else:
self.add_node(None, node1, level[0], None, add_parent=False)
self.add_node(node1, node2, level[1], None, add_parent=False)
self.add_node(node2, node3, level[2], None, add_parent=False)
self.add_node(node3, handle, sort_key, handle, add_parent=False)
def column_name(self, data):
name = ''
if data[5] is not None:
level = [data[5][0][i] for i in range(5,-1,-1)]
if not (level[3] or level[4] or level[5]):
name = cuni(level[2] or level[1] or level[0])
else:
name = ', '.join([item for item in level[3:] if item])
if not name:
name = cuni(data[2])
if name:
return cgi.escape(name)
if len(data[5]) > 0:
parent = data[5][0][0]
else:
return "<i>%s<i>" % cgi.escape(_("<no name>"))
def column_header(self, node):
"""
Return a column heading. This is called for nodes with no associated
Gramps handle.
"""
if node.name:
return '<i>%s</i>' % cgi.escape(node.name)
else:
level = len(self.do_get_path(self._get_iter(node)).get_indices())
heading = '<i>%s</i>' % cgi.escape(COUNTRYLEVELS['default'][level])
# This causes a problem with Gtk3 unless we cast to str.
return str(heading)
parent = None
# Add the node as a root node if the parent is not in the tree. This
# will happen when the view is filtered.
if not self._get_node(parent):
parent = None
self.add_node(parent, handle, sort_key, handle, add_parent=False)
def column_header(self, data):
# should not get here!
return '????'

View File

@ -44,7 +44,10 @@ import io
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from gramps.gen.lib import AttributeType, ChildRefType, Citation, Date, EventRoleType, EventType, LdsOrd, NameType, NoteType, Person, UrlType, SrcAttributeType
from gramps.gen.lib import (AttributeType, ChildRefType, Citation, Date,
EventRoleType, EventType, LdsOrd, NameType,
PlaceType, NoteType, Person, UrlType,
SrcAttributeType)
from gramps.version import VERSION
import gramps.plugins.lib.libgedcom as libgedcom
from gramps.gen.errors import DatabaseError
@ -53,6 +56,7 @@ from gramps.gen.updatecallback import UpdateCallback
from gramps.gen.utils.file import media_path_full
from gramps.gen.utils.place import conv_lat_lon
from gramps.gen.constfunc import cuni
from gramps.gen.utils.location import get_main_location
#-------------------------------------------------------------------------
#
@ -1373,23 +1377,28 @@ class GedcomWriter(UpdateCallback):
# The Gedcom standard shows that an optional address structure can
# be written out in the event detail.
# http://homepages.rootsweb.com/~pmcbride/gedcom/55gcch2.htm#EVENT_DETAIL
location = place.get_main_location()
if location and not location.is_empty():
self._writeln(level, "ADDR", location.get_street())
if location.get_street():
self._writeln(level + 1, 'ADR1', location.get_street())
if location.get_locality():
self._writeln(level + 1, 'ADR2', location.get_locality())
if location.get_city():
self._writeln(level + 1, 'CITY', location.get_city())
if location.get_state():
self._writeln(level + 1, 'STAE', location.get_state())
if location.get_postal_code():
self._writeln(level + 1, 'POST', location.get_postal_code())
if location.get_country():
self._writeln(level + 1, 'CTRY', location.get_country())
if location.get_phone():
self._writeln(level, 'PHON', location.get_phone())
location = get_main_location(self.dbase, place)
street = location.get(PlaceType.STREET)
locality = location.get(PlaceType.LOCALITY)
city = location.get(PlaceType.CITY)
state = location.get(PlaceType.STATE)
country = location.get(PlaceType.COUNTRY)
postal_code = place.get_code()
if (street or locality or city or state or postal_code or country):
self._writeln(level, "ADDR", street)
if street:
self._writeln(level + 1, 'ADR1', street)
if locality:
self._writeln(level + 1, 'ADR2', locality)
if city:
self._writeln(level + 1, 'CITY', city)
if state:
self._writeln(level + 1, 'STAE', state)
if postal_code:
self._writeln(level + 1, 'POST', postal_code)
if country:
self._writeln(level + 1, 'CTRY', country)
self._note_references(place.get_note_list(), level+1)

View File

@ -718,6 +718,16 @@ class GrampsXmlWriter(UpdateCallback):
self.write_note_list(note_list,index+1)
self.g.write('%s</eventref>\n' % sp)
def dump_place_ref(self, placeref, index=1):
sp = " " * index
date = placeref.get_date_object()
if date.is_empty():
self.write_ref('placeref', placeref.ref, index, close=True)
else:
self.write_ref('placeref', placeref.ref, index, close=False)
self.write_date(date, index+1)
self.g.write('%s</placeref>\n' % sp)
def write_event(self,event,index=1):
if not event:
return
@ -1185,25 +1195,21 @@ class GrampsXmlWriter(UpdateCallback):
self.write_primary_tag("placeobj", place, index)
title = self.fix(place.get_title())
name = self.fix(place.get_name())
ptype = self.fix(place.get_type().xml_str())
code = self.fix(place.get_code())
self.write_line_nofix("ptitle", title, index+1)
self.write_line_nofix("pname", name, index+1)
self.write_line_nofix("type", ptype, index+1)
self.write_line_nofix("code", code, index+1)
longitude = self.fix(place.get_longitude())
lat = self.fix(place.get_latitude())
main_loc = place.get_main_location()
llen = (len(place.get_alternate_locations()) +
len(place.get_url_list()) +
len(place.get_media_list()) +
len(place.get_citation_list())
)
ml_empty = main_loc.is_empty()
if title == "":
title = self.build_place_title(place.get_main_location())
self.write_line_nofix("ptitle", title, index+1)
if longitude or lat:
self.g.write('%s<coord long="%s" lat="%s"/>\n'
% (" "*(index+1), longitude, lat))
self.dump_location(main_loc)
for placeref in place.get_placeref_list():
self.dump_place_ref(placeref, index+1)
list(map(self.dump_location, place.get_alternate_locations()))
self.write_media_list(place.get_media_list(), index+1)
self.write_url_list(place.get_url_list())

View File

@ -25,6 +25,7 @@ from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from gramps.gen.utils.place import conv_lat_lon
from gramps.gen.utils.file import media_path_full
from gramps.gen.utils.location import get_location_list
from gi.repository import Gtk
from gi.repository import Pango
@ -108,7 +109,7 @@ class PlaceDetails(Gramplet):
self.title.set_text(place.get_title())
self.clear_table()
self.display_location(place.get_main_location())
self.display_location(place)
self.display_separator()
lat, lon = conv_lat_lon(place.get_latitude(),
place.get_longitude(),
@ -118,11 +119,11 @@ class PlaceDetails(Gramplet):
if lon:
self.add_row(_('Longitude'), lon)
def display_location(self, location):
def display_location(self, place):
"""
Display a location.
"""
lines = [line for line in location.get_text_data_list()[:-1] if line]
lines = get_location_list(self.dbstate.db, place)
self.add_row(_('Location'), '\n'.join(lines))
def display_empty(self):

View File

@ -53,7 +53,7 @@ log = logging.getLogger(".FamilyLines")
#------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from gramps.gen.lib import EventRoleType, EventType, Person
from gramps.gen.lib import EventRoleType, EventType, Person, PlaceType
from gramps.gen.utils.file import media_path_full
from gramps.gui.thumbnails import get_thumbnail_path
from gramps.gen.plug.report import Report
@ -65,6 +65,7 @@ from gramps.gen.plug.menu import (NumberOption, ColorOption, BooleanOption,
SurnameColorOption)
from gramps.gen.utils.db import get_birth_or_fallback, get_death_or_fallback
from gramps.gen.display.name import displayer as global_name_display
from gramps.gen.utils.location import get_main_location
#------------------------------------------------------------------------
#
@ -772,13 +773,13 @@ class FamilyLinesReport(Report):
if not bth_event.private or self._incprivate:
place = self._db.get_place_from_handle(bth_event.get_place_handle())
if place:
location = place.get_main_location()
if location.get_city:
birthplace = location.get_city()
elif location.get_state:
birthplace = location.get_state()
elif location.get_country:
birthplace = location.get_country()
location = get_main_location(self._db, place)
if location.get(PlaceType.CITY):
birthplace = location.get(PlaceType.CITY)
elif location.get(PlaceType.STATE):
birthplace = location.get(PlaceType.STATE)
elif location.get(PlaceType.COUNTRY):
birthplace = location.get(PlaceType.COUNTRY)
# see if we have a deceased date we can use
deathStr = None
@ -796,13 +797,13 @@ class FamilyLinesReport(Report):
if not dth_event.private or self._incprivate:
place = self._db.get_place_from_handle(dth_event.get_place_handle())
if place:
location = place.get_main_location()
if location.get_city:
deathplace = location.get_city()
elif location.get_state:
deathplace = location.get_state()
elif location.get_country:
deathplace = location.get_country()
location = get_main_location(self._db, place)
if location.get(PlaceType.CITY):
deathplace = location.get(PlaceType.CITY)
elif location.get(PlaceType.STATE):
deathplace = location.get(PlaceType.STATE)
elif location.get(PlaceType.COUNTRY):
deathplace = location.get(PlaceType.COUNTRY)
# see if we have an image to use for this person
imagePath = None
@ -920,13 +921,13 @@ class FamilyLinesReport(Report):
if self._incplaces:
place = self._db.get_place_from_handle(event.get_place_handle())
if place:
location = place.get_main_location()
if location.get_city:
weddingPlace = location.get_city()
elif location.get_state:
weddingPlace = location.get_state()
elif location.get_country:
weddingPlace = location.get_country()
location = get_main_location(self._db, place)
if location.get(PlaceType.CITY):
weddingPlace = location.get(PlaceType.CITY)
elif location.get(PlaceType.STATE):
weddingPlace = location.get(PlaceType.STATE)
elif location.get(PlaceType.COUNTRY):
weddingPlace = location.get(PlaceType.COUNTRY)
break
# figure out the number of children (if any)

View File

@ -53,9 +53,9 @@ from gramps.gen.lib import (Address, Attribute, AttributeType, ChildRef,
MediaObject, MediaRef, Name, NameOriginType,
NameType, Note, NoteType, Person, PersonRef,
Place, RepoRef, Repository, Researcher, Source,
SrcAttribute, SrcAttributeType,
SrcAttribute, SrcAttributeType, PlaceType,
StyledText, StyledTextTag, StyledTextTagType,
Surname, Tag, Url)
Surname, Tag, Url, PlaceRef)
from gramps.gen.db import DbTxn
from gramps.gen.db.write import CLASS_TO_KEY_MAP
from gramps.gen.errors import GrampsImportError
@ -75,6 +75,7 @@ from gramps.gen.config import config
#import gramps.plugins.lib.libgrampsxml
from gramps.plugins.lib import libgrampsxml
from gramps.gen.plug.utils import version_str_to_tup
from gramps.plugins.lib.libplaceimport import PlaceImport
#-------------------------------------------------------------------------
#
@ -542,6 +543,7 @@ class GrampsParser(UpdateCallback):
self.placeobj = None
self.locations = 0
self.place_map = {}
self.place_import = PlaceImport(self.db)
self.resname = ""
self.resaddr = ""
@ -650,6 +652,7 @@ class GrampsParser(UpdateCallback):
"phone": (None, self.stop_phone),
"date": (None, self.stop_date),
"cause": (None, self.stop_cause),
"code": (None, self.stop_code),
"description": (None, self.stop_description),
"event": (self.start_event, self.stop_event),
"type": (None, self.stop_type),
@ -684,6 +687,8 @@ class GrampsParser(UpdateCallback):
"datestr": (self.start_datestr, None),
"places": (None, self.stop_places),
"placeobj": (self.start_placeobj, self.stop_placeobj),
"placeref": (self.start_placeref, self.stop_placeref),
"pname": (None, self.stop_pname),
"ptitle": (None, self.stop_ptitle),
"location": (self.start_location, None),
"lds_ord": (self.start_lds_ord, self.stop_lds_ord),
@ -1166,11 +1171,32 @@ class GrampsParser(UpdateCallback):
loc.country = attrs.get('country', '')
loc.postal = attrs.get('postal', '')
loc.phone = attrs.get('phone', '')
if self.locations > 0:
self.placeobj.add_alternate_locations(loc)
if self.__xml_version < (1, 6, 0):
if self.locations > 0:
self.placeobj.add_alternate_locations(loc)
else:
location = (attrs.get('street', ''),
attrs.get('locality', ''),
attrs.get('parish', ''),
attrs.get('city', ''),
attrs.get('county', ''),
attrs.get('state', ''),
attrs.get('country', ''))
self.place_import.store_location(location, self.placeobj.handle)
for type_num, name in enumerate(location):
if name:
break
self.placeobj.set_name(name)
self.placeobj.set_type(PlaceType(7-type_num))
codes = [attrs.get('postal'), attrs.get('phone')]
self.placeobj.set_code(' '.join(code for code in codes if code))
else:
self.placeobj.set_main_location(loc)
self.locations = self.locations + 1
self.placeobj.add_alternate_locations(loc)
self.locations = self.locations + 1
def start_witness(self, attrs):
"""
@ -1293,6 +1319,15 @@ class GrampsParser(UpdateCallback):
else:
self.person.add_event_ref(self.eventref)
def start_placeref(self, attrs):
"""
Add a place reference to the place currently being processed.
"""
self.placeref = PlaceRef()
handle = self.inaugurate(attrs['hlink'], "place", Place)
self.placeref.ref = handle
self.placeobj.add_placeref(self.placeref)
def start_attribute(self, attrs):
self.attribute = Attribute()
self.attribute.private = bool(attrs.get("priv"))
@ -2279,8 +2314,10 @@ class GrampsParser(UpdateCallback):
date_value = self.address.get_date_object()
elif self.name:
date_value = self.name.get_date_object()
else:
elif self.event:
date_value = self.event.get_date_object()
else:
date_value = self.placeref.get_date_object()
start = attrs['start'].split('-')
stop = attrs['stop'].split('-')
@ -2361,8 +2398,10 @@ class GrampsParser(UpdateCallback):
date_value = self.address.get_date_object()
elif self.name:
date_value = self.name.get_date_object()
else:
elif self.event:
date_value = self.event.get_date_object()
else:
date_value = self.placeref.get_date_object()
bce = 1
val = attrs['val']
@ -2440,8 +2479,10 @@ class GrampsParser(UpdateCallback):
date_value = self.address.get_date_object()
elif self.name:
date_value = self.name.get_date_object()
else:
elif self.event:
date_value = self.event.get_date_object()
else:
date_value = self.placeref.get_date_object()
date_value.set_as_text(attrs['val'])
@ -2498,6 +2539,9 @@ class GrampsParser(UpdateCallback):
def stop_places(self, *tag):
self.placeobj = None
if self.__xml_version < (1, 6, 0):
self.place_import.generate_hierarchy(self.trans)
def stop_photo(self, *tag):
self.photo = None
@ -2505,11 +2549,13 @@ class GrampsParser(UpdateCallback):
def stop_ptitle(self, tag):
self.placeobj.title = tag
def stop_placeobj(self, *tag):
if self.placeobj.title == "":
loc = self.placeobj.get_main_location()
self.placeobj.title = build_place_title(loc)
def stop_pname(self, tag):
self.placeobj.name = tag
def stop_code(self, tag):
self.placeobj.code = tag
def stop_placeobj(self, *tag):
self.db.commit_place(self.placeobj, self.trans,
self.placeobj.get_change_time())
self.placeobj = None
@ -2526,6 +2572,9 @@ class GrampsParser(UpdateCallback):
elif self.repo:
# Repository type
self.repo.type.set_from_xml_str(tag)
elif self.placeobj:
# Place type
self.placeobj.place_type.set_from_xml_str(tag)
def stop_childref(self, tag):
self.childref = None
@ -2536,6 +2585,9 @@ class GrampsParser(UpdateCallback):
def stop_eventref(self, tag):
self.eventref = None
def stop_placeref(self, tag):
self.placeref = None
def stop_event(self, *tag):
if self.family:
ref = EventRef()

View File

@ -131,7 +131,7 @@ from gramps.gen.lib import (Address, Attribute, AttributeType, ChildRef,
MediaRef, Name, NameType, Note, NoteType, Person, PersonRef, Place,
RepoRef, Repository, RepositoryType, Researcher,
Source, SourceMediaType, SrcAttribute, SrcAttributeType,
Surname, Tag, Url, UrlType)
Surname, Tag, Url, UrlType, PlaceType, PlaceRef)
from gramps.gen.db import DbTxn
from gramps.gen.updatecallback import UpdateCallback
from gramps.gen.mime import get_type
@ -144,6 +144,7 @@ from gramps.gui.dialog import WarningDialog
from gramps.gen.lib.const import IDENTICAL, DIFFERENT
from gramps.gen.lib import (StyledText, StyledTextTag, StyledTextTagType)
from gramps.gen.constfunc import cuni, conv_to_unicode, STRTYPE, UNITYPE
from gramps.plugins.lib.libplaceimport import PlaceImport
#-------------------------------------------------------------------------
#
@ -1661,7 +1662,7 @@ class PlaceParser(object):
fcn = self.__field_map.get(item, lambda x, y: None)
self.parse_function.append(fcn)
def load_place(self, place, text):
def load_place(self, place_import, place, text):
"""
Takes the text string representing a place, splits it into
its subcomponents (comma separated), and calls the approriate
@ -1671,12 +1672,31 @@ class PlaceParser(object):
items = [item.strip() for item in text.split(',')]
if len(items) != len(self.parse_function):
return
loc = place.get_main_location()
index = 0
loc = Location()
for item in items:
self.parse_function[index](loc, item)
index += 1
location = (loc.get_street(),
loc.get_locality(),
loc.get_parish(),
loc.get_city(),
loc.get_county(),
loc.get_state(),
loc.get_country())
place_import.store_location(location, place.handle)
for type_num, name in enumerate(location):
if name:
break
place.set_name(name)
place.set_type(PlaceType(7-type_num))
code = loc.get_postal_code()
place.set_code(code)
#-------------------------------------------------------------------------
#
# IdFinder
@ -1908,6 +1928,8 @@ class GedcomParser(UpdateCallback):
self.rid2id = {}
self.nid2id = {}
self.place_import = PlaceImport(self.dbase)
#
# Parse table for <<SUBMITTER_RECORD>> below the level 0 SUBM tag
#
@ -2675,6 +2697,8 @@ class GedcomParser(UpdateCallback):
self.dbase.add_source(src, self.trans)
self.__clean_up()
self.place_import.generate_hierarchy(self.trans)
if not self.dbase.get_feature("skip-check-xref"):
self.__check_xref()
self.dbase.enable_signals()
@ -4370,7 +4394,8 @@ class GedcomParser(UpdateCallback):
state.msg += sub_state.msg
if sub_state.place:
sub_state.place_fields.load_place(sub_state.place,
sub_state.place_fields.load_place(self.place_import,
sub_state.place,
sub_state.place.get_title())
def __lds_temple(self, line, state):
@ -4929,7 +4954,8 @@ class GedcomParser(UpdateCallback):
state.msg += sub_state.msg
if sub_state.place:
sub_state.place_fields.load_place(sub_state.place,
sub_state.place_fields.load_place(self.place_import,
sub_state.place,
sub_state.place.get_title())
def __family_source(self, line, state):
@ -5236,7 +5262,6 @@ class GedcomParser(UpdateCallback):
@type state: CurrentState
"""
location = None
if self.is_ftw and state.event.type in FTW_BAD_PLACE:
state.event.set_description(line.data)
else:
@ -5247,9 +5272,6 @@ class GedcomParser(UpdateCallback):
place_handle = state.event.get_place_handle()
if place_handle:
place = self.dbase.get_place_from_handle(place_handle)
location = place.get_main_location()
empty_loc = Location()
place.set_main_location(empty_loc)
else:
place = self.__find_or_create_place(line.data)
place.set_title(line.data)
@ -5258,20 +5280,14 @@ class GedcomParser(UpdateCallback):
sub_state = CurrentState()
sub_state.place = place
sub_state.level = state.level+1
sub_state.pf = self.place_parser
sub_state.pf = PlaceParser()
self.__parse_level(sub_state, self.event_place_map,
self.__undefined)
state.msg += sub_state.msg
sub_state.pf.load_place(place, place.get_title())
# If we already had a remembered location, we set it into the main
# location if that is empty, else the alternate location
if location and not location.is_empty():
if place.get_main_location().is_empty():
place.set_main_location(location)
else:
place.add_alternate_locations(location)
sub_state.pf.load_place(self.place_import, place, place.get_title())
self.dbase.commit_place(place, self.trans)
def __event_place_note(self, line, state):
@ -5393,7 +5409,6 @@ class GedcomParser(UpdateCallback):
place_handle = place.handle
self.__add_location(place, location)
# place.set_main_location(location)
list(map(place.add_note, note_list))
@ -5407,19 +5422,11 @@ class GedcomParser(UpdateCallback):
@param location: A location we want to add to this place
@type location: gen.lib.location
"""
# If there is no main location, we add the location
if place.main_loc is None:
place.set_main_location(location)
elif place.get_main_location().is_equivalent(location) == IDENTICAL:
# the location is already present as the main location
pass
else:
for loc in place.get_alternate_locations():
if loc.is_equivalent(location) == IDENTICAL:
return
place.add_alternate_locations(location)
for loc in place.get_alternate_locations():
if loc.is_equivalent(location) == IDENTICAL:
return
place.add_alternate_locations(location)
def __event_phon(self, line, state):
"""
@param line: The current line in GedLine format
@ -5430,8 +5437,8 @@ class GedcomParser(UpdateCallback):
place_handle = state.event.get_place_handle()
if place_handle:
place = self.dbase.get_place_from_handle(place_handle)
location = place.get_main_location()
location.set_phone(line.data)
codes = [place.get_code(), line.data]
place.set_code(' '.join(code for code in codes if code))
self.dbase.commit_place(place, self.trans)
def __event_privacy(self, line, state):

View File

@ -0,0 +1,110 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Helper class for importing places.
"""
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gramps.gen.lib import Place, PlaceType, PlaceRef
#-------------------------------------------------------------------------
#
# PlaceImport class
#
#-------------------------------------------------------------------------
class PlaceImport(object):
"""
Helper class for importing places.
"""
def __init__(self, db):
self.db = db
self.loc2handle = {}
self.handle2loc = {}
def store_location(self, location, handle):
"""
Store the location of a place already in the database.
"""
self.loc2handle[location] = handle
self.handle2loc[handle] = location
def generate_hierarchy(self, trans):
"""
Generate missing places in the place hierarchy.
"""
for handle, location in self.handle2loc.iteritems():
# find title and type
for type_num, name in enumerate(location):
if name:
break
loc = list(location)
loc[type_num] = ''
# find top parent
parent = None
for n in range(7):
if loc[n]:
tup = tuple([''] * n + loc[n:])
parent = self.loc2handle.get(tup)
if parent:
break
# create missing parent places
if parent:
n -= 1
while n > type_num:
if loc[n]:
title = ', '.join([item for item in loc[n:] if item])
parent = self.__add_place(loc[n], n, parent, title, trans)
self.loc2handle[tuple([''] * n + loc[n:])] = parent
n -= 1
# link to existing place
if parent:
place = self.db.get_place_from_handle(handle)
placeref = PlaceRef()
placeref.ref = parent
place.set_placeref_list([placeref])
self.db.commit_place(place, trans, place.get_change_time())
def __add_place(self, name, type_num, parent, title, trans):
"""
Add a missing place to the database.
"""
place = Place()
place.name = name
place.title = title
place.place_type = PlaceType(7-type_num)
if parent is not None:
placeref = PlaceRef()
placeref.ref = parent
place.set_placeref_list([placeref])
handle = self.db.add_place(place, trans)
self.db.commit_place(place, trans)
return handle

View File

@ -47,7 +47,7 @@ from gi.repository import Gtk
#
#-------------------------------------------------------------------------
from gramps.gen.lib import Place
from gramps.gui.views.listview import ListView, TEXT, MARKUP, ICON
from gramps.gui.views.listview import ListView, TEXT, ICON
from gramps.gui.widgets.menuitem import add_menuitem
from gramps.gen.errors import WindowActiveError
from gramps.gui.views.bookmarks import PlaceBookmarks
@ -79,31 +79,21 @@ class PlaceBaseView(ListView):
"""
COL_NAME = 0
COL_ID = 1
COL_STREET = 2
COL_LOCALITY = 3
COL_CITY = 4
COL_COUNTY = 5
COL_STATE = 6
COL_COUNTRY = 7
COL_ZIP = 8
COL_PARISH = 9
COL_LAT = 10
COL_LON = 11
COL_PRIV = 12
COL_TAGS = 13
COL_CHAN = 14
COL_TITLE = 2
COL_TYPE = 3
COL_CODE = 4
COL_LAT = 5
COL_LON = 6
COL_PRIV = 7
COL_TAGS = 8
COL_CHAN = 9
# column definitions
COLUMNS = [
(_('Place Name'), MARKUP, None),
(_('Name'), TEXT, None),
(_('ID'), TEXT, None),
(_('Street'), TEXT, None),
(_('Locality'), TEXT, None),
(_('City'), TEXT, None),
(_('County'), TEXT, None),
(_('State'), TEXT, None),
(_('Country'), TEXT, None),
(_('ZIP/Postal Code'), TEXT, None),
(_('Church Parish'), TEXT, None),
(_('Title'), TEXT, None),
(_('Type'), TEXT, None),
(_('Code'), TEXT, None),
(_('Latitude'), TEXT, None),
(_('Longitude'), TEXT, None),
(_('Private'), ICON, 'gramps-lock'),
@ -112,14 +102,10 @@ class PlaceBaseView(ListView):
]
# default setting with visible columns, order of the col, and their size
CONFIGSETTINGS = (
('columns.visible', [COL_NAME, COL_ID, COL_STREET, COL_LOCALITY,
COL_CITY, COL_COUNTY, COL_STATE]),
('columns.rank', [COL_NAME, COL_ID, COL_STREET, COL_LOCALITY, COL_CITY,
COL_COUNTY, COL_STATE, COL_COUNTRY, COL_ZIP,
COL_PARISH, COL_LAT, COL_LON, COL_PRIV, COL_TAGS,
COL_CHAN]),
('columns.size', [250, 75, 150, 150, 150, 150, 100, 100, 100,
100, 150, 150, 40, 100, 100])
('columns.visible', [COL_TITLE, COL_ID, COL_TYPE, COL_CODE]),
('columns.rank', [COL_NAME, COL_TITLE, COL_ID, COL_TYPE, COL_CODE,
COL_LAT, COL_LON, COL_PRIV, COL_TAGS, COL_CHAN]),
('columns.size', [250, 250, 75, 100, 100, 150, 150, 40, 100, 100])
)
ADD_MSG = _("Add a new place")
EDIT_MSG = _("Edit the selected place")
@ -380,7 +366,14 @@ class PlaceBaseView(ListView):
pass
def remove(self, obj):
self.remove_selected_objects()
for handle in self.selected_handles():
for link in self.dbstate.db.find_backlink_handles(handle,['Place']):
msg = _("Cannot delete place.")
msg2 = _("This place is currently referenced by another place. "
"First remove the places it contains.")
ErrorDialog(msg, msg2)
return
self.remove_selected_objects()
def remove_object_from_handle(self, handle):
person_list = [
@ -423,7 +416,15 @@ class PlaceBaseView(ListView):
"control key while clicking on the desired place.")
ErrorDialog(msg, msg2)
else:
MergePlace(self.dbstate, self.uistate, mlist[0], mlist[1])
MergePlace(self.dbstate, self.uistate, mlist[0], mlist[1],
self.merged)
def merged(self):
"""
Rebuild the model after a merge to reflect changes in the hierarchy.
"""
if not (self.model.get_flags() & Gtk.TreeModelFlags.LIST_ONLY):
self.build_tree()
def get_handle_from_gramps_id(self, gid):
obj = self.dbstate.db.get_place_from_gramps_id(gid)

View File

@ -41,9 +41,10 @@ from __future__ import print_function
#------------------------------------------------------------------------
from gramps.gen.display.name import displayer as name_displayer
from gramps.gen.datehandler import displayer
from gramps.gen.lib import EventType
from gramps.gen.lib import EventType, PlaceType, Location
from gramps.gen.utils.db import get_birth_or_fallback, get_death_or_fallback
from gramps.gen.constfunc import STRTYPE, cuni
from gramps.gen.utils.location import get_main_location
#------------------------------------------------------------------------
@ -159,7 +160,7 @@ class NameFormat(GenericFormat):
def parse_format(self, name):
""" Parse the name """
if self.is_blank(name):
return
return
def common():
""" return the common name of the person """
@ -310,7 +311,7 @@ class PlaceFormat(GenericFormat):
def _default_format(self, place):
return place.get_title()
def parse_format(self, place):
def parse_format(self, database, place):
""" Parse the place """
if self.is_blank(place):
@ -318,16 +319,28 @@ class PlaceFormat(GenericFormat):
code = "elcuspn" + "oitxy"
upper = code.upper()
function = [place.get_main_location().get_street,
place.get_main_location().get_locality,
place.get_main_location().get_city,
place.get_main_location().get_county,
place.get_main_location().get_state,
place.get_main_location().get_postal_code,
place.get_main_location().get_country,
main_loc = get_main_location(database, place)
location = Location()
location.set_street(main_loc.get(PlaceType.STREET, ''))
location.set_locality(main_loc.get(PlaceType.LOCALITY, ''))
location.set_parish(main_loc.get(PlaceType.PARISH, ''))
location.set_city(main_loc.get(PlaceType.CITY, ''))
location.set_county(main_loc.get(PlaceType.COUNTY, ''))
location.set_state(main_loc.get(PlaceType.STATE, ''))
location.set_postal_code(main_loc.get(PlaceType.STREET, ''))
location.set_country(main_loc.get(PlaceType.COUNTRY, ''))
place.get_main_location().get_phone,
place.get_main_location().get_parish,
function = [location.get_street,
location.get_locality,
location.get_city,
location.get_county,
location.get_state,
place.get_code,
location.get_country,
location.get_phone,
location.get_parish,
place.get_title,
place.get_longitude,
place.get_latitude
@ -382,7 +395,7 @@ class EventFormat(GenericFormat):
""" start formatting a place in this event """
place_format = PlaceFormat(self.string_in)
place = place_format.get_place(self.database, event)
return place_format.parse_format(place)
return place_format.parse_format(self.database, place)
def format_attrib():
""" Get the name and then get the attributes value """
@ -839,7 +852,7 @@ class VariableParse(object):
place = place_f.get_place(self.database, event)
if self.empty_item(place):
return
return place_f.parse_format(place)
return place_f.parse_format(self.database, place)
def __parse_name(self, person):
name_format = NameFormat(self._in)

View File

@ -51,7 +51,7 @@ import cairo
# Gramps Modules
#
#-------------------------------------------------------------------------
from gramps.gen.lib import EventType, Place
from gramps.gen.lib import EventType, Place, PlaceType, PlaceRef
from gramps.gen.display.name import displayer as _nd
from gramps.gui.views.navigationview import NavigationView
from gramps.gen.utils.libformatting import FormattingHelper
@ -61,6 +61,7 @@ from gramps.gui.managedwindow import ManagedWindow
from gramps.gen.config import config
from gramps.gui.editors import EditPlace, EditEvent, EditFamily, EditPerson
from gramps.gui.selectors.selectplace import SelectPlace
from gramps.gen.utils.location import get_main_location
from gi.repository import OsmGpsMap as osmgpsmap
from . import constants
@ -804,12 +805,14 @@ class GeoGraphyView(OsmGps, NavigationView):
"""
self.mark = mark
place = self.dbstate.db.get_place_from_gramps_id(self.mark[9])
loc = place.get_main_location()
parent_list = place.get_placeref_list()
if len(parent_list) > 0:
parent = parent_list[0].ref
else:
parent = None
self.select_fct = PlaceSelection(self.uistate, self.dbstate, self.osm,
self.selection_layer, self.place_list,
lat, lon, self.__edit_place,
(loc.get_country(), loc.get_state(), loc.get_county())
)
lat, lon, self.__edit_place, parent)
def edit_person(self, menu, event, lat, lon, mark):
"""
@ -866,9 +869,11 @@ class GeoGraphyView(OsmGps, NavigationView):
selector = SelectPlace(self.dbstate, self.uistate, [])
place = selector.run()
if place:
loc = place.get_main_location()
oldv = (loc.get_country(), loc.get_state(),
loc.get_county()) if loc else None
parent_list = place.get_placeref_list()
if len(parent_list) > 0:
parent = parent_list[0].ref
else:
parent = None
places_handle = self.dbstate.db.iter_place_handles()
nb_places = 0
gids = ""
@ -903,9 +908,9 @@ class GeoGraphyView(OsmGps, NavigationView):
lat,
lon,
self.__edit_place,
oldv)
parent)
def __add_place(self, pcountry, pcounty, pstate, plat, plon):
def __add_place(self, parent, plat, plon):
"""
Add a new place using longitude and latitude of location centered
on the map
@ -914,18 +919,17 @@ class GeoGraphyView(OsmGps, NavigationView):
new_place = Place()
new_place.set_latitude(str(plat))
new_place.set_longitude(str(plon))
loc = new_place.get_main_location()
loc.set_country(pcountry)
loc.set_county(pcounty)
loc.set_state(pstate)
new_place.set_main_location(loc)
if parent:
placeref = PlaceRef()
placeref.ref = parent
new_place.add_placeref(placeref)
try:
EditPlace(self.dbstate, self.uistate, [], new_place)
self.add_marker(None, None, plat, plon, None, True, 0)
except WindowActiveError:
pass
def __edit_place(self, pcountry, pcounty, pstate, plat, plon):
def __edit_place(self, parent, plat, plon):
"""
Edit the selected place at the marker position
"""
@ -933,17 +937,16 @@ class GeoGraphyView(OsmGps, NavigationView):
place = self.dbstate.db.get_place_from_gramps_id(self.mark[9])
place.set_latitude(str(plat))
place.set_longitude(str(plon))
loc = place.get_main_location()
loc.set_country(pcountry)
loc.set_county(pcounty)
loc.set_state(pstate)
place.set_main_location(loc)
if parent:
placeref = PlaceRef()
placeref.ref = parent
place.add_placeref(placeref)
try:
EditPlace(self.dbstate, self.uistate, [], place)
except WindowActiveError:
pass
def __link_place(self, pcountry, pcounty, pstate, plat, plon):
def __link_place(self, parent, plat, plon):
"""
Link an existing place using longitude and latitude of location centered
on the map
@ -954,11 +957,10 @@ class GeoGraphyView(OsmGps, NavigationView):
self.select_fct.close()
place.set_latitude(str(plat))
place.set_longitude(str(plon))
loc = place.get_main_location()
loc.set_country(pcountry)
loc.set_county(pcounty)
loc.set_state(pstate)
place.set_main_location(loc)
if parent:
placeref = PlaceRef()
placeref.ref = parent
place.add_placeref(placeref)
try:
EditPlace(self.dbstate, self.uistate, [], place)
self.add_marker(None, None, plat, plon, None, True, 0)

View File

@ -56,6 +56,8 @@ from gi.repository import Gtk
from gramps.gen.errors import WindowActiveError
from gramps.gui.managedwindow import ManagedWindow
from .osmgps import OsmGps
from gramps.gen.utils.location import get_main_location
from gramps.gen.lib import PlaceType
#-------------------------------------------------------------------------
#
@ -77,9 +79,9 @@ def match(self, lat, lon, radius):
if (math.hypot(lat-float(entry[3]),
lon-float(entry[4])) <= rds) == True:
# Do we already have this place ? avoid duplicates
self.get_location(entry[9])
if not [self.country, self.state, self.county] in self.places:
self.places.append([self.country, self.state, self.county])
country, state, county, place = self.get_location(entry[9])
if not [country, state, county, place] in self.places:
self.places.append([country, state, county, place])
return self.places
#-------------------------------------------------------------------------
@ -100,8 +102,7 @@ class PlaceSelection(ManagedWindow, OsmGps):
Place Selection initialization
"""
try:
ManagedWindow.__init__(self, uistate, [],
PlaceSelection)
ManagedWindow.__init__(self, uistate, [], PlaceSelection)
except WindowActiveError:
return
self.uistate = uistate
@ -109,9 +110,6 @@ class PlaceSelection(ManagedWindow, OsmGps):
self.lat = lat
self.lon = lon
self.osm = maps
self.country = None
self.state = None
self.county = None
self.radius = 1.0
self.circle = None
self.oldvalue = oldvalue
@ -141,7 +139,7 @@ class PlaceSelection(ManagedWindow, OsmGps):
self.scroll = Gtk.ScrolledWindow(self.vadjust)
self.scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
self.scroll.set_shadow_type(Gtk.ShadowType.IN)
self.plist = Gtk.ListStore(str, str, str)
self.plist = Gtk.ListStore(str, str, str, str)
self.choices = Gtk.TreeView(self.plist)
self.scroll.add(self.choices)
self.renderer = Gtk.CellRendererText()
@ -191,17 +189,19 @@ class PlaceSelection(ManagedWindow, OsmGps):
# In this case, we change the color of the row.
# display the associated message
self.label2.show()
field1, field2, field3 = self.oldvalue
self.plist.append((PLACE_STRING % field1,
PLACE_STRING % field2,
PLACE_STRING % field3)
place = self.dbstate.db.get_place_from_handle(self.oldvalue)
loc = get_main_location(self.dbstate.db, place)
self.plist.append((PLACE_STRING % loc.get(PlaceType.COUNTRY, ''),
PLACE_STRING % loc.get(PlaceType.STATE, ''),
PLACE_STRING % loc.get(PlaceType.COUNTY, ''),
self.oldvalue)
)
for place in self.places:
self.plist.append(place)
# here, we could add value from geography names services ...
# if we found no place, we must create a default place.
self.plist.append((_("New place with empty fields"), "", "..."))
self.plist.append((_("New place with empty fields"), "", "...", None))
def hide_the_region(self):
"""
@ -220,37 +220,32 @@ class PlaceSelection(ManagedWindow, OsmGps):
self.selection_layer = self.add_selection_layer()
self.selection_layer.add_circle(rds/2.0, self.lat, self.lon)
def get_location(self, place):
def get_location(self, gramps_id):
"""
get location values
"""
place = self.dbstate.db.get_place_from_gramps_id(place)
loc = place.get_main_location()
data = loc.get_text_data_list()
# new background or font color on gtk fields ?
self.country = data[6]
self.state = data[5]
self.county = data[4]
return(self.country, self.state, self.county)
parent_place = None
country = state = county = ''
place = self.dbstate.db.get_place_from_gramps_id(gramps_id)
parent_list = place.get_placeref_list()
while len(parent_list) > 0:
place = self.dbstate.db.get_place_from_handle(parent_list[0].ref)
if int(place.get_type()) == PlaceType.COUNTY:
county = place.name
if parent_place is None:
parent_place = place.get_handle()
elif int(place.get_type()) == PlaceType.STATE:
state = place.name
if parent_place is None:
parent_place = place.get_handle()
elif int(place.get_type()) == PlaceType.COUNTRY:
country = place.name
if parent_place is None:
parent_place = place.get_handle()
return(country, state, county, parent_place)
def selection(self, obj, index, column, function):
"""
get location values and call the real function : add_place, edit_place
"""
if self.plist[index][2] == "...":
# case with blank values ( New place with empty fields )
self.function( "", "", "", self.lat, self.lon)
elif self.plist[index][0][1:5] == "span":
# case with old values ( keep the old values of the place )
name = PLACE_REGEXP.search(self.plist[index][0], 0)
country = name.group(1)
name = PLACE_REGEXP.search(self.plist[index][1], 0)
state = name.group(1)
name = PLACE_REGEXP.search(self.plist[index][2], 0)
county = name.group(1)
self.function( country, county, state, self.lat, self.lon)
else:
# Set the new values of the country, county and state fields.
self.function( self.plist[index][0], self.plist[index][2],
self.plist[index][1], self.lat, self.lon)
self.function(self.plist[index][3], self.lat, self.lon)

View File

@ -41,6 +41,8 @@ _ = glocale.translation.gettext
#------------------------------------------------------------------------
from gramps.plugins.lib.libmapservice import MapService
from gramps.gui.dialog import WarningDialog
from gramps.gen.utils.location import get_main_location
from gramps.gen.lib import PlaceType
# Make upper case of translaed country so string search works later
MAP_NAMES_SWEDEN = [_("Sweden").upper(),
@ -65,12 +67,13 @@ def _strip_leading_comma(descr):
descr = descr.strip()[1:]
return descr.strip()
def _build_title(self):
def _build_title(db, place):
""" Builds descrition string for title parameter in url """
descr = self.get_title()
parish = self.get_main_location().get_parish()
city = self.get_main_location().get_city()
state = self.get_main_location().get_state()
descr = place.get_title()
location = get_main_location(db, place)
parish = location.get(PlaceType.PARISH)
city = location.get(PlaceType.CITY)
state = location.get(PlaceType.STATE)
title_descr = ""
if descr:
title_descr += descr.strip()
@ -82,19 +85,21 @@ def _build_title(self):
title_descr += ', ' + state.strip() + _(" state")
return _strip_leading_comma(title_descr)
def _build_city(self):
def _build_city(db, place):
""" Builds description string for city parameter in url """
county = self.get_main_location().get_county()
location = get_main_location(db, place)
county = location.get(PlaceType.COUNTY)
# Build a title description string that will work for Eniro
city_descr = _build_area(self)
city_descr = _build_area(db, place)
if county:
city_descr += ', ' + county
return _strip_leading_comma(city_descr)
def _build_area(self):
def _build_area(db, place):
""" Builds string for area parameter in url """
street = self.get_main_location().get_street()
city = self.get_main_location().get_city()
location = get_main_location(db, place)
street = location.get(PlaceType.STREET)
city = location.get(PlaceType.CITY)
# Build a title description string that will work for Eniro
area_descr = ""
if street:
@ -121,7 +126,8 @@ class EniroSVMapService(MapService):
path = ""
# First see if we are in or near Sweden or Denmark
# Change country to upper case
country = place.get_main_location().get_country().upper().strip()
location = get_main_location(self.database, place)
country = location.get(PlaceType.COUNTRY, '').upper().strip()
country_given = (country in MAP_NAMES_SWEDEN or \
country in MAP_NAMES_DENMARK) and (country != "")
# if no country given, check if we might be in the vicinity defined by
@ -143,8 +149,8 @@ class EniroSVMapService(MapService):
return
if coord_ok:
place_title = _build_title(place)
place_city = _build_city(place)
place_title = _build_title(self.database, place)
place_city = _build_city(self.database, place)
x_coord, y_coord = self._lat_lon(place, format="RT90")
# Set zoom level to 5 if Sweden/Denmark, others 3
zoom = 5
@ -157,7 +163,7 @@ class EniroSVMapService(MapService):
self.url = path.replace(" ","%20")
return
place_area = _build_area(place)
place_area = _build_area(self.database, place)
if country_given and place_area:
if country in MAP_NAMES_SWEDEN:
path = "http://kartor.eniro.se/query?&what=map_adr&mop=aq" \

View File

@ -37,6 +37,8 @@ _ = glocale.translation.gettext
#
#------------------------------------------------------------------------
from gramps.plugins.lib.libmapservice import MapService
from gramps.gen.utils.location import get_main_location
from gramps.gen.lib import PlaceType
class GoogleMapService(MapService):
"""Map service using http://maps.google.com"""
@ -56,8 +58,9 @@ class GoogleMapService(MapService):
longitude)
return
city = place.get_main_location().get_city()
country = place.get_main_location().get_country()
location = get_main_location(self.database, place)
city = location.get(PlaceType.CITY)
country = location.get(PlaceType.COUNTRY)
if city and country:
self.url = "http://maps.google.com/maps?q=%s,%s" % (city, country)
return

View File

@ -37,7 +37,8 @@ _ = glocale.translation.gettext
#
#------------------------------------------------------------------------
from gramps.plugins.lib.libmapservice import MapService
from gramps.gen.utils.location import get_main_location
from gramps.gen.lib import PlaceType
class OpensStreetMapService(MapService):
"""Map service using http://openstreetmap.org
@ -60,8 +61,9 @@ class OpensStreetMapService(MapService):
return
city = place.get_main_location().get_city()
country = place.get_main_location().get_country()
location = get_main_location(self.database, place)
city = location.get(PlaceType.CITY)
country = location.get(PlaceType.COUNTRY)
if city and country:
self.url = "http://open.mapquestapi.com/nominatim/v1/"\
"search.php?q=%s%%2C%s" % (city, country)

View File

@ -51,6 +51,8 @@ from gramps.gen.proxy import PrivateProxyDb
from gramps.gen.datehandler import get_date
from gramps.gen.sort import Sort
from gramps.gen.display.name import displayer as _nd
from gramps.gen.utils.location import get_main_location
from gramps.gen.lib import PlaceType
class PlaceReport(Report):
"""
@ -148,16 +150,17 @@ class PlaceReport(Report):
This procedure writes out the details of a single place
"""
place = self.database.get_place_from_handle(handle)
location = place.get_main_location()
location = get_main_location(self.database, place)
place_details = [self._("Gramps ID: %s ") % place.get_gramps_id(),
self._("Street: %s ") % location.get_street(),
self._("Parish: %s ") % location.get_parish(),
self._("Locality: %s ") % location.get_locality(),
self._("City: %s ") % location.get_city(),
self._("County: %s ") % location.get_county(),
self._("State: %s") % location.get_state(),
self._("Country: %s ") % location.get_country()]
place_details = [
self._("Gramps ID: %s ") % place.get_gramps_id(),
self._("Street: %s ") % location.get(PlaceType.STREET, ''),
self._("Parish: %s ") % location.get(PlaceType.PARISH, ''),
self._("Locality: %s ") % location.get(PlaceType.LOCALITY, ''),
self._("City: %s ") % location.get(PlaceType.CITY, ''),
self._("County: %s ") % location.get(PlaceType.COUNTY, ''),
self._("State: %s") % location.get(PlaceType.STATE, ''),
self._("Country: %s ") % location.get(PlaceType.COUNTRY, '')]
self.doc.start_paragraph("PLC-PlaceTitle")
self.doc.write_text(("%(nbr)s. %(place)s") %
{'nbr' : place_nbr,

View File

@ -30,10 +30,10 @@ from __future__ import unicode_literals
# Gramps modules
#
#-------------------------------------------------------------------------
from gramps.gui.views.listview import TEXT, MARKUP, ICON
from gramps.gui.views.listview import TEXT, ICON
from gramps.plugins.lib.libplaceview import PlaceBaseView
from gramps.gui.views.treemodels.placemodel import PlaceTreeModel, COUNTRYLEVELS
from gramps.gen.lib import Place
from gramps.gui.views.treemodels.placemodel import PlaceTreeModel
from gramps.gen.lib import Place, PlaceRef
from gramps.gen.errors import WindowActiveError
from gramps.gui.editors import EditPlace
@ -54,51 +54,35 @@ class PlaceTreeView(PlaceBaseView):
"""
A hierarchical view of the top three levels of places.
"""
COL_PLACE = 0
COL_NAME = 0
COL_ID = 1
COL_STREET = 2
COL_LOCALITY = 3
COL_CITY = 4
COL_COUNTY = 5
COL_STATE = 6
COL_COUNTRY = 7
COL_ZIP = 8
COL_PARISH = 9
COL_LAT = 10
COL_LON = 11
COL_PRIV = 12
COL_TAGS = 13
COL_CHAN = 14
COL_NAME = 15
COL_TITLE = 2
COL_TYPE = 3
COL_CODE = 4
COL_LAT = 5
COL_LON = 6
COL_PRIV = 7
COL_TAGS = 8
COL_CHAN = 9
# column definitions
COLUMNS = [
(_('Place'), MARKUP, None),
(_('Name'), TEXT, None),
(_('ID'), TEXT, None),
(_('Street'), TEXT, None),
(_('Locality'), TEXT, None),
(_('City'), TEXT, None),
(_('County'), TEXT, None),
(_('State'), TEXT, None),
(_('Country'), TEXT, None),
(_('ZIP/Postal Code'), TEXT, None),
(_('Church Parish'), TEXT, None),
(_('Title'), TEXT, None),
(_('Type'), TEXT, None),
(_('Code'), TEXT, None),
(_('Latitude'), TEXT, None),
(_('Longitude'), TEXT, None),
(_('Private'), ICON, 'gramps-lock'),
(_('Tags'), TEXT, None),
(_('Last Changed'), TEXT, None),
(_('Place Name'), TEXT, None),
]
# default setting with visible columns, order of the col, and their size
CONFIGSETTINGS = (
('columns.visible', [COL_PLACE, COL_ID, COL_STREET, COL_LOCALITY,
COL_CITY, COL_COUNTY, COL_STATE]),
('columns.rank', [COL_PLACE, COL_ID, COL_STREET, COL_LOCALITY, COL_CITY,
COL_COUNTY, COL_STATE, COL_COUNTRY, COL_ZIP,
COL_PARISH, COL_LAT, COL_LON, COL_PRIV, COL_TAGS,
COL_CHAN, COL_NAME]),
('columns.size', [250, 75, 150, 150, 150, 150, 100, 100, 100,
100, 150, 150, 40, 100, 100, 150])
('columns.visible', [COL_NAME, COL_ID, COL_TYPE, COL_CODE]),
('columns.rank', [COL_NAME, COL_ID, COL_TITLE, COL_TYPE, COL_CODE,
COL_LAT, COL_LON, COL_PRIV, COL_TAGS, COL_CHAN]),
('columns.size', [250, 75, 150, 100, 100, 150, 150, 40, 100, 100])
)
def __init__(self, pdata, dbstate, uistate):
@ -196,41 +180,16 @@ class PlaceTreeView(PlaceBaseView):
Add a new place. Attempt to get the top three levels of hierarchy from
the currently selected row.
"""
place = Place()
model, pathlist = self.selection.get_selected_rows()
level = ["", "", ""]
level1 = level2 = level3 = ""
if len(pathlist) == 1:
path = pathlist[0]
iter_ = model.get_iter(path)
if iter_:
if len(path) == 1:
level[0] = model.get_node_from_iter(iter_).name
elif len(path) == 2:
level[1] = model.get_node_from_iter(iter_).name
parent = model.iter_parent(iter_)
level[0] = model.get_node_from_iter(parent).name
elif len(path) == 3:
level[2] = model.get_node_from_iter(iter_).name
parent = model.iter_parent(iter_)
level[1] = model.get_node_from_iter(parent).name
parent = model.iter_parent(parent)
level[0] = model.get_node_from_iter(parent).name
else:
parent = model.iter_parent(iter_)
level[2] = model.get_node_from_iter(parent).name
parent = model.iter_parent(parent)
level[1] = model.get_node_from_iter(parent).name
parent = model.iter_parent(parent)
level[0] = model.get_node_from_iter(parent).name
parent_list = []
for handle in self.selected_handles():
placeref = PlaceRef()
placeref.ref = handle
parent_list.append(placeref)
for ind in [0, 1, 2]:
if level[ind] and level[ind] == COUNTRYLEVELS['default'][ind+1]:
level[ind] = ""
place.get_main_location().set_country(level[0])
place.get_main_location().set_state(level[1])
place.get_main_location().set_county(level[2])
place = Place()
if len(parent_list) > 0:
place.parent = parent_list
try:
EditPlace(self.dbstate, self.uistate, [], place)
except WindowActiveError:

View File

@ -108,7 +108,7 @@ log = logging.getLogger(".NarrativeWeb")
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.sgettext
from gramps.gen.lib import (ChildRefType, Date, EventType, FamilyRelType, Name,
NameType, Person, UrlType, NoteType,
NameType, Person, UrlType, NoteType, PlaceType,
EventRoleType, Family, Event, Place, Source,
Citation, MediaObject, Repository, Note, Tag)
from gramps.gen.lib.date import Today
@ -148,6 +148,7 @@ from gramps.gen.utils.place import conv_lat_lon
from gramps.gui.pluginmanager import GuiPluginManager
from gramps.gen.relationship import get_relationship_calculator
from gramps.gen.utils.location import get_main_location
COLLATE_LANG = glocale.collation
SORT_KEY = glocale.sort_key
@ -508,14 +509,11 @@ def get_gendex_data(database, event_ref):
if place_handle:
place = database.get_place_from_handle(place_handle)
if place:
location = place.get_main_location()
if location and not location.is_empty():
poe = ", ".join(l for l in
[
location.get_city().strip(),
location.get_state().strip(),
location.get_country().strip()
] if l)
location = get_main_location(self.dbase_, place)
poe = ", ".join(l for l in [
location.get(PlaceType.CITY, '').strip(),
location.get(PlaceType.STATE, '').strip(),
location.get(PlaceType.COUNTRY, '').strip()] if l)
return doe, poe
def format_date(date):
@ -2641,26 +2639,22 @@ class BasePage(object):
)
tbody += trow
if place.main_loc:
ml = place.get_main_location()
if ml and not ml.is_empty():
for (label, data) in [
(STREET, ml.street),
(LOCALITY, ml.locality),
(CITY, ml.city),
(PARISH, ml.parish),
(COUNTY, ml.county),
(STATE, ml.state),
(POSTAL, ml.postal),
(COUNTRY, ml.country),
(_("Telephone"), ml.phone) ]:
if data:
trow = Html("tr") + (
Html("td", label, class_ = "ColumnAttribute", inline = True),
Html("td", data, class_ = "ColumnValue", inline = True)
)
tbody += trow
ml = get_main_location(self.dbase_, place)
for (label, data) in [
(STREET, ml.get(PlaceType.STREET, '')),
(LOCALITY, ml.get(PlaceType.LOCALITY, '')),
(CITY, ml.get(PlaceType.CITY, '')),
(PARISH, ml.get(PlaceType.PARISH, '')),
(COUNTY, ml.get(PlaceType.COUNTY, '')),
(STATE, ml.get(PlaceType.STATE, '')),
(POSTAL, place.get_code()),
(COUNTRY, ml.get(PlaceType.COUNTRY, ''))]:
if data:
trow = Html("tr") + (
Html("td", label, class_ = "ColumnAttribute", inline = True),
Html("td", data, class_ = "ColumnValue", inline = True)
)
tbody += trow
altloc = place.get_alternate_locations()
if altloc:
@ -3384,7 +3378,7 @@ class PlacePages(BasePage):
place = self.dbase_.get_place_from_handle(place_handle)
if place:
place_title = place.get_title()
ml = place.get_main_location()
ml = get_main_location(self.dbase_, place)
if place_title and not place_title.isspace():
letter = get_index_letter(first_letter(place_title),
@ -3414,8 +3408,8 @@ class PlacePages(BasePage):
trow.extend(
Html("td", data or "&nbsp;", class_ =colclass, inline =True)
for (colclass, data) in [
["ColumnState", ml.state],
["ColumnCountry", ml.country] ]
["ColumnState", ml.get(PlaceType.STATE, '')],
["ColumnCountry", ml.get(PlaceType.COUNTRY, '')] ]
)
tcell1 = Html("td", class_ ="ColumnLatitude", inline =True)