Initial version
svn: r20746
This commit is contained in:
parent
e2c48ddb54
commit
0758e411fd
@ -55,19 +55,15 @@ db.
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
import sys
|
||||
if sys.version_info[0] < 3:
|
||||
import cPickle as pickle
|
||||
else:
|
||||
import pickle
|
||||
import cPickle as pickle
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps libs
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from .exceptions import DbException
|
||||
from .write import FAMILY_TBL, PLACES_TBL, SOURCES_TBL, MEDIA_TBL, \
|
||||
from exceptions import DbException
|
||||
from write import FAMILY_TBL, PLACES_TBL, LOCATION_TBL, SOURCES_TBL, MEDIA_TBL,\
|
||||
EVENTS_TBL, PERSON_TBL, REPO_TBL, NOTE_TBL, TAG_TBL, META, CITATIONS_TBL
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
@ -91,7 +87,7 @@ def backup(database):
|
||||
"""
|
||||
try:
|
||||
__do_export(database)
|
||||
except (OSError, IOError) as msg:
|
||||
except (OSError, IOError), msg:
|
||||
raise DbException(str(msg))
|
||||
|
||||
def __mk_backup_name(database, base):
|
||||
@ -159,7 +155,7 @@ def restore(database):
|
||||
"""
|
||||
try:
|
||||
__do_restore(database)
|
||||
except (OSError, IOError) as msg:
|
||||
except (OSError, IOError), msg:
|
||||
raise DbException(str(msg))
|
||||
|
||||
def __do_restore(database):
|
||||
@ -215,5 +211,6 @@ def __build_tbl_map(database):
|
||||
( MEDIA_TBL, database.media_map.db),
|
||||
( EVENTS_TBL, database.event_map.db),
|
||||
( TAG_TBL, database.tag_map.db),
|
||||
( LOCATION_TBL, database.location_map.db),
|
||||
( META, database.metadata.db),
|
||||
]
|
||||
|
@ -41,8 +41,8 @@ from ..ggettext import gettext as _
|
||||
#-------------------------------------------------------------------------
|
||||
from ..lib.childreftype import ChildRefType
|
||||
from ..lib.childref import ChildRef
|
||||
from .txn import DbTxn
|
||||
from .exceptions import DbTransactionCancel
|
||||
from txn import DbTxn
|
||||
from exceptions import DbTransactionCancel
|
||||
|
||||
class DbReadBase(object):
|
||||
"""
|
||||
@ -321,6 +321,27 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_location_cursor(self):
|
||||
"""
|
||||
Return a reference to a cursor over Location objects
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_location_from_handle(self, handle):
|
||||
"""
|
||||
Find a Location in the database from the passed handle.
|
||||
|
||||
If no such Location exists, None is returned.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_location_handles(self):
|
||||
"""
|
||||
Return a list of database handles, one handle for each Location in
|
||||
the database.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_media_attribute_types(self):
|
||||
"""
|
||||
Return a list of all Attribute types associated with Media and MediaRef
|
||||
@ -436,6 +457,12 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_number_of_locations(self):
|
||||
"""
|
||||
Return the number of locations currently in the database.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_number_of_media_objects(self):
|
||||
"""
|
||||
Return the number of media objects currently in the database.
|
||||
@ -591,6 +618,12 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_raw_location_data(self, handle):
|
||||
"""
|
||||
Return raw (serialized and pickled) Location object from handle
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_raw_note_data(self, handle):
|
||||
"""
|
||||
Return raw (serialized and pickled) Note object from handle
|
||||
@ -867,6 +900,12 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def has_location_handle(self, handle):
|
||||
"""
|
||||
Return True if the handle exists in the current Location database.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def has_name_group_key(self, name):
|
||||
"""
|
||||
Return if a key exists in the name_group table.
|
||||
@ -945,6 +984,18 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def iter_location_handles(self):
|
||||
"""
|
||||
Return an iterator over handles for Locations in the database
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def iter_locations(self):
|
||||
"""
|
||||
Return an iterator over objects for Locations in the database
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def iter_media_object_handles(self):
|
||||
"""
|
||||
Return an iterator over handles for Media in the database
|
||||
@ -1235,6 +1286,13 @@ class DbWriteBase(DbReadBase):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def add_location(self, location, transaction):
|
||||
"""
|
||||
Add a Location to the database, assigning a handle if it has not already
|
||||
been defined.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def add_note(self, obj, transaction, set_gid=True):
|
||||
"""
|
||||
Add a Note to the database, assigning internal IDs if they have
|
||||
@ -1343,6 +1401,13 @@ class DbWriteBase(DbReadBase):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def commit_location(self, location, transaction, change_time=None):
|
||||
"""
|
||||
Commit the specified Location to the database, storing the changes as
|
||||
part of the transaction.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def commit_media_object(self, obj, transaction, change_time=None):
|
||||
"""
|
||||
Commit the specified MediaObject to the database, storing the changes
|
||||
@ -1460,6 +1525,15 @@ class DbWriteBase(DbReadBase):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def remove_location(self, handle, transaction):
|
||||
"""
|
||||
Remove the Location specified by the database handle from the
|
||||
database, preserving the change in the passed transaction.
|
||||
|
||||
This method must be overridden in the derived class.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def remove_note(self, handle, transaction):
|
||||
"""
|
||||
Remove the Note specified by the database handle from the
|
||||
|
@ -30,7 +30,6 @@ Declare constants used by database modules
|
||||
# standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import sys
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -45,8 +44,8 @@ __all__ = (
|
||||
) +
|
||||
|
||||
('PERSON_KEY', 'FAMILY_KEY', 'SOURCE_KEY', 'CITATION_KEY',
|
||||
'EVENT_KEY', 'MEDIA_KEY', 'PLACE_KEY', 'REPOSITORY_KEY',
|
||||
'NOTE_KEY', 'REFERENCE_KEY', 'TAG_KEY'
|
||||
'EVENT_KEY', 'MEDIA_KEY', 'PLACE_KEY', 'LOCATION_KEY',
|
||||
'REPOSITORY_KEY', 'NOTE_KEY', 'REFERENCE_KEY', 'TAG_KEY'
|
||||
) +
|
||||
|
||||
('TXNADD', 'TXNUPD', 'TXNDEL')
|
||||
@ -61,14 +60,14 @@ DBLOGNAME = ".Db" # Name of logger
|
||||
DBMODE_R = "r" # Read-only access
|
||||
DBMODE_W = "w" # Full Read/Write access
|
||||
DBPAGE = 16384 # Size of the pages used to hold items in the database
|
||||
DBMODE = 0o666 # Unix mode for database creation
|
||||
DBMODE = 0666 # Unix mode for database creation
|
||||
DBCACHE = 0x4000000 # Size of the shared memory buffer pool
|
||||
DBLOCKS = 100000 # Maximum number of locks supported
|
||||
DBOBJECTS = 100000 # Maximum number of simultaneously locked objects
|
||||
DBUNDO = 1000 # Maximum size of undo buffer
|
||||
|
||||
from ..config import config
|
||||
if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
|
||||
if config.get('preferences.use-bsddb3'):
|
||||
from bsddb3.db import DB_CREATE, DB_AUTO_COMMIT, DB_DUP, DB_DUPSORT, DB_RDONLY
|
||||
else:
|
||||
from bsddb.db import DB_CREATE, DB_AUTO_COMMIT, DB_DUP, DB_DUPSORT, DB_RDONLY
|
||||
@ -87,5 +86,6 @@ REFERENCE_KEY = 7
|
||||
NOTE_KEY = 8
|
||||
TAG_KEY = 9
|
||||
CITATION_KEY = 10
|
||||
LOCATION_KEY = 11
|
||||
|
||||
TXNADD, TXNUPD, TXNDEL = 0, 1, 2
|
||||
|
@ -25,27 +25,21 @@
|
||||
"""
|
||||
Read classes for the GRAMPS databases.
|
||||
"""
|
||||
|
||||
from __future__ import with_statement
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# libraries
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from __future__ import print_function, with_statement
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] < 3:
|
||||
import cPickle as pickle
|
||||
else:
|
||||
import pickle
|
||||
import cPickle
|
||||
import time
|
||||
import random
|
||||
import locale
|
||||
import os
|
||||
from sys import maxsize
|
||||
from sys import maxint
|
||||
|
||||
from ..config import config
|
||||
if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
|
||||
if config.get('preferences.use-bsddb3'):
|
||||
from bsddb3 import db
|
||||
else:
|
||||
from bsddb import db
|
||||
@ -66,6 +60,7 @@ from ..lib.src import Source
|
||||
from ..lib.citation import Citation
|
||||
from ..lib.event import Event
|
||||
from ..lib.place import Place
|
||||
from ..lib.location import Location
|
||||
from ..lib.repo import Repository
|
||||
from ..lib.note import Note
|
||||
from ..lib.tag import Tag
|
||||
@ -73,13 +68,12 @@ from ..lib.genderstats import GenderStats
|
||||
from ..lib.researcher import Researcher
|
||||
from ..lib.nameorigintype import NameOriginType
|
||||
|
||||
from .dbconst import *
|
||||
from dbconst import *
|
||||
from ..utils.callback import Callback
|
||||
from ..utils.cast import conv_dbstr_to_unicode
|
||||
from . import (BsddbBaseCursor, DbReadBase)
|
||||
from ..utils.id import create_id
|
||||
from ..errors import DbError
|
||||
from ..constfunc import UNITYPE, STRTYPE, cuni
|
||||
|
||||
LOG = logging.getLogger(DBLOGNAME)
|
||||
LOG = logging.getLogger(".citation")
|
||||
@ -88,10 +82,10 @@ LOG = logging.getLogger(".citation")
|
||||
# constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .dbconst import *
|
||||
from dbconst import *
|
||||
|
||||
_SIGBASE = ('person', 'family', 'source', 'citation',
|
||||
'event', 'media', 'place', 'repository',
|
||||
'event', 'media', 'place', 'location', 'repository',
|
||||
'reference', 'note', 'tag')
|
||||
|
||||
DBERRS = (db.DBRunRecoveryError, db.DBAccessError,
|
||||
@ -105,14 +99,12 @@ DBERRS = (db.DBRunRecoveryError, db.DBAccessError,
|
||||
def find_surname(key, data):
|
||||
"""
|
||||
Creating a surname from raw data of a person, to use for sort and index
|
||||
returns a byte string
|
||||
"""
|
||||
return __index_surname(data[3][5])
|
||||
|
||||
def find_surname_name(key, data):
|
||||
"""
|
||||
Creating a surname from raw name, to use for sort and index
|
||||
returns a byte string
|
||||
"""
|
||||
return __index_surname(data[5])
|
||||
|
||||
@ -120,13 +112,12 @@ def __index_surname(surn_list):
|
||||
"""
|
||||
All non pa/matronymic surnames are used in indexing.
|
||||
pa/matronymic not as they change for every generation!
|
||||
returns a byte string
|
||||
"""
|
||||
if surn_list:
|
||||
surn = " ".join([x[0] for x in surn_list if not (x[3][0] in [
|
||||
surn = u" ".join([x[0] for x in surn_list if not (x[3][0] in [
|
||||
NameOriginType.PATRONYMIC, NameOriginType.MATRONYMIC]) ])
|
||||
else:
|
||||
surn = ""
|
||||
surn = u""
|
||||
return surn.encode('utf-8')
|
||||
|
||||
|
||||
@ -175,6 +166,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 = [None]
|
||||
while to_do:
|
||||
data = self.set(str(to_do.pop()))
|
||||
_n = self.next_dup
|
||||
while data:
|
||||
payload = cPickle.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
|
||||
@ -324,6 +341,13 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"cursor_func": self.get_tag_cursor,
|
||||
"handles_func": self.get_tag_handles,
|
||||
},
|
||||
'Location':
|
||||
{
|
||||
"handle_func": self.get_location_from_handle,
|
||||
"gramps_id_func": None,
|
||||
"class_func": Location,
|
||||
"cursor_func": self.get_location_cursor,
|
||||
},
|
||||
}
|
||||
|
||||
self.set_person_id_prefix('I%04d')
|
||||
@ -378,6 +402,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
self.nid_trans = {}
|
||||
self.eid_trans = {}
|
||||
self.tag_trans = {}
|
||||
self.loc_trans = {}
|
||||
self.env = None
|
||||
self.person_map = {}
|
||||
self.family_map = {}
|
||||
@ -436,7 +461,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
|
||||
def get_table_names(self):
|
||||
"""Return a list of valid table names."""
|
||||
return list(self._tables.keys())
|
||||
return self._tables.keys()
|
||||
|
||||
def get_table_metadata(self, table_name):
|
||||
"""Return the metadata for a valid table name."""
|
||||
@ -447,7 +472,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
def get_cursor(self, table, *args, **kwargs):
|
||||
try:
|
||||
return DbReadCursor(table, self.txn)
|
||||
except DBERRS as msg:
|
||||
except DBERRS, msg:
|
||||
self.__log_error()
|
||||
raise DbError(msg)
|
||||
|
||||
@ -481,6 +506,9 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
def get_tag_cursor(self, *args, **kwargs):
|
||||
return self.get_cursor(self.tag_map, *args, **kwargs)
|
||||
|
||||
def get_location_cursor(self, *args, **kwargs):
|
||||
return DbBsddbTreeCursor(self.parents, self.txn)
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Close the specified database.
|
||||
@ -529,18 +557,16 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
self.emit('repository-rebuild')
|
||||
self.emit('note-rebuild')
|
||||
self.emit('tag-rebuild')
|
||||
self.emit('location-rebuild')
|
||||
|
||||
def __find_next_gramps_id(self, prefix, map_index, trans):
|
||||
"""
|
||||
Helper function for find_next_<object>_gramps_id methods
|
||||
"""
|
||||
index = prefix % map_index
|
||||
#in bytes
|
||||
bindex = index.encode('utf-8')
|
||||
while trans.get(bindex, txn=self.txn) is not None:
|
||||
while trans.get(str(index), txn=self.txn) is not None:
|
||||
map_index += 1
|
||||
index = prefix % map_index
|
||||
bindex = index.encode('utf-8')
|
||||
map_index += 1
|
||||
return (map_index, index)
|
||||
|
||||
@ -626,9 +652,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
return gid
|
||||
|
||||
def get_from_handle(self, handle, class_type, data_map):
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
data = data_map.get(handle)
|
||||
data = data_map.get(str(handle))
|
||||
if data:
|
||||
newobj = class_type()
|
||||
newobj.unserialize(data)
|
||||
@ -744,11 +768,17 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
return self.get_from_handle(handle, Tag, self.tag_map)
|
||||
|
||||
def get_location_from_handle(self, handle):
|
||||
"""
|
||||
Find a Location in the database from the passed handle.
|
||||
|
||||
If no such Location exists, None is returned.
|
||||
"""
|
||||
return self.get_from_handle(handle, Location, self.location_map)
|
||||
|
||||
def __get_obj_from_gramps_id(self, val, tbl, class_, prim_tbl):
|
||||
if isinstance(val, UNITYPE):
|
||||
val = val.encode('utf-8')
|
||||
try:
|
||||
data = tbl.get(val, txn=self.txn)
|
||||
data = tbl.get(str(val), txn=self.txn)
|
||||
if data is not None:
|
||||
obj = class_()
|
||||
### FIXME: this is a dirty hack that works without no
|
||||
@ -758,12 +788,12 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
if self.readonly:
|
||||
tuple_data = prim_tbl.get(data, txn=self.txn)
|
||||
else:
|
||||
tuple_data = pickle.loads(data)
|
||||
tuple_data = cPickle.loads(data)
|
||||
obj.unserialize(tuple_data)
|
||||
return obj
|
||||
else:
|
||||
return None
|
||||
except DBERRS as msg:
|
||||
except DBERRS, msg:
|
||||
self.__log_error()
|
||||
raise DbError(msg)
|
||||
|
||||
@ -862,15 +892,17 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
Return the default grouping name for a surname.
|
||||
Return type is a unicode object
|
||||
"""
|
||||
if isinstance(surname, UNITYPE):
|
||||
surname = surname.encode('utf-8')
|
||||
return conv_dbstr_to_unicode(self.name_group.get(surname, surname))
|
||||
if isinstance(surname, unicode):
|
||||
ssurname = surname.encode('utf-8')
|
||||
return conv_dbstr_to_unicode(self.name_group.get(ssurname, ssurname))
|
||||
else:
|
||||
return conv_dbstr_to_unicode(self.name_group.get(surname, surname))
|
||||
|
||||
def get_name_group_keys(self):
|
||||
"""
|
||||
Return the defined names that have been assigned to a default grouping.
|
||||
"""
|
||||
return list(map(conv_dbstr_to_unicode, list(self.name_group.keys())))
|
||||
return map(conv_dbstr_to_unicode, self.name_group.keys())
|
||||
|
||||
def has_name_group_key(self, name):
|
||||
"""
|
||||
@ -878,9 +910,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
# The use of has_key seems allright because there is no write lock
|
||||
# on the name_group table when this is called.
|
||||
if isinstance(name, UNITYPE):
|
||||
name = name.encode('utf-8')
|
||||
return name in self.name_group
|
||||
if isinstance(name, unicode):
|
||||
return self.name_group.has_key(name.encode('utf-8'))
|
||||
else:
|
||||
return self.name_group.has_key(name)
|
||||
|
||||
def get_number_of_records(self, table):
|
||||
if not self.db_is_open:
|
||||
@ -950,6 +983,12 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
return self.get_number_of_records(self.tag_map)
|
||||
|
||||
def get_number_of_locations(self):
|
||||
"""
|
||||
Return the number of locations currently in the database.
|
||||
"""
|
||||
return self.get_number_of_records(self.location_map)
|
||||
|
||||
def all_handles(self, table):
|
||||
return table.keys(txn=self.txn)
|
||||
|
||||
@ -1074,6 +1113,15 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
return handle_list
|
||||
return []
|
||||
|
||||
def get_location_handles(self):
|
||||
"""
|
||||
Return a list of database handles, one handle for each Location in the
|
||||
database.
|
||||
"""
|
||||
if self.db_is_open:
|
||||
return self.all_handles(self.location_map)
|
||||
return []
|
||||
|
||||
def _f(curs_):
|
||||
"""
|
||||
Closure that returns an iterator over handles in the database.
|
||||
@ -1096,6 +1144,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
iter_repository_handles = _f(get_repository_cursor)
|
||||
iter_note_handles = _f(get_note_cursor)
|
||||
iter_tag_handles = _f(get_tag_cursor)
|
||||
iter_location_handles = _f(get_location_cursor)
|
||||
del _f
|
||||
|
||||
def _f(curs_, obj_):
|
||||
@ -1122,6 +1171,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
iter_repositories = _f(get_repository_cursor, Repository)
|
||||
iter_notes = _f(get_note_cursor, Note)
|
||||
iter_tags = _f(get_tag_cursor, Tag)
|
||||
iter_locations = _f(get_location_cursor, Location)
|
||||
del _f
|
||||
|
||||
def get_gramps_ids(self, obj_key):
|
||||
@ -1138,7 +1188,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
}
|
||||
|
||||
table = key2table[obj_key]
|
||||
return list(table.keys())
|
||||
return table.keys()
|
||||
|
||||
def has_gramps_id(self, obj_key, gramps_id):
|
||||
key2table = {
|
||||
@ -1154,9 +1204,8 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
}
|
||||
|
||||
table = key2table[obj_key]
|
||||
if isinstance(gramps_id, UNITYPE):
|
||||
gramps_id = gramps_id.encode('utf-8')
|
||||
return table.get(gramps_id, txn=self.txn) is not None
|
||||
#return str(gramps_id) in table
|
||||
return table.get(str(gramps_id), txn=self.txn) is not None
|
||||
|
||||
def find_initial_person(self):
|
||||
person = self.get_default_person()
|
||||
@ -1168,7 +1217,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
|
||||
@staticmethod
|
||||
def _validated_id_prefix(val, default):
|
||||
if isinstance(val, STRTYPE) and val:
|
||||
if isinstance(val, basestring) and val:
|
||||
try:
|
||||
str_ = val % 1
|
||||
except TypeError: # missing conversion specifier
|
||||
@ -1190,24 +1239,23 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
pattern_match = re.match(r"(.*)%[0 ](\d+)[diu]$", id_pattern)
|
||||
if pattern_match:
|
||||
str_prefix = pattern_match.group(1)
|
||||
##nr_width = pattern_match.group(2)
|
||||
nr_width = pattern_match.group(2)
|
||||
def closure_func(gramps_id):
|
||||
if gramps_id and gramps_id.startswith(str_prefix):
|
||||
id_number = gramps_id[len(str_prefix):]
|
||||
if id_number.isdigit():
|
||||
id_value = int(id_number, 10)
|
||||
## this code never ran, as an int compared to str with > is False!
|
||||
## if len(cuni(id_value)) > nr_width:
|
||||
## # The ID to be imported is too large to fit in the
|
||||
## # users format. For now just create a new ID,
|
||||
## # because that is also what happens with IDs that
|
||||
## # are identical to IDs already in the database. If
|
||||
## # the problem of colliding import and already
|
||||
## # present IDs is solved the code here also needs
|
||||
## # some solution.
|
||||
## gramps_id = id_pattern % 1
|
||||
## else:
|
||||
gramps_id = id_pattern % id_value
|
||||
if len(str(id_value)) > nr_width:
|
||||
# The ID to be imported is too large to fit in the
|
||||
# users format. For now just create a new ID,
|
||||
# because that is also what happens with IDs that
|
||||
# are identical to IDs already in the database. If
|
||||
# the problem of colliding import and already
|
||||
# present IDs is solved the code here also needs
|
||||
# some solution.
|
||||
gramps_id = id_pattern % 1
|
||||
else:
|
||||
gramps_id = id_pattern % id_value
|
||||
return gramps_id
|
||||
else:
|
||||
def closure_func(gramps_id):
|
||||
@ -1391,13 +1439,13 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
if person:
|
||||
return person
|
||||
elif (self.metadata is not None) and (not self.readonly):
|
||||
self.metadata[b'default'] = None
|
||||
self.metadata['default'] = None
|
||||
return None
|
||||
|
||||
def get_default_handle(self):
|
||||
"""Return the default Person of the database."""
|
||||
if self.metadata is not None:
|
||||
return self.metadata.get(b'default')
|
||||
return self.metadata.get('default')
|
||||
return None
|
||||
|
||||
def get_save_path(self):
|
||||
@ -1513,11 +1561,9 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
Helper method for get_raw_<object>_data methods
|
||||
"""
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
try:
|
||||
return table.get(handle, txn=self.txn)
|
||||
except DBERRS as msg:
|
||||
return table.get(str(handle), txn=self.txn)
|
||||
except DBERRS, msg:
|
||||
self.__log_error()
|
||||
raise DbError(msg)
|
||||
|
||||
@ -1551,15 +1597,16 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
def get_raw_tag_data(self, handle):
|
||||
return self.__get_raw_data(self.tag_map, handle)
|
||||
|
||||
def get_raw_location_data(self, handle):
|
||||
return self.__get_raw_data(self.location_map, handle)
|
||||
|
||||
def __has_handle(self, table, handle):
|
||||
"""
|
||||
Helper function for has_<object>_handle methods
|
||||
"""
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
try:
|
||||
return table.get(handle, txn=self.txn) is not None
|
||||
except DBERRS as msg:
|
||||
return table.get(str(handle), txn=self.txn) is not None
|
||||
except DBERRS, msg:
|
||||
self.__log_error()
|
||||
raise DbError(msg)
|
||||
|
||||
@ -1623,94 +1670,68 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
return self.__has_handle(self.tag_map, handle)
|
||||
|
||||
def __sortbyperson_key(self, handle):
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
return locale.strxfrm(find_surname(handle,
|
||||
self.person_map.get(handle)))
|
||||
def has_location_handle(self, handle):
|
||||
"""
|
||||
Return True if the handle exists in the current Location database.
|
||||
"""
|
||||
return self.__has_handle(self.location_map, handle)
|
||||
|
||||
def __sortbyperson_key(self, person):
|
||||
return locale.strxfrm(find_surname(str(person),
|
||||
self.person_map.get(str(person))))
|
||||
|
||||
def __sortbyplace(self, first, second):
|
||||
if isinstance(first, UNITYPE):
|
||||
first = first.encode('utf-8')
|
||||
if isinstance(second, UNITYPE):
|
||||
second = second.encode('utf-8')
|
||||
return locale.strcoll(self.place_map.get(first)[2],
|
||||
self.place_map.get(second)[2])
|
||||
return locale.strcoll(self.place_map.get(str(first))[2],
|
||||
self.place_map.get(str(second))[2])
|
||||
|
||||
def __sortbyplace_key(self, place):
|
||||
if isinstance(place, UNITYPE):
|
||||
place = place.encode('utf-8')
|
||||
return locale.strxfrm(self.place_map.get(place)[2])
|
||||
return locale.strxfrm(self.place_map.get(str(place))[2])
|
||||
|
||||
def __sortbysource(self, first, second):
|
||||
if isinstance(first, UNITYPE):
|
||||
first = first.encode('utf-8')
|
||||
if isinstance(second, UNITYPE):
|
||||
second = second.encode('utf-8')
|
||||
source1 = cuni(self.source_map[first][2])
|
||||
source2 = cuni(self.source_map[second][2])
|
||||
source1 = unicode(self.source_map[str(first)][2])
|
||||
source2 = unicode(self.source_map[str(second)][2])
|
||||
return locale.strcoll(source1, source2)
|
||||
|
||||
def __sortbysource_key(self, key):
|
||||
if isinstance(key, UNITYPE):
|
||||
key = key.encode('utf-8')
|
||||
source = cuni(self.source_map[key][2])
|
||||
source = unicode(self.source_map[str(key)][2])
|
||||
return locale.strxfrm(source)
|
||||
|
||||
def __sortbycitation(self, first, second):
|
||||
if isinstance(first, UNITYPE):
|
||||
first = first.encode('utf-8')
|
||||
if isinstance(second, UNITYPE):
|
||||
second = second.encode('utf-8')
|
||||
citation1 = cuni(self.citation_map[first][3])
|
||||
citation2 = cuni(self.citation_map[second][3])
|
||||
citation1 = unicode(self.citation_map[str(first)][3])
|
||||
citation2 = unicode(self.citation_map[str(second)][3])
|
||||
return locale.strcoll(citation1, citation2)
|
||||
|
||||
def __sortbycitation_key(self, key):
|
||||
if isinstance(key, UNITYPE):
|
||||
key = key.encode('utf-8')
|
||||
citation = cuni(self.citation_map[key][3])
|
||||
citation = unicode(self.citation_map[str(key)][3])
|
||||
return locale.strxfrm(citation)
|
||||
|
||||
def __sortbymedia(self, first, second):
|
||||
if isinstance(first, UNITYPE):
|
||||
first = first.encode('utf-8')
|
||||
if isinstance(second, UNITYPE):
|
||||
second = second.encode('utf-8')
|
||||
media1 = self.media_map[first][4]
|
||||
media2 = self.media_map[second][4]
|
||||
media1 = self.media_map[str(first)][4]
|
||||
media2 = self.media_map[str(second)][4]
|
||||
return locale.strcoll(media1, media2)
|
||||
|
||||
def __sortbymedia_key(self, key):
|
||||
if isinstance(key, UNITYPE):
|
||||
key = key.encode('utf-8')
|
||||
media = self.media_map[key][4]
|
||||
media = self.media_map[str(key)][4]
|
||||
return locale.strxfrm(media)
|
||||
|
||||
def __sortbytag(self, first, second):
|
||||
if isinstance(first, UNITYPE):
|
||||
first = first.encode('utf-8')
|
||||
if isinstance(second, UNITYPE):
|
||||
second = second.encode('utf-8')
|
||||
tag1 = self.tag_map[first][1]
|
||||
tag2 = self.tag_map[second][1]
|
||||
tag1 = self.tag_map[str(first)][1]
|
||||
tag2 = self.tag_map[str(second)][1]
|
||||
return locale.strcoll(tag1, tag2)
|
||||
|
||||
def __sortbytag_key(self, key):
|
||||
if isinstance(key, UNITYPE):
|
||||
key = key.encode('utf-8')
|
||||
tag = self.tag_map[key][1]
|
||||
tag = self.tag_map[str(key)][1]
|
||||
return locale.strxfrm(tag)
|
||||
|
||||
def set_mediapath(self, path):
|
||||
"""Set the default media path for database, path should be utf-8."""
|
||||
if (self.metadata is not None) and (not self.readonly):
|
||||
self.metadata[b'mediapath'] = path
|
||||
self.metadata['mediapath'] = path
|
||||
|
||||
def get_mediapath(self):
|
||||
"""Return the default media path of the database."""
|
||||
if self.metadata is not None:
|
||||
return self.metadata.get(b'mediapath', None)
|
||||
return self.metadata.get('mediapath', None)
|
||||
return None
|
||||
|
||||
def find_backlink_handles(self, handle, include_classes=None):
|
||||
@ -1779,17 +1800,21 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
'cursor_func': self.get_tag_cursor,
|
||||
'class_func': Tag,
|
||||
},
|
||||
'Location': {
|
||||
'cursor_func': self.get_location_cursor,
|
||||
'class_func': Location,
|
||||
},
|
||||
}
|
||||
|
||||
# Find which tables to iterate over
|
||||
if (include_classes is None):
|
||||
the_tables = list(primary_tables.keys())
|
||||
the_tables = primary_tables.keys()
|
||||
else:
|
||||
the_tables = include_classes
|
||||
|
||||
# Now we use the functions and classes defined above to loop through
|
||||
# each of the existing primary object tables
|
||||
for primary_table_name, funcs in the_tables.items():
|
||||
for primary_table_name, funcs in the_tables.iteritems():
|
||||
with funcs['cursor_func']() as cursor:
|
||||
|
||||
# Grab the real object class here so that the lookup does
|
||||
@ -1834,7 +1859,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
name_file = open(filepath, "r")
|
||||
name = name_file.read()
|
||||
name_file.close()
|
||||
except (OSError, IOError) as msg:
|
||||
except (OSError, IOError), msg:
|
||||
self.__log_error()
|
||||
name = None
|
||||
return name
|
||||
|
@ -31,18 +31,13 @@ undos and redos.
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from __future__ import print_function, with_statement
|
||||
|
||||
from __future__ import with_statement
|
||||
import time, os
|
||||
import sys
|
||||
if sys.version_info[0] < 3:
|
||||
import cPickle as pickle
|
||||
else:
|
||||
import pickle
|
||||
import cPickle as pickle
|
||||
from collections import deque
|
||||
|
||||
from ..config import config
|
||||
if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
|
||||
if config.get('preferences.use-bsddb3'):
|
||||
from bsddb3 import db
|
||||
else:
|
||||
from bsddb import db
|
||||
@ -53,7 +48,7 @@ from ..ggettext import gettext as _
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .dbconst import *
|
||||
from dbconst import *
|
||||
from . import BSDDBTxn
|
||||
from ..errors import DbError
|
||||
|
||||
@ -65,8 +60,8 @@ from ..errors import DbError
|
||||
DBERRS = (db.DBRunRecoveryError, db.DBAccessError,
|
||||
db.DBPageNotFoundError, db.DBInvalidArgError)
|
||||
|
||||
_SIGBASE = ('person', 'family', 'source', 'event', 'media',
|
||||
'place', 'repository', 'reference', 'note', 'tag', 'citation')
|
||||
_SIGBASE = ('person', 'family', 'source', 'event', 'media', 'place',
|
||||
'location', 'repository', 'reference', 'note', 'tag', 'citation')
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# DbUndo class
|
||||
@ -104,6 +99,7 @@ class DbUndo(object):
|
||||
self.db.note_map,
|
||||
self.db.tag_map,
|
||||
self.db.citation_map,
|
||||
self.db.location_map,
|
||||
)
|
||||
|
||||
def clear(self):
|
||||
@ -212,7 +208,7 @@ class DbUndo(object):
|
||||
self.db.txn = None
|
||||
return status
|
||||
|
||||
except DBERRS as msg:
|
||||
except DBERRS, msg:
|
||||
self.db._log_error()
|
||||
raise DbError(msg)
|
||||
|
||||
@ -305,7 +301,7 @@ class DbUndo(object):
|
||||
else:
|
||||
db_map.put(handle, data, txn=self.txn)
|
||||
|
||||
except DBERRS as msg:
|
||||
except DBERRS, msg:
|
||||
self.db._log_error()
|
||||
raise DbError(msg)
|
||||
|
||||
@ -326,7 +322,7 @@ class DbUndo(object):
|
||||
db_map.put(handle, data, txn=self.txn)
|
||||
emit(signal, ([handle],))
|
||||
|
||||
except DBERRS as msg:
|
||||
except DBERRS, msg:
|
||||
self.db._log_error()
|
||||
raise DbError(msg)
|
||||
|
||||
@ -459,7 +455,7 @@ class DbUndoBSDDB(DbUndo):
|
||||
data = cursor.first()
|
||||
while data:
|
||||
yield data
|
||||
data = next(cursor)
|
||||
data = cursor.next()
|
||||
|
||||
def testundo():
|
||||
class T:
|
||||
@ -479,35 +475,36 @@ def testundo():
|
||||
self.place_map = {}
|
||||
self.note_map = {}
|
||||
self.tag_map = {}
|
||||
self.location_map = {}
|
||||
self.repository_map = {}
|
||||
self.reference_map = {}
|
||||
|
||||
print("list tests")
|
||||
print "list tests"
|
||||
undo = DbUndoList(D())
|
||||
print(undo.append('foo'))
|
||||
print(undo.append('bar'))
|
||||
print(undo[0])
|
||||
print undo.append('foo')
|
||||
print undo.append('bar')
|
||||
print undo[0]
|
||||
undo[0] = 'foobar'
|
||||
print(undo[0])
|
||||
print("len", len(undo))
|
||||
print("iter")
|
||||
print undo[0]
|
||||
print "len", len(undo)
|
||||
print "iter"
|
||||
for data in undo:
|
||||
print(data)
|
||||
print()
|
||||
print("bsddb tests")
|
||||
print data
|
||||
print
|
||||
print "bsddb tests"
|
||||
undo = DbUndoBSDDB(D(), '/tmp/testundo')
|
||||
undo.open()
|
||||
print(undo.append('foo'))
|
||||
print(undo.append('fo2'))
|
||||
print(undo.append('fo3'))
|
||||
print(undo[1])
|
||||
print undo.append('foo')
|
||||
print undo.append('fo2')
|
||||
print undo.append('fo3')
|
||||
print undo[1]
|
||||
undo[1] = 'bar'
|
||||
print(undo[1])
|
||||
print undo[1]
|
||||
for data in undo:
|
||||
print(data)
|
||||
print("len", len(undo))
|
||||
print data
|
||||
print "len", len(undo)
|
||||
|
||||
print("test commit")
|
||||
print "test commit"
|
||||
undo.commit(T(), msg="test commit")
|
||||
undo.close()
|
||||
|
||||
|
@ -21,9 +21,8 @@
|
||||
|
||||
# $Id$
|
||||
|
||||
from __future__ import with_statement, unicode_literals
|
||||
from __future__ import with_statement
|
||||
|
||||
import sys
|
||||
from ..lib.markertype import MarkerType
|
||||
from ..lib.tag import Tag
|
||||
import time
|
||||
@ -31,23 +30,87 @@ import logging
|
||||
LOG = logging.getLogger(".citation")
|
||||
|
||||
from ..ggettext import gettext as _
|
||||
from ..constfunc import cuni
|
||||
|
||||
"""
|
||||
methods to upgrade a database from version 13 to current version
|
||||
"""
|
||||
from ..config import config
|
||||
if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
|
||||
if config.get('preferences.use-bsddb3'):
|
||||
from bsddb3 import db
|
||||
else:
|
||||
from bsddb import db
|
||||
from . import BSDDBTxn
|
||||
from ..lib.nameorigintype import NameOriginType
|
||||
from .write import _mkname, SURNAMES
|
||||
from .dbconst import (PERSON_KEY, FAMILY_KEY, EVENT_KEY,
|
||||
MEDIA_KEY, PLACE_KEY, REPOSITORY_KEY)
|
||||
from write import _mkname, SURNAMES
|
||||
from dbconst import (PERSON_KEY, FAMILY_KEY, EVENT_KEY,
|
||||
MEDIA_KEY, PLACE_KEY, LOCATION_KEY, REPOSITORY_KEY)
|
||||
from gramps.gui.dialog import (InfoDialog)
|
||||
|
||||
def gramps_upgrade_17(self):
|
||||
self.set_total(len(self.place_map))
|
||||
self.children = {None: []}
|
||||
for handle in self.place_map.keys():
|
||||
place = self.place_map[handle]
|
||||
new_place = list(place)
|
||||
lat_long = (new_place[4], new_place[3])
|
||||
if new_place[5] is not None:
|
||||
new_place[5] = process_location(self, new_place[5], lat_long)
|
||||
else:
|
||||
new_place[5] = process_location(self, None, lat_long)
|
||||
add_reference(self, handle, new_place[5])
|
||||
alt_locs = []
|
||||
for alt_loc in new_place[6]:
|
||||
ref_handle = process_location(self, alt_loc, lat_long)
|
||||
add_reference(self, handle, ref_handle)
|
||||
alt_locs.append(ref_handle)
|
||||
new_place[6] = alt_locs
|
||||
new_place = tuple(new_place[:3] + new_place[5:])
|
||||
with BSDDBTxn(self.env, self.place_map) as txn:
|
||||
txn.put(str(handle), new_place)
|
||||
self.update()
|
||||
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put('version', 17)
|
||||
|
||||
def add_reference(self, pri_handle, ref_handle):
|
||||
key = (PLACE_KEY, pri_handle)
|
||||
data = ((PLACE_KEY, pri_handle), (LOCATION_KEY, ref_handle))
|
||||
with BSDDBTxn(self.env, self.reference_map) as txn:
|
||||
txn.put(str(key), data)
|
||||
|
||||
def process_location(self, loc, lat_long):
|
||||
if loc is None:
|
||||
location = ['Unknown']
|
||||
else:
|
||||
# (street, locality, parish, city, county, state, country)
|
||||
# We need to think about where to put ZIP code and Phone number
|
||||
location = loc[0][:2] + (loc[1],) + loc[0][2:6]
|
||||
location = list(location)
|
||||
location.reverse()
|
||||
items = [x for x in enumerate(location) if x[1]]
|
||||
parent = None
|
||||
for item in items:
|
||||
parent = match_location(self, parent, item, lat_long)
|
||||
return parent
|
||||
|
||||
def match_location(self, parent, item, lat_long):
|
||||
for handle in self.children[parent]:
|
||||
if self.location_map[handle][2] == item[1]:
|
||||
return handle
|
||||
handle = self.create_id()
|
||||
self.children[handle] = []
|
||||
self.children[parent].append(handle)
|
||||
new_location = (handle,
|
||||
parent,
|
||||
item[1], # Name
|
||||
item[0]+1, # Type
|
||||
lat_long[0],
|
||||
lat_long[1],
|
||||
int(time.time()))
|
||||
with BSDDBTxn(self.env, self.location_map) as txn:
|
||||
txn.put(str(handle), new_location)
|
||||
return handle
|
||||
|
||||
def gramps_upgrade_16(self):
|
||||
"""Upgrade database from version 15 to 16. This upgrade converts all
|
||||
SourceRef child objects to Citation Primary objects.
|
||||
@ -148,10 +211,10 @@ def gramps_upgrade_16(self):
|
||||
self.update()
|
||||
|
||||
LOG.debug("%d persons upgraded with %d citations in %d seconds. " %
|
||||
(len(list(self.person_map.keys())),
|
||||
(len(self.person_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time))
|
||||
data_upgradeobject[key2data[PERSON_KEY]] = (len(list(self.person_map.keys())),
|
||||
data_upgradeobject[key2data[PERSON_KEY]] = (len(self.person_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time)
|
||||
|
||||
@ -184,7 +247,7 @@ def gramps_upgrade_16(self):
|
||||
LOG.debug("Media upgrade %d citations upgraded in %d seconds" %
|
||||
(self.cmap_index - start_num_citations,
|
||||
int(time.time() - start_time)))
|
||||
data_upgradeobject[key2data[MEDIA_KEY]] = (len(list(self.media_map.keys())),
|
||||
data_upgradeobject[key2data[MEDIA_KEY]] = (len(self.media_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time)
|
||||
|
||||
@ -195,7 +258,7 @@ def gramps_upgrade_16(self):
|
||||
start_time = time.time()
|
||||
for place_handle in self.place_map.keys():
|
||||
place = self.place_map[place_handle]
|
||||
(handle, gramps_id, title, int, lat,
|
||||
(handle, gramps_id, title, long, lat,
|
||||
main_loc, alt_loc, urls, media_list, source_list, note_list,
|
||||
change, private) = place
|
||||
if source_list:
|
||||
@ -208,7 +271,7 @@ def gramps_upgrade_16(self):
|
||||
self, media_list)
|
||||
if source_list or media_list:
|
||||
new_place = (handle, gramps_id, title,
|
||||
int, lat, main_loc, alt_loc, urls,
|
||||
long, lat, main_loc, alt_loc, urls,
|
||||
media_list, new_citation_list, note_list,
|
||||
change, private)
|
||||
with BSDDBTxn(self.env, self.place_map) as txn:
|
||||
@ -216,10 +279,10 @@ def gramps_upgrade_16(self):
|
||||
self.update()
|
||||
|
||||
LOG.debug("%d places upgraded with %d citations in %d seconds. " %
|
||||
(len(list(self.place_map.keys())),
|
||||
(len(self.place_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time))
|
||||
data_upgradeobject[key2data[PLACE_KEY]] = (len(list(self.place_map.keys())),
|
||||
data_upgradeobject[key2data[PLACE_KEY]] = (len(self.place_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time)
|
||||
|
||||
@ -264,10 +327,10 @@ def gramps_upgrade_16(self):
|
||||
self.update()
|
||||
|
||||
LOG.debug("%d familys upgraded with %d citations in %d seconds. " %
|
||||
(len(list(self.family_map.keys())),
|
||||
(len(self.family_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time))
|
||||
data_upgradeobject[key2data[FAMILY_KEY]] = (len(list(self.family_map.keys())),
|
||||
data_upgradeobject[key2data[FAMILY_KEY]] = (len(self.family_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time)
|
||||
# ---------------------------------
|
||||
@ -309,10 +372,10 @@ def gramps_upgrade_16(self):
|
||||
|
||||
LOG.debug("%d events upgraded with %d citations in %d seconds. "
|
||||
"Backlinks took %d seconds" %
|
||||
(len(list(self.event_map.keys())),
|
||||
(len(self.event_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
int(upgrade_time), int(backlink_time)))
|
||||
data_upgradeobject[key2data[EVENT_KEY]] = (len(list(self.event_map.keys())),
|
||||
data_upgradeobject[key2data[EVENT_KEY]] = (len(self.event_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time)
|
||||
|
||||
@ -336,10 +399,10 @@ def gramps_upgrade_16(self):
|
||||
self.update()
|
||||
|
||||
LOG.debug("%d repositorys upgraded with %d citations in %d seconds. " %
|
||||
(len(list(self.repository_map.keys())),
|
||||
(len(self.repository_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time))
|
||||
data_upgradeobject[key2data[REPOSITORY_KEY]] = (len(list(self.repository_map.keys())),
|
||||
data_upgradeobject[key2data[REPOSITORY_KEY]] = (len(self.repository_map.keys()),
|
||||
self.cmap_index - start_num_citations,
|
||||
time.time() - start_time)
|
||||
# ---------------------------------
|
||||
@ -594,9 +657,9 @@ def gramps_upgrade_15(self):
|
||||
tags = [tag_handle]
|
||||
else:
|
||||
tags = []
|
||||
address_list = list(map(convert_address, address_list))
|
||||
address_list = map(convert_address, address_list)
|
||||
new_primary_name = convert_name_15(primary_name)
|
||||
new_alternate_names = list(map(convert_name_15, alternate_names))
|
||||
new_alternate_names = map(convert_name_15, alternate_names)
|
||||
new_person = (junk_handle, # 0
|
||||
gramps_id, # 1
|
||||
gender, # 2
|
||||
@ -700,7 +763,7 @@ def gramps_upgrade_15(self):
|
||||
new_place = list(place)
|
||||
if new_place[5] is not None:
|
||||
new_place[5] = convert_location(new_place[5])
|
||||
new_place[6] = list(map(convert_location, new_place[6]))
|
||||
new_place[6] = map(convert_location, new_place[6])
|
||||
new_place = new_place[:12] + new_place[13:]
|
||||
new_place = tuple(new_place)
|
||||
with BSDDBTxn(self.env, self.place_map) as txn:
|
||||
@ -728,7 +791,7 @@ def gramps_upgrade_15(self):
|
||||
repository = self.repository_map[handle]
|
||||
new_repository = list(repository)
|
||||
new_repository = new_repository[:8] + new_repository[9:]
|
||||
new_repository[5] = list(map(convert_address, new_repository[5]))
|
||||
new_repository[5] = map(convert_address, new_repository[5])
|
||||
new_repository = tuple(new_repository)
|
||||
with BSDDBTxn(self.env, self.repository_map) as txn:
|
||||
txn.put(str(handle), new_repository)
|
||||
@ -742,7 +805,7 @@ def convert_marker(self, marker_field):
|
||||
"""Convert a marker into a tag."""
|
||||
marker = MarkerType()
|
||||
marker.unserialize(marker_field)
|
||||
tag_name = cuni(marker)
|
||||
tag_name = unicode(marker)
|
||||
|
||||
if tag_name != '':
|
||||
if tag_name not in self.tags:
|
||||
@ -761,7 +824,7 @@ def convert_marker(self, marker_field):
|
||||
|
||||
def convert_locbase(loc):
|
||||
"""Convert location base to include an empty locality field."""
|
||||
return tuple([loc[0], ''] + list(loc[1:]))
|
||||
return tuple([loc[0], u''] + list(loc[1:]))
|
||||
|
||||
def convert_location(loc):
|
||||
"""Convert a location into the new format."""
|
||||
@ -777,26 +840,26 @@ def convert_name_15(name):
|
||||
name_type, prefix, patronymic,
|
||||
group_as, sort_as, display_as, call) = name
|
||||
|
||||
connector = ""
|
||||
origintype = (NameOriginType.NONE, "")
|
||||
patorigintype = (NameOriginType.PATRONYMIC, "")
|
||||
connector = u""
|
||||
origintype = (NameOriginType.NONE, u"")
|
||||
patorigintype = (NameOriginType.PATRONYMIC, u"")
|
||||
|
||||
if patronymic.strip() == "":
|
||||
if patronymic.strip() == u"":
|
||||
#no patronymic, create a single surname
|
||||
surname_list = [(surname, prefix, True, origintype, connector)]
|
||||
else:
|
||||
#a patronymic, if no surname or equal as patronymic, a single surname
|
||||
if (surname.strip() == "") or (surname == patronymic and prefix == ""):
|
||||
if (surname.strip() == u"") or (surname == patronymic and prefix == u""):
|
||||
surname_list = [(patronymic, prefix, True, patorigintype, connector)]
|
||||
else:
|
||||
#two surnames, first patronymic, then surname which is primary
|
||||
surname_list = [(patronymic, "", False, patorigintype, ""),
|
||||
surname_list = [(patronymic, u"", False, patorigintype, u""),
|
||||
(surname, prefix, True, origintype, connector)]
|
||||
|
||||
#return new value, add two empty strings for nick and family nick
|
||||
return (privacy, source_list, note_list, date,
|
||||
first_name, surname_list, suffix, title, name_type,
|
||||
group_as, sort_as, display_as, call, "", "")
|
||||
group_as, sort_as, display_as, call, u"", u"")
|
||||
|
||||
def gramps_upgrade_14(self):
|
||||
"""Upgrade database from version 13 to 14."""
|
||||
@ -1004,12 +1067,12 @@ def gramps_upgrade_14(self):
|
||||
# ---------------------------------
|
||||
for place_handle in self.place_map.keys():
|
||||
place = self.place_map[place_handle]
|
||||
(handle, gramps_id, title, int, lat,
|
||||
(handle, gramps_id, title, long, lat,
|
||||
main_loc, alt_loc, urls, media_list, source_list, note_list,
|
||||
change, marker, private) = place
|
||||
new_media_list = new_media_list_14(media_list)
|
||||
new_source_list = new_source_list_14(source_list)
|
||||
new_place = (handle, gramps_id, title, int, lat,
|
||||
new_place = (handle, gramps_id, title, long, lat,
|
||||
main_loc, alt_loc, urls, new_media_list,
|
||||
new_source_list, note_list, change, marker, private)
|
||||
|
||||
|
@ -32,23 +32,19 @@ This is used since GRAMPS version 3.0
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from __future__ import print_function, with_statement
|
||||
import sys
|
||||
if sys.version_info[0] < 3:
|
||||
import cPickle as pickle
|
||||
else:
|
||||
import pickle
|
||||
from __future__ import with_statement
|
||||
import cPickle as pickle
|
||||
import os
|
||||
import time
|
||||
import locale
|
||||
import bisect
|
||||
from functools import wraps
|
||||
import logging
|
||||
from sys import maxsize
|
||||
from sys import maxint
|
||||
|
||||
from ..ggettext import gettext as _
|
||||
from ..config import config
|
||||
if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
|
||||
if config.get('preferences.use-bsddb3'):
|
||||
from bsddb3 import dbshelve, db
|
||||
else:
|
||||
from bsddb import dbshelve, db
|
||||
@ -64,6 +60,7 @@ from ..lib.src import Source
|
||||
from ..lib.citation import Citation
|
||||
from ..lib.event import Event
|
||||
from ..lib.place import Place
|
||||
from ..lib.location import Location
|
||||
from ..lib.repo import Repository
|
||||
from ..lib.mediaobj import MediaObject
|
||||
from ..lib.note import Note
|
||||
@ -75,17 +72,17 @@ from . import (DbBsddbRead, DbWriteBase, BSDDBTxn,
|
||||
DbTxn, BsddbBaseCursor, BsddbDowngradeError, DbVersionError,
|
||||
DbEnvironmentError, DbUpgradeRequiredError, find_surname,
|
||||
find_surname_name, DbUndoBSDDB as DbUndo)
|
||||
from .dbconst import *
|
||||
from dbconst import *
|
||||
from ..utils.callback import Callback
|
||||
from ..utils.cast import (conv_unicode_tosrtkey, conv_dbstr_to_unicode)
|
||||
from ..updatecallback import UpdateCallback
|
||||
from ..errors import DbError
|
||||
from ..constfunc import win, conv_to_unicode, cuni, UNITYPE
|
||||
from ..constfunc import win
|
||||
|
||||
_LOG = logging.getLogger(DBLOGNAME)
|
||||
LOG = logging.getLogger(".citation")
|
||||
_MINVERSION = 9
|
||||
_DBVERSION = 16
|
||||
_DBVERSION = 17
|
||||
|
||||
IDTRANS = "person_id"
|
||||
FIDTRANS = "family_id"
|
||||
@ -97,6 +94,8 @@ NIDTRANS = "note_id"
|
||||
SIDTRANS = "source_id"
|
||||
CIDTRANS = "citation_id"
|
||||
TAGTRANS = "tag_name"
|
||||
LPARENTS = "location_parent"
|
||||
LNAMES = "location_name"
|
||||
SURNAMES = "surnames"
|
||||
NAME_GROUP = "name_group"
|
||||
META = "meta_data"
|
||||
@ -111,6 +110,7 @@ PERSON_TBL = "person"
|
||||
REPO_TBL = "repo"
|
||||
NOTE_TBL = "note"
|
||||
TAG_TBL = "tag"
|
||||
LOCATION_TBL = "location"
|
||||
|
||||
REF_MAP = "reference_map"
|
||||
REF_PRI = "primary_map"
|
||||
@ -134,7 +134,8 @@ CLASS_TO_KEY_MAP = {Person.__name__: PERSON_KEY,
|
||||
Place.__name__: PLACE_KEY,
|
||||
Repository.__name__:REPOSITORY_KEY,
|
||||
Note.__name__: NOTE_KEY,
|
||||
Tag.__name__: TAG_KEY}
|
||||
Tag.__name__: TAG_KEY,
|
||||
Location.__name__: LOCATION_KEY}
|
||||
|
||||
KEY_TO_CLASS_MAP = {PERSON_KEY: Person.__name__,
|
||||
FAMILY_KEY: Family.__name__,
|
||||
@ -145,7 +146,8 @@ KEY_TO_CLASS_MAP = {PERSON_KEY: Person.__name__,
|
||||
PLACE_KEY: Place.__name__,
|
||||
REPOSITORY_KEY: Repository.__name__,
|
||||
NOTE_KEY: Note.__name__,
|
||||
TAG_KEY: Tag.__name__}
|
||||
TAG_KEY: Tag.__name__,
|
||||
LOCATION_KEY: Location.__name__}
|
||||
|
||||
KEY_TO_NAME_MAP = {PERSON_KEY: 'person',
|
||||
FAMILY_KEY: 'family',
|
||||
@ -157,7 +159,8 @@ KEY_TO_NAME_MAP = {PERSON_KEY: 'person',
|
||||
REPOSITORY_KEY: 'repository',
|
||||
#REFERENCE_KEY: 'reference',
|
||||
NOTE_KEY: 'note',
|
||||
TAG_KEY: 'tag'}
|
||||
TAG_KEY: 'tag',
|
||||
LOCATION_KEY: 'location'}
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Helper functions
|
||||
@ -165,13 +168,13 @@ KEY_TO_NAME_MAP = {PERSON_KEY: 'person',
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
def find_idmap(key, data):
|
||||
""" return id for association of secondary index.
|
||||
returns a byte string
|
||||
"""
|
||||
val = data[1]
|
||||
if isinstance(val, UNITYPE):
|
||||
val = val.encode('utf-8')
|
||||
return val
|
||||
return str(data[1])
|
||||
|
||||
def find_parent(key, data):
|
||||
return str(data[1])
|
||||
|
||||
def find_name(key, data):
|
||||
return str(data[2]).upper()
|
||||
|
||||
# Secondary database key lookups for reference_map table
|
||||
# reference_map data values are of the form:
|
||||
@ -179,22 +182,10 @@ def find_idmap(key, data):
|
||||
# (referenced_object_class_name, referenced_object_handle))
|
||||
|
||||
def find_primary_handle(key, data):
|
||||
""" return handle for association of indexes
|
||||
returns byte string
|
||||
"""
|
||||
val = (data)[0][1]
|
||||
if isinstance(val, UNITYPE):
|
||||
val = val.encode('utf-8')
|
||||
return val
|
||||
return str((data)[0][1])
|
||||
|
||||
def find_referenced_handle(key, data):
|
||||
""" return handle for association of indexes
|
||||
returns byte string
|
||||
"""
|
||||
val = (data)[1][1]
|
||||
if isinstance(val, UNITYPE):
|
||||
val = val.encode('utf-8')
|
||||
return val
|
||||
return str((data)[1][1])
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -219,7 +210,7 @@ class DbBsddbAssocCursor(BsddbBaseCursor):
|
||||
BsddbBaseCursor.__init__(self, txn=txn, **kwargs)
|
||||
self.cursor = source.cursor(txn)
|
||||
self.source = source
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# DbBsddb
|
||||
@ -235,7 +226,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
# 1. Signals for primary objects
|
||||
__signals__ = dict((obj+'-'+op, signal)
|
||||
for obj in
|
||||
['person', 'family', 'event', 'place',
|
||||
['person', 'family', 'event', 'place', 'location',
|
||||
'source', 'citation', 'media', 'note', 'repository', 'tag']
|
||||
for op, signal in zip(
|
||||
['add', 'update', 'delete', 'rebuild'],
|
||||
@ -252,11 +243,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
# 3. Special signal for change in home person
|
||||
__signals__['home-person-changed'] = None
|
||||
|
||||
# 4. Signal for change in person group name, parameters are
|
||||
if sys.version_info[0] < 3:
|
||||
__signals__['person-groupname-rebuild'] = (unicode, unicode)
|
||||
else:
|
||||
__signals__['person-groupname-rebuild'] = (str, str)
|
||||
# 4. Signal for change in person group name, parameters are
|
||||
__signals__['person-groupname-rebuild'] = (unicode, unicode)
|
||||
|
||||
def __init__(self):
|
||||
"""Create a new GrampsDB."""
|
||||
@ -280,7 +268,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
def try_(self, *args, **kwargs):
|
||||
try:
|
||||
return func(self, *args, **kwargs)
|
||||
except DBERRS as msg:
|
||||
except DBERRS, msg:
|
||||
self.__log_error()
|
||||
raise DbError(msg)
|
||||
return try_
|
||||
@ -363,19 +351,30 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
return DbBsddbAssocCursor(self.reference_map_referenced_map,
|
||||
self.txn)
|
||||
|
||||
@catch_db_error
|
||||
def get_location_parent_cursor(self):
|
||||
"""
|
||||
Returns a reference to a cursor over the location parents
|
||||
"""
|
||||
return DbBsddbAssocCursor(self.parents, self.txn)
|
||||
|
||||
@catch_db_error
|
||||
def get_location_name_cursor(self):
|
||||
"""
|
||||
Returns a reference to a cursor over the location names
|
||||
"""
|
||||
return DbBsddbAssocCursor(self.names, self.txn)
|
||||
|
||||
# These are overriding the DbBsddbRead's methods of saving metadata
|
||||
# because we now have txn-capable metadata table
|
||||
|
||||
@catch_db_error
|
||||
def set_default_person_handle(self, handle):
|
||||
"""Set the default Person to the passed instance."""
|
||||
#we store a byte string!
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
if not self.readonly:
|
||||
# Start transaction
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'default', handle)
|
||||
txn.put('default', str(handle))
|
||||
self.emit('home-person-changed')
|
||||
|
||||
@catch_db_error
|
||||
@ -387,7 +386,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
elif (self.metadata) and (not self.readonly):
|
||||
# Start transaction
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'default', None)
|
||||
txn.put('default', None)
|
||||
return None
|
||||
|
||||
def set_mediapath(self, path):
|
||||
@ -395,7 +394,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
if self.metadata and not self.readonly:
|
||||
# Start transaction
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'mediapath', path)
|
||||
txn.put('mediapath', path)
|
||||
|
||||
def __check_bdb_version(self, name):
|
||||
"""Older version of Berkeley DB can't read data created by a newer
|
||||
@ -410,9 +409,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
except:
|
||||
# Just assume that the Berkeley DB version is OK.
|
||||
pass
|
||||
if not env_version:
|
||||
#empty file, assume it is ok to open
|
||||
env_version = (0, 0, 0)
|
||||
if (env_version[0] > bdb_version[0]) or \
|
||||
(env_version[0] == bdb_version[0] and
|
||||
env_version[1] > bdb_version[1]):
|
||||
@ -423,12 +419,12 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
|
||||
@catch_db_error
|
||||
def version_supported(self):
|
||||
dbversion = self.metadata.get(b'version', default=0)
|
||||
dbversion = self.metadata.get('version', default=0)
|
||||
return ((dbversion <= _DBVERSION) and (dbversion >= _MINVERSION))
|
||||
|
||||
@catch_db_error
|
||||
def need_upgrade(self):
|
||||
dbversion = self.metadata.get(b'version', default=0)
|
||||
dbversion = self.metadata.get('version', default=0)
|
||||
return not self.readonly and dbversion < _DBVERSION
|
||||
|
||||
def __check_readonly(self, name):
|
||||
@ -444,7 +440,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
# See if we lack write access to any files in the directory
|
||||
for base in [FAMILY_TBL, PLACES_TBL, SOURCES_TBL, CITATIONS_TBL,
|
||||
MEDIA_TBL, EVENTS_TBL, PERSON_TBL, REPO_TBL,
|
||||
NOTE_TBL, REF_MAP, META]:
|
||||
NOTE_TBL, TAG_TBL, LOCATION_TBL, REF_MAP, META]:
|
||||
path = os.path.join(name, base + DBEXT)
|
||||
if os.path.isfile(path) and not os.access(path, os.W_OK):
|
||||
return True
|
||||
@ -506,7 +502,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
|
||||
try:
|
||||
self.env.open(env_name, env_flags)
|
||||
except Exception as msg:
|
||||
except Exception, msg:
|
||||
_LOG.warning("Error opening db environment: " + str(msg))
|
||||
try:
|
||||
self.__close_early()
|
||||
@ -529,7 +525,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
raise DbVersionError()
|
||||
|
||||
self.__load_metadata()
|
||||
gstats = self.metadata.get(b'gender_stats', default=None)
|
||||
gstats = self.metadata.get('gender_stats', default=None)
|
||||
|
||||
# Ensure version info in metadata
|
||||
if not self.readonly:
|
||||
@ -537,12 +533,12 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
if gstats is None:
|
||||
# New database. Set up the current version.
|
||||
#self.metadata.put(b'version', _DBVERSION, txn=the_txn)
|
||||
txn.put(b'version', _DBVERSION)
|
||||
elif b'version' not in self.metadata:
|
||||
#self.metadata.put('version', _DBVERSION, txn=the_txn)
|
||||
txn.put('version', _DBVERSION)
|
||||
elif 'version' not in self.metadata:
|
||||
# Not new database, but the version is missing.
|
||||
# Use 0, but it is likely to fail anyway.
|
||||
txn.put(b'version', 0)
|
||||
txn.put('version', 0)
|
||||
|
||||
self.genderStats = GenderStats(gstats)
|
||||
|
||||
@ -558,6 +554,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
("repository_map", REPO_TBL, db.DB_HASH),
|
||||
("note_map", NOTE_TBL, db.DB_HASH),
|
||||
("tag_map", TAG_TBL, db.DB_HASH),
|
||||
("location_map", LOCATION_TBL, db.DB_HASH),
|
||||
("reference_map", REF_MAP, db.DB_BTREE),
|
||||
]
|
||||
|
||||
@ -629,7 +626,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
|
||||
def __load_metadata(self):
|
||||
# name display formats
|
||||
self.name_formats = self.metadata.get(b'name_formats', default=[])
|
||||
self.name_formats = self.metadata.get('name_formats', default=[])
|
||||
# upgrade formats if they were saved in the old way
|
||||
for format_ix in range(len(self.name_formats)):
|
||||
format = self.name_formats[format_ix]
|
||||
@ -639,7 +636,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
|
||||
# database owner
|
||||
try:
|
||||
owner_data = self.metadata.get(b'researcher')
|
||||
owner_data = self.metadata.get('researcher')
|
||||
if owner_data:
|
||||
if len(owner_data[0]) == 7: # Pre-3.3 format
|
||||
owner_data = upgrade_researcher(owner_data)
|
||||
@ -650,35 +647,35 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
# bookmarks
|
||||
meta = lambda meta: self.metadata.get(meta, default=[])
|
||||
|
||||
self.bookmarks.set(meta(b'bookmarks'))
|
||||
self.family_bookmarks.set(meta(b'family_bookmarks'))
|
||||
self.event_bookmarks.set(meta(b'event_bookmarks'))
|
||||
self.source_bookmarks.set(meta(b'source_bookmarks'))
|
||||
self.citation_bookmarks.set(meta(b'citation_bookmarks'))
|
||||
self.repo_bookmarks.set(meta(b'repo_bookmarks'))
|
||||
self.media_bookmarks.set(meta(b'media_bookmarks'))
|
||||
self.place_bookmarks.set(meta(b'place_bookmarks'))
|
||||
self.note_bookmarks.set(meta(b'note_bookmarks'))
|
||||
self.bookmarks.set(meta('bookmarks'))
|
||||
self.family_bookmarks.set(meta('family_bookmarks'))
|
||||
self.event_bookmarks.set(meta('event_bookmarks'))
|
||||
self.source_bookmarks.set(meta('source_bookmarks'))
|
||||
self.citation_bookmarks.set(meta('citation_bookmarks'))
|
||||
self.repo_bookmarks.set(meta('repo_bookmarks'))
|
||||
self.media_bookmarks.set(meta('media_bookmarks'))
|
||||
self.place_bookmarks.set(meta('place_bookmarks'))
|
||||
self.note_bookmarks.set(meta('note_bookmarks'))
|
||||
|
||||
# Custom type values
|
||||
self.family_event_names = set(meta(b'fevent_names'))
|
||||
self.individual_event_names = set(meta(b'pevent_names'))
|
||||
self.family_attributes = set(meta(b'fattr_names'))
|
||||
self.individual_attributes = set(meta(b'pattr_names'))
|
||||
self.marker_names = set(meta(b'marker_names'))
|
||||
self.child_ref_types = set(meta(b'child_refs'))
|
||||
self.family_rel_types = set(meta(b'family_rels'))
|
||||
self.event_role_names = set(meta(b'event_roles'))
|
||||
self.name_types = set(meta(b'name_types'))
|
||||
self.origin_types = set(meta(b'origin_types'))
|
||||
self.repository_types = set(meta(b'repo_types'))
|
||||
self.note_types = set(meta(b'note_types'))
|
||||
self.source_media_types = set(meta(b'sm_types'))
|
||||
self.url_types = set(meta(b'url_types'))
|
||||
self.media_attributes = set(meta(b'mattr_names'))
|
||||
self.family_event_names = set(meta('fevent_names'))
|
||||
self.individual_event_names = set(meta('pevent_names'))
|
||||
self.family_attributes = set(meta('fattr_names'))
|
||||
self.individual_attributes = set(meta('pattr_names'))
|
||||
self.marker_names = set(meta('marker_names'))
|
||||
self.child_ref_types = set(meta('child_refs'))
|
||||
self.family_rel_types = set(meta('family_rels'))
|
||||
self.event_role_names = set(meta('event_roles'))
|
||||
self.name_types = set(meta('name_types'))
|
||||
self.origin_types = set(meta('origin_types'))
|
||||
self.repository_types = set(meta('repo_types'))
|
||||
self.note_types = set(meta('note_types'))
|
||||
self.source_media_types = set(meta('sm_types'))
|
||||
self.url_types = set(meta('url_types'))
|
||||
self.media_attributes = set(meta('mattr_names'))
|
||||
|
||||
# surname list
|
||||
self.surname_list = meta(b'surname_list')
|
||||
self.surname_list = meta('surname_list')
|
||||
|
||||
def __connect_secondary(self):
|
||||
"""
|
||||
@ -706,6 +703,8 @@ 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", LPARENTS, db.DB_HASH, 0),
|
||||
("names", LNAMES, db.DB_BTREE, db.DB_DUPSORT),
|
||||
("reference_map_primary_map", REF_PRI, db.DB_BTREE, 0),
|
||||
("reference_map_referenced_map", REF_REF, db.DB_BTREE, db.DB_DUPSORT),
|
||||
]
|
||||
@ -729,6 +728,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
(self.repository_map, self.rid_trans, find_idmap),
|
||||
(self.note_map, self.nid_trans, find_idmap),
|
||||
(self.tag_map, self.tag_trans, find_idmap),
|
||||
(self.location_map, self.parents, find_parent),
|
||||
(self.location_map, self.names, find_name),
|
||||
(self.reference_map, self.reference_map_primary_map,
|
||||
find_primary_handle),
|
||||
(self.reference_map, self.reference_map_referenced_map,
|
||||
@ -770,6 +771,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
( self.nid_trans, NIDTRANS ),
|
||||
( self.cid_trans, CIDTRANS ),
|
||||
( self.tag_trans, TAGTRANS ),
|
||||
( self.parents, LPARENTS ),
|
||||
( self.names, LNAMES ),
|
||||
( self.reference_map_primary_map, REF_PRI),
|
||||
( self.reference_map_referenced_map, REF_REF),
|
||||
]
|
||||
@ -796,6 +799,60 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
if callback:
|
||||
callback(12)
|
||||
|
||||
@catch_db_error
|
||||
def find_location_child_handles(self, handle):
|
||||
"""
|
||||
"""
|
||||
handle = str(handle)
|
||||
parent_cur = self.get_location_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.location_map.get(data)
|
||||
else:
|
||||
data = pickle.loads(data)
|
||||
|
||||
yield data[0]
|
||||
ret = parent_cur.next_dup()
|
||||
|
||||
parent_cur.close()
|
||||
|
||||
@catch_db_error
|
||||
def find_location_from_name(self, name):
|
||||
"""
|
||||
"""
|
||||
name = str(name).upper()
|
||||
size = len(name)
|
||||
name_cur = self.get_location_name_cursor()
|
||||
|
||||
try:
|
||||
ret = name_cur.set_range(name)
|
||||
ret = name_cur.current()
|
||||
except:
|
||||
ret = None
|
||||
|
||||
while (ret is not None):
|
||||
(key, data) = ret
|
||||
|
||||
if key[:size] != name:
|
||||
break
|
||||
|
||||
yield data[0]
|
||||
ret = name_cur.next()
|
||||
|
||||
name_cur.close()
|
||||
|
||||
@catch_db_error
|
||||
def find_backlink_handles(self, handle, include_classes=None):
|
||||
"""
|
||||
@ -814,8 +871,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
|
||||
result_list = list(find_backlink_handles(handle))
|
||||
"""
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
|
||||
handle = str(handle)
|
||||
# Use the secondary index to locate all the reference_map entries
|
||||
# that include a reference to the object we are looking for.
|
||||
referenced_cur = self.get_reference_map_referenced_cursor()
|
||||
@ -949,34 +1006,25 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
Remove the reference specified by the key, preserving the change in
|
||||
the passed transaction.
|
||||
"""
|
||||
if isinstance(key, tuple):
|
||||
#create a string key
|
||||
key = str(key)
|
||||
if isinstance(key, UNITYPE):
|
||||
key = key.encode('utf-8')
|
||||
if not self.readonly:
|
||||
if not transaction.batch:
|
||||
old_data = self.reference_map.get(key, txn=txn)
|
||||
transaction.add(REFERENCE_KEY, TXNDEL, key, old_data, None)
|
||||
old_data = self.reference_map.get(str(key), txn=txn)
|
||||
transaction.add(REFERENCE_KEY, TXNDEL, str(key), old_data, None)
|
||||
#transaction.reference_del.append(str(key))
|
||||
self.reference_map.delete(key, txn=txn)
|
||||
self.reference_map.delete(str(key), txn=txn)
|
||||
|
||||
def __add_reference(self, key, data, transaction, txn):
|
||||
"""
|
||||
Add the reference specified by the key and the data, preserving the
|
||||
change in the passed transaction.
|
||||
"""
|
||||
if isinstance(key, tuple):
|
||||
#create a string key
|
||||
key = str(key)
|
||||
if isinstance(key, UNITYPE):
|
||||
key = key.encode('utf-8')
|
||||
|
||||
if self.readonly or not key:
|
||||
return
|
||||
|
||||
self.reference_map.put(key, data, txn=txn)
|
||||
self.reference_map.put(str(key), data, txn=txn)
|
||||
if not transaction.batch:
|
||||
transaction.add(REFERENCE_KEY, TXNADD, key, None, data)
|
||||
transaction.add(REFERENCE_KEY, TXNADD, str(key), None, data)
|
||||
#transaction.reference_add.append((str(key), data))
|
||||
|
||||
@catch_db_error
|
||||
@ -1063,45 +1111,45 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
|
||||
# name display formats
|
||||
txn.put(b'name_formats', self.name_formats)
|
||||
txn.put('name_formats', self.name_formats)
|
||||
|
||||
# database owner
|
||||
owner_data = self.owner.serialize()
|
||||
txn.put(b'researcher', owner_data)
|
||||
txn.put('researcher', owner_data)
|
||||
|
||||
# bookmarks
|
||||
txn.put(b'bookmarks', self.bookmarks.get())
|
||||
txn.put(b'family_bookmarks', self.family_bookmarks.get())
|
||||
txn.put(b'event_bookmarks', self.event_bookmarks.get())
|
||||
txn.put(b'source_bookmarks', self.source_bookmarks.get())
|
||||
txn.put(b'citation_bookmarks', self.citation_bookmarks.get())
|
||||
txn.put(b'place_bookmarks', self.place_bookmarks.get())
|
||||
txn.put(b'repo_bookmarks', self.repo_bookmarks.get())
|
||||
txn.put(b'media_bookmarks', self.media_bookmarks.get())
|
||||
txn.put(b'note_bookmarks', self.note_bookmarks.get())
|
||||
txn.put('bookmarks', self.bookmarks.get())
|
||||
txn.put('family_bookmarks', self.family_bookmarks.get())
|
||||
txn.put('event_bookmarks', self.event_bookmarks.get())
|
||||
txn.put('source_bookmarks', self.source_bookmarks.get())
|
||||
txn.put('citation_bookmarks', self.citation_bookmarks.get())
|
||||
txn.put('place_bookmarks', self.place_bookmarks.get())
|
||||
txn.put('repo_bookmarks', self.repo_bookmarks.get())
|
||||
txn.put('media_bookmarks', self.media_bookmarks.get())
|
||||
txn.put('note_bookmarks', self.note_bookmarks.get())
|
||||
|
||||
# gender stats
|
||||
txn.put(b'gender_stats', self.genderStats.save_stats())
|
||||
txn.put('gender_stats', self.genderStats.save_stats())
|
||||
|
||||
# Custom type values
|
||||
txn.put(b'fevent_names', list(self.family_event_names))
|
||||
txn.put(b'pevent_names', list(self.individual_event_names))
|
||||
txn.put(b'fattr_names', list(self.family_attributes))
|
||||
txn.put(b'pattr_names', list(self.individual_attributes))
|
||||
txn.put(b'marker_names', list(self.marker_names))
|
||||
txn.put(b'child_refs', list(self.child_ref_types))
|
||||
txn.put(b'family_rels', list(self.family_rel_types))
|
||||
txn.put(b'event_roles', list(self.event_role_names))
|
||||
txn.put(b'name_types', list(self.name_types))
|
||||
txn.put(b'origin_types', list(self.origin_types))
|
||||
txn.put(b'repo_types', list(self.repository_types))
|
||||
txn.put(b'note_types', list(self.note_types))
|
||||
txn.put(b'sm_types', list(self.source_media_types))
|
||||
txn.put(b'url_types', list(self.url_types))
|
||||
txn.put(b'mattr_names', list(self.media_attributes))
|
||||
txn.put('fevent_names', list(self.family_event_names))
|
||||
txn.put('pevent_names', list(self.individual_event_names))
|
||||
txn.put('fattr_names', list(self.family_attributes))
|
||||
txn.put('pattr_names', list(self.individual_attributes))
|
||||
txn.put('marker_names', list(self.marker_names))
|
||||
txn.put('child_refs', list(self.child_ref_types))
|
||||
txn.put('family_rels', list(self.family_rel_types))
|
||||
txn.put('event_roles', list(self.event_role_names))
|
||||
txn.put('name_types', list(self.name_types))
|
||||
txn.put('origin_types', list(self.origin_types))
|
||||
txn.put('repo_types', list(self.repository_types))
|
||||
txn.put('note_types', list(self.note_types))
|
||||
txn.put('sm_types', list(self.source_media_types))
|
||||
txn.put('url_types', list(self.url_types))
|
||||
txn.put('mattr_names', list(self.media_attributes))
|
||||
|
||||
# name display formats
|
||||
txn.put(b'surname_list', self.surname_list)
|
||||
txn.put('surname_list', self.surname_list)
|
||||
|
||||
self.metadata.close()
|
||||
|
||||
@ -1143,6 +1191,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.cid_trans.close()
|
||||
self.pid_trans.close()
|
||||
self.tag_trans.close()
|
||||
self.parents.close()
|
||||
self.names.close()
|
||||
self.reference_map_primary_map.close()
|
||||
self.reference_map_referenced_map.close()
|
||||
self.reference_map.close()
|
||||
@ -1160,6 +1210,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.media_map.close()
|
||||
self.event_map.close()
|
||||
self.tag_map.close()
|
||||
self.location_map.close()
|
||||
self.env.close()
|
||||
self.__close_undodb()
|
||||
|
||||
@ -1173,6 +1224,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.media_map = None
|
||||
self.event_map = None
|
||||
self.tag_map = None
|
||||
self.location_map = None
|
||||
self.surnames = None
|
||||
self.env = None
|
||||
self.metadata = None
|
||||
@ -1191,6 +1243,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.media_map = None
|
||||
self.event_map = None
|
||||
self.tag_map = None
|
||||
self.location_map = None
|
||||
self.reference_map_primary_map = None
|
||||
self.reference_map_referenced_map = None
|
||||
self.reference_map = None
|
||||
@ -1203,14 +1256,9 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
versionpath = os.path.join(self.path, BDBVERSFN)
|
||||
try:
|
||||
with open(versionpath, "w") as version_file:
|
||||
version = str(db.version())
|
||||
if sys.version_info[0] < 3:
|
||||
if isinstance(version, UNITYPE):
|
||||
version = version.encode('utf-8')
|
||||
version_file.write(version)
|
||||
version_file.write(str(db.version()))
|
||||
except:
|
||||
# Storing the version of Berkeley Db is not really vital.
|
||||
print ("Error storing berkeley db version")
|
||||
pass
|
||||
|
||||
try:
|
||||
@ -1220,7 +1268,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
|
||||
def create_id(self):
|
||||
return "%08x%08x" % ( int(time.time()*10000),
|
||||
self.rand.randint(0, maxsize))
|
||||
self.rand.randint(0, maxint))
|
||||
|
||||
def __add_object(self, obj, transaction, find_next_func, commit_func):
|
||||
if find_next_func and not obj.gramps_id:
|
||||
@ -1356,12 +1404,18 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
"""
|
||||
return self.__add_object(obj, transaction, None, self.commit_tag)
|
||||
|
||||
def add_location(self, obj, transaction):
|
||||
"""
|
||||
Add a Location to the database, assigning a handle if it has not already
|
||||
been defined.
|
||||
"""
|
||||
return self.__add_object(obj, transaction, None, self.commit_location)
|
||||
|
||||
def __do_remove(self, handle, transaction, data_map, key):
|
||||
if self.readonly or not handle:
|
||||
return
|
||||
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
handle = str(handle)
|
||||
if transaction.batch:
|
||||
with BSDDBTxn(self.env, data_map) as txn:
|
||||
self.delete_primary_from_reference_map(handle, transaction,
|
||||
@ -1385,8 +1439,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
person = self.get_person_from_handle(handle)
|
||||
self.genderStats.uncount_person (person)
|
||||
self.remove_from_surname_list(person)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
if transaction.batch:
|
||||
with BSDDBTxn(self.env, self.person_map) as txn:
|
||||
self.delete_primary_from_reference_map(handle, transaction,
|
||||
@ -1395,7 +1447,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
else:
|
||||
self.delete_primary_from_reference_map(handle, transaction,
|
||||
txn=self.txn)
|
||||
self.person_map.delete(handle, txn=self.txn)
|
||||
self.person_map.delete(str(handle), txn=self.txn)
|
||||
transaction.add(PERSON_KEY, TXNDEL, handle, person.serialize(), None)
|
||||
|
||||
def remove_source(self, handle, transaction):
|
||||
@ -1470,6 +1522,14 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.__do_remove(handle, transaction, self.tag_map,
|
||||
TAG_KEY)
|
||||
|
||||
def remove_location(self, handle, transaction):
|
||||
"""
|
||||
Remove the Location specified by the database handle from the
|
||||
database, preserving the change in the passed transaction.
|
||||
"""
|
||||
self.__do_remove(handle, transaction, self.location_map,
|
||||
LOCATION_KEY)
|
||||
|
||||
@catch_db_error
|
||||
def set_name_group_mapping(self, name, group):
|
||||
if not self.readonly:
|
||||
@ -1482,7 +1542,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
if group is not None:
|
||||
txn.put(sname, group)
|
||||
if group == None:
|
||||
grouppar = ''
|
||||
grouppar = u''
|
||||
else:
|
||||
grouppar = group
|
||||
self.emit('person-groupname-rebuild', (name, grouppar))
|
||||
@ -1508,7 +1568,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
"""
|
||||
if batch_transaction:
|
||||
return
|
||||
name = conv_to_unicode(find_surname_name(person.handle,
|
||||
name = unicode(find_surname_name(person.handle,
|
||||
person.get_primary_name().serialize()), 'utf-8')
|
||||
i = bisect.bisect(self.surname_list, name)
|
||||
if 0 < i <= len(self.surname_list):
|
||||
@ -1528,18 +1588,11 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
"""
|
||||
name = find_surname_name(person.handle,
|
||||
person.get_primary_name().serialize())
|
||||
if sys.version_info[0] < 3:
|
||||
if isinstance(name, unicode):
|
||||
uname = name
|
||||
name = str(name)
|
||||
else:
|
||||
uname = unicode(name, 'utf-8')
|
||||
if isinstance(name, unicode):
|
||||
uname = name
|
||||
name = str(name)
|
||||
else:
|
||||
if isinstance(name, str):
|
||||
uname = name
|
||||
name = name.encode('utf-8')
|
||||
else:
|
||||
uname = str(name)
|
||||
uname = unicode(name, 'utf-8')
|
||||
try:
|
||||
cursor = self.surnames.cursor(txn=self.txn)
|
||||
cursor_position = cursor.set(name)
|
||||
@ -1548,7 +1601,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
i = bisect.bisect(self.surname_list, uname)
|
||||
if 0 <= i-1 < len(self.surname_list):
|
||||
del self.surname_list[i-1]
|
||||
except db.DBError as err:
|
||||
except db.DBError, err:
|
||||
if str(err) == "(0, 'DB object has been closed')":
|
||||
pass # A batch transaction closes the surnames db table.
|
||||
else:
|
||||
@ -1566,9 +1619,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
return
|
||||
|
||||
obj.change = int(change_time or time.time())
|
||||
handle = obj.handle
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
handle = str(obj.handle)
|
||||
|
||||
self.update_reference_map(obj, transaction, self.txn)
|
||||
|
||||
@ -1790,11 +1841,17 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.commit_base(tag, self.tag_map, TAG_KEY,
|
||||
transaction, change_time)
|
||||
|
||||
def commit_location(self, location, transaction, change_time=None):
|
||||
"""
|
||||
Commit the specified Location to the database, storing the changes as
|
||||
part of the transaction.
|
||||
"""
|
||||
self.commit_base(location, self.location_map, LOCATION_KEY,
|
||||
transaction, change_time)
|
||||
|
||||
def get_from_handle(self, handle, class_type, data_map):
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
try:
|
||||
data = data_map.get(handle, txn=self.txn)
|
||||
data = data_map.get(str(handle), txn=self.txn)
|
||||
except:
|
||||
data = None
|
||||
# under certain circumstances during a database reload,
|
||||
@ -1879,7 +1936,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.env.log_flush()
|
||||
if not transaction.batch:
|
||||
emit = self.__emit
|
||||
for obj_type, obj_name in KEY_TO_NAME_MAP.items():
|
||||
for obj_type, obj_name in KEY_TO_NAME_MAP.iteritems():
|
||||
emit(transaction, obj_type, TXNADD, obj_name, '-add')
|
||||
emit(transaction, obj_type, TXNUPD, obj_name, '-update')
|
||||
emit(transaction, obj_type, TXNDEL, obj_name, '-delete')
|
||||
@ -1926,7 +1983,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
# "while Gtk.events_pending(): Gtk.main_iteration() loop"
|
||||
# (typically used in a progress bar), so emit rebuild signals
|
||||
# to correct that.
|
||||
object_types = set([x[0] for x in list(transaction.keys())])
|
||||
object_types = set([x[0] for x in transaction.keys()])
|
||||
for object_type in object_types:
|
||||
if object_type == REFERENCE_KEY:
|
||||
continue
|
||||
@ -1983,11 +2040,11 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
def gramps_upgrade(self, callback=None):
|
||||
UpdateCallback.__init__(self, callback)
|
||||
|
||||
version = self.metadata.get(b'version', default=_MINVERSION)
|
||||
version = self.metadata.get('version', default=_MINVERSION)
|
||||
|
||||
t = time.time()
|
||||
|
||||
from . import upgrade
|
||||
import upgrade
|
||||
if version < 14:
|
||||
upgrade.gramps_upgrade_14(self)
|
||||
if version < 15:
|
||||
@ -2007,6 +2064,9 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.__close_undodb()
|
||||
self.db_is_open = False
|
||||
|
||||
if version < 17:
|
||||
self.__connect_secondary()
|
||||
upgrade.gramps_upgrade_17(self)
|
||||
|
||||
_LOG.debug("Upgrade time: %d seconds" % int(time.time()-t))
|
||||
|
||||
@ -2060,7 +2120,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.metadata = self.__open_shelf(full_name, META)
|
||||
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'version', _DBVERSION)
|
||||
txn.put('version', _DBVERSION)
|
||||
|
||||
self.metadata.close()
|
||||
self.env.close()
|
||||
@ -2133,14 +2193,13 @@ if __name__ == "__main__":
|
||||
db_name = f.read()
|
||||
if db_name == 'Small Example':
|
||||
break
|
||||
print("loading", db_path)
|
||||
print "loading", db_path
|
||||
d.load(db_path, lambda x: x)
|
||||
|
||||
print(d.get_default_person())
|
||||
out = ''
|
||||
print d.get_default_person()
|
||||
with d.get_person_cursor() as c:
|
||||
for key, data in c:
|
||||
person = Person(data)
|
||||
out += key + person.get_primary_name().get_name()
|
||||
print key, person.get_primary_name().get_name(),
|
||||
|
||||
print(out, list(d.surnames.keys()))
|
||||
print d.surnames.keys()
|
||||
|
@ -25,25 +25,25 @@
|
||||
Package providing filter rules for GRAMPS.
|
||||
"""
|
||||
|
||||
from ._allplaces import AllPlaces
|
||||
from ._hascitation import HasCitation
|
||||
from ._hasgallery import HasGallery
|
||||
from ._hasidof import HasIdOf
|
||||
from ._regexpidof import RegExpIdOf
|
||||
from ._hasnote import HasNote
|
||||
from ._hasnoteregexp import HasNoteRegexp
|
||||
from ._hasnotematchingsubstringof import HasNoteMatchingSubstringOf
|
||||
from ._hasreferencecountof import HasReferenceCountOf
|
||||
from ._hassourcecount import HasSourceCount
|
||||
from ._hassourceof import HasSourceOf
|
||||
from ._placeprivate import PlacePrivate
|
||||
from ._matchesfilter import MatchesFilter
|
||||
from ._hasplace import HasPlace
|
||||
from ._hasnolatorlon import HasNoLatOrLon
|
||||
from ._inlatlonneighborhood import InLatLonNeighborhood
|
||||
from ._matcheseventfilter import MatchesEventFilter
|
||||
from ._matchessourceconfidence import MatchesSourceConfidence
|
||||
from ._changedsince import ChangedSince
|
||||
from _allplaces import AllPlaces
|
||||
from _hascitation import HasCitation
|
||||
from _hasgallery import HasGallery
|
||||
from _hasidof import HasIdOf
|
||||
from _regexpidof import RegExpIdOf
|
||||
from _hasnote import HasNote
|
||||
from _hasnoteregexp import HasNoteRegexp
|
||||
from _hasnotematchingsubstringof import HasNoteMatchingSubstringOf
|
||||
from _hasreferencecountof import HasReferenceCountOf
|
||||
from _hassourcecount import HasSourceCount
|
||||
from _hassourceof import HasSourceOf
|
||||
from _placeprivate import PlacePrivate
|
||||
from _matchesfilter import MatchesFilter
|
||||
from _haslocation import HasLocation
|
||||
from _hasnolatorlon import HasNoLatOrLon
|
||||
from _inlatlonneighborhood import InLatLonNeighborhood
|
||||
from _matcheseventfilter import MatchesEventFilter
|
||||
from _matchessourceconfidence import MatchesSourceConfidence
|
||||
from _changedsince import ChangedSince
|
||||
|
||||
editor_rule_list = [
|
||||
AllPlaces,
|
||||
@ -60,7 +60,7 @@ editor_rule_list = [
|
||||
PlacePrivate,
|
||||
MatchesFilter,
|
||||
MatchesSourceConfidence,
|
||||
HasPlace,
|
||||
HasLocation,
|
||||
HasNoLatOrLon,
|
||||
InLatLonNeighborhood,
|
||||
MatchesEventFilter,
|
||||
|
63
gramps/gen/filters/rules/place/_haslocation.py
Normal file
63
gramps/gen/filters/rules/place/_haslocation.py
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2012 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ....ggettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .. import Rule
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# HasLocation
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class HasLocation(Rule):
|
||||
"""Rule that checks if a Place is at a specified Location"""
|
||||
|
||||
labels = [ _('Location:') ]
|
||||
name = _('Place at <Location>')
|
||||
description = _("Matches places at a specified Location")
|
||||
category = _('General filters')
|
||||
|
||||
def prepare(self, db):
|
||||
self.children = []
|
||||
to_do = [self.list[0]]
|
||||
while to_do:
|
||||
for child in db.find_location_child_handles(to_do.pop()):
|
||||
to_do.append(child)
|
||||
self.children.append(child)
|
||||
|
||||
def apply(self, db, obj):
|
||||
"""
|
||||
apply the rule on the obj.
|
||||
return true if the rule passes, false otherwise.
|
||||
"""
|
||||
return obj.get_main_location() in self.children
|
@ -50,7 +50,8 @@ class HasNoLatOrLon(Rule):
|
||||
description = _("Matches places with empty latitude or longitude")
|
||||
category = _('Position filters')
|
||||
|
||||
def apply(self,db,place):
|
||||
if place.get_latitude().strip and place.get_longitude().strip() :
|
||||
def apply(self, db, place):
|
||||
location = db.get_location_from_handle(place.get_main_location())
|
||||
if location.get_latitude().strip and location.get_longitude().strip():
|
||||
return False
|
||||
return True
|
||||
|
@ -121,6 +121,10 @@ class InLatLonNeighborhood(Rule):
|
||||
|
||||
|
||||
def apply(self,db,place):
|
||||
location = db.get_location_from_handle(place.get_main_location())
|
||||
latitude = location.get_latitude().strip()
|
||||
longitude = location.get_longitude().strip()
|
||||
|
||||
if self.halfheight == -1 and self.halfwidth ==-1 :
|
||||
return False
|
||||
|
||||
|
@ -30,16 +30,14 @@ Location class for GRAMPS.
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .secondaryobj import SecondaryObject
|
||||
from .locationbase import LocationBase
|
||||
from .const import IDENTICAL, DIFFERENT
|
||||
from .tableobj import TableObject
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Location class for Places
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class Location(SecondaryObject, LocationBase):
|
||||
class Location(TableObject):
|
||||
"""
|
||||
Provide information about a place.
|
||||
|
||||
@ -52,17 +50,31 @@ class Location(SecondaryObject, LocationBase):
|
||||
"""
|
||||
Create a Location object, copying from the source object if it exists.
|
||||
"""
|
||||
LocationBase.__init__(self, source)
|
||||
TableObject.__init__(self, source)
|
||||
if source:
|
||||
self.parish = source.parish
|
||||
self.parent = source.parent
|
||||
self.name = source.name
|
||||
self.location_type = source.location_type
|
||||
self.lat = source.lat
|
||||
self.long = source.long
|
||||
else:
|
||||
self.parish = ""
|
||||
self.parent = None
|
||||
self.name = ''
|
||||
self.location_type = 1 # Country
|
||||
self.lat = ''
|
||||
self.long = ''
|
||||
|
||||
def serialize(self):
|
||||
"""
|
||||
Convert the object to a serialized tuple of data.
|
||||
"""
|
||||
return (LocationBase.serialize(self), self.parish)
|
||||
return (self.handle,
|
||||
self.parent,
|
||||
self.name,
|
||||
self.location_type,
|
||||
self.lat,
|
||||
self.long,
|
||||
self.change)
|
||||
|
||||
def to_struct(self):
|
||||
"""
|
||||
@ -98,9 +110,13 @@ class Location(SecondaryObject, LocationBase):
|
||||
"""
|
||||
Convert a serialized tuple of data to an object.
|
||||
"""
|
||||
(lbase, self.parish) = data
|
||||
LocationBase.unserialize(self, lbase)
|
||||
return self
|
||||
(self.handle,
|
||||
self.parent,
|
||||
self.name,
|
||||
self.location_type,
|
||||
self.lat,
|
||||
self.long,
|
||||
self.change) = data
|
||||
|
||||
def get_text_data_list(self):
|
||||
"""
|
||||
@ -109,42 +125,102 @@ class Location(SecondaryObject, LocationBase):
|
||||
:returns: Returns the list of all textual attributes of the object.
|
||||
:rtype: list
|
||||
"""
|
||||
return [self.parish] + LocationBase.get_text_data_list(self)
|
||||
|
||||
def is_equivalent(self, other):
|
||||
"""
|
||||
Return if this location is equivalent to other.
|
||||
|
||||
:param other: The location to compare this one to.
|
||||
:rtype other: Location
|
||||
:returns: Constant inidicating degree of equivalence.
|
||||
:rtype: int
|
||||
"""
|
||||
if self.is_equal(other):
|
||||
return IDENTICAL
|
||||
else:
|
||||
return DIFFERENT
|
||||
|
||||
def merge(self, acquisition):
|
||||
"""
|
||||
Merge the content of acquisition into this location.
|
||||
|
||||
Lost: everything of acquisition.
|
||||
|
||||
:param acquisition: The location to merge with the present location.
|
||||
:rtype acquisition: Location
|
||||
"""
|
||||
pass
|
||||
return [self.name, self.lat, self.long]
|
||||
|
||||
def is_empty(self):
|
||||
return not self.street and not self.locality and not self.city and \
|
||||
not self.county and not self.state and not self.country and \
|
||||
not self.postal and not self.phone
|
||||
|
||||
def set_parish(self, data):
|
||||
"""Set the religious parish name."""
|
||||
self.parish = data
|
||||
"""
|
||||
Return True if the Location is an empty object (no values set).
|
||||
|
||||
def get_parish(self):
|
||||
"""Get the religious parish name."""
|
||||
return self.parish
|
||||
:returns: True if the Location is empty
|
||||
:rtype: bool
|
||||
"""
|
||||
return self.name == ''
|
||||
|
||||
def are_equal(self, other):
|
||||
"""
|
||||
Return True if the passed Tag is equivalent to the current Location.
|
||||
|
||||
:param other: Location to compare against
|
||||
:type other: Location
|
||||
:returns: True if the Locations are equal
|
||||
:rtype: bool
|
||||
"""
|
||||
if other is None:
|
||||
other = Location()
|
||||
|
||||
if self.name != other.name or \
|
||||
self.parent != other.parent:
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_parent(self, parent):
|
||||
"""
|
||||
Set the parent of the Location to the passed string.
|
||||
"""
|
||||
self.parent = parent
|
||||
|
||||
def get_parent(self):
|
||||
"""
|
||||
Return the parent of the Location.
|
||||
"""
|
||||
return self.parent
|
||||
|
||||
def set_name(self, name):
|
||||
"""
|
||||
Set the name of the Location to the passed string.
|
||||
"""
|
||||
self.name = name
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Return the name of the Location.
|
||||
"""
|
||||
return self.name
|
||||
|
||||
def set_type(self, location_type):
|
||||
"""
|
||||
Set the type of the Location to the passed integer.
|
||||
"""
|
||||
self.location_type = location_type
|
||||
|
||||
def get_type(self):
|
||||
"""
|
||||
Return the type of the Location.
|
||||
"""
|
||||
return self.location_type
|
||||
|
||||
def set_latitude(self, latitude):
|
||||
"""
|
||||
Set the latitude of the Location object.
|
||||
|
||||
:param latitude: latitude to assign to the Location
|
||||
:type latitude: str
|
||||
"""
|
||||
self.lat = latitude
|
||||
|
||||
def get_latitude(self):
|
||||
"""
|
||||
Return the latitude of the Location object.
|
||||
|
||||
:returns: Returns the latitude of the Location
|
||||
:rtype: str
|
||||
"""
|
||||
return self.lat
|
||||
|
||||
def set_longitude(self, longitude):
|
||||
"""
|
||||
Set the longitude of the Location object.
|
||||
|
||||
:param longitude: longitude to assign to the Location
|
||||
:type longitude: str
|
||||
"""
|
||||
self.long = longitude
|
||||
|
||||
def get_longitude(self):
|
||||
"""
|
||||
Return the longitude of the Location object.
|
||||
|
||||
:returns: Returns the longitude of the Location
|
||||
:rtype: str
|
||||
"""
|
||||
return self.long
|
||||
|
@ -25,21 +25,18 @@
|
||||
"""
|
||||
Place object for GRAMPS.
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .primaryobj import PrimaryObject
|
||||
from .citationbase import CitationBase
|
||||
from .notebase import NoteBase
|
||||
from .mediabase import MediaBase
|
||||
from .urlbase import UrlBase
|
||||
from .location import Location
|
||||
|
||||
_EMPTY_LOC = Location().serialize()
|
||||
from primaryobj import PrimaryObject
|
||||
from citationbase import CitationBase
|
||||
from notebase import NoteBase
|
||||
from mediabase import MediaBase
|
||||
from urlbase import UrlBase
|
||||
from location import Location
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -66,14 +63,10 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
|
||||
MediaBase.__init__(self, source)
|
||||
UrlBase.__init__(self, source)
|
||||
if source:
|
||||
self.long = source.long
|
||||
self.lat = source.lat
|
||||
self.title = source.title
|
||||
self.main_loc = Location(source.main_loc)
|
||||
self.alt_loc = list(map(Location, source.alt_loc))
|
||||
self.main_loc = source.main_loc
|
||||
self.alt_loc = source.alt_loc
|
||||
else:
|
||||
self.long = ""
|
||||
self.lat = ""
|
||||
self.title = ""
|
||||
self.main_loc = None
|
||||
self.alt_loc = []
|
||||
@ -96,14 +89,8 @@ 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],
|
||||
return (self.handle, self.gramps_id, self.title,
|
||||
self.main_loc, self.alt_loc,
|
||||
UrlBase.serialize(self),
|
||||
MediaBase.serialize(self),
|
||||
CitationBase.serialize(self),
|
||||
@ -158,15 +145,11 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
|
||||
Person object
|
||||
: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,
|
||||
(self.handle, self.gramps_id, self.title,
|
||||
self.main_loc, self.alt_loc,
|
||||
urls, media_list, citation_list, note_list,
|
||||
self.change, self.private) = data
|
||||
|
||||
if main_loc is None:
|
||||
self.main_loc = None
|
||||
else:
|
||||
self.main_loc = Location().unserialize(main_loc)
|
||||
self.alt_loc = [Location().unserialize(al) for al in alt_loc]
|
||||
UrlBase.unserialize(self, urls)
|
||||
MediaBase.unserialize(self, media_list)
|
||||
CitationBase.unserialize(self, citation_list)
|
||||
@ -180,7 +163,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.title, self.gramps_id]
|
||||
|
||||
def get_text_data_child_list(self):
|
||||
"""
|
||||
@ -224,6 +207,20 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
|
||||
"""
|
||||
return self.get_citation_child_list()
|
||||
|
||||
def get_referenced_location_handles(self):
|
||||
"""
|
||||
Return the list of (classname, handle) tuples for all referenced notes.
|
||||
|
||||
This method should be used to get the :class:`~gen.lib.note.Note` portion of the list
|
||||
by objects that store note lists.
|
||||
|
||||
:returns: List of (classname, handle) tuples for referenced objects.
|
||||
:rtype: list
|
||||
"""
|
||||
refs = [('Location', self.main_loc)]
|
||||
refs.extend([('Location', handle) for handle in self.alt_loc])
|
||||
return refs
|
||||
|
||||
def get_referenced_handles(self):
|
||||
"""
|
||||
Return the list of (classname, handle) tuples for all directly
|
||||
@ -232,7 +229,8 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
|
||||
:returns: List of (classname, handle) tuples for referenced objects.
|
||||
:rtype: list
|
||||
"""
|
||||
return self.get_referenced_note_handles() + \
|
||||
return self.get_referenced_location_handles() + \
|
||||
self.get_referenced_note_handles() + \
|
||||
self.get_referenced_citation_handles()
|
||||
|
||||
def merge(self, acquisition):
|
||||
@ -266,42 +264,6 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
|
||||
"""
|
||||
return self.title
|
||||
|
||||
def set_longitude(self, longitude):
|
||||
"""
|
||||
Set the longitude of the Place object.
|
||||
|
||||
:param longitude: longitude to assign to the Place
|
||||
:type longitude: str
|
||||
"""
|
||||
self.long = longitude
|
||||
|
||||
def get_longitude(self):
|
||||
"""
|
||||
Return the longitude of the Place object.
|
||||
|
||||
:returns: Returns the longitude of the Place
|
||||
:rtype: str
|
||||
"""
|
||||
return self.long
|
||||
|
||||
def set_latitude(self, latitude):
|
||||
"""
|
||||
Set the latitude of the Place object.
|
||||
|
||||
:param latitude: latitude to assign to the Place
|
||||
:type latitude: str
|
||||
"""
|
||||
self.lat = latitude
|
||||
|
||||
def get_latitude(self):
|
||||
"""
|
||||
Return the latitude of the Place object.
|
||||
|
||||
:returns: Returns the latitude of the Place
|
||||
:rtype: str
|
||||
"""
|
||||
return self.lat
|
||||
|
||||
def get_main_location(self):
|
||||
"""
|
||||
Return the :class:`~gen.lib.location.Location` object representing the primary information for
|
||||
@ -313,8 +275,6 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
|
||||
location information about the Place.
|
||||
:rtype: :class:`~gen.lib.location.Location`
|
||||
"""
|
||||
if not self.main_loc:
|
||||
self.main_loc = Location()
|
||||
return self.main_loc
|
||||
|
||||
def set_main_location(self, location):
|
||||
@ -382,28 +342,3 @@ class Place(CitationBase, NoteBase, MediaBase, UrlBase, PrimaryObject):
|
||||
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(), '', '', '', '', '']
|
||||
|
@ -61,7 +61,6 @@ from gramps.gen.db.exceptions import (DbUpgradeRequiredError,
|
||||
BsddbDowngradeError,
|
||||
DbVersionError,
|
||||
DbEnvironmentError)
|
||||
from gramps.gen.constfunc import STRTYPE
|
||||
from gramps.gen.utils.file import get_unicode_path_from_file_chooser
|
||||
from .pluginmanager import GuiPluginManager
|
||||
from .dialog import (DBErrorDialog, ErrorDialog, QuestionDialog2,
|
||||
@ -133,13 +132,11 @@ class DbLoader(CLIDbLoader):
|
||||
|
||||
pmgr = GuiPluginManager.get_instance()
|
||||
|
||||
import_dialog = Gtk.FileChooserDialog(_('Gramps: Import Family Tree'),
|
||||
import_dialog = Gtk.FileChooserDialog(_('Gramps: Import database'),
|
||||
self.uistate.window,
|
||||
Gtk.FileChooserAction.OPEN,
|
||||
(Gtk.STOCK_CANCEL,
|
||||
Gtk.ResponseType.CANCEL,
|
||||
_('Import'),
|
||||
Gtk.ResponseType.OK))
|
||||
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||
'gramps-import', Gtk.ResponseType.OK))
|
||||
import_dialog.set_local_only(False)
|
||||
|
||||
# Always add automatic (match all files) filter
|
||||
@ -208,7 +205,8 @@ class DbLoader(CLIDbLoader):
|
||||
In this process, a warning dialog can pop up.
|
||||
|
||||
"""
|
||||
if not isinstance(filename, STRTYPE):
|
||||
|
||||
if not isinstance(filename, basestring):
|
||||
return True
|
||||
|
||||
filename = os.path.normpath(os.path.abspath(filename))
|
||||
@ -251,7 +249,7 @@ class DbLoader(CLIDbLoader):
|
||||
User(callback=self._pulse_progress))
|
||||
dirname = os.path.dirname(filename) + os.path.sep
|
||||
config.set('paths.recent-import-dir', dirname)
|
||||
except UnicodeError as msg:
|
||||
except UnicodeError, msg:
|
||||
ErrorDialog(
|
||||
_("Could not import file: %s") % filename,
|
||||
_("This file incorrectly identifies its character "
|
||||
@ -268,7 +266,7 @@ class DbLoader(CLIDbLoader):
|
||||
is returned
|
||||
"""
|
||||
if self.import_info is None:
|
||||
return ""
|
||||
return u""
|
||||
return self.import_info.info_text()
|
||||
|
||||
def read_file(self, filename):
|
||||
@ -308,12 +306,12 @@ class DbLoader(CLIDbLoader):
|
||||
db.load(filename, self._pulse_progress,
|
||||
mode, upgrade=False)
|
||||
self.dbstate.change_database(db)
|
||||
except DbUpgradeRequiredError as msg:
|
||||
except DbUpgradeRequiredError, msg:
|
||||
if QuestionDialog2(_("Need to upgrade database!"),
|
||||
str(msg),
|
||||
_("Upgrade now"),
|
||||
_("Cancel")).run():
|
||||
db = gen.db.DbBsddb()
|
||||
db = DbBsddb()
|
||||
db.disable_signals()
|
||||
db.load(filename, self._pulse_progress,
|
||||
mode, upgrade=True)
|
||||
@ -321,20 +319,20 @@ class DbLoader(CLIDbLoader):
|
||||
self.dbstate.change_database(db)
|
||||
else:
|
||||
self.dbstate.no_database()
|
||||
except BsddbDowngradeError as msg:
|
||||
except BsddbDowngradeError, msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except DbVersionError as msg:
|
||||
except DbVersionError, msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except DbEnvironmentError as msg:
|
||||
except DbEnvironmentError, msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except OSError as msg:
|
||||
except OSError, msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog(
|
||||
_("Could not open file: %s") % filename, str(msg))
|
||||
except DbError as msg:
|
||||
except DbError, msg:
|
||||
self.dbstate.no_database()
|
||||
self._dberrordialog(msg)
|
||||
except Exception as newerror:
|
||||
|
@ -36,8 +36,8 @@ from gi.repository import GObject
|
||||
from gramps.gen.lib import Location
|
||||
from gramps.gen.errors import WindowActiveError
|
||||
from ...ddtargets import DdTargets
|
||||
from .locationmodel import LocationModel
|
||||
from .embeddedlist import EmbeddedList
|
||||
from locationmodel import LocationModel
|
||||
from embeddedlist import EmbeddedList
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -46,18 +46,13 @@ from .embeddedlist import EmbeddedList
|
||||
#-------------------------------------------------------------------------
|
||||
class LocationEmbedList(EmbeddedList):
|
||||
|
||||
_HANDLE_COL = 6
|
||||
_HANDLE_COL = 1
|
||||
_DND_TYPE = DdTargets.LOCATION
|
||||
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Street'), 0, 150, 0, -1),
|
||||
(_('Locality'), 1, 100, 0, -1),
|
||||
(_('City'), 2, 100, 0, -1),
|
||||
(_('County'), 3, 100, 0, -1),
|
||||
(_('State'), 4, 100, 0, -1),
|
||||
(_('Country'), 5, 75, 0, -1),
|
||||
(_('Location'), 0, 300, 0, -1),
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data):
|
||||
@ -70,7 +65,7 @@ class LocationEmbedList(EmbeddedList):
|
||||
return self.data
|
||||
|
||||
def column_order(self):
|
||||
return ((1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5))
|
||||
return ((1, 0),)
|
||||
|
||||
def add_button_clicked(self, obj):
|
||||
loc = Location()
|
||||
@ -81,15 +76,16 @@ class LocationEmbedList(EmbeddedList):
|
||||
except WindowActiveError:
|
||||
pass
|
||||
|
||||
def add_callback(self, name):
|
||||
def add_callback(self, location):
|
||||
data = self.get_data()
|
||||
data.append(name)
|
||||
data.append(location.handle)
|
||||
self.rebuild()
|
||||
GObject.idle_add(self.tree.scroll_to_cell, len(data) - 1)
|
||||
|
||||
def edit_button_clicked(self, obj):
|
||||
loc = self.get_selected()
|
||||
if loc:
|
||||
handle = self.get_selected()
|
||||
if handle:
|
||||
loc = self.dbstate.db.get_location_from_handle(handle)
|
||||
try:
|
||||
from .. import EditLocation
|
||||
EditLocation(self.dbstate, self.uistate, self.track,
|
||||
|
@ -41,9 +41,19 @@ from gi.repository import Gtk
|
||||
#-------------------------------------------------------------------------
|
||||
class LocationModel(Gtk.ListStore):
|
||||
|
||||
def __init__(self, obj_list, db):
|
||||
Gtk.ListStore.__init__(self, str, str, str, str, str, str, object)
|
||||
def __init__(self, location_list, db):
|
||||
Gtk.ListStore.__init__(self, str, object)
|
||||
self.db = db
|
||||
for obj in obj_list:
|
||||
self.append(row=[obj.street, obj.locality, obj.city, obj.county,
|
||||
obj.state, obj.country, obj, ])
|
||||
for handle in location_list:
|
||||
self.__add_location(handle)
|
||||
|
||||
def __add_location(self, handle):
|
||||
"""
|
||||
Append a location to the model.
|
||||
"""
|
||||
loc = self.db.get_location_from_handle(handle)
|
||||
lines = [loc.name]
|
||||
while loc.parent is not None:
|
||||
loc = self.db.get_location_from_handle(loc.parent)
|
||||
lines.append(loc.name)
|
||||
self.append(row=[', '.join(lines), handle])
|
||||
|
@ -27,10 +27,22 @@
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .editsecondary import EditSecondary
|
||||
from gramps.gen.db import DbTxn
|
||||
from editsecondary import EditSecondary
|
||||
from ..glade import Glade
|
||||
from ..widgets import MonitoredEntry
|
||||
from gramps.gen.errors import ValidationError
|
||||
from gramps.gen.utils.place import conv_lat_lon
|
||||
from ..widgets import MonitoredEntry, LocationEntry
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
from ..selectors import SelectorFactory
|
||||
from ..dialog import ErrorDialog
|
||||
|
||||
SelectLocation = SelectorFactory('Location')
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
LOCATIONTYPES = [_('Country'), _('State'), _('County'), _('City'),
|
||||
_('Parish'), _('Locality'), _('Street')]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -47,72 +59,148 @@ class EditLocation(EditSecondary):
|
||||
self.width_key = 'interface.location-width'
|
||||
self.height_key = 'interface.location-height'
|
||||
self.top = Glade()
|
||||
self.set_window(self.top.toplevel, None,
|
||||
_('Location Editor'))
|
||||
self.set_window(self.top.toplevel, None, _('Location Editor'))
|
||||
|
||||
def _setup_fields(self):
|
||||
self.street = MonitoredEntry(
|
||||
self.top.get_object("street"),
|
||||
self.obj.set_street,
|
||||
self.obj.get_street,
|
||||
self.name = MonitoredEntry(self.top.get_object("entry1"),
|
||||
self.obj.set_name,
|
||||
self.obj.get_name,
|
||||
self.db.readonly)
|
||||
|
||||
self.longitude = MonitoredEntry(
|
||||
self.top.get_object("lon_entry"),
|
||||
self.obj.set_longitude, self.obj.get_longitude,
|
||||
self.db.readonly)
|
||||
self.longitude.connect("validate", self._validate_coordinate, "lon")
|
||||
#force validation now with initial entry
|
||||
self.top.get_object("lon_entry").validate(force=True)
|
||||
|
||||
self.locality = MonitoredEntry(
|
||||
self.top.get_object("locality"),
|
||||
self.obj.set_locality,
|
||||
self.obj.get_locality,
|
||||
self.latitude = MonitoredEntry(
|
||||
self.top.get_object("lat_entry"),
|
||||
self.obj.set_latitude, self.obj.get_latitude,
|
||||
self.db.readonly)
|
||||
self.latitude.connect("validate", self._validate_coordinate, "lat")
|
||||
#force validation now with initial entry
|
||||
self.top.get_object("lat_entry").validate(force=True)
|
||||
|
||||
self.loc_type = self.top.get_object('combobox1')
|
||||
active_iter = None
|
||||
model = Gtk.ListStore(int, str)
|
||||
for key, value in enumerate(LOCATIONTYPES):
|
||||
_iter = model.append((key+1, value))
|
||||
if key+1 == self.obj.get_type():
|
||||
active_iter = _iter
|
||||
self.loc_type.set_model(model)
|
||||
cell = Gtk.CellRendererText()
|
||||
self.loc_type.pack_start(cell, True)
|
||||
self.loc_type.add_attribute(cell, 'text', 1)
|
||||
if active_iter is not None:
|
||||
self.loc_type.set_active_iter(active_iter)
|
||||
|
||||
self.city = MonitoredEntry(
|
||||
self.top.get_object("city"),
|
||||
self.obj.set_city,
|
||||
self.obj.get_city,
|
||||
self.db.readonly)
|
||||
|
||||
self.state = MonitoredEntry(
|
||||
self.top.get_object("state"),
|
||||
self.obj.set_state,
|
||||
self.obj.get_state,
|
||||
self.db.readonly)
|
||||
|
||||
self.postal = MonitoredEntry(
|
||||
self.top.get_object("postal"),
|
||||
self.obj.set_postal_code,
|
||||
self.obj.get_postal_code,
|
||||
self.db.readonly)
|
||||
|
||||
self.phone = MonitoredEntry(
|
||||
self.top.get_object("phone"),
|
||||
self.obj.set_phone,
|
||||
self.obj.get_phone,
|
||||
self.db.readonly)
|
||||
|
||||
self.parish = MonitoredEntry(
|
||||
self.top.get_object("parish"),
|
||||
self.obj.set_parish,
|
||||
self.obj.get_parish,
|
||||
self.db.readonly)
|
||||
|
||||
self.county = MonitoredEntry(
|
||||
self.top.get_object("county"),
|
||||
self.obj.set_county,
|
||||
self.obj.get_county,
|
||||
self.db.readonly)
|
||||
|
||||
self.country = MonitoredEntry(
|
||||
self.top.get_object("country"),
|
||||
self.obj.set_country,
|
||||
self.obj.get_country,
|
||||
self.db.readonly)
|
||||
self.parent = self.top.get_object('label4')
|
||||
parent_loc = self.db.get_location_from_handle(self.obj.parent)
|
||||
if parent_loc:
|
||||
self.parent.set_text(parent_loc.get_name())
|
||||
else:
|
||||
self.parent.set_text(_('None'))
|
||||
|
||||
button = self.top.get_object('button1')
|
||||
button.connect('clicked', self.select_parent)
|
||||
|
||||
self.sibling_names = []
|
||||
for handle in self.db.find_location_child_handles(self.obj.parent):
|
||||
location = self.db.get_location_from_handle(handle)
|
||||
name = location.get_name()
|
||||
if name != self.obj.get_name():
|
||||
self.sibling_names.append(name)
|
||||
|
||||
def _validate_coordinate(self, widget, text, typedeg):
|
||||
if (typedeg == 'lat') and not conv_lat_lon(text, "0", "ISO-D"):
|
||||
return ValidationError(_(u"Invalid latitude (syntax: 18\u00b09'") +
|
||||
_('48.21"S, -18.2412 or -18:9:48.21)'))
|
||||
elif (typedeg == 'lon') and not conv_lat_lon("0", text, "ISO-D"):
|
||||
return ValidationError(_(u"Invalid longitude (syntax: 18\u00b09'") +
|
||||
_('48.21"E, -18.2412 or -18:9:48.21)'))
|
||||
|
||||
def select_parent(self, button):
|
||||
skip_list = []
|
||||
sel = SelectLocation(self.dbstate, self.uistate, self.track)
|
||||
parent = sel.run()
|
||||
if parent:
|
||||
self.parent.set_text(parent.get_name())
|
||||
self.obj.parent = parent.get_handle()
|
||||
|
||||
def _connect_signals(self):
|
||||
self.ok_button = self.top.get_object('button118')
|
||||
self.define_cancel_button(self.top.get_object('button119'))
|
||||
self.define_ok_button(self.top.get_object('button118'),self.save)
|
||||
self.define_ok_button(self.ok_button, self.save)
|
||||
self.define_help_button(self.top.get_object('button128'))
|
||||
|
||||
def save(self,*obj):
|
||||
|
||||
self.ok_button.set_sensitive(False)
|
||||
|
||||
model = self.loc_type.get_model()
|
||||
loc_type = model.get_value(self.loc_type.get_active_iter(), 0)
|
||||
self.obj.set_type(loc_type)
|
||||
|
||||
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
|
||||
|
||||
if self.obj.get_name() in self.sibling_names:
|
||||
msg1 = _("Cannot save location. Name already exists.")
|
||||
msg2 = _("You have attempted to use a name that is already "
|
||||
"used at this level in the location hierarchy.'")
|
||||
ErrorDialog(msg1, msg2)
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
if not self.obj.handle:
|
||||
with DbTxn(_("Add Location (%s)") % self.obj.get_name(),
|
||||
self.db) as trans:
|
||||
self.db.add_location(self.obj, trans)
|
||||
else:
|
||||
orig = self.db.get_location_from_handle(self.obj.handle)
|
||||
if self.obj.parent != orig.parent:
|
||||
# Location has moved in the tree
|
||||
for handle in self.db.find_location_child_handles(self.obj.parent):
|
||||
location = self.db.get_location_from_handle(handle)
|
||||
name = location.get_name()
|
||||
if name == self.obj.get_name():
|
||||
with DbTxn(_("Merge Location (%s)") % self.obj.get_name(),
|
||||
self.db) as trans:
|
||||
self.merge(location, self.obj, trans)
|
||||
|
||||
if cmp(self.obj.serialize(), orig.serialize()):
|
||||
with DbTxn(_("Edit Location (%s)") % self.obj.get_name(),
|
||||
self.db) as trans:
|
||||
self.db.commit_location(self.obj, trans)
|
||||
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
self.close()
|
||||
|
||||
def merge(self, location1, location2, trans):
|
||||
"""
|
||||
Merge location2 into location1.
|
||||
"""
|
||||
children = {}
|
||||
for handle in self.db.find_location_child_handles(location1.handle):
|
||||
child = self.db.get_location_from_handle(handle)
|
||||
children[child.get_name()] = child.handle
|
||||
|
||||
for handle in self.db.find_location_child_handles(location2.handle):
|
||||
child2 = self.db.get_location_from_handle(handle)
|
||||
if child2.get_name() in children:
|
||||
handle = children[child2.get_name()]
|
||||
child1 = self.db.get_location_from_handle(handle)
|
||||
self.merge(child1, child2, trans)
|
||||
else:
|
||||
child2.parent = location1.handle
|
||||
self.db.commit_location(child2, trans)
|
||||
|
||||
self.db.remove_location(location2.handle, trans)
|
||||
|
@ -28,8 +28,6 @@
|
||||
# python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
import logging
|
||||
log = logging.getLogger(".")
|
||||
@ -48,12 +46,10 @@ 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 editprimary import EditPrimary
|
||||
from displaytabs import (GrampsTab, LocationEmbedList, CitationEmbedList,
|
||||
GalleryTab, NoteTab, WebEmbedList, PlaceBackRefList)
|
||||
from ..widgets import MonitoredEntry, PrivacyButton
|
||||
from gramps.gen.errors import ValidationError
|
||||
from gramps.gen.utils.place import conv_lat_lon
|
||||
from ..widgets import MonitoredEntry, PrivacyButton, LocationEntry
|
||||
from ..dialog import ErrorDialog
|
||||
from ..glade import Glade
|
||||
|
||||
@ -123,12 +119,12 @@ class EditPlace(EditPrimary):
|
||||
|
||||
self.set_window(self.top.toplevel, None,
|
||||
self.get_menu_title())
|
||||
tblmloc = self.top.get_object('table19')
|
||||
self.tblmloc = self.top.get_object('loc_table')
|
||||
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)
|
||||
_('_Location'), self.tblmloc)
|
||||
self.track_ref_for_deletion("mloc")
|
||||
|
||||
|
||||
@ -154,24 +150,11 @@ 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.gid = MonitoredEntry(self.top.get_object("gid"),
|
||||
self.obj.set_gramps_id,
|
||||
self.obj.get_gramps_id, self.db.readonly)
|
||||
@ -179,54 +162,6 @@ 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.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.longitude = MonitoredEntry(
|
||||
self.top.get_object("lon_entry"),
|
||||
self.obj.set_longitude, self.obj.get_longitude,
|
||||
self.db.readonly)
|
||||
self.longitude.connect("validate", self._validate_coordinate, "lon")
|
||||
#force validation now with initial entry
|
||||
self.top.get_object("lon_entry").validate(force=True)
|
||||
|
||||
self.latitude = MonitoredEntry(
|
||||
self.top.get_object("lat_entry"),
|
||||
self.obj.set_latitude, self.obj.get_latitude,
|
||||
self.db.readonly)
|
||||
self.latitude.connect("validate", self._validate_coordinate, "lat")
|
||||
#force validation now with initial entry
|
||||
self.top.get_object("lat_entry").validate(force=True)
|
||||
|
||||
def _validate_coordinate(self, widget, text, typedeg):
|
||||
if (typedeg == 'lat') and not conv_lat_lon(text, "0", "ISO-D"):
|
||||
return ValidationError(_("Invalid latitude (syntax: 18\u00b09'") +
|
||||
_('48.21"S, -18.2412 or -18:9:48.21)'))
|
||||
elif (typedeg == 'lon') and not conv_lat_lon("0", text, "ISO-D"):
|
||||
return ValidationError(_("Invalid longitude (syntax: 18\u00b09'") +
|
||||
_('48.21"E, -18.2412 or -18:9:48.21)'))
|
||||
|
||||
def build_menu_names(self, place):
|
||||
return (_('Edit Place'), self.get_menu_title())
|
||||
|
||||
@ -240,6 +175,9 @@ class EditPlace(EditPrimary):
|
||||
|
||||
self._add_tab(notebook, self.mloc)
|
||||
|
||||
handle = self.obj.get_main_location()
|
||||
self.lentry = LocationEntry(self.tblmloc, self.dbstate.db, handle)
|
||||
|
||||
self.loc_list = LocationEmbedList(self.dbstate,
|
||||
self.uistate,
|
||||
self.track,
|
||||
@ -311,6 +249,16 @@ class EditPlace(EditPrimary):
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
handle, new_locations = self.lentry.get_result()
|
||||
with DbTxn(_('Add location'), self.dbstate.db) as trans:
|
||||
for loc_type, name in new_locations:
|
||||
new_location = gen.lib.Location()
|
||||
new_location.parent = handle
|
||||
new_location.name = name
|
||||
new_location.set_type(loc_type)
|
||||
handle = self.dbstate.db.add_location(new_location, trans)
|
||||
self.obj.set_main_location(handle)
|
||||
|
||||
with DbTxn('', self.db) as trans:
|
||||
if not self.obj.get_handle():
|
||||
self.db.add_place(self.obj, trans)
|
||||
|
@ -71,7 +71,6 @@ from ..selectors import SelectorFactory
|
||||
from gramps.gen.display.name import displayer as _nd
|
||||
from gramps.gen.utils.db import family_name
|
||||
from gramps.gen.utils.string import confidence
|
||||
from gramps.gen.constfunc import cuni
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -107,6 +106,14 @@ _name2typeclass = {
|
||||
_('Surname origin type:'): NameOriginType,
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Sorting function for the filter rules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def by_rule_name(f, s):
|
||||
return cmp(f.name, s.name)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# MyBoolean - check button with standard interface
|
||||
@ -330,7 +337,7 @@ class MyID(Gtk.Box):
|
||||
self.set_text(val.get_gramps_id())
|
||||
|
||||
def get_text(self):
|
||||
return cuni(self.entry.get_text())
|
||||
return unicode(self.entry.get_text())
|
||||
|
||||
def name_from_gramps_id(self, gramps_id):
|
||||
if self.namespace == 'Person':
|
||||
@ -422,6 +429,25 @@ class MyEntry(Gtk.Entry):
|
||||
GObject.GObject.__init__(self)
|
||||
self.show()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# MyLocation
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class MyLocation(Gtk.HBox):
|
||||
|
||||
def __init__(self, dbstate):
|
||||
Gtk.HBox.__init__(self)
|
||||
self.location = LocationEntry2(dbstate)
|
||||
self.pack_start(self.location)
|
||||
self.show_all()
|
||||
|
||||
def get_text(self):
|
||||
return self.location.get_handle()
|
||||
|
||||
def set_text(self, handle):
|
||||
self.location.set_handle(handle)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# EditRule
|
||||
@ -550,8 +576,10 @@ class EditRule(ManagedWindow):
|
||||
taglist = taglist + [tag.get_name() for tag in dbstate.db.iter_tags()]
|
||||
t = MyList(taglist, taglist)
|
||||
elif v == _('Confidence level:'):
|
||||
t = MyList(list(map(str, list(range(5)))),
|
||||
t = MyList(map(str, range(5)),
|
||||
[confidence[i] for i in range(5)])
|
||||
elif v == _('Location:'):
|
||||
t = MyLocation(dbstate)
|
||||
else:
|
||||
t = MyEntry()
|
||||
tlist.append(t)
|
||||
@ -589,7 +617,7 @@ class EditRule(ManagedWindow):
|
||||
else:
|
||||
self.sel_class = None
|
||||
|
||||
keys = sorted(the_map, key=lambda x: x.name, reverse=True)
|
||||
keys = sorted(the_map, by_rule_name, reverse=True)
|
||||
catlist = sorted(set(class_obj.category for class_obj in keys))
|
||||
|
||||
for category in catlist:
|
||||
@ -614,7 +642,7 @@ class EditRule(ManagedWindow):
|
||||
self.notebook.set_current_page(page)
|
||||
self.display_values(self.active_rule.__class__)
|
||||
(class_obj, vallist, tlist) = self.page[page]
|
||||
r = list(self.active_rule.values())
|
||||
r = self.active_rule.values()
|
||||
for i in range(0, min(len(tlist), len(r))):
|
||||
tlist[i].set_text(r[i])
|
||||
|
||||
@ -701,7 +729,7 @@ class EditRule(ManagedWindow):
|
||||
try:
|
||||
page = self.notebook.get_current_page()
|
||||
(class_obj, vallist, tlist) = self.page[page]
|
||||
value_list = [cuni(sclass.get_text()) for sclass in tlist]
|
||||
value_list = [unicode(sclass.get_text()) for sclass in tlist]
|
||||
new_rule = class_obj(value_list)
|
||||
|
||||
self.update_rule(self.active_rule, new_rule)
|
||||
@ -783,7 +811,7 @@ class EditFilter(ManagedWindow):
|
||||
self.close()
|
||||
|
||||
def filter_name_changed(self, obj):
|
||||
name = cuni(self.fname.get_text())
|
||||
name = unicode(self.fname.get_text())
|
||||
# Make sure that the name is not empty
|
||||
# and not in the list of existing filters (excluding this one)
|
||||
names = [filt.get_name()
|
||||
@ -806,14 +834,14 @@ class EditFilter(ManagedWindow):
|
||||
self.rlist.add([r.name,r.display_values()],r)
|
||||
|
||||
def on_ok_clicked(self, obj):
|
||||
n = cuni(self.fname.get_text()).strip()
|
||||
n = unicode(self.fname.get_text()).strip()
|
||||
if n == '':
|
||||
return
|
||||
if n != self.filter.get_name():
|
||||
self.uistate.emit('filter-name-changed',
|
||||
(self.namespace, cuni(self.filter.get_name()), n))
|
||||
(self.namespace,unicode(self.filter.get_name()), n))
|
||||
self.filter.set_name(n)
|
||||
self.filter.set_comment(cuni(self.comment.get_text()).strip())
|
||||
self.filter.set_comment(unicode(self.comment.get_text()).strip())
|
||||
for f in self.filterdb.get_filters(self.namespace)[:]:
|
||||
if n == f.get_name():
|
||||
self.filterdb.get_filters(self.namespace).remove(f)
|
||||
@ -946,7 +974,7 @@ class ShowResults(ManagedWindow):
|
||||
gid = repo.get_gramps_id()
|
||||
elif self.namespace == 'Note':
|
||||
note = self.db.get_note_from_handle(handle)
|
||||
name = note.get().replace('\n', ' ')
|
||||
name = note.get().replace(u'\n', u' ')
|
||||
if len(name) > 80:
|
||||
name = name[:80]+"..."
|
||||
gid = note.get_gramps_id()
|
||||
@ -1121,7 +1149,7 @@ class FilterEditor(ManagedWindow):
|
||||
|
||||
# Remove what we found
|
||||
filters = self.filterdb.get_filters(space)
|
||||
list(map(filters.remove, filter_set))
|
||||
map(filters.remove, filter_set)
|
||||
|
||||
def _find_dependent_filters(self, space, gfilter, filter_set):
|
||||
"""
|
||||
@ -1137,7 +1165,7 @@ class FilterEditor(ManagedWindow):
|
||||
if the_filter.get_name() == name:
|
||||
continue
|
||||
for rule in the_filter.get_rules():
|
||||
values = list(rule.values())
|
||||
values = rule.values()
|
||||
if issubclass(rule.__class__, MatchesFilterBase) \
|
||||
and (name in values):
|
||||
self._find_dependent_filters(space, the_filter, filter_set)
|
||||
@ -1175,7 +1203,7 @@ class FilterEditor(ManagedWindow):
|
||||
|
||||
for the_filter in self.filterdb.get_filters(space):
|
||||
for rule in the_filter.get_rules():
|
||||
values = list(rule.values())
|
||||
values = rule.values()
|
||||
if issubclass(rule.__class__, MatchesFilterBase) \
|
||||
and (old_name in values):
|
||||
ind = values.index(old_name)
|
||||
@ -1184,7 +1212,7 @@ class FilterEditor(ManagedWindow):
|
||||
def check_recursive_filters(self, space, name):
|
||||
for the_filter in self.filterdb.get_filters(space):
|
||||
for rule in the_filter.get_rules():
|
||||
values = list(rule.values())
|
||||
values = rule.values()
|
||||
if issubclass(rule.__class__, MatchesFilterBase) \
|
||||
and (name in values):
|
||||
return True
|
||||
|
@ -44,9 +44,8 @@ from gi.repository import Gtk
|
||||
from ... import widgets
|
||||
from .. import build_filter_model
|
||||
from . import SidebarFilter
|
||||
from gramps.gen.constfunc import cuni
|
||||
from gramps.gen.filters import GenericFilterFactory, rules
|
||||
from gramps.gen.filters.rules.place import (RegExpIdOf, HasIdOf, HasPlace,
|
||||
from gramps.gen.filters.rules.place import (RegExpIdOf, HasIdOf, HasLocation,
|
||||
HasNoteRegexp, HasNoteMatchingSubstringOf,
|
||||
MatchesFilter)
|
||||
|
||||
@ -63,14 +62,7 @@ class PlaceSidebarFilter(SidebarFilter):
|
||||
|
||||
self.filter_id = widgets.BasicEntry()
|
||||
self.filter_title = widgets.BasicEntry()
|
||||
self.filter_street = widgets.BasicEntry()
|
||||
self.filter_locality = widgets.BasicEntry()
|
||||
self.filter_city = widgets.BasicEntry()
|
||||
self.filter_county = widgets.BasicEntry()
|
||||
self.filter_state = widgets.BasicEntry()
|
||||
self.filter_country = widgets.BasicEntry()
|
||||
self.filter_zip = widgets.BasicEntry()
|
||||
self.filter_parish = widgets.BasicEntry()
|
||||
self.filter_location = widgets.LocationEntry2(dbstate)
|
||||
self.filter_note = widgets.BasicEntry()
|
||||
|
||||
self.filter_regex = Gtk.CheckButton(_('Use regular expressions'))
|
||||
@ -88,49 +80,28 @@ class PlaceSidebarFilter(SidebarFilter):
|
||||
|
||||
self.add_text_entry(_('ID'), self.filter_id)
|
||||
self.add_text_entry(_('Place Name'), self.filter_title)
|
||||
self.add_text_entry(_('Street'), self.filter_street)
|
||||
self.add_text_entry(_('Locality'), self.filter_locality)
|
||||
self.add_text_entry(_('City'), self.filter_city)
|
||||
self.add_text_entry(_('County'), self.filter_county)
|
||||
self.add_text_entry(_('State'), self.filter_state)
|
||||
self.add_text_entry(_('Country'), self.filter_country)
|
||||
self.add_text_entry(_('ZIP/Postal code'), self.filter_zip)
|
||||
self.add_text_entry(_('Church parish'), self.filter_parish)
|
||||
self.add_text_entry(_('Location'), self.filter_location)
|
||||
self.add_text_entry(_('Note'), self.filter_note)
|
||||
|
||||
self.add_filter_entry(_('Custom filter'), self.generic)
|
||||
self.add_regex_entry(self.filter_regex)
|
||||
|
||||
def clear(self, obj):
|
||||
self.filter_id.set_text('')
|
||||
self.filter_title.set_text('')
|
||||
self.filter_street.set_text('')
|
||||
self.filter_locality.set_text('')
|
||||
self.filter_city.set_text('')
|
||||
self.filter_county.set_text('')
|
||||
self.filter_state.set_text('')
|
||||
self.filter_country.set_text('')
|
||||
self.filter_zip.set_text('')
|
||||
self.filter_parish.set_text('')
|
||||
self.filter_location.set_text('')
|
||||
self.filter_note.set_text('')
|
||||
self.generic.set_active(0)
|
||||
|
||||
def get_filter(self):
|
||||
gid = cuni(self.filter_id.get_text()).strip()
|
||||
title = cuni(self.filter_title.get_text()).strip()
|
||||
street = cuni(self.filter_street.get_text()).strip()
|
||||
locality = cuni(self.filter_locality.get_text()).strip()
|
||||
city = cuni(self.filter_city.get_text()).strip()
|
||||
county = cuni(self.filter_county.get_text()).strip()
|
||||
state = cuni(self.filter_state.get_text()).strip()
|
||||
country = cuni(self.filter_country.get_text()).strip()
|
||||
zipc = cuni(self.filter_zip.get_text()).strip()
|
||||
parish = cuni(self.filter_parish.get_text()).strip()
|
||||
note = cuni(self.filter_note.get_text()).strip()
|
||||
gid = unicode(self.filter_id.get_text()).strip()
|
||||
title = unicode(self.filter_title.get_text()).strip()
|
||||
location = self.filter_location.get_handle()
|
||||
note = unicode(self.filter_note.get_text()).strip()
|
||||
regex = self.filter_regex.get_active()
|
||||
gen = self.generic.get_active() > 0
|
||||
|
||||
empty = not (gid or title or street or locality or city or county or
|
||||
state or country or zipc or parish or note or regex or gen)
|
||||
empty = not (gid or title or location or note or regex or gen)
|
||||
if empty:
|
||||
generic_filter = None
|
||||
else:
|
||||
@ -141,10 +112,10 @@ class PlaceSidebarFilter(SidebarFilter):
|
||||
else:
|
||||
rule = HasIdOf([gid])
|
||||
generic_filter.add_rule(rule)
|
||||
|
||||
rule = HasPlace([title, street, locality, city, county, state,
|
||||
country, zipc, parish], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
|
||||
if location:
|
||||
rule = HasLocation([location])
|
||||
generic_filter.add_rule(rule)
|
||||
|
||||
if note:
|
||||
if regex:
|
||||
@ -156,7 +127,7 @@ class PlaceSidebarFilter(SidebarFilter):
|
||||
if self.generic.get_active() != 0:
|
||||
model = self.generic.get_model()
|
||||
node = self.generic.get_active_iter()
|
||||
obj = cuni(model.get_value(node, 0))
|
||||
obj = unicode(model.get_value(node, 0))
|
||||
rule = MatchesFilter([obj])
|
||||
generic_filter.add_rule(rule)
|
||||
|
||||
|
@ -17,12 +17,10 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="button119">
|
||||
<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>
|
||||
@ -34,13 +32,11 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="button118">
|
||||
<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>
|
||||
@ -52,12 +48,10 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="button128">
|
||||
<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>
|
||||
@ -84,7 +78,7 @@
|
||||
<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="n_columns">3</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<child>
|
||||
@ -92,10 +86,9 @@
|
||||
<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="label" translatable="yes">Parent:</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>
|
||||
@ -104,79 +97,28 @@
|
||||
<property name="y_options"/>
|
||||
</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.</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"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label663">
|
||||
<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="label" translatable="yes">Name:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="mnemonic_widget">city</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label184">
|
||||
<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"/>
|
||||
</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"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label181">
|
||||
<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="label" translatable="yes">Latitude:</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>
|
||||
@ -185,64 +127,14 @@
|
||||
<property name="y_options"/>
|
||||
</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"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label183">
|
||||
<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"/>
|
||||
</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"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label182">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Cou_ntry:</property>
|
||||
<property name="label" translatable="yes">Longitude:</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>
|
||||
@ -251,106 +143,13 @@
|
||||
<property name="y_options"/>
|
||||
</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"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label297">
|
||||
<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="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"/>
|
||||
</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"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label296">
|
||||
<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"/>
|
||||
</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"/>
|
||||
</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.</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="y_options"/>
|
||||
</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="label" translatable="yes">Type:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">locality</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
@ -360,17 +159,85 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="locality">
|
||||
<object class="GtkEntry" id="entry1">
|
||||
<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.</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="invisible_char">•</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label4">
|
||||
<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="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="ValidatableMaskedEntry" id="lat_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">3</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="ValidatableMaskedEntry" id="lon_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button1">
|
||||
<property name="label" translatable="yes">...</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</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"/>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
|
@ -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,13 +76,10 @@
|
||||
<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">2</property>
|
||||
<property name="n_columns">4</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>
|
||||
@ -104,42 +95,6 @@
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label249">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">L_atitude:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="mnemonic_widget">lat_entry</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="label250">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">_Longitude:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="mnemonic_widget">lon_entry</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="place_title">
|
||||
<property name="visible">True</property>
|
||||
@ -163,8 +118,8 @@
|
||||
<property name="mnemonic_widget">gid</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_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>
|
||||
@ -179,18 +134,16 @@
|
||||
<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="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options"/>
|
||||
</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">
|
||||
@ -214,45 +167,14 @@
|
||||
<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">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"/>
|
||||
<property name="y_options"/>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="ValidatableMaskedEntry" id="lat_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Latitude (position above the Equator) of the place in decimal or degree notation.
|
||||
Eg, valid values are 12.0154, 50°52′21.92″N, N50°52′21.92″ or 50:52:21.92
|
||||
You can set these values via the Geography View by searching the place, or via a map service in the place view.</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="ValidatableMaskedEntry" id="lon_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Longitude (position relative to the Prime, or Greenwich, Meridian) of the place in decimal or degree notation.
|
||||
Eg, valid values are -124.3647, 124°52′21.92″E, E124°52′21.92″ or 124:52:21.92
|
||||
You can set these values via the Geography View by searching the place, or via a map service in the place view.</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"/>
|
||||
</packing>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
@ -266,305 +188,17 @@ 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">
|
||||
<object class="GtkTable" id="loc_table">
|
||||
<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"/>
|
||||
</packing>
|
||||
<placeholder/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</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"/>
|
||||
</packing>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
70
gramps/gui/selectors/selectlocation.py
Normal file
70
gramps/gui/selectors/selectlocation.py
Normal file
@ -0,0 +1,70 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2003-2006 Donald N. Allingham
|
||||
# Copyright (C) 2009-2010 Gary Burton
|
||||
# Copyright (C) 2010 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# internationalization
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ..views.treemodels.locationmodel import LocationTreeModel
|
||||
from baseselector import BaseSelector
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# SelectLocation
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class SelectLocation(BaseSelector):
|
||||
|
||||
def _local_init(self):
|
||||
"""
|
||||
Perform local initialisation for this class
|
||||
"""
|
||||
self.width_key = 'interface.place-sel-width'
|
||||
self.height_key = 'interface.place-sel-height'
|
||||
|
||||
def get_window_title(self):
|
||||
return _("Select Location")
|
||||
|
||||
def get_model_class(self):
|
||||
return LocationTreeModel
|
||||
|
||||
def get_column_titles(self):
|
||||
return [
|
||||
(_('Name'), 350, BaseSelector.TEXT, 0),
|
||||
(_('Type'), 75, BaseSelector.TEXT, 1),
|
||||
]
|
||||
|
||||
def get_from_handle_func(self):
|
||||
return self.db.get_location_from_handle
|
||||
|
||||
def get_handle_column(self):
|
||||
return LocationTreeModel.HANDLE_COL
|
@ -21,35 +21,38 @@
|
||||
|
||||
# $Id$
|
||||
|
||||
from .selectorexceptions import SelectorException
|
||||
from selectorexceptions import SelectorException
|
||||
|
||||
def SelectorFactory(classname):
|
||||
if classname == 'Person':
|
||||
from .selectperson import SelectPerson
|
||||
from selectperson import SelectPerson
|
||||
cls = SelectPerson
|
||||
elif classname == 'Family':
|
||||
from .selectfamily import SelectFamily
|
||||
from selectfamily import SelectFamily
|
||||
cls = SelectFamily
|
||||
elif classname == 'Event':
|
||||
from .selectevent import SelectEvent
|
||||
from selectevent import SelectEvent
|
||||
cls = SelectEvent
|
||||
elif classname == 'Place':
|
||||
from .selectplace import SelectPlace
|
||||
from selectplace import SelectPlace
|
||||
cls = SelectPlace
|
||||
elif classname == 'Location':
|
||||
from selectlocation import SelectLocation
|
||||
cls = SelectLocation
|
||||
elif classname == 'Source':
|
||||
from .selectsource import SelectSource
|
||||
from selectsource import SelectSource
|
||||
cls = SelectSource
|
||||
elif classname == 'Citation':
|
||||
from .selectcitation import SelectCitation
|
||||
from selectcitation import SelectCitation
|
||||
cls = SelectCitation
|
||||
elif classname in ['MediaObject', 'Media']:
|
||||
from .selectobject import SelectObject
|
||||
from selectobject import SelectObject
|
||||
cls = SelectObject
|
||||
elif classname == 'Repository':
|
||||
from .selectrepository import SelectRepository
|
||||
from selectrepository import SelectRepository
|
||||
cls = SelectRepository
|
||||
elif classname == 'Note':
|
||||
from .selectnote import SelectNote
|
||||
from selectnote import SelectNote
|
||||
cls = SelectNote
|
||||
else:
|
||||
raise SelectorException("Attempt to create unknown "
|
||||
|
@ -35,7 +35,7 @@ from gramps.gen.ggettext import gettext as _
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ..views.treemodels.placemodel import PlaceListModel
|
||||
from .baseselector import BaseSelector
|
||||
from baseselector import BaseSelector
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -59,15 +59,9 @@ class SelectPlace(BaseSelector):
|
||||
|
||||
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),
|
||||
(_('Title'), 350, BaseSelector.TEXT, 0),
|
||||
(_('ID'), 75, BaseSelector.TEXT, 1),
|
||||
(_('Location'), 350, BaseSelector.TEXT, 2),
|
||||
]
|
||||
|
||||
def get_from_handle_func(self):
|
||||
|
@ -24,14 +24,15 @@
|
||||
Package init for the treemodels package.
|
||||
"""
|
||||
|
||||
from .peoplemodel import PeopleBaseModel, PersonListModel, PersonTreeModel
|
||||
from .familymodel import FamilyModel
|
||||
from .eventmodel import EventModel
|
||||
from .sourcemodel import SourceModel
|
||||
from .placemodel import PlaceBaseModel, PlaceListModel, PlaceTreeModel
|
||||
from .mediamodel import MediaModel
|
||||
from .repomodel import RepositoryModel
|
||||
from .notemodel import NoteModel
|
||||
from .citationbasemodel import CitationBaseModel
|
||||
from .citationlistmodel import CitationListModel
|
||||
from .citationtreemodel import CitationTreeModel
|
||||
from peoplemodel import PeopleBaseModel, PersonListModel, PersonTreeModel
|
||||
from familymodel import FamilyModel
|
||||
from eventmodel import EventModel
|
||||
from sourcemodel import SourceModel
|
||||
from placemodel import PlaceBaseModel, PlaceListModel, PlaceTreeModel
|
||||
from locationmodel import LocationTreeModel
|
||||
from mediamodel import MediaModel
|
||||
from repomodel import RepositoryModel
|
||||
from notemodel import NoteModel
|
||||
from citationbasemodel import CitationBaseModel
|
||||
from citationlistmodel import CitationListModel
|
||||
from citationtreemodel import CitationTreeModel
|
||||
|
252
gramps/gui/views/treemodels/locationmodel.py
Normal file
252
gramps/gui/views/treemodels/locationmodel.py
Normal file
@ -0,0 +1,252 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# Copyright (C) 2009-2010 Nick Hall
|
||||
# Copyright (C) 2009 Benny Malengier
|
||||
# Copyright (C) 2010 Gary Burton
|
||||
#
|
||||
# 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 Model.
|
||||
"""
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import cgi
|
||||
import logging
|
||||
_LOG = logging.getLogger(".gui.views.treemodels.locationmodel")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GNOME/GTK modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.datehandler import format_time
|
||||
from gramps.gen.utils.place import conv_lat_lon
|
||||
from .flatbasemodel import FlatBaseModel
|
||||
from .treebasemodel import TreeBaseModel
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# internationalization
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
LOCATIONTYPES = [_('Country'), _('State'), _('County'), _('City'),
|
||||
_('Parish'), _('Locality'), _('Street')]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# LocationBaseModel
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class LocationBaseModel(object):
|
||||
|
||||
HANDLE_COL = 5
|
||||
|
||||
def __init__(self, db):
|
||||
self.gen_cursor = db.get_location_cursor
|
||||
self.map = db.get_raw_location_data
|
||||
self.fmap = [
|
||||
self.column_name,
|
||||
self.column_type,
|
||||
self.column_latitude,
|
||||
self.column_longitude,
|
||||
self.column_change,
|
||||
self.column_handle,
|
||||
]
|
||||
self.smap = [
|
||||
self.column_name,
|
||||
self.column_type,
|
||||
self.sort_latitude,
|
||||
self.sort_longitude,
|
||||
self.sort_change,
|
||||
self.column_handle,
|
||||
]
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
self.db = None
|
||||
self.gen_cursor = None
|
||||
self.map = None
|
||||
self.fmap = None
|
||||
self.smap = None
|
||||
|
||||
def on_get_n_columns(self):
|
||||
return len(self.fmap)+1
|
||||
|
||||
def column_handle(self, data):
|
||||
return unicode(data[0])
|
||||
|
||||
def column_name(self, data):
|
||||
return unicode(data[2])
|
||||
|
||||
def column_type(self, data):
|
||||
return LOCATIONTYPES[data[3]-1]
|
||||
|
||||
def column_latitude(self, data):
|
||||
if not data[4]:
|
||||
return u' '
|
||||
value = conv_lat_lon(data[4], '0', format='DEG')[0]
|
||||
if not value:
|
||||
return _("Error in format")
|
||||
return value
|
||||
|
||||
def column_longitude(self, data):
|
||||
if not data[5]:
|
||||
return u' '
|
||||
value = conv_lat_lon('0', data[5], format='DEG')[1]
|
||||
if not value:
|
||||
return _("Error in format")
|
||||
return value
|
||||
|
||||
def sort_latitude(self, data):
|
||||
if not data[4]:
|
||||
return u' '
|
||||
value = conv_lat_lon(data[4], '0', format='ISO-DMS') if data[4] else u''
|
||||
if not value:
|
||||
return _("Error in format")
|
||||
return value
|
||||
|
||||
def sort_longitude(self, data):
|
||||
if not data[5]:
|
||||
return u' '
|
||||
value = conv_lat_lon('0', data[5], format='ISO-DMS') if data[5] else u''
|
||||
if not value:
|
||||
return _("Error in format")
|
||||
return value
|
||||
|
||||
def sort_change(self, data):
|
||||
return "%012x" % data[6]
|
||||
|
||||
def column_change(self, data):
|
||||
return Utils.format_time(data[6])
|
||||
|
||||
def column_place_name(self, data):
|
||||
return unicode(data[2])
|
||||
|
||||
def sort_place_change(self, data):
|
||||
return "%012x" % data[9]
|
||||
|
||||
def column_place_change(self, data):
|
||||
return Utils.format_time(data[9])
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# LocationTreeModel
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class LocationTreeModel(LocationBaseModel, TreeBaseModel):
|
||||
"""
|
||||
Hierarchical place model.
|
||||
"""
|
||||
def __init__(self, db, scol=0, order=Gtk.SortType.ASCENDING, search=None,
|
||||
skip=set(), sort_map=None):
|
||||
|
||||
LocationBaseModel.__init__(self, db)
|
||||
TreeBaseModel.__init__(self, db, scol=scol, order=order,
|
||||
tooltip_column=15,
|
||||
search=search, skip=skip, sort_map=sort_map,
|
||||
nrgroups = 3,
|
||||
group_can_have_handle = True,
|
||||
has_secondary=False)
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Unset all elements that can prevent garbage collection
|
||||
"""
|
||||
LocationBaseModel.destroy(self)
|
||||
self.number_items = None
|
||||
TreeBaseModel.destroy(self)
|
||||
|
||||
def _set_base_data(self):
|
||||
"""See TreeBaseModel, for place, most have been set in init of
|
||||
PlaceBaseModel
|
||||
"""
|
||||
self.number_items = self.db.get_number_of_locations
|
||||
|
||||
self.gen_cursor2 = self.db.get_place_cursor
|
||||
self.map2 = self.db.get_raw_place_data
|
||||
self.fmap2 = [
|
||||
self.column_place_name,
|
||||
lambda handle, data: u'',
|
||||
self.column_place_change,
|
||||
self.column_handle,
|
||||
]
|
||||
self.smap2 = [
|
||||
self.column_place_name,
|
||||
lambda handle, data: u'',
|
||||
self.sort_place_change,
|
||||
self.column_handle,
|
||||
]
|
||||
self.number_items2 = self.db.get_number_of_places
|
||||
|
||||
def get_tree_levels(self):
|
||||
"""
|
||||
Return the headings of the levels in the hierarchy.
|
||||
"""
|
||||
return [_('Country'), _('State'), _('County'), _('Place')]
|
||||
|
||||
def add_row(self, handle, data):
|
||||
"""
|
||||
Add nodes to the node map for a single location.
|
||||
|
||||
handle The handle of the gramps object.
|
||||
data The object data.
|
||||
"""
|
||||
sort_key = self.sort_func(data)
|
||||
parent = data[1]
|
||||
|
||||
# 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 add_row2(self, handle, data):
|
||||
"""
|
||||
Add nodes to the node map for a single place.
|
||||
|
||||
handle The handle of the gramps object.
|
||||
data The object data.
|
||||
"""
|
||||
sort_key = self.sort_func2(data)
|
||||
parent = data[5]
|
||||
|
||||
if self.get_node(parent):
|
||||
self.add_node(parent, handle, sort_key, handle, add_parent=False,
|
||||
secondary=True)
|
@ -48,7 +48,6 @@ from gi.repository import Gtk
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.datehandler import format_time
|
||||
from gramps.gen.utils.place import conv_lat_lon
|
||||
from gramps.gen.constfunc import cuni
|
||||
from .flatbasemodel import FlatBaseModel
|
||||
from .treebasemodel import TreeBaseModel
|
||||
|
||||
@ -76,7 +75,7 @@ COUNTRYLEVELS = {
|
||||
#-------------------------------------------------------------------------
|
||||
class PlaceBaseModel(object):
|
||||
|
||||
HANDLE_COL = 14
|
||||
HANDLE_COL = 5
|
||||
|
||||
def __init__(self, db):
|
||||
self.gen_cursor = db.get_place_cursor
|
||||
@ -84,16 +83,7 @@ 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_latitude,
|
||||
self.column_longitude,
|
||||
self.column_location,
|
||||
self.column_change,
|
||||
self.column_place_name,
|
||||
self.column_handle,
|
||||
@ -102,16 +92,7 @@ class PlaceBaseModel(object):
|
||||
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.sort_latitude,
|
||||
self.sort_longitude,
|
||||
self.column_location,
|
||||
self.sort_change,
|
||||
self.column_place_name,
|
||||
self.column_handle,
|
||||
@ -131,102 +112,33 @@ class PlaceBaseModel(object):
|
||||
return len(self.fmap)+1
|
||||
|
||||
def column_handle(self, data):
|
||||
return cuni(data[0])
|
||||
return unicode(data[0])
|
||||
|
||||
def column_place_name(self, data):
|
||||
return cuni(data[2])
|
||||
|
||||
def column_longitude(self, data):
|
||||
if not data[3]:
|
||||
return ''
|
||||
value = conv_lat_lon('0', data[3], format='DEG')[1]
|
||||
if not value:
|
||||
return _("Error in format")
|
||||
return value
|
||||
|
||||
def column_latitude(self, data):
|
||||
if not data[4]:
|
||||
return ''
|
||||
value = conv_lat_lon(data[4], '0', format='DEG')[0]
|
||||
if not value:
|
||||
return _("Error in format")
|
||||
return value
|
||||
|
||||
def sort_longitude(self, data):
|
||||
if not data[3]:
|
||||
return ''
|
||||
value = conv_lat_lon('0', data[3], format='ISO-DMS') if data[3] else ''
|
||||
if not value:
|
||||
return _("Error in format")
|
||||
return value
|
||||
|
||||
def sort_latitude(self, data):
|
||||
if not data[4]:
|
||||
return ''
|
||||
value = conv_lat_lon(data[4], '0', format='ISO-DMS') if data[4] else ''
|
||||
if not value:
|
||||
return _("Error in format")
|
||||
return value
|
||||
return unicode(data[2])
|
||||
|
||||
def column_id(self, data):
|
||||
return cuni(data[1])
|
||||
return unicode(data[1])
|
||||
|
||||
def column_parish(self, data):
|
||||
def column_location(self, data):
|
||||
try:
|
||||
return data[5][1]
|
||||
loc = self.db.get_location_from_handle(data[3])
|
||||
lines = [loc.name]
|
||||
while loc.parent is not None:
|
||||
loc = self.db.get_location_from_handle(loc.parent)
|
||||
lines.append(loc.name)
|
||||
return ', '.join(lines)
|
||||
except:
|
||||
return ''
|
||||
|
||||
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 ''
|
||||
return u''
|
||||
|
||||
def sort_change(self, data):
|
||||
return "%012x" % data[11]
|
||||
return "%012x" % data[9]
|
||||
|
||||
def column_change(self, data):
|
||||
return format_time(data[11])
|
||||
return format_time(data[9])
|
||||
|
||||
def column_tooltip(self, data):
|
||||
return cuni('Place tooltip')
|
||||
return u'Place tooltip'
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -252,7 +164,7 @@ class PlaceListModel(PlaceBaseModel, FlatBaseModel):
|
||||
FlatBaseModel.destroy(self)
|
||||
|
||||
def column_name(self, data):
|
||||
return cuni(data[2])
|
||||
return unicode(data[2])
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -342,16 +254,16 @@ class PlaceTreeModel(PlaceBaseModel, TreeBaseModel):
|
||||
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])
|
||||
name = unicode(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])
|
||||
name = unicode(data[2])
|
||||
|
||||
if name:
|
||||
return cgi.escape(name)
|
||||
else:
|
||||
return "<i>%s<i>" % cgi.escape(_("<no name>"))
|
||||
return u"<i>%s<i>" % cgi.escape(_("<no name>"))
|
||||
|
||||
def column_header(self, node):
|
||||
"""
|
||||
|
@ -23,23 +23,25 @@
|
||||
|
||||
"""Custom widgets."""
|
||||
|
||||
from .basicentry import *
|
||||
from .buttons import *
|
||||
from .expandcollapsearrow import *
|
||||
from .labels import *
|
||||
from .linkbox import *
|
||||
from .photo import *
|
||||
from .monitoredwidgets import *
|
||||
from .shortlistcomboentry import *
|
||||
from .springseparator import *
|
||||
from .statusbar import Statusbar
|
||||
from .styledtextbuffer import *
|
||||
from .styledtexteditor import *
|
||||
from .toolcomboentry import *
|
||||
from .undoablebuffer import *
|
||||
from .undoableentry import *
|
||||
from .undoablestyledbuffer import *
|
||||
from .validatedcomboentry import *
|
||||
from .validatedmaskedentry import *
|
||||
from .valueaction import *
|
||||
from .valuetoolitem import *
|
||||
from basicentry import *
|
||||
from buttons import *
|
||||
from expandcollapsearrow import *
|
||||
from labels import *
|
||||
from locationentry import *
|
||||
from locationentry2 import *
|
||||
from linkbox import *
|
||||
from photo import *
|
||||
from monitoredwidgets import *
|
||||
from shortlistcomboentry import *
|
||||
from springseparator import *
|
||||
from statusbar import Statusbar
|
||||
from styledtextbuffer import *
|
||||
from styledtexteditor import *
|
||||
from toolcomboentry import *
|
||||
from undoablebuffer import *
|
||||
from undoableentry import *
|
||||
from undoablestyledbuffer import *
|
||||
from validatedcomboentry import *
|
||||
from validatedmaskedentry import *
|
||||
from valueaction import *
|
||||
from valuetoolitem import *
|
||||
|
196
gramps/gui/widgets/locationentry.py
Normal file
196
gramps/gui/widgets/locationentry.py
Normal file
@ -0,0 +1,196 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2012 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$
|
||||
#
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
LOCATIONTYPES = [_('Country'), _('State'), _('County'), _('City'),
|
||||
_('Parish'), _('Locality'), _('Street')]
|
||||
MAX_LEVELS = 7
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# LocationEntry class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class LocationEntry(object):
|
||||
"""
|
||||
Allows the hierarchical entry of a location.
|
||||
"""
|
||||
def __init__(self, table, db, handle):
|
||||
|
||||
self.db = db
|
||||
self.widgets = []
|
||||
self.labels = []
|
||||
self.types = [-1] * MAX_LEVELS
|
||||
self.signals = []
|
||||
|
||||
table.set_col_spacings(10)
|
||||
|
||||
for row in range(MAX_LEVELS):
|
||||
widget = self.create_widget(table, row)
|
||||
sig_id = widget.connect('changed', self.changed_cb, row)
|
||||
self.signals.append(sig_id)
|
||||
|
||||
if handle:
|
||||
locs = []
|
||||
loc = db.get_location_from_handle(handle)
|
||||
while loc.parent is not None:
|
||||
locs.append(loc)
|
||||
loc = db.get_location_from_handle(loc.parent)
|
||||
locs.append(loc)
|
||||
locs.reverse()
|
||||
|
||||
for row, loc in enumerate(locs):
|
||||
self.populate_widget(row, loc.parent, loc.handle)
|
||||
else:
|
||||
self.populate_widget(0, None, None)
|
||||
|
||||
def create_widget(self, table, row):
|
||||
model = Gtk.ListStore(str, str, int)
|
||||
widget = Gtk.ComboBox.new_with_model_and_entry(model)
|
||||
widget.set_entry_text_column(1)
|
||||
widget.set_sensitive(False)
|
||||
label = Gtk.Label()
|
||||
label.set_alignment(1, 0.5)
|
||||
label.show()
|
||||
table.attach(label, 0, 1, row, row+1, xoptions=Gtk.AttachOptions.FILL, yoptions=0)
|
||||
self.labels.append(label)
|
||||
table.attach(widget, 1, 2, row, row+1, yoptions=0)
|
||||
self.widgets.append(widget)
|
||||
return widget
|
||||
|
||||
def populate_widget(self, row, parent_handle, default):
|
||||
widget = self.widgets[row]
|
||||
model = widget.get_model()
|
||||
widget.set_model(None)
|
||||
model.clear()
|
||||
active_iter = None
|
||||
children = self.db.find_location_child_handles(str(parent_handle))
|
||||
loc_type = None
|
||||
has_children = False
|
||||
for handle in children:
|
||||
child = self.db.get_location_from_handle(handle)
|
||||
iter_ = model.append((handle, child.name, child.get_type()))
|
||||
if handle == default:
|
||||
active_iter = iter_
|
||||
loc_type = child.get_type()
|
||||
has_children = True
|
||||
model.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
||||
widget.set_model(model)
|
||||
widget.get_child().set_text('')
|
||||
if active_iter is not None:
|
||||
widget.set_active_iter(active_iter)
|
||||
widget.set_sensitive(True)
|
||||
if has_children:
|
||||
if loc_type is None:
|
||||
loc_type = child.get_type()
|
||||
self.set_label(row, loc_type)
|
||||
else:
|
||||
if parent_handle:
|
||||
parent = self.db.get_location_from_handle(parent_handle)
|
||||
if parent.get_type() < len(LOCATIONTYPES):
|
||||
self.set_label(row, parent.get_type() + 1)
|
||||
else:
|
||||
self.set_label(row, 1)
|
||||
|
||||
def set_label(self, row, loc_type):
|
||||
self.types[row] = loc_type
|
||||
label_text = '%s:' % LOCATIONTYPES[loc_type - 1]
|
||||
self.labels[row].set_label(label_text)
|
||||
|
||||
def clear_widget(self, row):
|
||||
widget = self.widgets[row]
|
||||
widget.get_child().set_text('')
|
||||
model = widget.get_model()
|
||||
model.clear()
|
||||
|
||||
def changed_cb(self, widget, row):
|
||||
self.disable_signals()
|
||||
if widget.get_active() == -1:
|
||||
# Text entry
|
||||
if row+1 < MAX_LEVELS:
|
||||
self.clear_widget(row+1)
|
||||
if self.types[row] < len(LOCATIONTYPES):
|
||||
self.widgets[row+1].set_sensitive(True)
|
||||
self.set_label(row + 1, self.types[row] + 1)
|
||||
else:
|
||||
# New selection
|
||||
model = widget.get_model()
|
||||
parent = model.get_value(widget.get_active_iter(), 0)
|
||||
loc_type = model.get_value(widget.get_active_iter(), 2)
|
||||
self.set_label(row, loc_type)
|
||||
if row+1 < MAX_LEVELS:
|
||||
if self.types[row] < len(LOCATIONTYPES):
|
||||
self.populate_widget(row+1, parent, None)
|
||||
else:
|
||||
self.clear_widget(row+1)
|
||||
self.widgets[row+1].set_sensitive(False)
|
||||
self.labels[row+1].set_label('')
|
||||
|
||||
# Clear rows below the active row
|
||||
for row in range(row+2, MAX_LEVELS):
|
||||
widget = self.widgets[row]
|
||||
self.clear_widget(row)
|
||||
widget.set_sensitive(False)
|
||||
self.labels[row].set_label('')
|
||||
|
||||
self.enable_signals()
|
||||
|
||||
def enable_signals(self):
|
||||
for row in range(MAX_LEVELS):
|
||||
self.widgets[row].handler_unblock(self.signals[row])
|
||||
|
||||
def disable_signals(self):
|
||||
for row in range(MAX_LEVELS):
|
||||
self.widgets[row].handler_block(self.signals[row])
|
||||
|
||||
def get_result(self):
|
||||
handle = None
|
||||
new_locations = []
|
||||
for row in range(MAX_LEVELS):
|
||||
widget = self.widgets[row]
|
||||
if widget.get_active() == -1:
|
||||
# New name
|
||||
new_name = widget.get_child().get_text().strip()
|
||||
if new_name:
|
||||
new_locations.append((self.types[row], new_name))
|
||||
else:
|
||||
# Existing location
|
||||
model = widget.get_model()
|
||||
handle = model.get_value(widget.get_active_iter(), 0)
|
||||
return (handle, new_locations)
|
138
gramps/gui/widgets/locationentry2.py
Normal file
138
gramps/gui/widgets/locationentry2.py
Normal file
@ -0,0 +1,138 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2012 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$
|
||||
|
||||
__all__ = ["LocationEntry2"]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger(".widgets.locationentry2")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
MIN_CHARACTERS = 3
|
||||
MAX_ENTRIES = 20
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# LocationEntry2 class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class LocationEntry2(Gtk.Entry):
|
||||
|
||||
def __init__(self, dbstate):
|
||||
Gtk.Entry.__init__(self)
|
||||
self.dbstate = dbstate
|
||||
self.set_width_chars(5)
|
||||
self.connect('changed', self.changed)
|
||||
self.connect('focus-out-event', self.lost_focus)
|
||||
self.show()
|
||||
|
||||
self.handle = None
|
||||
|
||||
self.pwin = Gtk.Window(Gtk.WindowType.POPUP)
|
||||
self.vbox = Gtk.VBox()
|
||||
self.pwin.add(self.vbox)
|
||||
|
||||
def get_handle(self):
|
||||
return self.handle
|
||||
|
||||
def set_handle(handle):
|
||||
self.set_text(self.get_location_text(handle))
|
||||
|
||||
def changed(self, widget):
|
||||
txt = self.get_text()
|
||||
if len(txt) >= MIN_CHARACTERS:
|
||||
loc_list = self.get_location_list(txt)
|
||||
if loc_list:
|
||||
self.build_menu(loc_list)
|
||||
else:
|
||||
self.pwin.hide()
|
||||
self.handle = None
|
||||
|
||||
def lost_focus(self, widget, event):
|
||||
self.pwin.hide()
|
||||
|
||||
def build_menu(self, loc_list):
|
||||
self.pwin.hide() # required to get correct allocation
|
||||
self.pwin.resize(1, 1)
|
||||
map(self.vbox.remove, self.vbox.get_children())
|
||||
count = 0
|
||||
for loc in loc_list:
|
||||
item = Gtk.Button(loc[1])
|
||||
item.set_alignment(0, 0.5)
|
||||
item.set_relief(Gtk.ReliefStyle.NONE)
|
||||
item.connect("clicked", self.item_selected, loc[0])
|
||||
item.show()
|
||||
self.vbox.pack_start(item, False, False, 0)
|
||||
count += 1
|
||||
if count >= MAX_ENTRIES:
|
||||
break
|
||||
self.pwin.show_all()
|
||||
|
||||
unused, x_pos, y_pos = self.get_window().get_origin()
|
||||
x_pos += self.get_allocation().x
|
||||
y_pos += self.get_allocation().y
|
||||
y_pos += self.get_allocation().height
|
||||
screen = self.pwin.get_screen()
|
||||
width = self.pwin.get_allocation().width
|
||||
height = self.pwin.get_allocation().height
|
||||
|
||||
if x_pos + width > screen.get_width():
|
||||
x_pos = screen.get_width() - width
|
||||
|
||||
if y_pos + height > screen.get_height():
|
||||
y_pos -= height + self.get_allocation().height
|
||||
|
||||
self.pwin.move(x_pos, y_pos)
|
||||
|
||||
def item_selected(self, menu_item, handle):
|
||||
self.set_text(menu_item.get_label())
|
||||
self.handle = handle
|
||||
self.pwin.hide()
|
||||
|
||||
def get_location_list(self, txt):
|
||||
loc_list = []
|
||||
for handle in self.dbstate.db.find_location_from_name(txt):
|
||||
loc_list.append((handle, self.get_location_text(handle)))
|
||||
return loc_list
|
||||
|
||||
def get_location_text(self, handle):
|
||||
loc = self.dbstate.db.get_location_from_handle(handle)
|
||||
lines = [loc.name]
|
||||
while loc.parent is not None:
|
||||
loc = self.dbstate.db.get_location_from_handle(loc.parent)
|
||||
lines.append(loc.name)
|
||||
return ', '.join(lines)
|
@ -75,7 +75,7 @@ class PlaceDetails(Gramplet):
|
||||
"""
|
||||
Remove all the rows from the table.
|
||||
"""
|
||||
list(map(self.table.remove, self.table.get_children()))
|
||||
map(self.table.remove, self.table.get_children())
|
||||
self.table.resize(1, 2)
|
||||
|
||||
def db_changed(self):
|
||||
@ -107,21 +107,27 @@ class PlaceDetails(Gramplet):
|
||||
self.title.set_text(place.get_title())
|
||||
|
||||
self.clear_table()
|
||||
self.display_location(place.get_main_location())
|
||||
mloc = place.get_main_location()
|
||||
self.display_location(mloc)
|
||||
self.display_separator()
|
||||
lat, lon = conv_lat_lon(place.get_latitude(),
|
||||
place.get_longitude(),
|
||||
location = self.dbstate.db.get_location_from_handle(mloc)
|
||||
lat, lon = conv_lat_lon(location.get_latitude(),
|
||||
location.get_longitude(),
|
||||
format='DEG')
|
||||
if lat:
|
||||
self.add_row(_('Latitude'), lat)
|
||||
if lon:
|
||||
self.add_row(_('Longitude'), lon)
|
||||
|
||||
def display_location(self, location):
|
||||
def display_location(self, handle):
|
||||
"""
|
||||
Display a location.
|
||||
"""
|
||||
lines = [line for line in location.get_text_data_list()[:-1] if line]
|
||||
loc = self.dbstate.db.get_location_from_handle(handle)
|
||||
lines = [loc.name]
|
||||
while loc.parent is not None:
|
||||
loc = self.dbstate.db.get_location_from_handle(loc.parent)
|
||||
lines.append(loc.name)
|
||||
self.add_row(_('Location'), '\n'.join(lines))
|
||||
|
||||
def display_empty(self):
|
||||
|
@ -83,8 +83,10 @@ class MapService():
|
||||
"""return the lat, lon value of place in the requested format
|
||||
None, None if invalid
|
||||
"""
|
||||
return conv_lat_lon(place.get_latitude(),
|
||||
place.get_longitude(), format)
|
||||
mloc = place.get_main_location()
|
||||
location = self.database.get_location_from_handle(mloc)
|
||||
return conv_lat_lon(location.get_latitude(),
|
||||
location.get_longitude(), format)
|
||||
|
||||
def calc_url(self):
|
||||
"""Base class needs to overwrite this, calculation of the self.path"""
|
||||
|
@ -31,7 +31,7 @@ Base view for Place Views
|
||||
# Global modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -78,44 +78,22 @@ 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_CHAN = 12
|
||||
COL_LOCATION = 2
|
||||
COL_CHAN = 3
|
||||
# name of the columns
|
||||
COLUMN_NAMES = [
|
||||
_('Place Name'),
|
||||
_('ID'),
|
||||
_('Street'),
|
||||
_('Locality'),
|
||||
_('City'),
|
||||
_('County'),
|
||||
_('State'),
|
||||
_('Country'),
|
||||
_('ZIP/Postal Code'),
|
||||
_('Church Parish'),
|
||||
_('Latitude'),
|
||||
_('Longitude'),
|
||||
_('Location'),
|
||||
_('Last Changed'),
|
||||
]
|
||||
# columns that contain markup
|
||||
MARKUP_COLS = [COL_NAME]
|
||||
# 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_CHAN]),
|
||||
('columns.size', [250, 75, 150, 150, 150, 150, 100, 100, 100,
|
||||
100, 150, 150, 100])
|
||||
('columns.visible', [COL_NAME, COL_ID, COL_LOCATION]),
|
||||
('columns.rank', [COL_NAME, COL_ID, COL_LOCATION, COL_CHAN]),
|
||||
('columns.size', [250, 75, 350, 100])
|
||||
)
|
||||
ADD_MSG = _("Add a new place")
|
||||
EDIT_MSG = _("Edit the selected place")
|
||||
@ -139,7 +117,7 @@ class PlaceBaseView(ListView):
|
||||
|
||||
ListView.__init__(
|
||||
self, title, pdata, dbstate, uistate,
|
||||
self.COLUMN_NAMES, 14,
|
||||
self.COLUMN_NAMES, 5,
|
||||
model, signal_map,
|
||||
dbstate.db.get_place_bookmarks(),
|
||||
PlaceBookmarks, nav_group,
|
||||
@ -150,7 +128,7 @@ class PlaceBaseView(ListView):
|
||||
'<PRIMARY>J' : self.jump,
|
||||
'<PRIMARY>BackSpace' : self.key_delete,
|
||||
})
|
||||
self.maptoolbtn = None
|
||||
|
||||
self.additional_uis.append(self.additional_ui())
|
||||
|
||||
def navigation_type(self):
|
||||
@ -161,6 +139,11 @@ class PlaceBaseView(ListView):
|
||||
|
||||
def define_actions(self):
|
||||
ListView.define_actions(self)
|
||||
self._add_toolmenu_action('MapsList', _('Loading...'),
|
||||
_("Attempt to see selected locations with a Map "
|
||||
"Service (OpenstreetMap, Google Maps, ...)"),
|
||||
self.gotomap,
|
||||
_('Select a Map Service'))
|
||||
self._add_action('GotoMap', Gtk.STOCK_JUMP_TO,
|
||||
_('_Look up with Map Service'),
|
||||
callback=self.gotomap,
|
||||
@ -170,13 +153,6 @@ class PlaceBaseView(ListView):
|
||||
callback=self.filter_editor)
|
||||
self._add_action('QuickReport', None, _("Quick View"), None, None, None)
|
||||
|
||||
def set_inactive(self):
|
||||
"""called by viewmanager when moving away from the page
|
||||
Here we need to remove the menutoolbutton from the menu
|
||||
"""
|
||||
tb = self.uistate.viewmanager.uimanager.get_widget('/ToolBar')
|
||||
tb.remove(self.maptoolbtn)
|
||||
|
||||
def change_page(self):
|
||||
"""
|
||||
Called by viewmanager at end of realization when arriving on the page
|
||||
@ -188,18 +164,11 @@ class PlaceBaseView(ListView):
|
||||
5. store label so it can be changed when selection changes
|
||||
"""
|
||||
ListView.change_page(self)
|
||||
#menutoolbutton has to be made and added in correct place on toolbar
|
||||
if not self.maptoolbtn:
|
||||
self.maptoolbtn = Gtk.MenuToolButton.new_from_stock(Gtk.STOCK_JUMP_TO)
|
||||
self.maptoolbtn.connect('clicked', self.gotomap)
|
||||
self.mmenu = self.__create_maps_menu_actions()
|
||||
self.maptoolbtn.set_menu(self.mmenu)
|
||||
self.maptoolbtn.show()
|
||||
tb = self.uistate.viewmanager.uimanager.get_widget('/ToolBar')
|
||||
ind = tb.get_item_index(self.uistate.viewmanager.uimanager.get_widget(
|
||||
'/ToolBar/CommonEdit/Merge'))
|
||||
tb.insert(self.maptoolbtn, ind+1)
|
||||
widget = self.maptoolbtn
|
||||
#menutoolbutton actions are stored in PageView class,
|
||||
# obtain the widgets where we need to add to menu
|
||||
actionservices = self.action_toolmenu['MapsList']
|
||||
widgets = actionservices.get_proxies()
|
||||
mmenu = self.__create_maps_menu_actions()
|
||||
|
||||
if not self.mapservicedata:
|
||||
return
|
||||
@ -207,19 +176,18 @@ class PlaceBaseView(ListView):
|
||||
self.mapslistlabel = []
|
||||
if not self.mapservice in self.mapservicedata:
|
||||
#stored val no longer exists, use the first key instead
|
||||
self.set_mapservice(list(self.mapservicedata.keys())[0])
|
||||
self.set_mapservice(self.mapservicedata.keys()[0])
|
||||
|
||||
#store all gtk labels to be able to update label on selection change_('Loading...'),
|
||||
widget.set_menu(self.mmenu)
|
||||
widget.set_arrow_tooltip_text(_('Select a Map Service'))
|
||||
widget.set_tooltip_text(
|
||||
_("Attempt to see selected locations with a Map "
|
||||
"Service (OpenstreetMap, Google Maps, ...)"))
|
||||
lbl = Gtk.Label(label=self.mapservice_label())
|
||||
lbl.show()
|
||||
self.mapslistlabel.append(lbl)
|
||||
widget.set_label_widget(self.mapslistlabel[-1])
|
||||
widget.set_stock_id(Gtk.STOCK_JUMP_TO)
|
||||
#store all gtk labels to be able to update label on selection change
|
||||
for widget in widgets :
|
||||
if isinstance(widget, Gtk.MenuToolButton):
|
||||
widget.set_menu(mmenu)
|
||||
widget.set_arrow_tooltip_text(actionservices.arrowtooltip)
|
||||
lbl = Gtk.Label(label=self.mapservice_label())
|
||||
lbl.show()
|
||||
self.mapslistlabel.append(lbl)
|
||||
widget.set_label_widget(self.mapslistlabel[-1])
|
||||
widget.set_stock_id(Gtk.STOCK_JUMP_TO)
|
||||
if self.drag_info():
|
||||
self.list.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
|
||||
[],
|
||||
@ -228,7 +196,7 @@ class PlaceBaseView(ListView):
|
||||
tglist.add(self.drag_info().atom_drag_type,
|
||||
self.drag_info().target_flags,
|
||||
self.drag_info().app_id)
|
||||
tglist.add_text_targets (0)
|
||||
tglist.add_text_targets (0L)
|
||||
self.list.drag_source_set_target_list(tglist)
|
||||
|
||||
def __create_maps_menu_actions(self):
|
||||
@ -301,7 +269,7 @@ class PlaceBaseView(ListView):
|
||||
servfunc = eval('mod.' + serv.mapservice)
|
||||
servfunc()(self.dbstate.db, places)
|
||||
else:
|
||||
print('Failed to load map plugin, see Plugin Manager')
|
||||
print 'Failed to load map plugin, see Plugin Manager'
|
||||
|
||||
def drag_info(self):
|
||||
return DdTargets.PLACE_LINK
|
||||
@ -351,6 +319,7 @@ class PlaceBaseView(ListView):
|
||||
<toolitem action="Remove"/>
|
||||
<toolitem action="Merge"/>
|
||||
<separator/>
|
||||
<toolitem action="MapsList"/>
|
||||
</placeholder>
|
||||
</toolbar>
|
||||
<popup name="Popup">
|
||||
|
@ -33,6 +33,7 @@ Geography for events
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
import os
|
||||
import sys
|
||||
import urlparse
|
||||
import operator
|
||||
import locale
|
||||
from gi.repository import Gdk
|
||||
@ -207,8 +208,10 @@ class GeoEvents(GeoGraphyView):
|
||||
place = dbstate.db.get_place_from_handle(place_handle)
|
||||
if place:
|
||||
descr1 = place.get_title()
|
||||
longitude = place.get_longitude()
|
||||
latitude = place.get_latitude()
|
||||
mloc = place.get_main_location()
|
||||
location = self.dbstate.db.get_location_from_handle(mloc)
|
||||
longitude = location.get_longitude()
|
||||
latitude = location.get_latitude()
|
||||
latitude, longitude = conv_lat_lon(latitude, longitude, "D.D8")
|
||||
# place.get_longitude and place.get_latitude return
|
||||
# one string. We have coordinates when the two values
|
||||
|
@ -33,6 +33,7 @@ Geography for one family
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
import os
|
||||
import sys
|
||||
import urlparse
|
||||
import operator
|
||||
import locale
|
||||
from gi.repository import Gdk
|
||||
@ -202,8 +203,10 @@ class GeoFamily(GeoGraphyView):
|
||||
if place_handle:
|
||||
place = dbstate.db.get_place_from_handle(place_handle)
|
||||
if place:
|
||||
longitude = place.get_longitude()
|
||||
latitude = place.get_latitude()
|
||||
mloc = place.get_main_location()
|
||||
location = self.dbstate.db.get_location_from_handle(mloc)
|
||||
longitude = location.get_longitude()
|
||||
latitude = location.get_latitude()
|
||||
latitude, longitude = conv_lat_lon(latitude,
|
||||
longitude, "D.D8")
|
||||
descr = place.get_title()
|
||||
|
@ -33,6 +33,7 @@ Geography for one person
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
import os
|
||||
import sys
|
||||
import urlparse
|
||||
import operator
|
||||
import locale
|
||||
from gi.repository import Gdk
|
||||
@ -318,8 +319,10 @@ class GeoPerson(GeoGraphyView):
|
||||
if place_handle:
|
||||
place = dbstate.db.get_place_from_handle(place_handle)
|
||||
if place:
|
||||
longitude = place.get_longitude()
|
||||
latitude = place.get_latitude()
|
||||
mloc = place.get_main_location()
|
||||
location = self.dbstate.db.get_location_from_handle(mloc)
|
||||
longitude = location.get_longitude()
|
||||
latitude = location.get_latitude()
|
||||
latitude, longitude = conv_lat_lon(latitude,
|
||||
longitude, "D.D8")
|
||||
descr = place.get_title()
|
||||
|
@ -34,6 +34,7 @@ from gramps.gen.ggettext import gettext as _
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import urlparse
|
||||
import operator
|
||||
import locale
|
||||
from gi.repository import Gdk
|
||||
@ -201,8 +202,10 @@ class GeoPlaces(GeoGraphyView):
|
||||
if self.nbplaces >= self._config.get("geography.max_places"):
|
||||
return
|
||||
descr = place.get_title()
|
||||
longitude = place.get_longitude()
|
||||
latitude = place.get_latitude()
|
||||
mloc = place.get_main_location()
|
||||
location = self.dbstate.db.get_location_from_handle(mloc)
|
||||
longitude = location.get_longitude()
|
||||
latitude = location.get_latitude()
|
||||
latitude, longitude = conv_lat_lon(latitude, longitude, "D.D8")
|
||||
# place.get_longitude and place.get_latitude return
|
||||
# one string. We have coordinates when the two values
|
||||
|
281
gramps/plugins/view/locationview.py
Normal file
281
gramps/plugins/view/locationview.py
Normal file
@ -0,0 +1,281 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2001-2007 Donald N. Allingham
|
||||
# Copyright (C) 2008 Gary Burton
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
#
|
||||
# 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 location view.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
import logging
|
||||
_LOG = logging.getLogger(".plugins.locationview")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.lib import Location
|
||||
from gramps.gen.db import DbTxn
|
||||
from gramps.gui.views.listview import ListView
|
||||
from gramps.gui.views.treemodels import LocationTreeModel
|
||||
from gramps.gen.errors import WindowActiveError
|
||||
from gramps.gui.views.bookmarks import PlaceBookmarks
|
||||
from gramps.gui.ddtargets import DdTargets
|
||||
from gramps.gui.dialog import ErrorDialog
|
||||
from gramps.gui.editors import EditLocation
|
||||
from gramps.gen.plug import CATEGORY_QR_PLACE
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# LocationView
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class LocationView(ListView):
|
||||
"""
|
||||
LocationView class, derived from the ListView
|
||||
"""
|
||||
# columns in the model used in view
|
||||
COL_NAME = 0
|
||||
COL_TYPE = 1
|
||||
COL_LAT = 2
|
||||
COL_LON = 3
|
||||
COL_CHAN = 4
|
||||
# name of the columns
|
||||
COLUMN_NAMES = [
|
||||
_('Name'),
|
||||
_('Type'),
|
||||
_('Latitude'),
|
||||
_('Longitude'),
|
||||
_('Last Changed'),
|
||||
]
|
||||
# columns that contain markup
|
||||
#MARKUP_COLS = [COL_DATE]
|
||||
# default setting with visible columns, order of the col, and their size
|
||||
CONFIGSETTINGS = (
|
||||
('columns.visible', [COL_NAME, COL_TYPE]),
|
||||
('columns.rank', [COL_NAME, COL_TYPE, COL_LAT, COL_LON, COL_CHAN]),
|
||||
('columns.size', [400, 100, 150, 150, 100])
|
||||
)
|
||||
ADD_MSG = _("Add a new location")
|
||||
EDIT_MSG = _("Edit the selected location")
|
||||
DEL_MSG = _("Delete the selected location")
|
||||
MERGE_MSG = _("Merge the selected locations")
|
||||
FILTER_TYPE = "Place"
|
||||
QR_CATEGORY = CATEGORY_QR_PLACE
|
||||
|
||||
def __init__(self, pdata, dbstate, uistate, nav_group=0):
|
||||
"""
|
||||
Create the Location View
|
||||
"""
|
||||
signal_map = {
|
||||
'location-add' : self.row_add,
|
||||
'location-update' : self.row_update,
|
||||
'location-delete' : self.row_delete,
|
||||
'location-rebuild' : self.object_build,
|
||||
}
|
||||
|
||||
ListView.__init__(
|
||||
self, _('Locations'), pdata, dbstate, uistate,
|
||||
LocationView.COLUMN_NAMES, len(LocationView.COLUMN_NAMES),
|
||||
LocationTreeModel,
|
||||
signal_map, dbstate.db.get_place_bookmarks(),
|
||||
PlaceBookmarks, nav_group,
|
||||
multiple=True)
|
||||
|
||||
self.func_list.update({
|
||||
'<CONTROL>J' : self.jump,
|
||||
'<CONTROL>BackSpace' : self.key_delete,
|
||||
})
|
||||
|
||||
self.additional_uis.append(self.additional_ui())
|
||||
|
||||
def navigation_type(self):
|
||||
return 'Place'
|
||||
|
||||
def get_bookmarks(self):
|
||||
"""
|
||||
Return the bookmark object
|
||||
"""
|
||||
return self.dbstate.db.get_place_bookmarks()
|
||||
|
||||
def drag_info(self):
|
||||
"""
|
||||
Indicate that the drag type is a PLACE_LINK
|
||||
"""
|
||||
return DdTargets.PLACE_LINK
|
||||
|
||||
def get_stock(self):
|
||||
"""
|
||||
Use the gramps-place stock icon
|
||||
"""
|
||||
return 'gramps-place'
|
||||
|
||||
def additional_ui(self):
|
||||
"""
|
||||
Defines the UI string for UIManager
|
||||
"""
|
||||
return '''<ui>
|
||||
<menubar name="MenuBar">
|
||||
<menu action="BookMenu">
|
||||
<placeholder name="AddEditBook">
|
||||
<menuitem action="AddBook"/>
|
||||
<menuitem action="EditBook"/>
|
||||
</placeholder>
|
||||
</menu>
|
||||
<menu action="GoMenu">
|
||||
<placeholder name="CommonGo">
|
||||
<menuitem action="Back"/>
|
||||
<menuitem action="Forward"/>
|
||||
<separator/>
|
||||
</placeholder>
|
||||
</menu>
|
||||
<menu action="FileMenu">
|
||||
<placeholder name="LocalExport">
|
||||
<menuitem action="ExportTab"/>
|
||||
</placeholder>
|
||||
</menu>
|
||||
<menu action="EditMenu">
|
||||
<placeholder name="CommonEdit">
|
||||
<menuitem action="Add"/>
|
||||
<menuitem action="Edit"/>
|
||||
<menuitem action="Remove"/>
|
||||
<menuitem action="Merge"/>
|
||||
</placeholder>
|
||||
</menu>
|
||||
</menubar>
|
||||
<toolbar name="ToolBar">
|
||||
<placeholder name="CommonNavigation">
|
||||
<toolitem action="Back"/>
|
||||
<toolitem action="Forward"/>
|
||||
</placeholder>
|
||||
<placeholder name="CommonEdit">
|
||||
<toolitem action="Add"/>
|
||||
<toolitem action="Edit"/>
|
||||
<toolitem action="Remove"/>
|
||||
</placeholder>
|
||||
</toolbar>
|
||||
<popup name="Popup">
|
||||
<menuitem action="OpenBranch"/>
|
||||
<menuitem action="CloseBranch"/>
|
||||
<menuitem action="OpenAllNodes"/>
|
||||
<menuitem action="CloseAllNodes"/>
|
||||
<separator/>
|
||||
<menuitem action="Add"/>
|
||||
<menuitem action="Edit"/>
|
||||
<menuitem action="Remove"/>
|
||||
<menuitem action="Merge"/>
|
||||
<separator/>
|
||||
<menu name="QuickReport" action="QuickReport">
|
||||
<menuitem action="Dummy"/>
|
||||
</menu>
|
||||
</popup>
|
||||
</ui>'''
|
||||
|
||||
def define_actions(self):
|
||||
ListView.define_actions(self)
|
||||
self._add_action('QuickReport', None,
|
||||
_("Quick View"), None, None, None)
|
||||
self._add_action('Dummy', None,
|
||||
' ', None, None, self.dummy_report)
|
||||
|
||||
self._add_action('OpenBranch', None, _("Expand this Entire Group"),
|
||||
callback=self.open_branch)
|
||||
self._add_action('CloseBranch', None, _("Collapse this Entire Group"),
|
||||
callback=self.close_branch)
|
||||
self._add_action('OpenAllNodes', None, _("Expand all Nodes"),
|
||||
callback=self.open_all_nodes)
|
||||
self._add_action('CloseAllNodes', None, _("Collapse all Nodes"),
|
||||
callback=self.close_all_nodes)
|
||||
|
||||
def get_handle_from_gramps_id(self, gid):
|
||||
obj = self.dbstate.db.get_place_from_gramps_id(gid)
|
||||
if obj:
|
||||
return obj.get_handle()
|
||||
else:
|
||||
return None
|
||||
|
||||
def add(self, obj):
|
||||
loc = Location()
|
||||
selected = self.selected_handles()
|
||||
if len(selected) == 1:
|
||||
loc.parent = selected[0]
|
||||
parent_loc = self.dbstate.db.get_location_from_handle(selected[0])
|
||||
parent_type = parent_loc.get_type()
|
||||
if parent_type < 7:
|
||||
loc.set_type(parent_type + 1)
|
||||
else:
|
||||
loc.set_type(7)
|
||||
try:
|
||||
EditLocation(self.dbstate, self.uistate, [], loc, None)
|
||||
except WindowActiveError:
|
||||
pass
|
||||
|
||||
def remove(self, obj):
|
||||
for handle in self.selected_handles():
|
||||
place_list = [
|
||||
item[1] for item in
|
||||
self.dbstate.db.find_backlink_handles(handle, ['Place'])]
|
||||
children = [handle for handle in
|
||||
self.dbstate.db.find_location_child_handles(handle)]
|
||||
if place_list or children:
|
||||
msg = _("Cannot remove location object.")
|
||||
msg2 = _("The location is in use.")
|
||||
ErrorDialog(msg, msg2)
|
||||
else:
|
||||
location = self.dbstate.db.get_location_from_handle(handle)
|
||||
with DbTxn(_("Delete Location (%s)") % location.get_name(),
|
||||
self.dbstate.db) as trans:
|
||||
self.dbstate.db.remove_location(handle, trans)
|
||||
|
||||
def edit(self, obj):
|
||||
for handle in self.selected_handles():
|
||||
loc = self.dbstate.db.get_location_from_handle(handle)
|
||||
try:
|
||||
EditLocation(self.dbstate, self.uistate, [], loc, None)
|
||||
except WindowActiveError:
|
||||
pass
|
||||
|
||||
def merge(self, obj):
|
||||
"""
|
||||
Merge the selected locations.
|
||||
"""
|
||||
msg = _("Not yet implemented.")
|
||||
ErrorDialog(msg, msg)
|
||||
|
||||
def dummy_report(self, obj):
|
||||
""" For the xml UI definition of popup to work, the submenu
|
||||
Quick Report must have an entry in the xml
|
||||
As this submenu will be dynamically built, we offer a dummy action
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_default_gramplets(self):
|
||||
"""
|
||||
Define the default gramplets for the sidebar and bottombar.
|
||||
"""
|
||||
return ((), ())
|
@ -38,7 +38,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'eventview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Events", _("Events")),
|
||||
viewclass = 'EventView',
|
||||
@ -53,7 +53,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'familyview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Families", _("Families")),
|
||||
viewclass = 'FamilyView',
|
||||
@ -68,7 +68,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'grampletview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Gramplets", _("Gramplets")),
|
||||
viewclass = 'GrampletView',
|
||||
@ -83,7 +83,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'mediaview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Media", _("Media")),
|
||||
viewclass = 'MediaView',
|
||||
@ -98,7 +98,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'noteview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Notes", _("Notes")),
|
||||
viewclass = 'NoteView',
|
||||
@ -113,7 +113,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'relview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Relationships", _("Relationships")),
|
||||
viewclass = 'RelationshipView',
|
||||
@ -128,7 +128,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'pedigreeview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Ancestry", _("Charts")),
|
||||
viewclass = 'PedigreeView',
|
||||
@ -145,7 +145,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'fanchartview.py',
|
||||
authors = ["Douglas S. Blank", "B. Malengier"],
|
||||
authors = [u"Douglas S. Blank", u"B. Malengier"],
|
||||
authors_email = ["doug.blank@gmail.com", "benny.malengier@gmail.com"],
|
||||
viewclass = 'FanChartView',
|
||||
stock_icon = 'gramps-fanchart',
|
||||
@ -160,7 +160,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'fanchartdescview.py',
|
||||
authors = ["B. Malengier"],
|
||||
authors = [u"B. Malengier"],
|
||||
authors_email = ["benny.malengier@gmail.com"],
|
||||
viewclass = 'FanChartDescView',
|
||||
stock_icon = 'gramps-fanchartdesc',
|
||||
@ -175,7 +175,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'persontreeview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("People", _("People")),
|
||||
viewclass = 'PersonTreeView',
|
||||
@ -192,7 +192,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'personlistview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("People", _("People")),
|
||||
viewclass = 'PersonListView',
|
||||
@ -208,7 +208,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'placelistview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Places", _("Places")),
|
||||
viewclass = 'PlaceListView',
|
||||
@ -216,20 +216,20 @@ order = START,
|
||||
stock_icon = 'gramps-tree-list',
|
||||
)
|
||||
|
||||
register(VIEW,
|
||||
id = 'placetreeview',
|
||||
name = _("Place Tree"),
|
||||
description = _("A view displaying places in a tree format."),
|
||||
version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'placetreeview.py',
|
||||
authors = ["Donald N. Allingham", "Gary Burton", "Nick Hall"],
|
||||
authors_email = [""],
|
||||
category = ("Places", _("Places")),
|
||||
viewclass = 'PlaceTreeView',
|
||||
stock_icon = 'gramps-tree-group',
|
||||
)
|
||||
#register(VIEW,
|
||||
#id = 'placetreeview',
|
||||
#name = _("Place Tree"),
|
||||
#description = _("A view displaying places in a tree format."),
|
||||
#version = '1.0',
|
||||
#gramps_target_version = '4.0',
|
||||
#status = STABLE,
|
||||
#fname = 'placetreeview.py',
|
||||
#authors = [u"Donald N. Allingham", u"Gary Burton", u"Nick Hall"],
|
||||
#authors_email = [""],
|
||||
#category = ("Places", _("Places")),
|
||||
#viewclass = 'PlaceTreeView',
|
||||
#stock_icon = 'gramps-tree-group',
|
||||
#)
|
||||
|
||||
register(VIEW,
|
||||
id = 'repoview',
|
||||
@ -239,7 +239,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'repoview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Repositories", _("Repositories")),
|
||||
viewclass = 'RepositoryView',
|
||||
@ -254,7 +254,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'sourceview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Sources", _("Sources")),
|
||||
viewclass = 'SourceView',
|
||||
@ -270,7 +270,7 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'citationlistview.py',
|
||||
authors = ["The Gramps project"],
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Citations", _("Citations")),
|
||||
viewclass = 'CitationListView',
|
||||
@ -285,9 +285,25 @@ version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'citationtreeview.py',
|
||||
authors = ["Tim G L Lyons", "Nick Hall"],
|
||||
authors = [u"Tim G L Lyons", u"Nick Hall"],
|
||||
authors_email = [""],
|
||||
category = ("Sources", _("Sources")),
|
||||
viewclass = 'CitationTreeView',
|
||||
stock_icon = 'gramps-tree-select',
|
||||
)
|
||||
|
||||
register(VIEW,
|
||||
id = 'locationview',
|
||||
name = _("Location View"),
|
||||
description = _("The view showing all locations"),
|
||||
version = '1.0',
|
||||
gramps_target_version = '4.0',
|
||||
status = STABLE,
|
||||
fname = 'locationview.py',
|
||||
authors = [u"The Gramps project"],
|
||||
authors_email = ["http://gramps-project.org"],
|
||||
category = ("Places", _("Places")),
|
||||
viewclass = 'LocationView',
|
||||
order = START,
|
||||
stock_icon = 'gramps-tree-group',
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user