move database code into new package
svn: r5598
This commit is contained in:
251
gramps2/src/GrampsDb/_GedcomInfo.py
Normal file
251
gramps2/src/GrampsDb/_GedcomInfo.py
Normal file
@@ -0,0 +1,251 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
import const
|
||||
|
||||
ADOPT_NONE = 0
|
||||
ADOPT_EVENT = 1
|
||||
ADOPT_FTW = 2
|
||||
ADOPT_LEGACY = 3
|
||||
ADOPT_PEDI = 4
|
||||
ADOPT_STD = 5
|
||||
CONC_OK = 0
|
||||
CONC_BROKEN = 1
|
||||
ALT_NAME_NONE = 0
|
||||
ALT_NAME_STD = 1
|
||||
ALT_NAME_ALIAS = 2
|
||||
ALT_NAME_AKA = 3
|
||||
ALT_NAME_EVENT_AKA = 4
|
||||
ALT_NAME_UALIAS = 5
|
||||
CALENDAR_NO = 0
|
||||
CALENDAR_YES = 1
|
||||
OBJE_NO = 0
|
||||
OBJE_YES = 1
|
||||
PREFIX_NO = 0
|
||||
PREFIX_YES = 1
|
||||
RESIDENCE_ADDR = 0
|
||||
RESIDENCE_PLAC = 1
|
||||
SOURCE_REFS_NO = 0
|
||||
SOURCE_REFS_YES = 1
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# XML parser
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from xml.parsers.expat import ParserCreate
|
||||
|
||||
class GedcomDescription:
|
||||
def __init__(self,name):
|
||||
self.name = name
|
||||
self.dest = ""
|
||||
self.adopt = ADOPT_STD
|
||||
self.conc = CONC_OK
|
||||
self.altname = ALT_NAME_STD
|
||||
self.cal = CALENDAR_YES
|
||||
self.obje = OBJE_YES
|
||||
self.resi = RESIDENCE_ADDR
|
||||
self.source_refs = SOURCE_REFS_YES
|
||||
self.gramps2tag_map = {}
|
||||
self.tag2gramps_map = {}
|
||||
self.prefix = PREFIX_YES
|
||||
self.endl = "\n"
|
||||
|
||||
def set_dest(self,val):
|
||||
self.dest = val
|
||||
|
||||
def get_dest(self):
|
||||
return self.dest
|
||||
|
||||
def set_endl(self,val):
|
||||
self.endl = val.replace('\\r','\r').replace('\\n','\n')
|
||||
|
||||
def get_endl(self):
|
||||
return self.endl
|
||||
|
||||
def set_adopt(self,val):
|
||||
self.adopt = val
|
||||
|
||||
def get_adopt(self):
|
||||
return self.adopt
|
||||
|
||||
def set_prefix(self,val):
|
||||
self.prefix=val
|
||||
|
||||
def get_prefix(self):
|
||||
return self.prefix
|
||||
|
||||
def set_conc(self,val):
|
||||
self.conc = val
|
||||
|
||||
def get_conc(self):
|
||||
return self.conc
|
||||
|
||||
def set_alt_name(self,val):
|
||||
self.altname = val
|
||||
|
||||
def get_alt_name(self):
|
||||
return self.altname
|
||||
|
||||
def set_alt_calendar(self,val):
|
||||
self.cal = val
|
||||
|
||||
def get_alt_calendar(self):
|
||||
return self.cal
|
||||
|
||||
def set_obje(self,val):
|
||||
self.obje = val
|
||||
|
||||
def get_obje(self):
|
||||
return self.obje
|
||||
|
||||
def set_resi(self,val):
|
||||
self.resi = val
|
||||
|
||||
def get_resi(self):
|
||||
return self.resi
|
||||
|
||||
def set_source_refs(self,val):
|
||||
self.source_refs = val
|
||||
|
||||
def get_source_refs(self):
|
||||
return self.source_refs
|
||||
|
||||
def add_tag_value(self,tag,value):
|
||||
self.gramps2tag_map[value] = tag
|
||||
self.tag2gramps_map[tag] = value
|
||||
|
||||
def gramps2tag(self,key):
|
||||
if self.gramps2tag_map.has_key(key):
|
||||
return self.gramps2tag_map[key]
|
||||
return ""
|
||||
|
||||
def tag2gramps(self,key):
|
||||
if self.tag2gramps_map.has_key(key):
|
||||
return self.tag2gramps_map[key]
|
||||
return key
|
||||
|
||||
class GedcomInfoDB:
|
||||
def __init__(self):
|
||||
self.map = {}
|
||||
|
||||
self.standard = GedcomDescription("GEDCOM 5.5 standard")
|
||||
self.standard.set_dest("GEDCOM 5.5")
|
||||
|
||||
try:
|
||||
filepath = "%s/gedcom.xml" % const.dataDir
|
||||
f = open(filepath.encode('iso8859-1'),"r")
|
||||
except:
|
||||
return
|
||||
|
||||
parser = GedInfoParser(self)
|
||||
parser.parse(f)
|
||||
f.close()
|
||||
|
||||
def add_description(self,name,obj):
|
||||
self.map[name] = obj
|
||||
|
||||
def get_description(self,name):
|
||||
if self.map.has_key(name):
|
||||
return self.map[name]
|
||||
return self.standard
|
||||
|
||||
def get_from_source_tag(self,name):
|
||||
for k in self.map.keys():
|
||||
val = self.map[k]
|
||||
if val.get_dest() == name:
|
||||
return val
|
||||
return self.standard
|
||||
|
||||
def get_name_list(self):
|
||||
mylist = self.map.keys()
|
||||
mylist.sort()
|
||||
return ["GEDCOM 5.5 standard"] + mylist
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class GedInfoParser:
|
||||
def __init__(self,parent):
|
||||
self.parent = parent
|
||||
self.current = None
|
||||
|
||||
def parse(self,file):
|
||||
p = ParserCreate()
|
||||
p.StartElementHandler = self.startElement
|
||||
p.ParseFile(file)
|
||||
|
||||
def startElement(self,tag,attrs):
|
||||
if tag == "target":
|
||||
name = attrs['name']
|
||||
self.current = GedcomDescription(name)
|
||||
self.parent.add_description(name,self.current)
|
||||
elif tag == "dest":
|
||||
self.current.set_dest(attrs['val'])
|
||||
elif tag == "endl":
|
||||
self.current.set_endl(attrs['val'])
|
||||
elif tag == "adopt":
|
||||
val = attrs['val']
|
||||
if val == 'none':
|
||||
self.current.set_adopt(ADOPT_NONE)
|
||||
elif val == 'event':
|
||||
self.current.set_adopt(ADOPT_EVENT)
|
||||
elif val == 'ftw':
|
||||
self.current.set_adopt(ADOPT_FTW)
|
||||
elif val == 'legacy':
|
||||
self.current.set_adopt(ADOPT_LEGACY)
|
||||
elif val == 'pedigree':
|
||||
self.current.set_adopt(ADOPT_PEDI)
|
||||
elif tag == "conc":
|
||||
if attrs['val'] == 'broken':
|
||||
self.current.set_conc(CONC_BROKEN)
|
||||
elif tag == "alternate_names":
|
||||
val = attrs['val']
|
||||
if val == 'none':
|
||||
self.current.set_alt_name(ALT_NAME_NONE)
|
||||
elif val == 'event_aka':
|
||||
self.current.set_alt_name(ALT_NAME_EVENT_AKA)
|
||||
elif val == 'alias':
|
||||
self.current.set_alt_name(ALT_NAME_ALIAS)
|
||||
elif val == 'aka':
|
||||
self.current.set_alt_name(ALT_NAME_AKA)
|
||||
elif val == '_alias':
|
||||
self.current.set_alt_name(ALT_NAME_UALIAS)
|
||||
elif tag == "calendars":
|
||||
if attrs['val'] == 'no':
|
||||
self.current.set_alt_calendar(CALENDAR_NO)
|
||||
elif tag == "event":
|
||||
self.current.add_tag_value(attrs['tag'],attrs['value'])
|
||||
elif tag == "object_support":
|
||||
if attrs['val'] == 'no':
|
||||
self.current.set_obje(OBJE_NO)
|
||||
elif tag == "prefix":
|
||||
if attrs['val'] == 'no':
|
||||
self.current.set_obje(PREFIX_NO)
|
||||
elif tag == "residence":
|
||||
if attrs['val'] == 'place':
|
||||
self.current.set_resi(RESIDENCE_PLAC)
|
||||
elif tag == "source_refs":
|
||||
if attrs['val'] == 'no':
|
||||
self.current.set_source_refs(SOURCE_REFS_NO)
|
1330
gramps2/src/GrampsDb/_GrampsBSDDB.py
Normal file
1330
gramps2/src/GrampsDb/_GrampsBSDDB.py
Normal file
File diff suppressed because it is too large
Load Diff
758
gramps2/src/GrampsDb/_GrampsDBCallback.py
Normal file
758
gramps2/src/GrampsDb/_GrampsDBCallback.py
Normal file
@@ -0,0 +1,758 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Introduction
|
||||
============
|
||||
|
||||
Gramps is devided into two parts. The database code, that does not
|
||||
require any particular GUI libraries, and the gtk-based UI code
|
||||
that requires gtk and gnome libraries. The gtk-based code can use
|
||||
the gobject signal support to manage callback signals but the database
|
||||
code can not.
|
||||
|
||||
The module provides a subset of the signal mechanisms that are available
|
||||
from the gobject framework. It enables the database code to use signals
|
||||
to communicate events to any callback methods in either the database code
|
||||
or the UI code.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import types
|
||||
import traceback
|
||||
import inspect
|
||||
|
||||
log = sys.stderr.write
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Callback signal support for non-gtk parts of Gramps
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class GrampsDBCallback(object):
|
||||
"""
|
||||
Callback and signal support for non-gtk parts of gramps.
|
||||
|
||||
Declaring signals
|
||||
=================
|
||||
|
||||
Classes that want to emit signals need to inherit from the
|
||||
GrampsDBCallback class and ensure that its __init__ method
|
||||
is called. They then need to declare the signals that they
|
||||
can emit and the types of each callbacks arguments. For
|
||||
example::
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-signal' : (int,),
|
||||
'test-noarg' : None
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
GrampsDBCallback.__init__(self)
|
||||
|
||||
The type signature is a tuple of types or classes. The type
|
||||
checking code uses the isinstance method to check that the
|
||||
argument passed to the emit call is an instance of the type
|
||||
in the signature declaration.
|
||||
|
||||
If the signal does not have an argument use None as the
|
||||
signature.
|
||||
|
||||
The signals will be inherited by any subclasses. Duplicate
|
||||
signal names in subclasses are not alowed.
|
||||
|
||||
|
||||
Emitting signals
|
||||
================
|
||||
|
||||
Signals are emitted using the emit method. e.g.::
|
||||
|
||||
def emit_signal(self):
|
||||
self.emit('test-signal',(1,))
|
||||
|
||||
The parameters are passed as a tuple so a single parameter
|
||||
must be passed as a 1 element tuple.
|
||||
|
||||
Connecting callbacks to signals
|
||||
===============================
|
||||
|
||||
Attaching a callback to the signals is similar to the gtk
|
||||
connect methods. e.g.::
|
||||
|
||||
# connect to a function.
|
||||
def fn(i):
|
||||
print 'got signal value = ', i
|
||||
|
||||
t = TestSignals()
|
||||
t.connect('test-signal', fn)
|
||||
|
||||
# connect to a bound method
|
||||
class C(object):
|
||||
|
||||
def cb_func(self, i):
|
||||
print 'got class signal = ', 1
|
||||
|
||||
r = R()
|
||||
t.connect('test-signal', r.cb_func)
|
||||
|
||||
|
||||
Disconnecting callbacks
|
||||
=======================
|
||||
|
||||
If you want to disconnect a callback from a signals you must remember the
|
||||
key returned from the connect call. This key can be passed to the disconnect
|
||||
method to remove the callback from the signals callback list.
|
||||
|
||||
e.g.::
|
||||
|
||||
t = TestSignals()
|
||||
|
||||
# connect to a bound method
|
||||
class C(object):
|
||||
|
||||
def cb_func(self, i):
|
||||
print 'got class signal = ', 1
|
||||
|
||||
r = R()
|
||||
key = t.connect('test-signal', r.cb_func)
|
||||
|
||||
...
|
||||
|
||||
t.disconnect(key)
|
||||
|
||||
|
||||
Stopping and starting signals
|
||||
=============================
|
||||
|
||||
Signals can be blocked on a per instance bassis or they can be blocked
|
||||
for all instances of the GrampsDBCallback class. disable_signals() can
|
||||
be used to block the signals for a single instance and disable_all_signals()
|
||||
can be used to block signals for the class:
|
||||
|
||||
e.g.::
|
||||
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-signal' : (int,),
|
||||
'test-noarg' : None
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
GrampsDBCallback.__init__(self)
|
||||
|
||||
def emit_signal(self):
|
||||
self.emit('test-signal',(1,))
|
||||
|
||||
t = TestSignals()
|
||||
|
||||
# block signals from instance t
|
||||
t.disable_signals()
|
||||
|
||||
...
|
||||
|
||||
# unblock
|
||||
t.enable_signals()
|
||||
|
||||
# block all signals
|
||||
GrampsDBCallback.disable_all_signals()
|
||||
|
||||
...
|
||||
|
||||
# unblock all signals
|
||||
GrampsDBCallback.enable_all_signals()
|
||||
|
||||
|
||||
Any signals emited whilst signals are blocked will be lost.
|
||||
|
||||
|
||||
Debugging signal callbacks
|
||||
==========================
|
||||
|
||||
|
||||
To help with debugging the signals and callbacks you can turn on
|
||||
lots of logging information. To switch on logging for a single
|
||||
instance call self.enable_logging(), to switch it off again call
|
||||
self.disable_logging(). To switch on logging for all instance
|
||||
you can toggle GrampsDBCallback.__LOG_ALL to True.
|
||||
|
||||
"""
|
||||
|
||||
# If this True no signals will be emitted from any instance of
|
||||
# any class derived from this class. This should be toggled using
|
||||
# the class methods, dissable_all_signals() and enable_all_signals().
|
||||
__BLOCK_ALL_SIGNALS = False
|
||||
|
||||
|
||||
# If this is True logging will be turned on for all instances
|
||||
# whether or not instance based logging is enabled.
|
||||
try:
|
||||
__LOG_ALL = int(os.environ.get('GRAMPS_SIGNAL',"0")) == 1
|
||||
except:
|
||||
__LOG_ALL = False
|
||||
|
||||
def __init__(self):
|
||||
self.__enable_logging = False # controls whether lots of debug
|
||||
# information will be produced.
|
||||
self.__block_instance_signals = False # controls the blocking of
|
||||
# signals from this instance
|
||||
self.__callback_map = {} # dictionary containing all the connected
|
||||
# callback functions. The keys are the
|
||||
# signal names and the values are tuples
|
||||
# of the form (key,bound_method), where
|
||||
# the key is unique within the instance
|
||||
# and the bound_method is the callback
|
||||
# that will be called when the signal is
|
||||
# emitted
|
||||
self.__signal_map = {} # dictionary contains all the signals that
|
||||
# this instance can emit. The keys are the
|
||||
# signal names and the values are tuples
|
||||
# containing the list of types of the arguments
|
||||
# that the callback methods must accept.
|
||||
self._current_key = 0 # counter to give a unique key to each callback.
|
||||
self._current_signals = [] # list of all the signals that are currently
|
||||
# being emitted by this instance. This is
|
||||
# used to prevent recursive emittion of the
|
||||
# same signal.
|
||||
|
||||
# To speed up the signal type checking the signals declared by
|
||||
# each of the classes in the inheritance tree of this instance
|
||||
# are consolidated into a single dictionary.
|
||||
# The signals can't change so we only need to do this once.
|
||||
|
||||
def trav(cls):
|
||||
"""A traversal function to walk through all the classes in
|
||||
the inheritance tree. The return is a list of all the
|
||||
__signals__ dictionaries."""
|
||||
if cls.__dict__.has_key('__signals__'):
|
||||
signal_list = [cls.__signals__]
|
||||
else:
|
||||
signal_list = []
|
||||
|
||||
for base_cls in cls.__bases__:
|
||||
base_list = trav(base_cls)
|
||||
if len(base_list) > 0:
|
||||
signal_list = signal_list + base_list
|
||||
|
||||
return signal_list
|
||||
|
||||
# Build a signal dict from the list of signal dicts
|
||||
for s in trav(self.__class__):
|
||||
for (k,v) in s.items():
|
||||
if self.__signal_map.has_key(k):
|
||||
# signal name clash
|
||||
sys.err.write("Warning: signal name clash: %s\n" % str(k))
|
||||
self.__signal_map[k] = v
|
||||
|
||||
# self.__signal_map now contains the connonical list
|
||||
# of signals that this instance can emit.
|
||||
|
||||
self._log("registed signals: \n %s\n" %
|
||||
"\n ".join([ "%s: %s" % (k,v) for (k,v)
|
||||
in self.__signal_map.items() ]))
|
||||
|
||||
|
||||
def connect(self, signal_name, callback):
|
||||
"""
|
||||
Connect a callable to a signal_name. The callable will be called
|
||||
with the signal is emitted. The callable must accept the argument
|
||||
types declared in the signals signature.
|
||||
|
||||
returns a unique key that can be passed to disconnect().
|
||||
"""
|
||||
# Check that signal exists.
|
||||
if signal_name not in self.__signal_map.keys():
|
||||
self._log("Warning: attempt to connect to unknown signal: %s\n" % str(signal_name))
|
||||
return
|
||||
|
||||
# Add callable to callback_map
|
||||
if signal_name not in self.__callback_map.keys():
|
||||
self.__callback_map[signal_name] = []
|
||||
|
||||
self._current_key += 1
|
||||
self._log("Connecting callback to signal: "
|
||||
"%s with key: %s\n"
|
||||
% (signal_name,str(self._current_key)))
|
||||
self.__callback_map[signal_name].append((self._current_key,callback))
|
||||
|
||||
return self._current_key
|
||||
|
||||
def disconnect(self,key):
|
||||
"""
|
||||
Disconnect a callback.
|
||||
"""
|
||||
|
||||
# Find the key in the callback map.
|
||||
for signal_name in self.__callback_map.keys():
|
||||
for cb in self.__callback_map[signal_name]:
|
||||
(skey,fn) = cb
|
||||
if skey == key:
|
||||
# delete the callback from the map.
|
||||
self._log("Disconnecting callback from signal"
|
||||
": %s with key: %s\n" % (signal_name,
|
||||
str(key)))
|
||||
self.__callback_map[signal_name].remove(cb)
|
||||
|
||||
|
||||
def emit(self, signal_name, args=tuple()):
|
||||
"""
|
||||
Emit the signal called signal_name. The args must be a tuple of
|
||||
arguments that match the types declared for the signals signature.
|
||||
"""
|
||||
# Check that signals are not blocked
|
||||
if GrampsDBCallback.__BLOCK_ALL_SIGNALS or \
|
||||
self.__block_instance_signals:
|
||||
return
|
||||
|
||||
# Check signal exists
|
||||
if signal_name not in self.__signal_map.keys():
|
||||
self._warn("Attempt to emit to unknown signal: %s\n"
|
||||
" from: file: %s\n"
|
||||
" line: %d\n"
|
||||
" func: %s\n"
|
||||
% ((str(signal_name),) + inspect.stack()[1][1:4]))
|
||||
return
|
||||
|
||||
# check that the signal is not already being emitted. This prevents
|
||||
# against recursive signal emmissions.
|
||||
if signal_name in self._current_signals:
|
||||
self._warn("Signal recursion blocked. "
|
||||
"Signals was : %s\n"
|
||||
" from: file: %s\n"
|
||||
" line: %d\n"
|
||||
" func: %s\n"
|
||||
% ((str(signal_name),) + inspect.stack()[1][1:4]))
|
||||
return
|
||||
|
||||
try:
|
||||
self._current_signals.append(signal_name)
|
||||
|
||||
# check that args is a tuple. This is a common programming error.
|
||||
if not (isinstance(args,tuple) or args == None):
|
||||
self._warn("Signal emitted with argument that is not a tuple.\n"
|
||||
" emit() takes two arguments, the signal name and a \n"
|
||||
" tuple that contains the arguments that are to be \n"
|
||||
" passed to the callbacks. If you are passing a signal \n"
|
||||
" argument it must be done as a single element tuple \n"
|
||||
" e.g. emit('my-signal',(1,)) \n"
|
||||
" signal was: %s\n"
|
||||
" from: file: %s\n"
|
||||
" line: %d\n"
|
||||
" func: %s\n"
|
||||
% ((str(signal_name),) + inspect.stack()[1][1:4]))
|
||||
return
|
||||
|
||||
# type check arguments
|
||||
arg_types = self.__signal_map[signal_name]
|
||||
if arg_types == None and len(args) > 0:
|
||||
self._warn("Signal emitted with "
|
||||
"wrong number of args: %s\n"
|
||||
" from: file: %s\n"
|
||||
" line: %d\n"
|
||||
" func: %s\n"
|
||||
% ((str(signal_name),) + inspect.stack()[1][1:4]))
|
||||
return
|
||||
|
||||
if len(args) > 0:
|
||||
if len(args) != len(arg_types):
|
||||
self._warn("Signal emitted with "
|
||||
"wrong number of args: %s\n"
|
||||
" from: file: %s\n"
|
||||
" line: %d\n"
|
||||
" func: %s\n"
|
||||
% ((str(signal_name),) + inspect.stack()[1][1:4]))
|
||||
return
|
||||
|
||||
if arg_types != None:
|
||||
for i in range(0,len(arg_types)):
|
||||
if not isinstance(args[i],arg_types[i]):
|
||||
self._warn("Signal emitted with "
|
||||
"wrong arg types: %s\n"
|
||||
" from: file: %s\n"
|
||||
" line: %d\n"
|
||||
" func: %s\n"
|
||||
" arg passed was: %s, type of arg passed %s, type should be: %s\n"
|
||||
% ((str(signal_name),) + inspect.stack()[1][1:4] +\
|
||||
(args[i],repr(type(args[i])),repr(arg_types[i]))))
|
||||
return
|
||||
|
||||
if signal_name in self.__callback_map.keys():
|
||||
self._log("emmitting signal: %s\n" % (signal_name,))
|
||||
# Don't bother if there are no callbacks.
|
||||
for (key,fn) in self.__callback_map[signal_name]:
|
||||
self._log("Calling callback with key: %s\n" % (key,))
|
||||
try:
|
||||
if type(fn) == tuple: # call class method
|
||||
cb[0](fn[1],*args)
|
||||
elif type(fn) == types.FunctionType or \
|
||||
type(fn) == types.MethodType: # call func
|
||||
fn(*args)
|
||||
else:
|
||||
self._warn("Badly formed entry in callback map.\n")
|
||||
except:
|
||||
self._warn("Exception occured in callback function.\n"
|
||||
"%s" % ("".join(traceback.format_exception(*sys.exc_info())),))
|
||||
finally:
|
||||
self._current_signals.remove(signal_name)
|
||||
|
||||
#
|
||||
# instance signals control methods
|
||||
#
|
||||
def disable_signals(self):
|
||||
self.__block_instance_signals = True
|
||||
|
||||
def enable_signals(self):
|
||||
self.__block_instance_signals = False
|
||||
|
||||
|
||||
# logging methods
|
||||
|
||||
def disable_logging(self):
|
||||
self.__enable_logging = False
|
||||
|
||||
def enable_logging(self):
|
||||
self.__enable_logging = True
|
||||
|
||||
def _log(self,msg):
|
||||
if GrampsDBCallback.__LOG_ALL or self.__enable_logging:
|
||||
log("%s: %s" % (self.__class__.__name__, str(msg)))
|
||||
|
||||
def _warn(self,msg):
|
||||
log("Warning: %s: %s" % (self.__class__.__name__, str(msg)))
|
||||
|
||||
#
|
||||
# Class methods
|
||||
#
|
||||
|
||||
def __disable_all_signals(cls):
|
||||
GrampsDBCallback.__BLOCK_ALL_SIGNALS = True
|
||||
|
||||
disable_all_signals = classmethod(__disable_all_signals)
|
||||
|
||||
def __enable_all_signals(cls):
|
||||
GrampsDBCallback.__BLOCK_ALL_SIGNALS = False
|
||||
|
||||
enable_all_signals = classmethod(__enable_all_signals)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Testing code below this point
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import unittest
|
||||
|
||||
class TestGrampsDBCallback(unittest.TestCase):
|
||||
|
||||
def test_simple(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-signal' : (int,)
|
||||
}
|
||||
|
||||
rl = []
|
||||
def fn(i,r=rl):
|
||||
rl.append(i)
|
||||
|
||||
t = TestSignals()
|
||||
t.connect('test-signal',fn)
|
||||
t.emit('test-signal',(1,))
|
||||
|
||||
|
||||
assert len(rl) == 1, "No signal emitted"
|
||||
assert rl[0] == 1, "Wrong argument recieved"
|
||||
|
||||
|
||||
def test_exception_catch(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-signal' : (int,)
|
||||
}
|
||||
|
||||
rl = []
|
||||
def fn(i,r=rl):
|
||||
rl.append(i)
|
||||
|
||||
def borked(i):
|
||||
rubish.append(i)
|
||||
|
||||
t = TestSignals()
|
||||
|
||||
def null(s):
|
||||
pass
|
||||
|
||||
|
||||
global log
|
||||
_log = log
|
||||
log = null
|
||||
|
||||
t.connect('test-signal',borked)
|
||||
t.connect('test-signal',fn)
|
||||
t.emit('test-signal',(1,))
|
||||
log = _log
|
||||
|
||||
assert len(rl) == 1, "No signal emitted"
|
||||
assert rl[0] == 1, "Wrong argument recieved"
|
||||
|
||||
def test_disconnect(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-signal' : (int,)
|
||||
}
|
||||
|
||||
rl = []
|
||||
def fn(i,r=rl):
|
||||
rl.append(i)
|
||||
|
||||
t = TestSignals()
|
||||
key = t.connect('test-signal',fn)
|
||||
t.emit('test-signal',(1,))
|
||||
|
||||
|
||||
assert len(rl) == 1, "No signal emitted"
|
||||
assert rl[0] == 1, "Wrong argument recieved"
|
||||
|
||||
t.disconnect(key)
|
||||
|
||||
t.emit('test-signal',(1,))
|
||||
|
||||
assert len(rl) == 1, "Callback not disconnected"
|
||||
assert rl[0] == 1, "Callback not disconnected"
|
||||
|
||||
def test_noargs(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-noargs' : None
|
||||
}
|
||||
|
||||
rl = []
|
||||
def fn(r=rl):
|
||||
rl.append(1)
|
||||
|
||||
t = TestSignals()
|
||||
t.connect('test-noargs',fn)
|
||||
t.emit('test-noargs')
|
||||
|
||||
|
||||
assert len(rl) == 1, "No signal emitted"
|
||||
assert rl[0] == 1, "Wrong argument recieved"
|
||||
|
||||
def test_no_callback(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-noargs' : None
|
||||
}
|
||||
|
||||
t = TestSignals()
|
||||
t.emit('test-noargs')
|
||||
|
||||
def test_subclassing(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
__signals__ = {
|
||||
'test-signal' : (int,)
|
||||
}
|
||||
|
||||
class TestSignalsSubclass(TestSignals):
|
||||
__signals__ = {
|
||||
'test-sub-signal' : (int,),
|
||||
}
|
||||
|
||||
rl = []
|
||||
def fn(i,r=rl):
|
||||
rl.append(i)
|
||||
|
||||
t = TestSignalsSubclass()
|
||||
t.connect('test-signal',fn)
|
||||
t.emit('test-signal',(1,))
|
||||
|
||||
assert len(rl) == 1, "No signal emitted"
|
||||
assert rl[0] == 1, "Wrong argument recieved"
|
||||
|
||||
t.connect('test-sub-signal',fn)
|
||||
t.emit('test-sub-signal',(1,))
|
||||
|
||||
assert len(rl) == 2, "No subclass signal emitted"
|
||||
assert rl[1] == 1, "Wrong argument recieved in subclass"
|
||||
|
||||
def test_signal_block(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-signal' : (int,)
|
||||
}
|
||||
|
||||
rl = []
|
||||
def fn(i,r=rl):
|
||||
rl.append(i)
|
||||
|
||||
t = TestSignals()
|
||||
t.connect('test-signal',fn)
|
||||
t.emit('test-signal',(1,))
|
||||
|
||||
assert len(rl) == 1, "No signal emitted"
|
||||
assert rl[0] == 1, "Wrong argument recieved"
|
||||
|
||||
GrampsDBCallback.disable_all_signals()
|
||||
t.emit('test-signal',(1,))
|
||||
assert len(rl) == 1, "Signal emitted while class blocked"
|
||||
|
||||
GrampsDBCallback.enable_all_signals()
|
||||
t.emit('test-signal',(1,))
|
||||
assert len(rl) == 2, "Signals not class unblocked"
|
||||
|
||||
t.disable_signals()
|
||||
t.emit('test-signal',(1,))
|
||||
assert len(rl) == 2, "Signal emitted while instance blocked"
|
||||
|
||||
t.enable_signals()
|
||||
t.emit('test-signal',(1,))
|
||||
assert len(rl) == 3, "Signals not instance unblocked"
|
||||
|
||||
def test_type_checking(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
__signals__ = {
|
||||
'test-int' : (int,),
|
||||
'test-list': (list,),
|
||||
'test-object': (object,),
|
||||
'test-str': (str,),
|
||||
'test-float': (float,),
|
||||
'test-dict': (dict,),
|
||||
'test-lots': (int,str,list,object,float)
|
||||
}
|
||||
|
||||
rl = []
|
||||
def fn(i,r=rl):
|
||||
rl.append(i)
|
||||
|
||||
t = TestSignals()
|
||||
t.connect('test-int',fn), t.emit('test-int',(1,))
|
||||
assert type(rl[0]) == int, "not int"
|
||||
|
||||
t.connect('test-list',fn), t.emit('test-list',([1,2],))
|
||||
assert type(rl[1]) == list, "not list"
|
||||
|
||||
t.connect('test-object',fn), t.emit('test-object',(t,))
|
||||
assert isinstance(rl[2],object), "not object"
|
||||
|
||||
t.connect('test-float',fn), t.emit('test-float',(2.3,))
|
||||
assert type(rl[3]) == float, "not float"
|
||||
|
||||
t.connect('test-dict',fn), t.emit('test-dict',({1:2},))
|
||||
assert type(rl[4]) == dict, "not dict"
|
||||
|
||||
rl = []
|
||||
def fn2(i,s,l,o,f,r=rl):
|
||||
rl.append(i)
|
||||
|
||||
t.connect('test-lots',fn2), t.emit('test-lots',(1,'a',[1,2],t,1.2))
|
||||
assert type(rl[0]) == int, "not lots"
|
||||
|
||||
# This should fail because the type of arg1 is wrong
|
||||
res=[]
|
||||
def fn(s,r=res):
|
||||
res.append(s)
|
||||
t._warn = fn
|
||||
t.connect('test-lots',fn2), t.emit('test-lots',('a','a',[1,2],t,1.2))
|
||||
assert res[0][0:6] == "Signal", "Type error not detected"
|
||||
|
||||
def test_recursion_block(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-recursion' : (GrampsDBCallback,)
|
||||
}
|
||||
|
||||
def fn(cb):
|
||||
cb.emit('test-recursion',(t,))
|
||||
|
||||
res=[]
|
||||
def fn2(s,r=res):
|
||||
res.append(s)
|
||||
|
||||
t = TestSignals()
|
||||
t._warn = fn2
|
||||
t.connect('test-recursion',fn)
|
||||
|
||||
try:
|
||||
t.emit('test-recursion',(t,))
|
||||
except RuntimeError:
|
||||
assert False, "signal recursion not blocked1."
|
||||
|
||||
assert res[0][0:6] == "Signal", "signal recursion not blocked"
|
||||
|
||||
|
||||
def test_multisignal_recursion_block(self):
|
||||
|
||||
class TestSignals(GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'test-top' : (GrampsDBCallback,),
|
||||
'test-middle' : (GrampsDBCallback,),
|
||||
'test-bottom' : (GrampsDBCallback,)
|
||||
}
|
||||
|
||||
def top(cb):
|
||||
cb.emit('test-middle',(t,))
|
||||
def middle(cb):
|
||||
cb.emit('test-bottom',(t,))
|
||||
def bottom(cb):
|
||||
cb.emit('test-top',(t,))
|
||||
|
||||
res=[]
|
||||
def fn2(s,r=res):
|
||||
res.append(s)
|
||||
|
||||
t = TestSignals()
|
||||
t._warn = fn2
|
||||
t.connect('test-top',top)
|
||||
t.connect('test-middle',middle)
|
||||
t.connect('test-bottom',bottom)
|
||||
|
||||
try:
|
||||
t.emit('test-top',(t,))
|
||||
except RuntimeError:
|
||||
assert False, "multisignal recursion not blocked1."
|
||||
|
||||
assert res[0][0:6] == "Signal", "multisignal recursion not blocked"
|
||||
|
||||
|
||||
unittest.main()
|
1710
gramps2/src/GrampsDb/_GrampsDbBase.py
Normal file
1710
gramps2/src/GrampsDb/_GrampsDbBase.py
Normal file
File diff suppressed because it is too large
Load Diff
32
gramps2/src/GrampsDb/_GrampsDbExceptions.py
Normal file
32
gramps2/src/GrampsDb/_GrampsDbExceptions.py
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2004-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""Exceptions generated by the GrampsDb package."""
|
||||
|
||||
|
||||
class GrampsDbException(Exception):
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
123
gramps2/src/GrampsDb/_GrampsDbFactories.py
Normal file
123
gramps2/src/GrampsDb/_GrampsDbFactories.py
Normal file
@@ -0,0 +1,123 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2004-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
This module contains factory methods for accessing the different
|
||||
GrampsDb backends. These methods should be used obtain the correct class
|
||||
for a database backend.
|
||||
|
||||
The app_* constants in const.py can be used to indicate which backend is
|
||||
required e.g.:
|
||||
|
||||
# To get the class for the grdb backend
|
||||
db_class = GrampsDb.gramps_db_factory(db_type = const.app_gramps)
|
||||
|
||||
# To get a XML writer
|
||||
GrampsDb.gramps_db_writer_factory(db_type = const.app_gramps_xml)
|
||||
|
||||
# To get a Gedcom reader
|
||||
GrampsDb.gramps_db_reader_factory(db_type = const.app_gedcom)
|
||||
|
||||
"""
|
||||
import const
|
||||
|
||||
from _GrampsDbExceptions import GrampsDbException
|
||||
|
||||
def gramps_db_factory(db_type):
|
||||
"""Factory class for obtaining a Gramps database backend.
|
||||
|
||||
@param db_type: the type of backend required.
|
||||
@type db_type: one of the app_* constants in const.py
|
||||
|
||||
Raises GrampsDbException if the db_type is not recognised.
|
||||
"""
|
||||
|
||||
if db_type == const.app_gramps:
|
||||
from _GrampsBSDDB import GrampsBSDDB
|
||||
cls = GrampsBSDDB
|
||||
elif db_type == const.app_gramps_xml:
|
||||
from _GrampsXMLDB import GrampsXMLDB
|
||||
cls = GrampsXMLDB
|
||||
elif db_type == const.app_gedcom:
|
||||
from _GrampsGEDDB import GrampsGEDDB
|
||||
cls = GrampsGEDDB
|
||||
else:
|
||||
raise GrampsDbException("Attempt to create unknown "
|
||||
"database backend class: "
|
||||
"db_type = %s" % (str(db_type),))
|
||||
|
||||
return cls
|
||||
|
||||
|
||||
def gramps_db_writer_factory(db_type):
|
||||
"""Factory class for obtaining a Gramps database writers.
|
||||
|
||||
|
||||
@param db_type: the type of backend required.
|
||||
@type db_type: one of the app_* constants in const.py
|
||||
|
||||
Raises GrampsDbException if the db_type is not recognised.
|
||||
"""
|
||||
|
||||
if db_type == const.app_gramps:
|
||||
import _WriteGrdb as WriteGrdb
|
||||
md = WriteGrdb.exportData
|
||||
elif db_type == const.app_gramps_xml:
|
||||
import _WriteXML as WriteXML
|
||||
md = WriteXML.exportData
|
||||
elif db_type == const.app_gedcom:
|
||||
import _WriteGedcom as WriteGedcom
|
||||
md = WriteGedcom.exportData
|
||||
else:
|
||||
raise GrampsDbException("Attempt to create a database "
|
||||
"writer for unknown format: "
|
||||
"db_type = %s" % (str(db_type),))
|
||||
|
||||
return md
|
||||
|
||||
def gramps_db_reader_factory(db_type):
|
||||
"""Factory class for obtaining a Gramps database writers.
|
||||
|
||||
@param db_type: the type of backend required.
|
||||
@type db_type: one of the app_* constants in const.py
|
||||
|
||||
Raises GrampsDbException if the db_type is not recognised.
|
||||
"""
|
||||
|
||||
if db_type == const.app_gramps:
|
||||
import _ReadGrdb as ReadGrdb
|
||||
md = ReadGrdb.importData
|
||||
elif db_type == const.app_gramps_xml:
|
||||
import _ReadXML as ReadXML
|
||||
md = ReadXML.importData
|
||||
elif db_type == const.app_gedcom:
|
||||
import _ReadGedcom as ReadGedcom
|
||||
md = ReadGedcom.importData
|
||||
else:
|
||||
raise GrampsDbException("Attempt to create a database "
|
||||
"reader for unknown format: "
|
||||
"db_type = %s" % (str(db_type),))
|
||||
|
||||
return md
|
||||
|
||||
|
||||
|
60
gramps2/src/GrampsDb/_GrampsGEDDB.py
Normal file
60
gramps2/src/GrampsDb/_GrampsGEDDB.py
Normal file
@@ -0,0 +1,60 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2004 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Provides the GRAMPS DB interface for supporting in-memory editing
|
||||
of GEDCOM files.
|
||||
"""
|
||||
|
||||
from RelLib import *
|
||||
from _GrampsInMemDB import *
|
||||
|
||||
import _ReadGedcom as ReadGedcom
|
||||
import _WriteGedcom as WriteGedcom
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GrampsGEDDB
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class GrampsGEDDB(GrampsInMemDB):
|
||||
"""GRAMPS database object. This object is a base class for other
|
||||
objects."""
|
||||
|
||||
def __init__(self):
|
||||
"""creates a new GrampsDB"""
|
||||
GrampsInMemDB.__init__(self)
|
||||
|
||||
def load(self,name,callback, mode="w"):
|
||||
GrampsInMemDB.load(self,name,callback,mode)
|
||||
ReadGedcom.importData(self,name,use_trans=False)
|
||||
|
||||
self.bookmarks = self.metadata.get('bookmarks')
|
||||
if self.bookmarks == None:
|
||||
self.bookmarks = []
|
||||
return 1
|
||||
|
||||
def close(self):
|
||||
if not self.readonly and len(self.undodb) > 0:
|
||||
writer = WriteGedcom.GedcomWriter(self,self.get_default_person())
|
||||
writer.export_data(self.filename)
|
||||
|
327
gramps2/src/GrampsDb/_GrampsInMemDB.py
Normal file
327
gramps2/src/GrampsDb/_GrampsInMemDB.py
Normal file
@@ -0,0 +1,327 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Provides the common infrastructure for database formats that
|
||||
must hold all of their data in memory.
|
||||
"""
|
||||
|
||||
from bsddb import dbshelve, db
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from RelLib import *
|
||||
from _GrampsDbBase import *
|
||||
import sets
|
||||
|
||||
class GrampsInMemCursor(GrampsCursor):
|
||||
"""
|
||||
Cursor class for in-memory database classes. Since the in-memory
|
||||
classes use python dictionaries, the python iter class is used
|
||||
to provide the cursor function.
|
||||
"""
|
||||
def __init__(self,src_map):
|
||||
self.src_map = src_map
|
||||
self.current = iter(src_map)
|
||||
|
||||
def first(self):
|
||||
self.current = iter(self.src_map)
|
||||
return self.next()
|
||||
|
||||
def next(self):
|
||||
try:
|
||||
index = self.current.next()
|
||||
return (index,self.src_map[index])
|
||||
except StopIteration:
|
||||
return None
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GrampsInMemDB
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class GrampsInMemDB(GrampsDbBase):
|
||||
"""GRAMPS database object. This object is a base class for other
|
||||
objects."""
|
||||
|
||||
def __init__(self):
|
||||
"""creates a new GrampsDB"""
|
||||
GrampsDbBase.__init__(self)
|
||||
self.person_map = {}
|
||||
self.name_group = {}
|
||||
self.family_map = {}
|
||||
self.place_map = {}
|
||||
self.source_map = {}
|
||||
self.repository_map = {}
|
||||
self.media_map = {}
|
||||
self.event_map = {}
|
||||
self.metadata = {}
|
||||
self.filename = ""
|
||||
self.id_trans = {}
|
||||
self.pid_trans = {}
|
||||
self.fid_trans = {}
|
||||
self.eid_trans = {}
|
||||
self.sid_trans = {}
|
||||
self.rid_trans = {}
|
||||
self.oid_trans = {}
|
||||
self.eventnames = {}
|
||||
self.repository_types = {}
|
||||
self.undodb = []
|
||||
|
||||
def load(self,name,callback,mode="w"):
|
||||
self.undolog = "%s.log" % name
|
||||
self.undodb = db.DB()
|
||||
self.undodb.open(self.undolog, db.DB_RECNO, db.DB_CREATE)
|
||||
self.filename = name
|
||||
self.readonly = mode == "r"
|
||||
|
||||
def get_person_cursor(self):
|
||||
return GrampsInMemCursor(self.person_map)
|
||||
|
||||
def get_family_cursor(self):
|
||||
return GrampsInMemCursor(self.family_map)
|
||||
|
||||
def get_event_cursor(self):
|
||||
return GrampsInMemCursor(self.event_map)
|
||||
|
||||
def get_place_cursor(self):
|
||||
return GrampsInMemCursor(self.place_map)
|
||||
|
||||
def get_source_cursor(self):
|
||||
return GrampsInMemCursor(self.source_map)
|
||||
|
||||
def get_repository_cursor(self):
|
||||
return GrampsInMemCursor(self.repository_map)
|
||||
|
||||
def get_media_cursor(self):
|
||||
return GrampsInMemCursor(self.media_map)
|
||||
|
||||
def get_event_cursor(self):
|
||||
return GrampsInMemCursor(self.event_map)
|
||||
|
||||
def close(self):
|
||||
if not self.readonly:
|
||||
self.undodb.close()
|
||||
try:
|
||||
os.remove(self.undolog)
|
||||
except:
|
||||
pass
|
||||
|
||||
def abort_changes(self):
|
||||
pass
|
||||
|
||||
def set_name_group_mapping(self,name,group):
|
||||
if group == None and self.name_group.has_key(name):
|
||||
del self.name_group[name]
|
||||
else:
|
||||
self.name_group[name] = group
|
||||
|
||||
def get_surname_list(self):
|
||||
a = {}
|
||||
for person_id in iter(self.person_map):
|
||||
p = self.get_person_from_handle(person_id)
|
||||
a[p.get_primary_name().get_group_as()] = 1
|
||||
vals = a.keys()
|
||||
vals.sort()
|
||||
return vals
|
||||
|
||||
def get_person_event_type_list(self):
|
||||
names = self.eventnames.keys()
|
||||
a = {}
|
||||
for name in names:
|
||||
a[unicode(name)] = 1
|
||||
vals = a.keys()
|
||||
vals.sort()
|
||||
return vals
|
||||
|
||||
def get_repository_type_list(self):
|
||||
repos_types = self.repository_types.keys()
|
||||
a = {}
|
||||
for repos_type in repos_types:
|
||||
a[unicode(repos_type)] = 1
|
||||
vals = a.keys()
|
||||
vals.sort()
|
||||
return vals
|
||||
|
||||
|
||||
#FIXME: WHICH one to keep?
|
||||
def _del_person(self,handle):
|
||||
#def remove_person(self,handle,transaction):
|
||||
if self.readonly or not handle or str(handle) not in self.person_map:
|
||||
return
|
||||
person = self.get_person_from_handle(handle)
|
||||
self.genderStats.uncount_person (person)
|
||||
if transaction != None:
|
||||
old_data = self.person_map.get(handle)
|
||||
transaction.add(PERSON_KEY,handle,old_data)
|
||||
self.emit('person-delete',([handle],))
|
||||
del self.id_trans[person.get_gramps_id()]
|
||||
del self.person_map[handle]
|
||||
|
||||
def _del_source(self,handle):
|
||||
del self.sid_trans[source.get_gramps_id()]
|
||||
del self.source_map[str(handle)]
|
||||
|
||||
def _del_repository(self,handle):
|
||||
del self.rid_trans[repository.get_gramps_id()]
|
||||
del self.repository_map[str(handle)]
|
||||
|
||||
def _del_place(self,handle):
|
||||
del self.pid_trans[place.get_gramps_id()]
|
||||
del self.place_map[str(handle)]
|
||||
|
||||
def _del_media(self,handle):
|
||||
del self.oid_trans[obj.get_gramps_id()]
|
||||
del self.media_map[str(handle)]
|
||||
|
||||
def _del_family(self,handle):
|
||||
del self.fid_trans[family.get_gramps_id()]
|
||||
del self.family_map[str(handle)]
|
||||
|
||||
def _del_event(self,handle):
|
||||
del self.eid_trans[event.get_gramps_id()]
|
||||
del self.event_map[str(handle)]
|
||||
|
||||
def commit_person(self,person,transaction,change_time=None):
|
||||
if self.readonly or not person.get_handle():
|
||||
return
|
||||
gid = person.get_gramps_id()
|
||||
self.id_trans[gid] = person.get_handle()
|
||||
GrampsDbBase.commit_person(self,person,transaction,change_time)
|
||||
|
||||
def commit_place(self,place,transaction,change_time=None):
|
||||
if self.readonly or not place.get_handle():
|
||||
return
|
||||
gid = place.get_gramps_id()
|
||||
self.pid_trans[gid] = place.get_handle()
|
||||
GrampsDbBase.commit_place(self,place,transaction,change_time)
|
||||
|
||||
def commit_family(self,family,transaction,change_time=None):
|
||||
if self.readonly or not family.get_handle():
|
||||
return
|
||||
gid = family.get_gramps_id()
|
||||
self.fid_trans[gid] = family.get_handle()
|
||||
GrampsDbBase.commit_family(self,family,transaction,change_time)
|
||||
|
||||
def commit_event(self,event,transaction,change_time=None):
|
||||
if self.readonly or not event.get_handle():
|
||||
return
|
||||
gid = event.get_gramps_id()
|
||||
self.eid_trans[gid] = event.get_handle()
|
||||
GrampsDbBase.commit_event(self,event,transaction,change_time)
|
||||
|
||||
def commit_media_object(self,obj,transaction,change_time=None):
|
||||
if self.readonly or not obj.get_handle():
|
||||
return
|
||||
gid = obj.get_gramps_id()
|
||||
self.oid_trans[gid] = obj.get_handle()
|
||||
GrampsDbBase.commit_media_object(self,obj,transaction,change_time)
|
||||
|
||||
def commit_source(self,source,transaction,change_time=None):
|
||||
if self.readonly or not source.get_handle():
|
||||
return
|
||||
gid = source.get_gramps_id()
|
||||
self.sid_trans[gid] = source.get_handle()
|
||||
GrampsDbBase.commit_source(self,source,transaction,change_time)
|
||||
|
||||
def commit_repository(self,repository,transaction,change_time=None):
|
||||
if self.readonly or not repository.get_handle():
|
||||
return
|
||||
gid = repository.get_gramps_id()
|
||||
self.rid_trans[gid] = repository.get_handle()
|
||||
GrampsDbBase.commit_repository(self,repository,transaction,change_time)
|
||||
|
||||
def get_person_from_gramps_id(self,val):
|
||||
handle = self.id_trans.get(str(val))
|
||||
if handle:
|
||||
data = self.person_map[handle]
|
||||
if data:
|
||||
person = Person()
|
||||
person.unserialize(data)
|
||||
return person
|
||||
return None
|
||||
|
||||
def get_family_from_gramps_id(self,val):
|
||||
handle = self.fid_trans.get(str(val))
|
||||
if handle:
|
||||
data = self.family_map[handle]
|
||||
if data:
|
||||
family = Family()
|
||||
family.unserialize(data)
|
||||
return family
|
||||
return None
|
||||
|
||||
def get_event_from_gramps_id(self,val):
|
||||
handle = self.eid_trans.get(str(val))
|
||||
if handle:
|
||||
data = self.event_map[handle]
|
||||
if data:
|
||||
event = Event()
|
||||
event.unserialize(data)
|
||||
return event
|
||||
return None
|
||||
|
||||
def get_place_from_gramps_id(self,val):
|
||||
handle = self.pid_trans.get(str(val))
|
||||
if handle:
|
||||
data = self.place_map[handle]
|
||||
if data:
|
||||
place = Place()
|
||||
place.unserialize(data)
|
||||
return place
|
||||
return None
|
||||
|
||||
def get_source_from_gramps_id(self,val):
|
||||
handle = self.sid_trans.get(str(val))
|
||||
if handle:
|
||||
data = self.source_map[handle]
|
||||
if data:
|
||||
source = Source()
|
||||
source.unserialize(data)
|
||||
return source
|
||||
return None
|
||||
|
||||
def get_repository_from_gramps_id(self,val):
|
||||
handle = self.rid_trans.get(str(val))
|
||||
if handle:
|
||||
data = self.repository_map[handle]
|
||||
if data:
|
||||
repository = Repository()
|
||||
repository.unserialize(data)
|
||||
return repository
|
||||
return None
|
||||
|
||||
def get_object_from_gramps_id(self,val):
|
||||
handle = self.oid_trans.get(str(val))
|
||||
if handle:
|
||||
data = self.media_map[handle]
|
||||
if data:
|
||||
obj = MediaObject()
|
||||
obj.unserialize(data)
|
||||
return obj
|
||||
return None
|
61
gramps2/src/GrampsDb/_GrampsXMLDB.py
Normal file
61
gramps2/src/GrampsDb/_GrampsXMLDB.py
Normal file
@@ -0,0 +1,61 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2004 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Provides the GRAMPS DB interface for supporting in-memory editing
|
||||
of GRAMPS XML format.
|
||||
"""
|
||||
|
||||
from RelLib import *
|
||||
from _GrampsInMemDB import *
|
||||
|
||||
import _ReadXML as ReadXML
|
||||
import _WriteXML as WriteXML
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GrampsXMLDB
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class GrampsXMLDB(GrampsInMemDB):
|
||||
"""GRAMPS database object. This object is a base class for other
|
||||
objects."""
|
||||
|
||||
def __init__(self):
|
||||
"""creates a new GrampsDB"""
|
||||
GrampsInMemDB.__init__(self)
|
||||
|
||||
def load(self,name,callback,mode="w"):
|
||||
GrampsInMemDB.load(self,name,callback,mode)
|
||||
self.id_trans = {}
|
||||
|
||||
ReadXML.importData(self,name,callback,use_trans=False)
|
||||
|
||||
self.bookmarks = self.metadata.get('bookmarks')
|
||||
if self.bookmarks == None:
|
||||
self.bookmarks = []
|
||||
return 1
|
||||
|
||||
def close(self):
|
||||
if not self.readonly and len(self.undodb) > 0:
|
||||
WriteXML.quick_write(self,self.filename)
|
||||
|
2157
gramps2/src/GrampsDb/_ReadGedcom.py
Normal file
2157
gramps2/src/GrampsDb/_ReadGedcom.py
Normal file
File diff suppressed because it is too large
Load Diff
193
gramps2/src/GrampsDb/_ReadGrdb.py
Normal file
193
gramps2/src/GrampsDb/_ReadGrdb.py
Normal file
@@ -0,0 +1,193 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
# Written by Alex Roitman,
|
||||
# largely based on ReadXML by Don Allingham
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard Python Modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
from gettext import gettext as _
|
||||
import sets
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps Modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from _GrampsBSDDB import GrampsBSDDB
|
||||
from QuestionDialog import ErrorDialog
|
||||
import Errors
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Importing data into the currently open database.
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def importData(database, filename, callback=None,cl=0,use_trans=True):
|
||||
|
||||
filename = os.path.normpath(filename)
|
||||
|
||||
other_database = GrampsBSDDB()
|
||||
try:
|
||||
other_database.load(filename,callback)
|
||||
except:
|
||||
if cl:
|
||||
print "Error: %s could not be opened. Exiting." % filename
|
||||
else:
|
||||
ErrorDialog(_("%s could not be opened") % filename)
|
||||
return
|
||||
if not other_database.version_supported():
|
||||
if cl:
|
||||
print "Error: %s could not be opened.\n%s Exiting." \
|
||||
% (filename,
|
||||
_("The database version is not supported "
|
||||
"by this version of GRAMPS.\n"\
|
||||
"Please upgrade to the corresponding version "
|
||||
"or use XML for porting data between different "
|
||||
"database versions."))
|
||||
else:
|
||||
ErrorDialog(_("%s could not be opened") % filename,
|
||||
_("The Database version is not supported "
|
||||
"by this version of GRAMPS."))
|
||||
return
|
||||
|
||||
# Check for duplicate handles. At the moment we simply exit here,
|
||||
# before modifying any data. In the future we will need to handle
|
||||
# this better.
|
||||
handles = sets.Set(database.person_map.keys())
|
||||
other_handles = sets.Set(other_database.person_map.keys())
|
||||
if handles.intersection(other_handles):
|
||||
raise Errors.HandleError('Personal handles in two databases overlap.')
|
||||
|
||||
handles = sets.Set(database.family_map.keys())
|
||||
other_handles = sets.Set(other_database.family_map.keys())
|
||||
if handles.intersection(other_handles):
|
||||
raise Errors.HandleError('Family handles in two databases overlap.')
|
||||
|
||||
handles = sets.Set(database.place_map.keys())
|
||||
other_handles = sets.Set(other_database.place_map.keys())
|
||||
if handles.intersection(other_handles):
|
||||
raise Errors.HandleError('Place handles in two databases overlap.')
|
||||
|
||||
handles = sets.Set(database.source_map.keys())
|
||||
other_handles = sets.Set(other_database.source_map.keys())
|
||||
if handles.intersection(other_handles):
|
||||
raise Errors.HandleError('Source handles in two databases overlap.')
|
||||
|
||||
handles = sets.Set(database.media_map.keys())
|
||||
other_handles = sets.Set(other_database.media_map.keys())
|
||||
if handles.intersection(other_handles):
|
||||
raise Errors.HandleError('Media handles in two databases overlap.')
|
||||
|
||||
handles = sets.Set(database.event_map.keys())
|
||||
other_handles = sets.Set(other_database.event_map.keys())
|
||||
if handles.intersection(other_handles):
|
||||
raise Errors.HandleError('Event handles in two databases overlap.')
|
||||
|
||||
# Proceed with preparing for import
|
||||
if use_trans:
|
||||
trans = database.transaction_begin()
|
||||
trans.set_batch(True)
|
||||
else:
|
||||
trans = None
|
||||
|
||||
database.disable_signals()
|
||||
|
||||
# copy all data from new_database to database,
|
||||
# rename gramps IDs of first-class objects when conflicts are found
|
||||
|
||||
# People table
|
||||
for person_handle in other_database.person_map.keys():
|
||||
person = other_database.get_person_from_handle(person_handle)
|
||||
|
||||
# Then we check gramps_id for conflicts and change it if needed
|
||||
gramps_id = str(person.get_gramps_id())
|
||||
if database.id_trans.has_key(gramps_id):
|
||||
gramps_id = database.find_next_person_gramps_id()
|
||||
person.set_gramps_id(gramps_id)
|
||||
database.add_person(person,trans)
|
||||
|
||||
# Family table
|
||||
for family_handle in other_database.family_map.keys():
|
||||
family = other_database.get_family_from_handle(family_handle)
|
||||
|
||||
# Then we check gramps_id for conflicts and change it if needed
|
||||
gramps_id = str(family.get_gramps_id())
|
||||
if database.fid_trans.has_key(gramps_id):
|
||||
gramps_id = database.find_next_family_gramps_id()
|
||||
family.set_gramps_id(gramps_id)
|
||||
database.add_family(family,trans)
|
||||
|
||||
# Place table
|
||||
for place_handle in other_database.place_map.keys():
|
||||
place = other_database.get_place_from_handle(place_handle)
|
||||
|
||||
# Then we check gramps_id for conflicts and change it if needed
|
||||
gramps_id = str(place.get_gramps_id())
|
||||
if database.pid_trans.has_key(gramps_id):
|
||||
gramps_id = database.find_next_place_gramps_id()
|
||||
place.set_gramps_id(gramps_id)
|
||||
database.add_place(place,trans)
|
||||
|
||||
# Source table
|
||||
for source_handle in other_database.source_map.keys():
|
||||
source = other_database.get_source_from_handle(source_handle)
|
||||
|
||||
# Then we check gramps_id for conflicts and change it if needed
|
||||
gramps_id = str(source.get_gramps_id())
|
||||
if database.sid_trans.has_key(gramps_id):
|
||||
gramps_id = database.find_next_source_gramps_id()
|
||||
source.set_gramps_id(gramps_id)
|
||||
database.add_source(source,trans)
|
||||
|
||||
# Media table
|
||||
for media_handle in other_database.media_map.keys():
|
||||
media = other_database.get_object_from_handle(media_handle)
|
||||
|
||||
# Then we check gramps_id for conflicts and change it if needed
|
||||
gramps_id = str(media.get_gramps_id())
|
||||
if database.oid_trans.has_key(gramps_id):
|
||||
gramps_id = database.find_next_object_gramps_id()
|
||||
media.set_gramps_id(gramps_id)
|
||||
database.add_object(media,trans)
|
||||
|
||||
# Event table
|
||||
for event_handle in other_database.event_map.keys():
|
||||
event = other_database.get_event_from_handle(event_handle)
|
||||
|
||||
# Then we check gramps_id for conflicts and change it if needed
|
||||
gramps_id = str(event.get_gramps_id())
|
||||
if database.eid_trans.has_key(gramps_id):
|
||||
gramps_id = database.find_next_event_gramps_id()
|
||||
event.set_gramps_id(gramps_id)
|
||||
database.add_event(event,trans)
|
||||
|
||||
# close the other database and clean things up
|
||||
other_database.close()
|
||||
|
||||
database.transaction_commit(trans,_("Import database"))
|
||||
database.enable_signals()
|
||||
database.request_rebuild()
|
1624
gramps2/src/GrampsDb/_ReadXML.py
Normal file
1624
gramps2/src/GrampsDb/_ReadXML.py
Normal file
File diff suppressed because it is too large
Load Diff
1346
gramps2/src/GrampsDb/_WriteGedcom.py
Normal file
1346
gramps2/src/GrampsDb/_WriteGedcom.py
Normal file
File diff suppressed because it is too large
Load Diff
84
gramps2/src/GrampsDb/_WriteGrdb.py
Normal file
84
gramps2/src/GrampsDb/_WriteGrdb.py
Normal file
@@ -0,0 +1,84 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
# Written by Alex Roitman
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard Python Modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps Modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from _GrampsBSDDB import GrampsBSDDB
|
||||
from QuestionDialog import ErrorDialog
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Importing data into the currently open database.
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def exportData(database, filename, person=None, callback=None, cl=False):
|
||||
|
||||
filename = os.path.normpath(filename)
|
||||
|
||||
new_database = GrampsBSDDB()
|
||||
try:
|
||||
new_database.load(filename,callback)
|
||||
except:
|
||||
if cl:
|
||||
print "Error: %s could not be opened. Exiting." % filename
|
||||
else:
|
||||
ErrorDialog(_("%s could not be opened") % filename)
|
||||
return
|
||||
|
||||
# copy all data from new_database to database,
|
||||
|
||||
for handle in database.person_map.keys():
|
||||
new_database.person_map.put(handle,
|
||||
database.person_map.get(handle))
|
||||
for handle in database.family_map.keys():
|
||||
new_database.family_map.put(handle,
|
||||
database.family_map.get(handle))
|
||||
for handle in database.place_map.keys():
|
||||
new_database.place_map.put(handle,
|
||||
database.place_map.get(handle))
|
||||
for handle in database.source_map.keys():
|
||||
new_database.source_map.put(handle,
|
||||
database.source_map.get(handle))
|
||||
for handle in database.media_map.keys():
|
||||
new_database.media_map.put(handle,
|
||||
database.media_map.get(handle))
|
||||
for handle in database.event_map.keys():
|
||||
new_database.event_map.put(handle,
|
||||
database.event_map.get(handle))
|
||||
for handle in database.metadata.keys():
|
||||
new_database.metadata.put(handle,
|
||||
database.metadata.get(handle))
|
||||
|
||||
new_database.close()
|
914
gramps2/src/GrampsDb/_WriteXML.py
Normal file
914
gramps2/src/GrampsDb/_WriteXML.py
Normal file
@@ -0,0 +1,914 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Contains the interface to allow a database to get written using
|
||||
GRAMPS' XML file format.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# load standard python libraries
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import time
|
||||
import shutil
|
||||
import os
|
||||
import codecs
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# load gtk libraries
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# load GRAMPS libraries
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
import RelLib
|
||||
import Date
|
||||
from QuestionDialog import ErrorDialog
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Attempt to load the GZIP library. Some version of python do not seem
|
||||
# to be compiled with this available.
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
try:
|
||||
import gzip
|
||||
_gzip_ok = 1
|
||||
except:
|
||||
_gzip_ok = 0
|
||||
|
||||
|
||||
_xml_version = "1.0.0"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def exportData(database, filename, person, callback=None):
|
||||
ret = 0
|
||||
if os.path.isfile(filename):
|
||||
try:
|
||||
shutil.copyfile(filename, filename + ".bak")
|
||||
shutil.copystat(filename, filename + ".bak")
|
||||
except:
|
||||
pass
|
||||
|
||||
compress = _gzip_ok == 1
|
||||
|
||||
try:
|
||||
g = XmlWriter(database,callback,0,compress)
|
||||
ret = g.write(filename)
|
||||
except:
|
||||
import DisplayTrace
|
||||
|
||||
DisplayTrace.DisplayTrace()
|
||||
ErrorDialog(_("Failure writing %s") % filename,
|
||||
_("An attempt is being made to recover the original file"))
|
||||
shutil.copyfile(filename + ".bak", filename)
|
||||
try:
|
||||
shutil.copystat(filename + ".bak", filename)
|
||||
except:
|
||||
pass
|
||||
|
||||
return ret
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def quick_write(database, filename,callback=None):
|
||||
g = XmlWriter(database,callback,0,1)
|
||||
g.write(filename)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class XmlWriter:
|
||||
"""
|
||||
Writes a database to the XML file.
|
||||
"""
|
||||
|
||||
def __init__(self,db,callback,strip_photos,compress=1):
|
||||
"""
|
||||
Initializes, but does not write, an XML file.
|
||||
|
||||
db - database to write
|
||||
callback - function to provide progress indication
|
||||
strip_photos - remove full paths off of media object paths
|
||||
compress - attempt to compress the database
|
||||
"""
|
||||
self.compress = compress
|
||||
self.db = db
|
||||
self.callback = callback
|
||||
self.strip_photos = strip_photos
|
||||
|
||||
def write(self,filename):
|
||||
"""
|
||||
Write the database to the specified file.
|
||||
"""
|
||||
base = os.path.dirname(filename)
|
||||
if os.path.isdir(base):
|
||||
if not os.access(base,os.W_OK) or not os.access(base,os.R_OK):
|
||||
ErrorDialog(_('Failure writing %s') % filename,
|
||||
_("The database cannot be saved because you do not "
|
||||
"have permission to write to the directory. "
|
||||
"Please make sure you have write access to the "
|
||||
"directory and try again."))
|
||||
return 0
|
||||
|
||||
if os.path.exists(filename):
|
||||
if not os.access(filename,os.W_OK):
|
||||
ErrorDialog(_('Failure writing %s') % filename,
|
||||
_("The database cannot be saved because you do not "
|
||||
"have permission to write to the file. "
|
||||
"Please make sure you have write access to the "
|
||||
"file and try again."))
|
||||
return 0
|
||||
|
||||
self.fileroot = os.path.dirname(filename)
|
||||
try:
|
||||
if self.compress:
|
||||
try:
|
||||
g = gzip.open(filename,"wb")
|
||||
except:
|
||||
g = open(filename,"w")
|
||||
else:
|
||||
g = open(filename,"w")
|
||||
except IOError,msg:
|
||||
ErrorDialog(_('Failure writing %s') % filename,msg)
|
||||
return 0
|
||||
|
||||
self.g = codecs.getwriter("utf8")(g)
|
||||
|
||||
self.write_xml_data()
|
||||
g.close()
|
||||
return 1
|
||||
|
||||
def write_handle(self,handle):
|
||||
"""
|
||||
Write the database to the specified file handle.
|
||||
"""
|
||||
|
||||
if self.compress:
|
||||
try:
|
||||
g = gzip.GzipFile(mode="wb",fileobj=handle)
|
||||
except:
|
||||
g = handle
|
||||
else:
|
||||
g = handle
|
||||
|
||||
self.g = codecs.getwriter("utf8")(g)
|
||||
|
||||
self.write_xml_data()
|
||||
g.close()
|
||||
return 1
|
||||
|
||||
def write_xml_data(self):
|
||||
|
||||
date = time.localtime(time.time())
|
||||
owner = self.db.get_researcher()
|
||||
person_len = self.db.get_number_of_people()
|
||||
family_len = len(self.db.get_family_handles())
|
||||
source_len = len(self.db.get_source_handles())
|
||||
place_len = len(self.db.get_place_handles())
|
||||
objList = self.db.get_media_object_handles()
|
||||
|
||||
total = person_len + family_len + place_len + source_len
|
||||
|
||||
self.g.write('<?xml version="1.0" encoding="UTF-8"?>\n')
|
||||
self.g.write('<!DOCTYPE database '
|
||||
'PUBLIC "-//GRAMPS//DTD GRAMPS XML %s//EN"\n'
|
||||
'"http://gramps-project.org/xml/%s/grampsxml.dtd">\n'
|
||||
% (_xml_version,_xml_version))
|
||||
self.g.write('<database xmlns="http://gramps-project.org/xml/%s/">\n'
|
||||
% _xml_version)
|
||||
self.g.write(" <header>\n")
|
||||
self.g.write(' <created date="%04d-%02d-%02d\"' %
|
||||
(date[0],date[1],date[2]) )
|
||||
self.g.write(" version=\"" + const.version + "\"")
|
||||
self.g.write("/>\n")
|
||||
self.g.write(" <researcher>\n")
|
||||
self.write_line("resname",owner.get_name(),3)
|
||||
self.write_line("resaddr",owner.get_address(),3)
|
||||
self.write_line("rescity",owner.get_city(),3)
|
||||
self.write_line("resstate",owner.get_state(),3)
|
||||
self.write_line("rescountry",owner.get_country(),3)
|
||||
self.write_line("respostal",owner.get_postal_code(),3)
|
||||
self.write_line("resphone",owner.get_phone(),3)
|
||||
self.write_line("resemail",owner.get_email(),3)
|
||||
self.g.write(" </researcher>\n")
|
||||
self.g.write(" </header>\n")
|
||||
|
||||
count = 0
|
||||
delta = max(int(total/50),1)
|
||||
|
||||
if person_len > 0:
|
||||
self.g.write(" <people")
|
||||
person = self.db.get_default_person()
|
||||
if person:
|
||||
self.g.write(' default="%s" home="%s"' %
|
||||
(person.get_gramps_id (),
|
||||
"_"+person.get_handle()))
|
||||
self.g.write(">\n")
|
||||
|
||||
keys = self.db.get_person_handles(sort_handles=False)
|
||||
sorted_keys = []
|
||||
for key in keys:
|
||||
person = self.db.get_person_from_handle (key)
|
||||
value = (person.get_gramps_id (), person)
|
||||
sorted_keys.append (value)
|
||||
|
||||
sorted_keys.sort ()
|
||||
for (gramps_id, person) in sorted_keys:
|
||||
if self.callback and count % delta == 0:
|
||||
self.callback(float(count)/float(total))
|
||||
count += 1
|
||||
|
||||
self.write_id("person",person,2)
|
||||
if person.get_gender() == RelLib.Person.MALE:
|
||||
self.write_line("gender","M",3)
|
||||
elif person.get_gender() == RelLib.Person.FEMALE:
|
||||
self.write_line("gender","F",3)
|
||||
else:
|
||||
self.write_line("gender","U",3)
|
||||
self.dump_name(person.get_primary_name(),False,3)
|
||||
for name in person.get_alternate_names():
|
||||
self.dump_name(name,True,3)
|
||||
|
||||
self.write_line("nick",person.get_nick_name(),3)
|
||||
birth = self.db.get_event_from_handle(person.get_birth_handle())
|
||||
death = self.db.get_event_from_handle(person.get_death_handle())
|
||||
self.dump_my_event("Birth",birth,3)
|
||||
self.dump_my_event("Death",death,3)
|
||||
for event_handle in person.get_event_list():
|
||||
event = self.db.get_event_from_handle(event_handle)
|
||||
self.dump_event(event,3)
|
||||
|
||||
self.dump_ordinance("baptism",person.get_lds_baptism(),3)
|
||||
self.dump_ordinance("endowment",person.get_lds_endowment(),3)
|
||||
self.dump_ordinance("sealed_to_parents",person.get_lds_sealing(),3)
|
||||
|
||||
self.write_media_list(person.get_media_list())
|
||||
|
||||
if len(person.get_address_list()) > 0:
|
||||
for address in person.get_address_list():
|
||||
self.g.write(' <address%s>\n' % conf_priv(address))
|
||||
self.write_date(address.get_date_object(),4)
|
||||
self.write_line("street",address.get_street(),4)
|
||||
self.write_line("city",address.get_city(),4)
|
||||
self.write_line("state",address.get_state(),4)
|
||||
self.write_line("country",address.get_country(),4)
|
||||
self.write_line("postal",address.get_postal_code(),4)
|
||||
self.write_line("phone",address.get_phone(),4)
|
||||
if address.get_note() != "":
|
||||
self.write_note("note",address.get_note_object(),4)
|
||||
for s in address.get_source_references():
|
||||
self.dump_source_ref(s,4)
|
||||
self.g.write(' </address>\n')
|
||||
|
||||
self.write_attribute_list(person.get_attribute_list())
|
||||
self.write_url_list(person.get_url_list())
|
||||
|
||||
for alt in person.get_parent_family_handle_list():
|
||||
if alt[1] != RelLib.Person.CHILD_BIRTH:
|
||||
mrel=' mrel="%s"' % const.child_rel_notrans[alt[1]]
|
||||
else:
|
||||
mrel=''
|
||||
if alt[2] != RelLib.Person.CHILD_BIRTH:
|
||||
frel=' frel="%s"' % const.child_rel_notrans[alt[2]]
|
||||
else:
|
||||
frel=''
|
||||
self.g.write(" <childof hlink=\"%s\"%s%s/>\n" % \
|
||||
("_"+alt[0], mrel, frel))
|
||||
|
||||
for family_handle in person.get_family_handle_list():
|
||||
self.write_ref("parentin",family_handle,3)
|
||||
|
||||
self.write_note("note",person.get_note_object(),3)
|
||||
for s in person.get_source_references():
|
||||
self.dump_source_ref(s,4)
|
||||
|
||||
self.g.write(" </person>\n")
|
||||
self.g.write(" </people>\n")
|
||||
|
||||
if family_len > 0:
|
||||
self.g.write(" <families>\n")
|
||||
|
||||
keys = self.db.get_family_handles()
|
||||
sorted_keys = []
|
||||
for key in keys:
|
||||
family = self.db.get_family_from_handle(key)
|
||||
value = (family.get_gramps_id (), family)
|
||||
sorted_keys.append (value)
|
||||
|
||||
sorted_keys.sort ()
|
||||
for (gramps_id, family) in sorted_keys:
|
||||
if self.callback and count % delta == 0:
|
||||
self.callback(float(count)/float(total))
|
||||
count = count + 1
|
||||
|
||||
self.write_family_handle(family,2)
|
||||
fhandle = family.get_father_handle()
|
||||
mhandle = family.get_mother_handle()
|
||||
if fhandle:
|
||||
self.write_ref("father",fhandle,3)
|
||||
if mhandle:
|
||||
self.write_ref("mother",mhandle,3)
|
||||
for event_handle in family.get_event_list():
|
||||
event = self.db.get_event_from_handle(event_handle)
|
||||
self.dump_event(event,3)
|
||||
self.dump_ordinance("sealed_to_spouse",family.get_lds_sealing(),3)
|
||||
|
||||
self.write_media_list(family.get_media_list())
|
||||
|
||||
if len(family.get_child_handle_list()) > 0:
|
||||
for person_handle in family.get_child_handle_list():
|
||||
self.write_ref("child",person_handle,3)
|
||||
self.write_attribute_list(family.get_attribute_list())
|
||||
self.write_note("note",family.get_note_object(),3)
|
||||
for s in family.get_source_references():
|
||||
self.dump_source_ref(s,3)
|
||||
self.g.write(" </family>\n")
|
||||
self.g.write(" </families>\n")
|
||||
|
||||
if source_len > 0:
|
||||
self.g.write(" <sources>\n")
|
||||
keys = self.db.get_source_handles ()
|
||||
keys.sort ()
|
||||
for key in keys:
|
||||
source = self.db.get_source_from_handle(key)
|
||||
if self.callback and count % delta == 0:
|
||||
self.callback(float(count)/float(total))
|
||||
count = count + 1
|
||||
self.g.write(" <source id=\"%s\" handle=\"%s\" change=\"%d\">\n" %
|
||||
(source.get_gramps_id(), "_"+source.get_handle(),
|
||||
source.get_change_time()))
|
||||
self.write_force_line("stitle",source.get_title(),3)
|
||||
self.write_line("sauthor",source.get_author(),3)
|
||||
self.write_line("spubinfo",source.get_publication_info(),3)
|
||||
self.write_line("sabbrev",source.get_abbreviation(),3)
|
||||
if source.get_note() != "":
|
||||
self.write_note("note",source.get_note_object(),3)
|
||||
self.write_media_list(source.get_media_list())
|
||||
self.write_data_map(source.get_data_map())
|
||||
self.g.write(" </source>\n")
|
||||
self.g.write(" </sources>\n")
|
||||
|
||||
if place_len > 0:
|
||||
self.g.write(" <places>\n")
|
||||
keys = self.db.get_place_handles()
|
||||
keys.sort ()
|
||||
for key in keys:
|
||||
try:
|
||||
place = self.db.get_place_from_handle(key)
|
||||
if self.callback and count % delta == 0:
|
||||
self.callback(float(count)/float(total))
|
||||
self.write_place_obj(place)
|
||||
except:
|
||||
print "Could not find place %s" % key
|
||||
count = count + 1
|
||||
|
||||
self.g.write(" </places>\n")
|
||||
|
||||
if len(objList) > 0:
|
||||
self.g.write(" <objects>\n")
|
||||
keys = self.db.get_media_object_handles()
|
||||
sorted_keys = []
|
||||
for key in keys:
|
||||
obj = self.db.get_object_from_handle (key)
|
||||
value = (obj.get_gramps_id (), obj)
|
||||
sorted_keys.append (value)
|
||||
|
||||
sorted_keys.sort ()
|
||||
for (gramps_id, obj) in sorted_keys:
|
||||
self.write_object(obj)
|
||||
self.g.write(" </objects>\n")
|
||||
|
||||
if len(self.db.get_bookmarks()) > 0:
|
||||
self.g.write(" <bookmarks>\n")
|
||||
for person_handle in self.db.get_bookmarks():
|
||||
self.g.write(' <bookmark hlink="%s"/>\n' % ("_"+person_handle))
|
||||
self.g.write(" </bookmarks>\n")
|
||||
|
||||
if len(self.db.name_group) > 0:
|
||||
self.g.write(' <groups>\n')
|
||||
for key in self.db.name_group.keys():
|
||||
self.g.write(' <group_map name="%s" group="%s"/>\n' %
|
||||
(key,self.db.name_group[key]))
|
||||
self.g.write(' </groups>\n')
|
||||
|
||||
self.g.write("</database>\n")
|
||||
|
||||
def fix(self,line):
|
||||
l = line.strip()
|
||||
l = l.replace('&','&')
|
||||
l = l.replace('>','>')
|
||||
l = l.replace('<','<')
|
||||
return l.replace('"','"')
|
||||
|
||||
def write_note(self,val,noteobj,indent=0):
|
||||
if not noteobj:
|
||||
return
|
||||
text = noteobj.get()
|
||||
if not text:
|
||||
return
|
||||
if indent != 0:
|
||||
self.g.write(" " * indent)
|
||||
|
||||
format = noteobj.get_format()
|
||||
if format:
|
||||
self.g.write('<%s format="%d">' % (val,format))
|
||||
else:
|
||||
self.g.write('<%s>' % val)
|
||||
self.g.write(self.fix(text.rstrip()))
|
||||
self.g.write("</%s>\n" % val)
|
||||
|
||||
def write_text(self,val,text,indent=0):
|
||||
if not text:
|
||||
return
|
||||
if indent != 0:
|
||||
self.g.write(" " * indent)
|
||||
|
||||
self.g.write('<%s>' % val)
|
||||
self.g.write(self.fix(text.rstrip()))
|
||||
self.g.write("</%s>\n" % val)
|
||||
|
||||
def dump_event(self,event,index=1):
|
||||
if event:
|
||||
self.dump_my_event(event.get_name(),event,index)
|
||||
|
||||
def write_witness(self,witness_list,index):
|
||||
if not witness_list:
|
||||
return
|
||||
for w in witness_list:
|
||||
sp = " "*index
|
||||
com = self.fix(w.get_comment())
|
||||
if w.get_type() == RelLib.Event.ID:
|
||||
self.g.write('%s<witness hlink="%s">\n' % (sp,"_"+w.get_value()))
|
||||
if com:
|
||||
self.g.write(' %s<comment>%s</comment>\n' % (sp,com))
|
||||
self.g.write('%s</witness>\n' % sp)
|
||||
else:
|
||||
nm = self.fix(w.get_value())
|
||||
self.g.write('%s<witness name="%s">\n' % (sp,nm))
|
||||
if com:
|
||||
self.g.write(' %s<comment>%s</comment>\n' % (sp,com))
|
||||
self.g.write('%s</witness>\n' % sp)
|
||||
|
||||
def dump_my_event(self,name,event,index=1):
|
||||
if not event or event.is_empty():
|
||||
return
|
||||
|
||||
sp = " " * index
|
||||
name = const.save_event(name)
|
||||
self.g.write('%s<event type="%s"%s>\n' % (sp,self.fix(name),conf_priv(event)))
|
||||
self.write_date(event.get_date_object(),index+1)
|
||||
|
||||
self.write_witness(event.get_witness_list(),index+1)
|
||||
self.write_ref("place",event.get_place_handle(),index+1)
|
||||
self.write_line("cause",event.get_cause(),index+1)
|
||||
self.write_line("description",event.get_description(),index+1)
|
||||
if event.get_note():
|
||||
self.write_note("note",event.get_note_object(),index+1)
|
||||
|
||||
for s in event.get_source_references():
|
||||
self.dump_source_ref(s,index+1)
|
||||
self.write_media_list(event.get_media_list(),index+1)
|
||||
self.g.write("%s</event>\n" % sp)
|
||||
|
||||
def dump_ordinance(self,name,ord,index=1):
|
||||
if not ord:
|
||||
return
|
||||
|
||||
sp = " " * index
|
||||
sp2 = " " * (index+1)
|
||||
self.g.write('%s<lds_ord type="%s">\n' % (sp,self.fix(name)))
|
||||
dateobj = ord.get_date_object()
|
||||
if dateobj and not dateobj.is_empty():
|
||||
self.write_date(dateobj,index+1)
|
||||
if ord.get_temple():
|
||||
self.g.write('%s<temple val="%s"/>\n' % (sp2,self.fix(ord.get_temple())))
|
||||
self.write_ref("place",ord.get_place_handle(),index+1)
|
||||
if ord.get_status() != 0:
|
||||
self.g.write('%s<status val="%d"/>\n' % (sp2,ord.get_status()))
|
||||
if ord.get_family_handle():
|
||||
self.g.write('%s<sealed_to hlink="%s"/>\n' %
|
||||
(sp2,"_"+self.fix(ord.get_family_handle())))
|
||||
if ord.get_note() != "":
|
||||
self.write_note("note",ord.get_note_object(),index+1)
|
||||
for s in ord.get_source_references():
|
||||
self.dump_source_ref(s,index+1)
|
||||
self.g.write('%s</lds_ord>\n' % sp)
|
||||
|
||||
def dump_source_ref(self,source_ref,index=1):
|
||||
source = self.db.get_source_from_handle(source_ref.get_base_handle())
|
||||
if source:
|
||||
p = source_ref.get_page()
|
||||
c = source_ref.get_note()
|
||||
t = source_ref.get_text()
|
||||
d = source_ref.get_date_object()
|
||||
q = source_ref.get_confidence_level()
|
||||
self.g.write(" " * index)
|
||||
if p == "" and c == "" and t == "" and d.is_empty() and q == 2:
|
||||
self.g.write('<sourceref hlink="%s"/>\n' % ("_"+source.get_handle()))
|
||||
else:
|
||||
if q == 2:
|
||||
self.g.write('<sourceref hlink="%s">\n' % ("_"+source.get_handle()))
|
||||
else:
|
||||
self.g.write('<sourceref hlink="%s" conf="%d">\n' % ("_"+source.get_handle(),q))
|
||||
self.write_line("spage",p,index+1)
|
||||
self.write_text("scomments",c,index+1)
|
||||
self.write_text("stext",t,index+1)
|
||||
self.write_date(d,index+1)
|
||||
self.g.write("%s</sourceref>\n" % (" " * index))
|
||||
|
||||
def write_ref(self,label,gid,index=1):
|
||||
if gid:
|
||||
self.g.write('%s<%s hlink="%s"/>\n' % (" "*index,label,"_"+gid))
|
||||
|
||||
def write_id(self,label,person,index=1):
|
||||
if person:
|
||||
self.g.write('%s<%s id="%s" handle="%s" change="%d"' %
|
||||
(" "*index,label,person.get_gramps_id(),"_"+person.get_handle(),
|
||||
person.get_change_time()))
|
||||
comp = person.get_complete_flag()
|
||||
if comp:
|
||||
self.g.write(' complete="1"')
|
||||
self.g.write('>\n')
|
||||
|
||||
def write_family_handle(self,family,index=1):
|
||||
if family:
|
||||
rel = family.get_relationship()
|
||||
comp = family.get_complete_flag()
|
||||
sp = " " * index
|
||||
self.g.write('%s<family id="%s" handle="%s" change="%d"' %
|
||||
(sp,family.get_gramps_id(),"_"+family.get_handle(),family.get_change_time()))
|
||||
if comp:
|
||||
self.g.write(' complete="1"')
|
||||
if rel != "":
|
||||
self.g.write(' type="%s">\n' % const.save_frel(rel))
|
||||
else:
|
||||
self.g.write('>\n')
|
||||
|
||||
def write_last(self,name,indent=1):
|
||||
p = name.get_surname_prefix()
|
||||
n = name.get_surname()
|
||||
g = name.get_group_as()
|
||||
self.g.write('%s<last' % (' '*indent))
|
||||
if p:
|
||||
self.g.write(' prefix="%s"' % p)
|
||||
if g:
|
||||
self.g.write(' group="%s"' % g)
|
||||
self.g.write('>%s</last>\n' % self.fix(n))
|
||||
|
||||
def write_line(self,label,value,indent=1):
|
||||
if value:
|
||||
self.g.write('%s<%s>%s</%s>\n' % (' '*indent,label,self.fix(value),label))
|
||||
|
||||
def get_iso_date(self,date):
|
||||
if date[2] == 0:
|
||||
y = "????"
|
||||
else:
|
||||
y = "%04d" % date[2]
|
||||
|
||||
if date[1] == 0:
|
||||
if date[0] == 0:
|
||||
m = ""
|
||||
else:
|
||||
m = "-??"
|
||||
else:
|
||||
m = "-%02d" % (date[1])
|
||||
if date[0] == 0:
|
||||
d = ''
|
||||
else:
|
||||
d = "-%02d" % date[0]
|
||||
ret = "%s%s%s" % (y,m,d)
|
||||
# If the result does not contain anything beyond dashes
|
||||
# and question marks then it's as good as empty
|
||||
if ret.replace('-','').replace('?','') == '':
|
||||
ret = ''
|
||||
return ret
|
||||
|
||||
def write_date(self,date,indent=1):
|
||||
sp = ' '*indent
|
||||
|
||||
cal= date.get_calendar()
|
||||
if cal != Date.CAL_GREGORIAN:
|
||||
calstr = ' cformat="%s"' % Date.Date.calendar_names[cal]
|
||||
else:
|
||||
calstr = ''
|
||||
|
||||
qual = date.get_quality()
|
||||
if qual == Date.QUAL_ESTIMATED:
|
||||
qual_str = ' quality="estimated"'
|
||||
elif qual == Date.QUAL_CALCULATED:
|
||||
qual_str = ' quality="calculated"'
|
||||
else:
|
||||
qual_str = ""
|
||||
|
||||
mode = date.get_modifier()
|
||||
|
||||
if date.is_compound():
|
||||
d1 = self.get_iso_date(date.get_start_date())
|
||||
d2 = self.get_iso_date(date.get_stop_date())
|
||||
if d1 != "" or d2 != "":
|
||||
self.g.write('%s<daterange start="%s" stop="%s"%s%s/>\n'
|
||||
% (sp,d1,d2,qual_str,calstr))
|
||||
elif mode != Date.MOD_TEXTONLY:
|
||||
date_str = self.get_iso_date(date.get_start_date())
|
||||
if date_str == "":
|
||||
return
|
||||
|
||||
if mode == Date.MOD_BEFORE:
|
||||
mode_str = ' type="before"'
|
||||
elif mode == Date.MOD_AFTER:
|
||||
mode_str = ' type="after"'
|
||||
elif mode == Date.MOD_ABOUT:
|
||||
mode_str = ' type="about"'
|
||||
else:
|
||||
mode_str = ""
|
||||
|
||||
self.g.write('%s<dateval val="%s"%s%s%s/>\n'
|
||||
% (sp,date_str,mode_str,qual_str,calstr))
|
||||
else:
|
||||
self.g.write('%s<datestr val="%s"/>\n'
|
||||
%(sp,self.fix(date.get_text())))
|
||||
|
||||
def write_force_line(self,label,value,indent=1):
|
||||
if value != None:
|
||||
self.g.write('%s<%s>%s</%s>\n' % (' '*indent,label,self.fix(value),label))
|
||||
|
||||
def dump_name(self,name,alternative=False,index=1):
|
||||
sp = " "*index
|
||||
name_type = name.get_type()
|
||||
self.g.write('%s<name' % sp)
|
||||
if alternative:
|
||||
self.g.write(' alt="1"')
|
||||
if name_type:
|
||||
self.g.write(' type="%s"' % name_type)
|
||||
if name.get_privacy() != 0:
|
||||
self.g.write(' priv="%d"' % name.get_privacy())
|
||||
if name.get_sort_as() != 0:
|
||||
self.g.write(' sort="%d"' % name.get_sort_as())
|
||||
if name.get_display_as() != 0:
|
||||
self.g.write(' display="%d"' % name.get_display_as())
|
||||
self.g.write('>\n')
|
||||
self.write_line("first",name.get_first_name(),index+1)
|
||||
self.write_last(name,index+1)
|
||||
self.write_line("suffix",name.get_suffix(),index+1)
|
||||
self.write_line("patronymic",name.get_patronymic(),index+1)
|
||||
self.write_line("title",name.get_title(),index+1)
|
||||
if name.date:
|
||||
self.write_date(name.date,4)
|
||||
if name.get_note() != "":
|
||||
self.write_note("note",name.get_note_object(),index+1)
|
||||
for s in name.get_source_references():
|
||||
self.dump_source_ref(s,index+1)
|
||||
|
||||
self.g.write('%s</name>\n' % sp)
|
||||
|
||||
def append_value(self,orig,val):
|
||||
if orig:
|
||||
return "%s, %s" % (orig,val)
|
||||
else:
|
||||
return val
|
||||
|
||||
def build_place_title(self,loc):
|
||||
"Builds a title from a location"
|
||||
city = self.fix(loc.get_city())
|
||||
parish = self.fix(loc.get_parish())
|
||||
state = self.fix(loc.get_state())
|
||||
country = self.fix(loc.get_country())
|
||||
county = self.fix(loc.get_county())
|
||||
|
||||
value = ""
|
||||
|
||||
if city:
|
||||
value = city
|
||||
if parish:
|
||||
value = self.append_value(value,parish)
|
||||
if county:
|
||||
value = self.append_value(value,county)
|
||||
if state:
|
||||
value = self.append_value(value,state)
|
||||
if country:
|
||||
value = self.append_value(value,country)
|
||||
return value
|
||||
|
||||
def dump_location(self,loc):
|
||||
"Writes the location information to the output file"
|
||||
city = self.fix(loc.get_city())
|
||||
parish = self.fix(loc.get_parish())
|
||||
state = self.fix(loc.get_state())
|
||||
country = self.fix(loc.get_country())
|
||||
county = self.fix(loc.get_county())
|
||||
zip_code = self.fix(loc.get_postal_code())
|
||||
phone = self.fix(loc.get_phone())
|
||||
|
||||
self.g.write(' <location')
|
||||
if city:
|
||||
self.g.write(' city="%s"' % city)
|
||||
if parish:
|
||||
self.g.write(' parish="%s"' % parish)
|
||||
if county:
|
||||
self.g.write(' county="%s"' % county)
|
||||
if state:
|
||||
self.g.write(' state="%s"' % state)
|
||||
if country:
|
||||
self.g.write(' country="%s"' % country)
|
||||
if zip_code:
|
||||
self.g.write(' postal="%s"' % zip_code)
|
||||
if phone:
|
||||
self.g.write(' phone="%s"' % phone)
|
||||
self.g.write('/>\n')
|
||||
|
||||
def write_attribute_list(self, list, indent=3):
|
||||
sp = ' ' * indent
|
||||
for attr in list:
|
||||
self.g.write('%s<attribute%s type="%s" value="%s"' % \
|
||||
(sp,conf_priv(attr),const.save_attr(attr.get_type()),
|
||||
self.fix(attr.get_value())))
|
||||
slist = attr.get_source_references()
|
||||
note = attr.get_note()
|
||||
if note == "" and len(slist) == 0:
|
||||
self.g.write('/>\n')
|
||||
else:
|
||||
self.g.write('>\n')
|
||||
for s in attr.get_source_references():
|
||||
self.dump_source_ref(s,indent+1)
|
||||
self.write_note("note",attr.get_note_object(),4)
|
||||
self.g.write('%s</attribute>\n' % sp)
|
||||
|
||||
def write_media_list(self,list,indent=3):
|
||||
sp = ' '*indent
|
||||
for photo in list:
|
||||
mobj_id = photo.get_reference_handle()
|
||||
self.g.write('%s<objref hlink="%s"' % (sp,"_"+mobj_id))
|
||||
if photo.get_privacy():
|
||||
self.g.write(' priv="1"')
|
||||
proplist = photo.get_attribute_list()
|
||||
refslist = photo.get_source_references()
|
||||
if len(proplist) == 0 and len(refslist) == 0 \
|
||||
and photo.get_note() == "":
|
||||
self.g.write("/>\n")
|
||||
else:
|
||||
self.g.write(">\n")
|
||||
self.write_attribute_list(proplist,indent+1)
|
||||
for ref in refslist:
|
||||
self.dump_source_ref(ref,indent+1)
|
||||
self.write_note("note",photo.get_note_object(),indent+1)
|
||||
self.g.write('%s</objref>\n' % sp)
|
||||
|
||||
def write_data_map(self,datamap,indent=3):
|
||||
if len(datamap) == 0:
|
||||
return
|
||||
|
||||
sp = ' '*indent
|
||||
for key in datamap.keys():
|
||||
self.g.write('%s<data_item key="%s" value="%s"/>' %
|
||||
(sp,key,datamap[key]))
|
||||
|
||||
def write_url_list(self,list):
|
||||
for url in list:
|
||||
self.g.write(' <url priv="%d" href="%s"' % \
|
||||
(url.get_privacy(),self.fix(url.get_path())))
|
||||
if url.get_description() != "":
|
||||
self.g.write(' description="%s"' % self.fix(url.get_description()))
|
||||
self.g.write('/>\n')
|
||||
|
||||
def write_place_obj(self,place):
|
||||
title = self.fix(place.get_title())
|
||||
longitude = self.fix(place.get_longitude())
|
||||
lat = self.fix(place.get_latitude())
|
||||
handle = place.get_gramps_id()
|
||||
main_loc = place.get_main_location()
|
||||
llen = len(place.get_alternate_locations()) + len(place.get_url_list()) + \
|
||||
len(place.get_media_list()) + len(place.get_source_references())
|
||||
|
||||
ml_empty = main_loc.is_empty()
|
||||
note = place.get_note()
|
||||
|
||||
if title == "":
|
||||
title = self.fix(self.build_place_title(place.get_main_location()))
|
||||
|
||||
self.g.write(' <placeobj id="%s" handle="%s" change="%d" title="%s"' %
|
||||
(handle,"_"+place.get_handle(),place.get_change_time(),title))
|
||||
|
||||
if longitude or lat or not ml_empty or llen > 0 or note:
|
||||
self.g.write('>\n')
|
||||
else:
|
||||
self.g.write('/>\n')
|
||||
return
|
||||
|
||||
if longitude or lat:
|
||||
self.g.write(' <coord long="%s" lat="%s"/>\n' % (longitude,lat))
|
||||
|
||||
self.dump_location(main_loc)
|
||||
for loc in place.get_alternate_locations():
|
||||
self.dump_location(loc)
|
||||
self.write_media_list(place.get_media_list())
|
||||
self.write_url_list(place.get_url_list())
|
||||
if note != "":
|
||||
self.write_note("note",place.get_note_object(),3)
|
||||
for s in place.get_source_references():
|
||||
self.dump_source_ref(s,3)
|
||||
self.g.write(" </placeobj>\n")
|
||||
|
||||
def write_object(self,obj):
|
||||
handle = obj.get_gramps_id()
|
||||
mime_type = obj.get_mime_type()
|
||||
path = obj.get_path()
|
||||
if self.strip_photos:
|
||||
path = os.path.basename(path)
|
||||
self.g.write(' <object id="%s" handle="%s" change="%d" src="%s" mime="%s"' %
|
||||
(handle,"_"+obj.get_handle(),obj.get_change_time(),path,mime_type))
|
||||
self.g.write(' description="%s"' % self.fix(obj.get_description()))
|
||||
alist = obj.get_attribute_list()
|
||||
note = obj.get_note()
|
||||
dval = obj.get_date_object()
|
||||
slist = obj.get_source_references()
|
||||
if len(alist) == 0 and len(slist) == 0 and note == "" \
|
||||
and not dval.is_empty():
|
||||
self.g.write('/>\n')
|
||||
else:
|
||||
self.g.write('>\n')
|
||||
self.write_attribute_list(alist)
|
||||
if note != "":
|
||||
self.write_note("note",obj.get_note_object(),3)
|
||||
if not dval.is_empty():
|
||||
self.write_date(dval,3)
|
||||
for s in slist:
|
||||
self.dump_source_ref(s,3)
|
||||
self.g.write(" </object>\n")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def sortById(first,second):
|
||||
fid = first.get_gramps_id()
|
||||
sid = second.get_gramps_id()
|
||||
|
||||
if fid < sid:
|
||||
return -1
|
||||
else:
|
||||
return fid != sid
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def conf_priv(obj):
|
||||
if obj.get_privacy() != 0:
|
||||
return ' priv="%d"' % obj.get_privacy()
|
||||
else:
|
||||
return ''
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
_title = _('GRAMPS _XML database')
|
||||
_description = _('The GRAMPS XML database is a format used by older '
|
||||
'versions of GRAMPS. It is read-write compatible with '
|
||||
'the present GRAMPS database format.')
|
||||
_config = None
|
||||
_filename = 'gramps'
|
||||
|
||||
from PluginMgr import register_export
|
||||
register_export(exportData,_title,_description,_config,_filename)
|
56
gramps2/src/GrampsDb/__init__.py
Normal file
56
gramps2/src/GrampsDb/__init__.py
Normal file
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2004-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
This package implements the GrampsDb database. It provides a number
|
||||
of different backends for different storage mechanisms.
|
||||
|
||||
A number of importers and exporters are provided to convert between
|
||||
the different backend formats.
|
||||
|
||||
To obtain a class that implements the backend required you should use the
|
||||
gramps_db_factory method, likewise for writers use the gramps_db_writer_factory
|
||||
method and for readers use the gramps_db_reader_factory method. For information
|
||||
on using these factories see the _GrampsDbFactories.py file comments.
|
||||
|
||||
The package also contains GrampsDBCallback which provides signal/slot type
|
||||
functionality to allow objects to hook into signals that are generated from
|
||||
the database objects. Read the comments in _GrampsDBCallback.py for more
|
||||
information.
|
||||
"""
|
||||
|
||||
from _GrampsDbBase import DbState
|
||||
|
||||
from _GrampsDbFactories import \
|
||||
gramps_db_factory, \
|
||||
gramps_db_writer_factory, \
|
||||
gramps_db_reader_factory
|
||||
|
||||
|
||||
from _ReadGedcom import GedcomParser
|
||||
from _WriteGedcom import GedcomWriter
|
||||
from _WriteXML import XmlWriter
|
||||
|
||||
from _GrampsDbExceptions import GrampsDbException
|
||||
|
||||
from _GrampsDBCallback import GrampsDBCallback
|
||||
|
Reference in New Issue
Block a user