2007-12-28 Benny Malengier <benny.malengier@gramps-project.org>

* src/ViewManager.py: remove unused functions, add alt actions left/right
	* src/GrampsDb: deleted with _GrampsDbWriteXML.py,
		_GrampsDbFactories.py, _GrampsGEDDB.py, _GrampsXMLDB.py,
		__init__.py, Makefile.am, _GrampsInMemDB.py, _GrampsBSDDB.py.
		No more inmemory databases
	* src/GrampsDbUtils: moved here _GrampsDbWriteXML.py and _GrampsBSDDB.py
	* src/plugins/ReadGrdb.py:
	* src/plugins/Checkpoint.py:
	* src/ObjectSelector/_ObjectSelectorWindow.py:
	* src/DbManager.py:
	* src/GrampsDbUtils/_WriteGrdb.py:
	* src/GrampsDbUtils/__init__.py:
	* src/GrampsDbUtils/_GrampsDbWRFactories.py:
	* src/GrampsDbUtils/_WriteXML.py:
	* src/GrampsDbUtils/Makefile.am:
	* src/gramps_main.py:
	* src/RecentFiles.py: recent-files-gramps.xml, don't overwrite 2.2.x data
	* src/ArgHandler.py:
	* src/DbLoader.py: remove unused functions
	* src/Makefile.am:
	* po/POTFILES.in:
	* src/GrampsDbUtils/importdbdir.py: allow import of new database via cli
	Remove inMem Editing, move remaining to DbUtils, fix ArgHandler



svn: r9613
This commit is contained in:
Benny Malengier 2007-12-28 15:09:01 +00:00
parent 5ea0cd4b3e
commit dc9f03b6c0
26 changed files with 760 additions and 1392 deletions

View File

@ -1,3 +1,28 @@
2007-12-28 Benny Malengier <benny.malengier@gramps-project.org>
* src/ViewManager.py: remove unused functions, add alt actions left/right
* src/GrampsDb: deleted with _GrampsDbWriteXML.py,
_GrampsDbFactories.py, _GrampsGEDDB.py, _GrampsXMLDB.py,
__init__.py, Makefile.am, _GrampsInMemDB.py, _GrampsBSDDB.py.
No more inmemory databases
* src/GrampsDbUtils: moved here _GrampsDbWriteXML.py and _GrampsBSDDB.py
* src/plugins/ReadGrdb.py:
* src/plugins/Checkpoint.py:
* src/ObjectSelector/_ObjectSelectorWindow.py:
* src/DbManager.py:
* src/GrampsDbUtils/_WriteGrdb.py:
* src/GrampsDbUtils/__init__.py:
* src/GrampsDbUtils/_GrampsDbWRFactories.py:
* src/GrampsDbUtils/_WriteXML.py:
* src/GrampsDbUtils/Makefile.am:
* src/gramps_main.py:
* src/RecentFiles.py: recent-files-gramps.xml, don't overwrite 2.2.x data
* src/ArgHandler.py:
* src/DbLoader.py: remove unused functions
* src/Makefile.am:
* po/POTFILES.in:
* src/GrampsDbUtils/importdbdir.py: allow import of new database via cli
Remove inMem Editing, move remaining to DbUtils, fix ArgHandler
2007-12-28 Stéphane Charette <stephanecharette@gmail.com>
* src/ReportBase/_GraphvizReportDialog.py
* src/plugins/GVFamilyLines.py

View File

@ -193,11 +193,6 @@ src/Editors/_EditSourceRef.py
src/Editors/_EditUrl.py
src/Editors/__init__.py
# GrampsDb package
src/GrampsDb/_GrampsDbFactories.py
src/GrampsDb/_GrampsDbWriteXML.py
src/GrampsDb/__init__.py
# GrampsDbUtils package
src/GrampsDbUtils/_Backup.py
src/GrampsDbUtils/_GedcomInfo.py
@ -205,7 +200,10 @@ src/GrampsDbUtils/_GedcomStageOne.py
#src/GrampsDbUtils/_GedcomLex.py
src/GrampsDbUtils/_GedcomParse.py
src/GrampsDbUtils/_GedcomTokens.py
src/GrampsDbUtils/_GrampsBSDDB.py
src/GrampsDbUtils/_GrampsDbWriteXML.py
src/GrampsDbUtils/_GrampsDbWRFactories.py
src/GrampsDbUtils/importdbdir.py
src/GrampsDbUtils/_ReadGedcom.py
src/GrampsDbUtils/_ReadXML.py
src/GrampsDbUtils/_WriteGedcom.py

View File

@ -1,7 +1,8 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2000-2006 Donald N. Allingham, A. Roitman
# Copyright (C) 2007 B. Malengier
#
# 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
@ -20,8 +21,6 @@
# $Id$
# Written by Alex Roitman
"""
Module responsible for handling the command line arguments for GRAMPS.
"""
@ -51,7 +50,6 @@ import glob
#
#-------------------------------------------------------------------------
import const
import GrampsDb
import GrampsDbUtils
import Mime
import QuestionDialog
@ -59,10 +57,14 @@ import Config
import RecentFiles
import Utils
import gen.db.exceptions as GX
from DbManager import CLIDbManager, NAME_FILE
from PluginUtils import Tool, cl_list, cli_tool_list
from ReportBase import CATEGORY_BOOK, CATEGORY_CODE, CATEGORY_WEB, cl_report
IMPORT_TYPES = (const.APP_GRAMPS_XML, const.APP_GEDCOM,
const.APP_GRAMPS_PKG, const.APP_GENEWEB,
const.APP_GRAMPS)
#-------------------------------------------------------------------------
# ArgHandler
@ -72,16 +74,15 @@ class ArgHandler:
This class is responsible for handling command line arguments (if any)
given to gramps. The valid arguments are:
FILE : filename to open.
FAMTREE : family tree name or database dir to open.
All following arguments will be ignored.
-O, --open=FAMTREE : Family tree or family tree database dir to open.
-i, --import=FILE : filename to import.
-O, --open=FILE : filename to open.
-o, --output=FILE : filename to export.
-f, --format=FORMAT : format of the file preceding this option.
If the filename (no flags) is specified, the interactive session is
launched using data from filename. If the filename is not in a natvive
(grdb) format, dialog will be presented to set up a grdb database.
launched using data from filename.
In this mode (filename, no flags), the rest of the arguments is ignored.
This is a mode suitable by default for GUI launchers, mime type handlers,
and the like
@ -96,7 +97,7 @@ class ArgHandler:
interactive session will not be launched.
"""
def __init__(self,state,vm,args):
def __init__(self, state, vm, args):
self.state = state
self.vm = vm
self.args = args
@ -107,11 +108,11 @@ class ArgHandler:
self.exports = []
self.actions = []
self.imports = []
self.imp_db_path = None
self.list = False
self.parse_args()
#-------------------------------------------------------------------------
# Argument parser: sorts out given arguments
#-------------------------------------------------------------------------
@ -120,11 +121,21 @@ class ArgHandler:
Fill in lists with open, exports, imports, and actions options.
Any parsing errors lead to abort via sys.exit(1).
Possible:
1/ Just the family tree (name or database dir)
2/ -O, Open of a family tree
3/ -i, Import of any format understood by an importer, optionally provide
-f to indicate format (possible: 'gedcom','gramps-xml','gramps-pkg',
'grdb','geneweb'
4/ -o, output a family tree in required format, optionally provide
-f to indicate format (possible: 'gedcom',
'gramps-xml','gramps-pkg','iso','wft','geneweb')
5/ An action
"""
try:
options,leftargs = getopt.getopt(self.args[1:],
const.SHORTOPTS,const.LONGOPTS)
options, leftargs = getopt.getopt(self.args[1:],
const.SHORTOPTS, const.LONGOPTS)
except getopt.GetoptError:
# return without filling anything if we could not parse the args
print "Error parsing arguments: %s " % self.args[1:]
@ -139,47 +150,49 @@ class ArgHandler:
# Go over all given option and place them into appropriate lists
for opt_ix in range(len(options)):
o,v = options[opt_ix]
if o in ( '-O', '--open'):
fname = v
option, value = options[opt_ix]
if option in ( '-O', '--open'):
#only family trees can be opened
format = 'famtree'
fname = value
fullpath = os.path.abspath(os.path.expanduser(fname))
if not os.path.exists(fullpath):
print "Input file does not exist: %s" % fullpath
continue
ftype = Mime.get_type(fullpath)
if opt_ix<len(options)-1 \
and options[opt_ix+1][0] in ( '-f', '--format'):
format = options[opt_ix+1][1]
if format not in ('gedcom','gramps-xml','grdb'):
print "Invalid format: %s" % format
print "Ignoring input file: %s" % fname
if not os.path.exists(fullpath):
#see if not just a name of a database is given
dbman = CLIDbManager(self.state)
data = dbman.family_tree(fname)
if data is not None:
fname, ftype, title = data
else:
print "Input family tree does not exist: %s" % fullpath
print "If gedcom, gramps-xml or grdb, use the -i option"
continue
elif ftype == const.APP_GEDCOM:
format = 'gedcom'
elif ftype == const.APP_GRAMPS_XML:
format = 'gramps-xml'
elif ftype == const.APP_GRAMPS:
format = 'grdb'
elif ftype in [const.APP_GRAMPS_PKG,const.APP_GENEWEB]:
print 'Unsupported type: "%s" for input file: %s' \
% (ftype,fname)
print 'Please create a new GRAMPS database and import the file.'
continue
else:
print 'Unrecognized type: "%s" for input file: %s' \
% (ftype,fname)
print "Ignoring input file: %s" % fname
continue
self.open = (fname,format)
elif o in ( '-i', '--import'):
fname = v
if not os.path.isdir(fullpath):
print "A file is given, not an existing family tree",
print ", use the -i option to import in a family tree",
print " instead"
continue
self.open = (fname, format)
elif option in ( '-i', '--import'):
fname = value
fullpath = os.path.abspath(os.path.expanduser(fname))
if not os.path.exists(fullpath):
print "Input file does not exist: %s" % fullpath
continue
ftype = Mime.get_type(fullpath)
if opt_ix<len(options)-1 \
format = 'famtree'
ftype = Mime.get_type(fullpath)
if not os.path.exists(fullpath):
#see if not just a name of a database is given
dbman = CLIDbManager(self.state)
data = dbman.family_tree(fname)
if data is not None:
fname, ftype, title = data
else:
print "Input file does not exist: %s" % fullpath
continue
elif os.path.isdir(fullpath):
ftype = const.APP_FAMTREE
fname = fullpath
elif opt_ix<len(options)-1 \
and options[opt_ix+1][0] in ( '-f', '--format'):
format = options[opt_ix+1][1]
if format not in ('gedcom',
@ -205,16 +218,16 @@ class ArgHandler:
% (ftype,fname)
print "Ignoring input file: %s" % fname
continue
self.imports.append((fname,format))
elif o in ( '-o', '--output' ):
outfname = v
self.imports.append((fname, format))
elif option in ( '-o', '--output' ):
outfname = value
fullpath = os.path.abspath(os.path.expanduser(outfname))
if os.path.exists(fullpath):
print "WARNING: Output file already exist!"
print "WARNING: It will be overwritten:\n %s" % fullpath
answer = None
while not answer:
answer = raw_input('OK to overwrite? ')
answer = raw_input('OK to overwrite? (yes/no) ')
if answer.upper() in ('Y','YES'):
print "Will overwrite the existing file: %s" % fullpath
else:
@ -230,7 +243,7 @@ class ArgHandler:
'iso',
'wft',
'geneweb'):
print "Invalid format: %s" % outformat
print "Invalid format for output: %s" % outformat
print "Ignoring output file: %s" % outfname
continue
elif outfname[-3:].upper() == "GED":
@ -249,9 +262,9 @@ class ArgHandler:
print "Unrecognized format for output file %s" % outfname
print "Ignoring output file: %s" % outfname
continue
self.exports.append((outfname,outformat))
elif o in ( '-a', '--action' ):
action = v
self.exports.append((fullpath,outformat))
elif option in ( '-a', '--action' ):
action = value
if action not in ( 'check', 'summary', 'report', 'tool' ):
print "Unknown action: %s. Ignoring." % action
continue
@ -260,9 +273,11 @@ class ArgHandler:
and options[opt_ix+1][0] in ( '-p', '--options' ):
options_str = options[opt_ix+1][1]
self.actions.append((action,options_str))
elif o in ('-d', '--debug'):
l = logging.getLogger(v)
l.setLevel(logging.DEBUG)
elif option in ('-d', '--debug'):
logger = logging.getLogger(value)
logger.setLevel(logging.DEBUG)
elif option in ('-l',) :
self.list = True
#-------------------------------------------------------------------------
# Determine the need for GUI
@ -297,94 +312,98 @@ class ArgHandler:
session, write files, and/or perform actions.
"""
if self.list:
print 'List of known family trees in your database path\n'
dbman = CLIDbManager(self.state)
for name, dirname in dbman.family_tree_list():
print name, ', in dir ', dirname
if self.open_gui:
# Filename was given. Open a session with that file. Forget
# the rest of given arguments.
# Filename was given as gramps FILENAME.
# Open a session with that file. Forget the rest of given arguments
success = False
filename = os.path.abspath(os.path.expanduser(self.open_gui))
filetype = Mime.get_type(filename)
if filetype in (const.APP_GRAMPS,const.APP_GEDCOM,
const.APP_GRAMPS_XML, 'x-directory/normal'):
if os.path.isdir(self.open_gui):
#only accept if a name.txt is found
path_name = os.path.join(self.open_gui, NAME_FILE)
if os.path.isfile(path_name):
filetype = const.APP_FAMTREE
filename = self.open_gui
else:
filetype = 'No Fam Tree Dir'
filename = self.open_gui
else:
filename = os.path.abspath(os.path.expanduser(self.open_gui))
filetype = Mime.get_type(filename)
if filetype in ('x-directory/normal',):
success = True
pass
elif filetype in IMPORT_TYPES:
# Say the type outloud
if filetype == const.APP_GRAMPS:
print "Type: GRAMPS database"
print "Type: GRAMPS 2.2.x GRDB database"
elif filetype == const.APP_GEDCOM:
print "Type: GEDCOM file"
elif filetype == const.APP_GRAMPS_XML:
print "Type: GRAMPS XML database"
try:
self.vm.db_loader.read_file(filename, filetype)
print "Opened successfully!"
success = True
except:
print "Cannot open '%s'. Exiting..." % filename
elif filetype in (const.APP_GRAMPS_PKG,):
QuestionDialog.OkDialog( _("Opening non-native format"),
_("New GRAMPS database has to be set up "
"when opening non-native formats. The "
"following dialog will let you select "
"the new database."),
self.vm.window)
prompter = NewNativeDbPrompter(self.vm,self.state)
if not prompter.chooser():
QuestionDialog.ErrorDialog(
_("New GRAMPS database was not set up"),
_('GRAMPS cannot open non-native data '
'without setting up new GRAMPS database.'))
print "Cannot continue without native database. Exiting..."
sys.exit(1)
elif filetype == const.APP_GRAMPS_PKG:
print "Type: GRAMPS package"
self.vm.import_pkg(filename)
print "Type: GRAMPS XML package"
dbman = CLIDbManager(self.state)
filename, filetype, name = dbman.import_new_db(filetype,
filename, None)
success = True
else:
print "Unknown file type: %s" % filetype
QuestionDialog.ErrorDialog(
#see if not just a name of a database is given
dbman = CLIDbManager(self.state)
data = dbman.family_tree(self.open_gui)
if data is not None:
filename, filetype= data[0], data[1]
success = True
else:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
_('File type "%s" is unknown to GRAMPS.\n\n'
'Valid types are: GRAMPS database, GRAMPS XML, '
'GRAMPS package, and GEDCOM.') % filetype)
print "Exiting..."
sys.exit(1)
_('Not a valid Family tree given to open\n\n'
))
print "Exiting..."
sys.exit(1)
if success:
# Add the file to the recent items
RecentFiles.recent_files(filename,const.APP_GRAMPS)
path = os.path.join(filename, "name.txt")
try:
ifile = open(path)
title = ifile.readline().strip()
ifile.close()
except:
title = filename
RecentFiles.recent_files(filename, title)
else:
sys.exit(1)
return (filename, filetype)
if self.open:
# Filename to open was given. Open it natively (grdb or any of
# the InMem formats, without setting up a new database. Then
# go on and process the rest of the command line arguments.
# Family Tree to open was given. Open it
# Then go on and process the rest of the command line arguments.
self.cl = bool(self.exports or self.actions)
name,format = self.open
name, format = self.open
success = False
filename = os.path.abspath(os.path.expanduser(name))
if format == 'grdb':
filetype = const.APP_GRAMPS
print "Type: GRAMPS database"
elif format == 'gedcom':
filetype = const.APP_GEDCOM
print "Type: GEDCOM"
elif format == 'gramps-xml':
filetype = const.APP_GRAMPS_XML
print "Type: GRAMPS XML"
elif format == 'x-directory/normal':
filetype = 'x-directory/normal'
print "Type: GRAMPS DIR"
if format == 'famtree':
path_name = os.path.join(name, NAME_FILE)
if os.path.isfile(path_name):
filetype = const.APP_FAMTREE
filename = name
success = True
else:
print "No valid Family tree given, cannot be opened."
print "Exiting..."
sys.exit(1)
else:
print "Unknown file type: %s" % format
print "Only Family trees can be opened."
print "Exiting..."
sys.exit(1)
try:
self.vm.read_recent_file(filename, filetype)
self.vm.open_activate(filename)
print "Opened successfully!"
success = True
except:
@ -395,14 +414,14 @@ class ArgHandler:
if self.imports:
self.cl = bool(self.exports or self.actions or self.cl)
# Create empty dir for imported database(s)
self.imp_db_path = Utils.get_empty_tempdir("import_dbdir")
self.vm.db_loader.read_file(self.imp_db_path,const.APP_GRAMPS)
if not self.open:
# Create empty dir for imported database(s)
self.imp_db_path = Utils.get_empty_tempdir("import_dbdir")
self.vm.db_loader.read_file(self.imp_db_path)
for imp in self.imports:
print "Importing: file %s, format %s." % imp
self.cl_import(imp[0],imp[1])
self.cl_import(imp[0], imp[1])
elif len(self.args) > 1 and not self.open:
print "No data was given -- will launch interactive session."
@ -429,7 +448,6 @@ class ArgHandler:
print "Exiting."
sys.exit(0)
## read recent file is broken in GRAMPS 30 ! DISABLE
elif Config.get(Config.RECENT_FILE) and Config.get(Config.AUTOLOAD):
filename = Config.get(Config.RECENT_FILE)
self.vm.db_loader.read_file(filename, const.APP_GRAMPS)
@ -448,12 +466,21 @@ class ArgHandler:
# Import handler
#
#-------------------------------------------------------------------------
def cl_import(self,filename,format):
def cl_import(self, filename, format):
"""
Command-line import routine. Try to import filename using the format.
Any errors will cause the sys.exit(1) call.
"""
if format == 'grdb':
if format == 'famtree':
#3.x database
try:
GrampsDbUtils.gramps_db_reader_factory(const.APP_FAMTREE)(
self.state.db, filename, empty)
except AttributeError:
print "Error importing Family Tree %s" % filename
sys.exit(1)
elif format == 'grdb':
#2.x database
filename = os.path.normpath(os.path.abspath(filename))
try:
GrampsDbUtils.gramps_db_reader_factory(const.APP_GRAMPS)(
@ -534,7 +561,10 @@ class ArgHandler:
print "Invalid format: %s" % format
sys.exit(1)
if not self.cl:
return self.vm.post_load()
if self.imp_db_path:
return self.vm.open_activate(self.imp_db_path)
else:
return self.vm.open_activate(self.open[0])
#-------------------------------------------------------------------------
#
@ -549,16 +579,13 @@ class ArgHandler:
"""
filename = os.path.abspath(os.path.expanduser(filename))
if format == 'grdb':
try:
GrampsDbUtils.gramps_db_writer_factory(const.APP_GRAMPS)(
self.state.db,filename)
except:
print "Error exporting %s" % filename
sys.exit(1)
print "GRDB format write is no longer supported!"
sys.exit(1)
elif format == 'gedcom':
try:
gw = GrampsDbUtils.GedcomWriter(self.state.db, None, 1)
ret = gw.write_gedcom_file(filename)
print "... finished writing %s" % filename
except:
print "Error exporting %s" % filename
sys.exit(1)
@ -568,30 +595,37 @@ class ArgHandler:
try:
g = GrampsDbUtils.XmlWriter(self.state.db,None,0,1)
ret = g.write(filename)
print "... finished writing %s" % filename
except:
print "Error exporting %s" % filename
sys.exit(1)
else:
print "Error exporting %s" % filename
elif format == 'gramps-pkg':
try:
import WritePkg
writer = WritePkg.PackageWriter(self.state.db,filename)
writer = WritePkg.PackageWriter(self.state.db, filename)
ret = writer.export()
print "... finished writing %s" % filename
except:
print "Error creating %s" % filename
sys.exit(1)
elif format == 'iso':
import WriteCD
try:
writer = WriteCD.PackageWriter(self.state.db,filename,1)
writer = WriteCD.PackageWriter(self.state.db, filename, 1)
ret = writer.export()
print "... finished writing %s" % filename
except:
print "Error exporting %s" % filename
sys.exit(1)
elif format == 'wft':
import WriteFtree
try:
writer = WriteFtree.FtreeWriter(self.state.db,None,1,filename)
writer = WriteFtree.FtreeWriter(self.state.db, None, 1,
filename)
ret = writer.export_data()
print "... finished writing %s" % filename
except:
print "Error exporting %s" % filename
sys.exit(1)
@ -599,8 +633,9 @@ class ArgHandler:
import WriteGeneWeb
try:
writer = WriteGeneWeb.GeneWebWriter(self.state.db,
None,1,filename)
None, 1, filename)
ret = writer.export_data()
print "... finished writing %s" % filename
except:
print "Error exporting %s" % filename
sys.exit(1)
@ -690,78 +725,6 @@ class ArgHandler:
print "Unknown action: %s." % action
sys.exit(1)
#-------------------------------------------------------------------------
#
# NewNativeDbPrompter
#
#-------------------------------------------------------------------------
class NewNativeDbPrompter:
"""
This class allows to set up a new empty native (grdb) database.
The filename is forced to have an '.grdb' extension. If not given,
it is appended.
"""
def __init__(self,vm,state):
self.vm = vm
self.state = state
def chooser(self):
"""
Select the new file. Suggest the Untitled_X.grdb name.
Return 1 when selection is made and 0 otherwise.
"""
choose = gtk.FileChooserDialog(_('GRAMPS: Create GRAMPS database'),
self.vm.window,
gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_NEW,
gtk.RESPONSE_OK))
self.state.db.close()
# Always add automatic (macth all files) filter
add_all_files_filter(choose)
add_grdb_filter(choose)
# Suggested folder: try last open file, import, then last export,
# then home.
default_dir = os.path.split(Config.get(Config.RECENT_FILE))[0] + os.path.sep
if len(default_dir)<=1:
default_dir = Config.get(Config.RECENT_IMPORT_DIR)
if len(default_dir)<=1:
default_dir = Config.get(Config.RECENT_EXPORT_DIR)
if len(default_dir)<=1:
default_dir = '~/'
new_filename = Utils.get_new_filename('grdb',default_dir)
choose.set_current_folder(default_dir)
choose.set_current_name(os.path.split(new_filename)[1])
while (True):
response = choose.run()
if response == gtk.RESPONSE_OK:
filename = Utils.get_unicode_path(choose.get_filename())
if filename == None:
continue
if os.path.splitext(filename)[1] != ".grdb":
filename = filename + ".grdb"
choose.destroy()
self.state.db = GrampsDb.gramps_db_factory(const.APP_GRAMPS)(
Config.TRANSACTIONS)
self.vm.db_loader.read_file(filename, const.APP_GRAMPS)
self.state.signal_change()
#self.change_page(None, None)
# Add the file to the recent items
RecentFiles.recent_files(filename,const.APP_GRAMPS)
return True
else:
choose.destroy()
return False
choose.destroy()
return False
def add_all_files_filter(chooser):
"""
Add an all-permitting filter to the file chooser dialog.

View File

@ -56,7 +56,6 @@ import gtk
import const
import Config
import Mime
import GrampsDb
import gen.db
import GrampsDbUtils
import Utils
@ -87,122 +86,6 @@ class DbLoader:
self.dbstate = dbstate
self.uistate = uistate
def open_file(self):
"""
Presents a file open dialog and opens the corresponding exsting file
"""
choose = gtk.FileChooserDialog(
_('GRAMPS: Open database'),
self.uistate.window,
gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
# Always add automatic (macth all files) filter
add_all_files_filter(choose)
add_grdb_filter(choose)
add_xml_filter(choose)
add_gedcom_filter(choose)
(box, type_selector) = format_maker(OPEN_FORMATS)
choose.set_extra_widget(box)
choose.set_current_folder(get_default_dir())
response = choose.run()
if response == gtk.RESPONSE_OK:
filename = Utils.get_unicode_path(choose.get_filename())
if self.check_errors(filename):
return ('','')
filetype = type_selector.get_value()
if filetype == 'auto':
filetype = Mime.get_type(filename)
# (the_path, the_file) = os.path.split(filename)
choose.destroy()
if filetype in OPEN_FORMATS:
self.read_file(filename, filetype)
try:
os.chdir(os.path.dirname(filename))
except:
return ('', '')
return (filename, filetype)
elif filetype in [const.APP_GRAMPS_PKG, const.APP_GENEWEB]:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
_('Files of type "%s" cannot be opened directly.\n\n'
'Please create a new GRAMPS database and import '
'the file.') % filetype)
return ('', '')
else:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
_('File type "%s" is unknown to GRAMPS.\n\n'
'Valid types are: GRAMPS database, GRAMPS XML, '
'GRAMPS package, and GEDCOM.') % filetype)
return ('', '')
choose.destroy()
return ('', '')
def save_as(self):
choose = gtk.FileChooserDialog(
_('GRAMPS: Create GRAMPS database'),
self.uistate.window,
gtk.FILE_CHOOSER_ACTION_SAVE,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
# Always add automatic (macth all files) filter
add_all_files_filter(choose)
add_gramps_files_filter(choose)
add_grdb_filter(choose)
add_xml_filter(choose)
add_gedcom_filter(choose)
(box, type_selector) = format_maker(OPEN_FORMATS)
choose.set_extra_widget(box)
default_dir = get_default_dir()
new_filename = Utils.get_new_filename('grdb', default_dir)
choose.set_current_folder(default_dir)
choose.set_current_name(os.path.split(new_filename)[1])
response = choose.run()
if response == gtk.RESPONSE_OK:
filename = Utils.get_unicode_path(choose.get_filename())
if self.check_errors(filename):
return ('','')
# Do not allow saving as into the currently open file
if filename == self.dbstate.db.full_name:
return ('','')
filetype = type_selector.get_value()
if filetype == 'auto':
try:
the_file = open(filename,'wb')
the_file.close()
filetype = Mime.get_type(filename)
os.remove(filename)
except RuntimeError, msg:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
str(msg))
return ('','')
# First we try our best formats
if filetype not in OPEN_FORMATS:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
_("Unknown type: %s") % filetype
)
return ('','')
choose.destroy()
self.open_saved_as(filename, filetype)
return (filename, filetype)
else:
choose.destroy()
return ('','')
def import_file(self):
# First thing first: import is a batch transaction
# so we will lose the undo history. Warn the user.
@ -342,9 +225,11 @@ class DbLoader:
return False
def read_file(self, filename, filetype):
def read_file(self, filename):
"""
This method takes care of changing database, and loading the data.
In 3.0 we only allow reading of real databases of filetype
'x-directory/normal'
This method should only return on success.
Returning on failure makes no sense, because we cannot recover,
@ -363,26 +248,10 @@ class DbLoader:
'to the selected file.'))
else:
mode = "w"
elif filetype == 'unknown':
QuestionDialog.WarningDialog(
_('Missing or Invalid database'),
_('%s could not be found.\n'
'It is possible that this file no longer exists '
'or has been moved.') % filename)
return False
else:
mode = 'w'
try:
#dbclass = GrampsDb.gramps_db_factory(db_type = filetype)
dbclass = gen.db.GrampsDBDir
except gen.db.GrampsDbException, msg:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
_("This may be caused by an improper installation of GRAMPS.") +
"\n" + str(msg))
return
dbclass = gen.db.GrampsDBDir
self.dbstate.change_database(dbclass(Config.get(Config.TRANSACTIONS)))
self.dbstate.db.disable_signals()
@ -395,38 +264,19 @@ class DbLoader:
self.dbstate.db.set_save_path(filename)
try:
os.chdir(os.path.dirname(filename))
except:
except (OSError, IOError):
print "could not change directory"
except OSError, msg:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename, str(msg))
except Errors.DbError, msg:
QuestionDialog.DBErrorDialog(str(msg.value))
self.dbstate.db.close()
self.state.no_database()
except Exception:
_LOG.error("Failed to open database.", exc_info=True)
return True
def open_saved_as(self, filename, filetype):
dbclass = GrampsDb.gramps_db_factory(db_type = filetype)
new_database = dbclass()
old_database = self.dbstate.db
self.dbstate.change_database_noclose(new_database)
old_database.disable_signals()
new_database.disable_signals()
self.uistate.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
self.uistate.progress.show()
try:
new_database.load_from(old_database, filename,
self.uistate.pulse_progressbar)
old_database.close()
except Exception:
_LOG.error("Failed to open database.", exc_info=True)
return False
def do_import(self, dialog, importer, filename):
dialog.destroy()

View File

@ -66,7 +66,7 @@ import pango
#-------------------------------------------------------------------------
import const
import QuestionDialog
import GrampsDb
import gen.db
import GrampsDbUtils
import Config
import Mime
@ -97,7 +97,145 @@ STOCK_COL = 6
RCS_BUTTON = { True : _('Extract'), False : _('Archive') }
class DbManager:
class CLIDbManager:
"""
Database manager without GTK functionality, allows users to create and
open databases
"""
def __init__(self, dbstate):
self.dbstate = dbstate
self.msg = None
if dbstate:
self.active = dbstate.db.get_save_path()
else:
self.active = None
self.current_names = []
self._populate_cli()
def empty(self, val):
'''Callback that does nothing
'''
pass
def _populate_cli(self):
''' Get the list of current names in the database dir
'''
# make the default directory if it does not exist
dbdir = os.path.expanduser(Config.get(Config.DATABASE_PATH))
make_dbdir(dbdir)
self.current_names = []
for dpath in os.listdir(dbdir):
dirpath = os.path.join(dbdir, dpath)
path_name = os.path.join(dirpath, NAME_FILE)
if os.path.isfile(path_name):
name = file(path_name).readline().strip()
(tval, last) = time_val(dirpath)
(enable, stock_id) = icon_values(dirpath, self.active,
self.dbstate.db.is_open())
if (stock_id == 'gramps-lock'):
last = find_locker_name(dirpath)
self.current_names.append(
(name, os.path.join(dbdir, dpath), path_name,
last, tval, enable, stock_id))
self.current_names.sort()
def family_tree(self, name):
'''Given a name, return None if name not existing or
filename, filetype, name
if a known database name
'''
for data in self.current_names:
if data[0] == name:
return data[1], 'x-directory/normal', name
return None
def family_tree_list(self):
'''Return a list of name, dirname of the known family trees
'''
lst = [(x[0], x[1]) for x in self.current_names]
return lst
def __start_cursor(self, msg):
"""
Do needed things to start import visually, eg busy cursor
"""
print _('Starting Import, %s') % msg
def __end_cursor(self):
"""
Set end of a busy cursor
"""
print _('Import finished...')
def __create_new_db_cli(self, title=None):
"""
Create a new database.
"""
new_path = find_next_db_dir()
os.mkdir(new_path)
path_name = os.path.join(new_path, NAME_FILE)
if title == None:
name_list = [ name[0] for name in self.current_names ]
title = find_next_db_name(name_list)
name_file = open(path_name, "w")
name_file.write(title)
name_file.close()
self.current_names.append(title)
return new_path
def __create_new_db(self, title=None):
"""
Create a new database, do extra stuff needed
"""
return self.__create_new_db_cli(title)
def import_new_db(self, filetype, filename, callback):
if filetype in IMPORT_TYPES:
# get the name of the database from the filename of the file
(name, ext) = os.path.splitext(os.path.basename(filename))
# create the database
new_path = self.__create_new_db(name)
trans = Config.TRANSACTIONS
# get the import function using the filetype, but create a db
# based on the DBDir
self.__start_cursor(_("Importing data..."))
dbclass = gen.db.GrampsDBDir
dbase = dbclass(trans)
dbase.load(new_path, callback)
rdr = GrampsDbUtils.gramps_db_reader_factory(filetype)
rdr(dbase, filename, callback)
# finish up
self.__end_cursor()
dbase.close()
path = os.path.join(new_path, "name.txt")
try:
ifile = open(path)
title = ifile.readline().strip()
ifile.close()
except:
title = new_path
return new_path, 'x-directory/normal', title
return None, None, None
class DbManager(CLIDbManager):
"""
Database Manager. Opens a database manager window that allows users to
create, rename, delete and open databases.
@ -108,6 +246,7 @@ class DbManager:
Creates the top level window from the glade description, and extracts
the GTK widgets that are needed.
"""
CLIDbManager.__init__(self, dbstate)
self.glade = gtk.glade.XML(const.GLADE_FILE, "dbmanager", "gramps")
self.top = self.glade.get_widget('dbmanager')
if parent:
@ -123,24 +262,16 @@ class DbManager:
self.rcs = self.glade.get_widget('rcs')
self.msg = self.glade.get_widget('msg')
self.model = None
self.dbstate = dbstate
self.column = None
self.lock_file = None
self.data_to_delete = None
if dbstate:
self.active = dbstate.db.get_save_path()
else:
self.active = None
self.selection = self.dblist.get_selection()
self.dblist.set_rules_hint(True)
self.current_names = []
self.__connect_signals()
self.__build_interface()
self.__populate()
self._populate_model()
def __connect_signals(self):
"""
@ -276,37 +407,19 @@ class DbManager:
self.dblist.set_rules_hint(True)
def __populate(self):
"""
Builds the data and the display model.
"""
self._populate_cli()
self._populate_model()
def _populate_model(self):
"""
Builds the display model.
"""
self.model = gtk.TreeStore(str, str, str, str, int, bool, str)
# make the default directory if it does not exist
dbdir = os.path.expanduser(Config.get(Config.DATABASE_PATH))
make_dbdir(dbdir)
self.current_names = []
for dpath in os.listdir(dbdir):
dirpath = os.path.join(dbdir, dpath)
path_name = os.path.join(dirpath, NAME_FILE)
if os.path.isfile(path_name):
name = file(path_name).readline().strip()
(tval, last) = time_val(dirpath)
(enable, stock_id) = icon_values(dirpath, self.active,
self.dbstate.db.is_open())
if (stock_id == 'gramps-lock'):
last = find_locker_name(dirpath)
self.current_names.append(
(name, os.path.join(dbdir, dpath), path_name,
last, tval, enable, stock_id))
self.current_names.sort()
#use current names to set up the model
for items in self.current_names:
data = [items[0], items[1], items[2], items[3],
items[4], items[5], items[6]]
@ -473,10 +586,10 @@ class DbManager:
"""
new_path = self.__create_new_db("%s : %s" % (parent_name, name))
trans = Config.TRANSACTIONS
dbtype = 'x-directory/normal'
self.__start_cursor(_("Extracting archive..."))
dbase = GrampsDb.gramps_db_factory(dbtype)(trans)
dbclass = gen.db.GrampsDBDir
dbase = dbclass(trans)
dbase.load(new_path, None)
self.__start_cursor(_("Importing archive..."))
@ -600,7 +713,7 @@ class DbManager:
fname = os.path.join(dirname, filename)
os.unlink(fname)
dbclass = GrampsDb.gramps_db_factory(db_type = "x-directory/normal")
dbclass = gen.db.GrampsDBDir
dbase = dbclass(Config.get(Config.TRANSACTIONS))
dbase.set_save_path(dirname)
dbase.load(dirname, None)
@ -642,29 +755,16 @@ class DbManager:
QuestionDialog.ErrorDialog(_("Could not create family tree"),
str(msg))
def __create_new_db(self, title=None):
"""
Create a new database.
Create a new database, append to model
"""
new_path = find_next_db_dir()
os.mkdir(new_path)
new_path = self.__create_new_db_cli(title)
path_name = os.path.join(new_path, NAME_FILE)
if title == None:
name_list = [ name[0] for name in self.current_names ]
title = find_next_db_name(name_list)
name_file = open(path_name, "w")
name_file.write(title)
name_file.close()
self.current_names.append(title)
node = self.model.append(None, [title, new_path, path_name,
_("Never"), 0, False, ''])
self.selection.select_iter(node)
path = self.model.get_path(node)
self.dblist.set_cursor(path, focus_column=self.column,
start_editing=True)
@ -675,10 +775,11 @@ class DbManager:
"""
Handle the reception of drag data
"""
drag_value = selection.data
print drag_value
fname = None
type = None
title = None
# we are only interested in this if it is a file:// URL.
if drag_value and drag_value[0:7] == "file://":
@ -687,30 +788,10 @@ class DbManager:
# deterimine the mime type. If it is one that we are interested in,
# we process it
filetype = Mime.get_type(drag_value)
if filetype in IMPORT_TYPES:
fname, type, title = self.import_new_db(filetype, drag_value[7:],
None)
# get the name of the database from the filename of the file
(name, ext) = os.path.splitext(os.path.basename(drag_value))
# create the database
new_path = self.__create_new_db(name)
trans = Config.TRANSACTIONS
dbtype = 'x-directory/normal'
# get the import function using the filetype, but create a db
# based on the DBDir
self.__start_cursor(_("Importing data..."))
dbase = GrampsDb.gramps_db_factory(dbtype)(trans)
dbase.load(new_path, None)
rdr = GrampsDbUtils.gramps_db_reader_factory(filetype)
rdr(dbase, drag_value[7:], None)
# finish up
self.__end_cursor()
dbase.close()
return True
return fname, type, title
def drag_motion(wid, context, xpos, ypos, time_stamp):
"""

View File

@ -1,26 +0,0 @@
# This is the src/RelLib level Makefile for Gramps
# We could use GNU make's ':=' syntax for nice wildcard use,
# but that is not necessarily portable.
# If not using GNU make, then list all .py files individually
pkgdatadir = $(datadir)/@PACKAGE@/GrampsDb
pkgdata_PYTHON = \
_GrampsDbFactories.py\
_GrampsDbWriteXML.py \
_GrampsGEDDB.py\
_GrampsInMemDB.py\
__init__.py
pkgpyexecdir = @pkgpyexecdir@/GrampsDb
pkgpythondir = @pkgpythondir@/GrampsDb
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo
GRAMPS_PY_MODPATH = "../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));

View File

@ -1,89 +0,0 @@
#
# 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 gen.db.dbconst as const
from gen.db.exceptions import GrampsDbException
import logging
log = logging.getLogger(".GrampDb")
try:
import Config
config = Config
except:
log.warn("No Config module available, using defaults.")
config = None
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 gen.db import GrampsBSDDB
#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 gen.db import GrampsGEDDB
#from _GrampsGEDDB import GrampsGEDDB
cls = GrampsGEDDB
elif db_type == 'x-directory/normal':
from gen.db import GrampsDBDir
#from _GrampsDBDir import GrampsGEDDB
cls = GrampsDBDir
else:
raise GrampsDbException("Attempt to create unknown "
"database backend class: "
"db_type = %s" % (str(db_type),))
cls.__config__ = config
return cls

View File

@ -1,97 +0,0 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Provides the GRAMPS DB interface for supporting in-memory editing
of GEDCOM files.
"""
from gen.lib import *
from _GrampsInMemDB import *
from _GrampsDbExceptions import GrampsDbException
from gen.utils import db_copy
#-------------------------------------------------------------------------
#
# GrampsGEDDB
#
#-------------------------------------------------------------------------
class GrampsGEDDB(GrampsInMemDB):
"""GRAMPS database object. This object is a base class for other
objects."""
def __init__(self, use_txn = False):
"""creates a new GrampsDB"""
GrampsInMemDB.__init__(self)
def load(self, name, callback, mode="w"):
if self.db_is_open:
self.close()
GrampsInMemDB.load(self,name,callback,mode)
try:
from GrampsDbUtils._ReadGedcom import importData
except:
log.warning("Failed to load Gedcom reader", exc_info=True)
raise GrampsDbException("Failed to load Gedcom reader")
importData(self,name,callback,use_trans=False)
self.bookmarks = GrampsDbBookmarks(self.metadata.get('bookmarks',[]))
self.db_is_open = True
self.readonly = True
self.abort_possible = True
return 1
def load_from(self, other_database, filename, callback):
db_copy(other_database,self,callback)
GrampsInMemDB.load(self,filename,callback)
self.bookmarks = GrampsDbBookmarks(self.metadata.get('bookmarks',[]))
self.db_is_open = True
try:
from GrampsDbUtils._WriteGedcom import GedcomWriter
except:
log.warning("Failed to load Gedcom writer", exc_info=True)
raise GrampsDbException("Failed to load Gedcom writer")
writer = GedcomWriter(self,self.get_default_person(),
callback=callback)
writer.export_data(self.full_name)
return 1
def close(self):
if not self.db_is_open:
return
try:
from GrampsDbUtils._WriteGedcom import GedcomWriter
except:
log.warning("Failed to load Gedcom writer", exc_info=True)
raise GrampsDbException("Failed to load Gedcom writer")
if self.db_is_changed():
writer = GedcomWriter(self,self.get_default_person())
writer.export_data(self.full_name)
self.db_is_open = False
GrampsInMemDB.close(self)

View File

@ -1,392 +0,0 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Provides the common infrastructure for database formats that
must hold all of their data in memory.
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
import time
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gen.lib import *
from _GrampsDbBase import *
from _GrampsCursor import GrampsCursor
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
def get_length(self):
return len(self.src_map)
#-------------------------------------------------------------------------
#
# GrampsInMemDB
#
#-------------------------------------------------------------------------
class GrampsInMemDB(GrampsDbBase):
"""GRAMPS database object. This object is a base class for other
objects."""
ID_INDEX = 1 # an index of the gramps id in the data tuple
def __init__(self):
"""creates a new GrampsDB"""
GrampsDbBase.__init__(self)
self.filename = ""
def load(self,name,callback,mode="w"):
self.full_name = name
self.readonly = mode == "r"
self.open_undodb()
# Re-set the undo history to a fresh session start
self.undoindex = -1
self.translist = [None] * len(self.translist)
self.abort_possible = True
self.undo_history_timestamp = time.time()
def transaction_commit(self,transaction,msg):
GrampsDbBase.transaction_commit(self,transaction,msg)
if transaction.batch:
self.build_surname_list()
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_note_cursor(self):
return GrampsInMemCursor(self.note_map)
def get_media_cursor(self):
return GrampsInMemCursor(self.media_map)
def close(self):
self.close_undodb()
def set_name_group_mapping(self,name,group):
if group == None and self.name_group.has_key(name):
del self.name_group[name]
if group is not None :
self.name_group[name] = group
def build_surname_list(self):
a = set()
for person_id in iter(self.person_map):
p = self.get_person_from_handle(person_id)
a.add(unicode(p.get_primary_name().get_surname()))
self.surname_list = list(a)
self.sort_surname_list()
def remove_from_surname_list(self,person):
"""
Check whether there are persons with the same surname left in
the database. If not then we need to remove the name from the list.
The function must be overridden in the derived class.
"""
name = str(person.get_primary_name().get_surname())
count = 0
do_remove = True
for person_id in iter(self.person_map):
p = self.get_person_from_handle(person_id)
pn = str(p.get_primary_name().get_surname())
if pn == name:
count += 1
if count > 1:
do_remove = False
break
if do_remove:
self.surname_list.remove(unicode(name))
def del_person(self,handle):
person = self.get_person_from_handle(str(handle))
del self.id_trans[person.get_gramps_id()]
del self.person_map[str(handle)]
def del_source(self,handle):
source = self.get_source_from_handle(str(handle))
del self.sid_trans[source.get_gramps_id()]
del self.source_map[str(handle)]
def del_repository(self,handle):
repository = self.get_repository_from_handle(str(handle))
del self.rid_trans[repository.get_gramps_id()]
del self.repository_map[str(handle)]
def del_note(self,handle):
note = self.get_note_from_handle(str(handle))
del self.nid_trans[note.get_gramps_id()]
del self.note_map[str(handle)]
def del_place(self,handle):
place = self.get_place_from_handle(str(handle))
del self.pid_trans[place.get_gramps_id()]
del self.place_map[str(handle)]
def del_media(self,handle):
obj = self.get_object_from_handle(str(handle))
del self.oid_trans[obj.get_gramps_id()]
del self.media_map[str(handle)]
def del_family(self,handle):
family = self.get_family_from_handle(str(handle))
del self.fid_trans[family.get_gramps_id()]
del self.family_map[str(handle)]
def del_event(self,handle):
event = self.get_event_from_handle(str(handle))
del self.eid_trans[event.get_gramps_id()]
del self.event_map[str(handle)]
def get_trans_map(self,signal_root):
"""
A silly method to get the secondary index map based on the
signal name root for a given object type. The BDB backend
manages this transparently, but we need to manually take
care of secondary indices in the InMem backend.
"""
trans_maps = {
'person': self.id_trans,
'family': self.fid_trans,
'source': self.sid_trans,
'event' : self.eid_trans,
'media' : self.oid_trans,
'place' : self.pid_trans,
'repository': self.rid_trans,
'note': self.nid_trans,
}
return trans_maps[signal_root]
def undo_data(self, data, handle, db_map, signal_root):
"""
The BDB backend manages secondary indices transparently,
but we need to manually take care of secondary indices
in the InMem backend.
"""
trans_map = self.get_trans_map(signal_root)
obj = db_map.get(handle)
if data == None:
self.emit(signal_root + '-delete', ([handle], ))
del trans_map[obj[self.ID_INDEX]]
del db_map[handle]
else:
if obj:
signal = signal_root + '-update'
if obj[self.ID_INDEX] != data[self.ID_INDEX]:
del trans_map[obj[self.ID_INDEX]]
else:
signal = signal_root + '-add'
db_map[handle] = data
trans_map[data[self.ID_INDEX]] = str(handle)
self.emit(signal, ([handle], ))
def __commit_inmem_base(self,obj,db_map,trans_map):
if self.readonly or not obj or not obj.get_handle():
return False
gid = obj.gramps_id
old_data = db_map.get(obj.handle)
if old_data:
old_id = old_data[self.ID_INDEX]
if old_id is not None and obj.gramps_id != old_id:
del trans_map[old_id]
#on load of xml for backref that are encountered before object exists,
#the object is created empty with gid None. Do not add this to
#trans_map. Broken ref will then also not be exported (good!)
if gid is not None:
trans_map[gid] = obj.handle
return True
def commit_person(self,person,transaction,change_time=None):
if not self.__commit_inmem_base(person,self.person_map,self.id_trans):
return
GrampsDbBase.commit_person(self,person,transaction,change_time)
def commit_place(self,place,transaction,change_time=None):
if not self.__commit_inmem_base(place,self.place_map,self.pid_trans):
return
GrampsDbBase.commit_place(self,place,transaction,change_time)
def commit_family(self,family,transaction,change_time=None):
if not self.__commit_inmem_base(family,self.family_map,self.fid_trans):
return
GrampsDbBase.commit_family(self,family,transaction,change_time)
def commit_event(self,event,transaction,change_time=None):
if not self.__commit_inmem_base(event,self.event_map,self.eid_trans):
return
GrampsDbBase.commit_event(self,event,transaction,change_time)
def commit_media_object(self,obj,transaction,change_time=None):
if not self.__commit_inmem_base(obj,self.media_map,self.oid_trans):
return
GrampsDbBase.commit_media_object(self,obj,transaction,change_time)
def commit_source(self,source,transaction,change_time=None):
if not self.__commit_inmem_base(source,self.source_map,self.sid_trans):
return
GrampsDbBase.commit_source(self,source,transaction,change_time)
def commit_repository(self,repository,transaction,change_time=None):
if not self.__commit_inmem_base(repository,self.repository_map,
self.rid_trans):
return
GrampsDbBase.commit_repository(self,repository,transaction,change_time)
def commit_note(self,note,transaction,change_time=None):
if not self.__commit_inmem_base(note, self.note_map,
self.nid_trans):
return
GrampsDbBase.commit_note(self,note,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_note_from_gramps_id(self,val):
handle = self.nid_trans.get(str(val))
if handle:
data = self.note_map[handle]
if data:
note = Note()
note.unserialize(data)
return note
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
def db_is_changed(self):
"""return True if core data of database has changed in Memory
Note: this excludes most meta-data, you should check that separately
"""
return not self.readonly and \
(len(self.undodb) > 0 or
not self.abort_possible)

View File

@ -1,100 +0,0 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Provides the GRAMPS DB interface for supporting in-memory editing
of GRAMPS XML format.
"""
import logging
log = logging.getLogger(".GrampsDb")
from gen.lib import *
from _GrampsInMemDB import *
from _GrampsDbExceptions import GrampsDbException
from gen.utils import db_copy
#-------------------------------------------------------------------------
#
# GrampsXMLDB
#
#-------------------------------------------------------------------------
class GrampsXMLDB(GrampsInMemDB):
"""GRAMPS database object. This object is a base class for other
objects."""
def __init__(self, use_txn = True):
"""creates a new GrampsDB"""
GrampsInMemDB.__init__(self)
def load(self, name, callback, mode="w"):
if self.db_is_open:
self.close()
GrampsInMemDB.load(self, name, callback, mode)
self.id_trans = {}
try:
from GrampsDbUtils._ReadXML import importData
except:
log.warning("Failed to load XML reader", exc_info=True)
raise GrampsDbException("Failed to load XML reader")
try:
importData(self, name, callback, use_trans=False)
except OSError, IOError:
return 1
self.db_is_open = True
self.abort_possible = True
return 1
def load_from(self, other_database, filename, callback):
self.id_trans = {}
db_copy(other_database,self,callback)
GrampsInMemDB.load(self,filename,callback)
self.db_is_open = True
try:
from GrampsDbUtils._WriteXML import quick_write
except:
log.warning("Failed to load XML writer", exc_info=True)
raise GrampsDbException("Failed to load XML writer")
quick_write(self,self.full_name,callback)
return 1
def close(self):
if not self.db_is_open:
return
try:
from GrampsDbUtils._WriteXML import quick_write
except:
log.warning("Failed to load XML writer", exc_info=True)
raise GrampsDbException("Failed to load XML writer")
if self.db_is_changed() or self.db_has_bm_changes():
quick_write(self,self.full_name)
self.db_is_open = False
GrampsInMemDB.close(self)

View File

@ -1,46 +0,0 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2004-2006 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
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 _GrampsDbFactories import gramps_db_factory
from _GrampsDbWriteXML import GrampsDbXmlWriter, \
exportData, quick_write

View File

@ -14,7 +14,10 @@ pkgdata_PYTHON = \
_GedcomStageOne.py\
_GedcomTokens.py\
_GedcomUtils.py\
_GrampsBSDDB.py\
_GrampsDbWRFactories.py\
_GrampsDbWriteXML.py\
importdbdir.py\
__init__.py\
_ReadGedcom.py\
_ReadXML.py\

View File

@ -47,7 +47,7 @@ __LOG = logging.getLogger(".GrampsDb")
from gen.lib import *
from gen.db.base import *
from gen.utils import db_copy
import const
import gen.db.dbconst as const
from gen.db.exceptions import FileVersionError
from BasicUtils import UpdateCallback
@ -398,7 +398,8 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
if self.readonly:
self.UseTXN = False
callback(12)
if callback:
callback(12)
self.full_name = os.path.abspath(name)
self.brief_name = os.path.basename(name)
@ -427,7 +428,8 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
if self.UseTXN:
self.env.txn_checkpoint()
callback(25)
if callback:
callback(25)
self.metadata = self.__open_table(self.full_name, "meta")
# If we cannot work with this DB version,
@ -689,71 +691,83 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
self.id_trans.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "idtrans")
callback(1)
if callback:
callback(1)
self.surnames.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "surnames")
callback(2)
if callback:
callback(2)
# Repair secondary indices related to family_map
self.fid_trans.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "fidtrans")
callback(3)
if callback:
callback(3)
# Repair secondary indices related to place_map
self.pid_trans.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "pidtrans")
callback(4)
if callback:
callback(4)
# Repair secondary indices related to media_map
self.oid_trans.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "oidtrans")
callback(5)
if callback:
callback(5)
# Repair secondary indices related to source_map
self.sid_trans.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "sidtrans")
callback(6)
if callback:
callback(6)
# Repair secondary indices related to event_map
self.eid_trans.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "eidtrans")
callback(7)
if callback:
callback(7)
# Repair secondary indices related to repository_map
self.rid_trans.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "ridtrans")
callback(8)
if callback:
callback(8)
# Repair secondary indices related to note_map
self.nid_trans.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "nidtrans")
callback(9)
if callback:
callback(9)
# Repair secondary indices related to reference_map
self.reference_map_primary_map.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "reference_map_primary_map")
callback(10)
if callback:
callback(10)
self.reference_map_referenced_map.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "reference_map_referenced_map")
callback(11)
if callback:
callback(11)
# Set flag saying that we have removed secondary indices
# and then call the creating routine
self.secondary_connected = False
self.connect_secondary()
callback(12)
if callback:
callback(12)
def find_backlink_handles(self, handle, include_classes=None):
"""
@ -966,17 +980,20 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
self.reference_map_referenced_map.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "reference_map_referenced_map")
callback(1)
if callback:
callback(1)
self.reference_map_primary_map.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "reference_map_primary_map")
callback(2)
if callback:
callback(2)
self.reference_map.close()
junk = db.DB(self.env)
junk.remove(self.full_name, "reference_map")
callback(3)
if callback:
callback(3)
# Open reference_map and primapry map
self.reference_map = self.__open_table(self.full_name, "reference_map",
@ -1014,7 +1031,8 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
}
transaction = self.transaction_begin(batch=True, no_magic=True)
callback(4)
if callback:
callback(4)
# Now we use the functions and classes defined above
# to loop through each of the primary object tables.
@ -1044,7 +1062,8 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
data = cursor.next()
cursor.close()
callback(5)
if callback:
callback(5)
self.transaction_commit(transaction, _("Rebuild reference map"))
self.reference_map_referenced_map = db.DB(self.env)
@ -1054,7 +1073,8 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
db.DB_BTREE, flags=open_flags)
self.reference_map.associate(self.reference_map_referenced_map,
find_referenced_handle, open_flags)
callback(6)
if callback:
callback(6)
return

View File

@ -42,6 +42,7 @@ log = logging.getLogger(".GrampDb")
from gen.db import GrampsDbException
from PluginUtils import import_list
def gramps_db_writer_factory(db_type):
@ -54,10 +55,7 @@ def gramps_db_writer_factory(db_type):
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:
if db_type == const.APP_GRAMPS_XML:
import _WriteXML as WriteXML
md = WriteXML.exportData
elif db_type == const.APP_GEDCOM:
@ -71,24 +69,35 @@ def gramps_db_writer_factory(db_type):
return md
def gramps_db_reader_factory(db_type):
"""Factory class for obtaining a Gramps database writers.
"""Factory class for obtaining a Gramps database importers.
@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_XML:
if db_type == const.APP_FAMTREE :
import importdbdir
md = importdbdir.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),))
#see if registered importer
found = False
for data in import_list:
if db_type == data[2]:
print "Found import plugin for %s" % data[4]
found = True
md = data[0]
break
if not found:
raise GrampsDbException("Attempt to create a database "
"reader for unknown format: "
"db_type = %s" % (str(db_type),))
return md

View File

@ -35,7 +35,7 @@ from gettext import gettext as _
# Gramps Modules
#
#-------------------------------------------------------------------------
from GrampsDb._GrampsBSDDB import GrampsBSDDB
from GrampsDbUtils._GrampsBSDDB import GrampsBSDDB
from QuestionDialog import ErrorDialog
from gen.utils import db_copy

View File

@ -40,8 +40,9 @@ from gettext import gettext as _
import const
from QuestionDialog import ErrorDialog
import GrampsDb
import GrampsDbUtils
import ExportOptions
from gen.db.exceptions import GrampsDbWriteFailure
#-------------------------------------------------------------------------
#
@ -52,7 +53,7 @@ def export_data(database, filename, person, option_box, callback=None):
"""
Calls the XML writer with the syntax expected by the export plugin
"""
return GrampsDb.exportData(database, filename, person, option_box,
return GrampsDbUtils.exportData(database, filename, person, option_box,
callback, const.VERSION)
#-------------------------------------------------------------------------
@ -60,13 +61,13 @@ def export_data(database, filename, person, option_box, callback=None):
# XmlWriter
#
#-------------------------------------------------------------------------
class XmlWriter(GrampsDb.GrampsDbXmlWriter):
class XmlWriter(GrampsDbUtils.GrampsDbXmlWriter):
"""
Writes a database to the XML file.
"""
def __init__(self, dbase, callback, strip_photos, compress=1):
GrampsDb.GrampsDbXmlWriter.__init__(
GrampsDbUtils.GrampsDbXmlWriter.__init__(
self, dbase, strip_photos, compress, const.VERSION, callback)
def write(self, filename):
@ -74,8 +75,8 @@ class XmlWriter(GrampsDb.GrampsDbXmlWriter):
Write the database to the specified file.
"""
try:
ret = GrampsDb.GrampsDbXmlWriter.write(self, filename)
except GrampsDb.GrampsDbWriteFailure, val:
ret = GrampsDbUtils.GrampsDbXmlWriter.write(self, filename)
except GrampsDbWriteFailure, val:
ErrorDialog(val[0], val[1])
return ret
@ -85,8 +86,8 @@ class XmlWriter(GrampsDb.GrampsDbXmlWriter):
#
#-------------------------------------------------------------------------
TITLE = _('GRAMPS _XML database')
DESCRIPTION = _('The GRAMPS XML database is a format used by older '
'versions of GRAMPS. It is read-write compatible with '
DESCRIPTION = _('The GRAMPS XML database is a text version of a family tree. '
'It is read-write compatible with '
'the present GRAMPS database format.')
CONFIG = (_('GRAMPS XML export options'), ExportOptions.WriterOptionBox)
FILENAME = 'gramps'

View File

@ -45,10 +45,9 @@ from _GrampsDbWRFactories import \
from _GedcomParse import GedcomParser
from _WriteGedcom import GedcomWriter
from _GrampsDbWriteXML import GrampsDbXmlWriter, \
exportData, quick_write
from _WriteXML import XmlWriter
import _Backup as Backup
#from _PrivateProxyDb import PrivateProxyDb
#from _LivingProxyDb import LivingProxyDb

View File

@ -0,0 +1,288 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2005-2007 Donald N. Allingham
# Copyright (C) 2007 B. Malengier
#
# 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: $
# Based on ReadGrdb of version 2.x
#-------------------------------------------------------------------------
#
# Standard Python Modules
#
#-------------------------------------------------------------------------
import os
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# Gramps Modules
#
#-------------------------------------------------------------------------
from gen.db import GrampsDBDir
from QuestionDialog import ErrorDialog
from Errors import HandleError
from BasicUtils import UpdateCallback
from BasicUtils import name_displayer
#-------------------------------------------------------------------------
#
# Importing data into the currently open database.
#
#-------------------------------------------------------------------------
def importData(database, dirname, callback=None, cl=0, use_trans=True):
'''
Import dbdir database in dirname into dbdir database.
'''
name = os.path.normpath(dirname)
other_database = GrampsDBDir()
try:
other_database.load(name, 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
# If other_database contains its custom name formats,
# we need to do tricks to remap the format numbers
if len(other_database.name_formats) > 0:
formats_map = remap_name_formats(database, other_database)
name_displayer.set_name_format(database.name_formats)
get_person = make_peron_name_remapper(other_database, formats_map)
else:
# No remapping necessary, proceed as usual
get_person = other_database.get_person_from_handle
# Prepare table and method definitions
tables = {
'Person' : {'table' : database.person_map,
'id_table' : database.id_trans,
'add_obj' : database.add_person,
'find_next_gramps_id' :database.find_next_person_gramps_id,
'other_get_from_handle':
get_person,
'other_table': other_database.person_map,
},
'Family' : {'table' : database.family_map,
'id_table' : database.fid_trans,
'add_obj' : database.add_family,
'find_next_gramps_id' :database.find_next_family_gramps_id,
'other_get_from_handle':
other_database.get_family_from_handle,
'other_table': other_database.family_map,
},
'Event' : {'table' : database.event_map,
'id_table' : database.eid_trans,
'add_obj' : database.add_event,
'find_next_gramps_id' : database.find_next_event_gramps_id,
'other_get_from_handle':
other_database.get_event_from_handle,
'other_table': other_database.event_map,
},
'Source' : {'table' : database.source_map,
'id_table' : database.sid_trans,
'add_obj' : database.add_source,
'find_next_gramps_id': database.find_next_source_gramps_id,
'other_get_from_handle':
other_database.get_source_from_handle,
'other_table': other_database.source_map,
},
'Place' : {'table' : database.place_map,
'id_table' : database.pid_trans,
'add_obj' : database.add_place,
'find_next_gramps_id' :database.find_next_place_gramps_id,
'other_get_from_handle':
other_database.get_place_from_handle,
'other_table': other_database.place_map,
},
'Media' : {'table' : database.media_map,
'id_table' : database.oid_trans,
'add_obj' : database.add_object,
'find_next_gramps_id' : database.find_next_object_gramps_id,
'other_get_from_handle':
other_database.get_object_from_handle,
'other_table': other_database.media_map,
},
'Repository' : {'table' : database.repository_map,
'id_table' : database.rid_trans,
'add_obj' : database.add_repository,
'find_next_gramps_id' :
database.find_next_repository_gramps_id,
'other_get_from_handle':
other_database.get_repository_from_handle,
'other_table': other_database.repository_map,
},
'Note' : {'table': database.note_map,
'id_table': database.nid_trans,
'add_obj': database.add_note,
'find_next_gramps_id': database.find_next_note_gramps_id,
'other_get_from_handle':
other_database.get_note_from_handle,
'other_table': other_database.note_map,
},
}
uc = UpdateCallback(callback)
uc.set_total(len(tables.keys()))
the_len = 0
# Check for duplicate handles.
for key in tables:
table_dict = tables[key]
table = table_dict['table']
other_table = table_dict['other_table']
msg = '%s handles in two databases overlap.' % key
the_len += check_common_handles(table, other_table, msg)
uc.update()
# Proceed with preparing for import
if use_trans:
trans = database.transaction_begin("", batch=True)
else:
print "Transaction is None! This is no way to go!"
trans = None
database.disable_signals()
# copy all data from new_database to database,
# rename gramps IDs of first-class objects when conflicts are found
uc.set_total(the_len)
for key in tables:
table_dict = tables[key]
id_table = table_dict['id_table']
add_obj = table_dict['add_obj']
find_next_gramps_id = table_dict['find_next_gramps_id']
other_table = table_dict['other_table']
other_get_from_handle = table_dict['other_get_from_handle']
import_table(id_table, add_obj, find_next_gramps_id,
other_table, other_get_from_handle, trans, uc)
# Copy bookmarks over:
# we already know that there's no overlap in handles anywhere
database.bookmarks.append_list(other_database.bookmarks.get())
database.family_bookmarks.append_list(other_database.family_bookmarks.get())
database.event_bookmarks.append_list(other_database.event_bookmarks.get())
database.source_bookmarks.append_list(other_database.source_bookmarks.get())
database.place_bookmarks.append_list(other_database.place_bookmarks.get())
database.media_bookmarks.append_list(other_database.media_bookmarks.get())
database.repo_bookmarks.append_list(other_database.repo_bookmarks.get())
database.note_bookmarks.append_list(other_database.note_bookmarks.get())
# Copy grouping table
group_map = other_database.get_name_group_keys()
name_len = len(group_map)
if name_len > 0:
for key in group_map:
value = other_database.get_name_group_mapping(key)
if database.has_name_group_key(key) :
present = database.get_name_group_mapping(key)
if not value == present:
msg = _("Your family tree groups name %s together"
" with %s, did not change this grouping to %s") % (
key, present, value)
print msg
else:
database.set_name_group_mapping(key, value)
# close the other database and clean things up
other_database.close()
database.transaction_commit(trans, _("Import database"))
database.enable_signals()
database.request_rebuild()
def check_common_handles(table, other_table, msg):
# 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. How?
handles = set(table.keys())
other_handles = set(other_table.keys())
if handles.intersection(other_handles):
raise HandleError(msg)
return len(other_handles)
def import_table(id_table, add_obj, find_next_gramps_id,
other_table, other_get_from_handle, trans, uc):
for handle in other_table.keys():
obj = other_get_from_handle(handle)
# Then we check gramps_id for conflicts and change it if needed
gramps_id = str(obj.gramps_id)
if id_table.has_key(gramps_id):
gramps_id = find_next_gramps_id()
obj.gramps_id = gramps_id
add_obj(obj, trans)
uc.update()
def remap_name_formats(database, other_database):
formats_map = {}
taken_numbers = [num for (num, name, fmt_str, active)
in database.name_formats]
for (number, name, fmt_str, act) in other_database.name_formats:
if number in taken_numbers:
new_number = -1
while new_number in taken_numbers:
new_number -= 1
taken_numbers.append(new_number)
formats_map[number] = new_number
else:
new_number = number
database.name_formats.append((new_number, name, fmt_str, act))
return formats_map
def remap_name(person, formats_map):
for name in [person.primary_name] + person.alternate_names:
try:
name.sort_as = formats_map[name.sort_as]
except KeyError:
pass
try:
name.display_as = formats_map[name.display_as]
except KeyError:
pass
def make_peron_name_remapper(other_database, formats_map):
def new_get_person(handle):
person = other_database.get_person_from_handle(handle)
remap_name(person, formats_map)
return person
return new_get_person

View File

@ -10,7 +10,6 @@ SUBDIRS = \
Filters \
FilterEditor \
gen \
GrampsDb \
GrampsDbUtils \
GrampsLocale \
Merge \

View File

@ -345,61 +345,3 @@ class ObjectSelectorWindow(gtk.Window,ManagedWindow):
if gtk.pygtk_version < (2,8,0):
gobject.type_register(ObjectSelectorWindow)
if __name__ == "__main__":
import GrampsDb
import ViewManager
import const
import logging
import sys,os.path
form = logging.Formatter(fmt="%(relativeCreated)d: %(levelname)s: %(filename)s: line %(lineno)d: %(message)s")
stderrh = logging.StreamHandler(sys.stderr)
stderrh.setFormatter(form)
stderrh.setLevel(logging.DEBUG)
# everything.
l = logging.getLogger()
l.setLevel(logging.DEBUG)
l.addHandler(stderrh)
def cb(d):
pass
state = GrampsDb.DbState()
vm = ViewManager.ViewManager(state)
db = GrampsDb.gramps_db_factory(const.APP_GRAMPS)()
db.load(os.path.realpath(sys.argv[1]),
cb, # callback
"w")
class D:
pass
dbstate = D()
dbstate.db = db
def prof_fun():
global dbstate, vm
w = ObjectSelectorWindow(dbstate=dbstate,
uistate=vm.uistate,
track=[],
filter_spec=None,
default_object_type = ObjectTypes.PERSON,
object_list=[ObjectTypes.PERSON,])
#object_list=[ObjectTypes.PERSON,ObjectTypes.FAMILY])
w.show()
w.connect("destroy", gtk.main_quit)
def add(w,results):
print str(results)
w.connect('add-object',add)
gtk.main()
prof_fun()
import profile
profile.run("prof_fun()",'profile.dat')

View File

@ -44,7 +44,7 @@ import const
# Constants
#
#-------------------------------------------------------------------------
GRAMPS_FILENAME = os.path.join(const.HOME_DIR,"recent-files.xml")
GRAMPS_FILENAME = os.path.join(const.HOME_DIR,"recent-files-gramps.xml")
MAX_GRAMPS_ITEMS = 10
#-------------------------------------------------------------------------
@ -242,7 +242,7 @@ class RecentParser:
# Helper functions
#
#-------------------------------------------------------------------------
def recent_files(filename,name):
def recent_files(filename, name):
"""
Add an entry to both GNOME and GRAMPS recent-items storages.
"""

View File

@ -186,6 +186,8 @@ UIDEFAULT = '''<ui>
<accelerator action="<CONTROL>J"/>
<accelerator action="<Alt>N"/>
<accelerator action="<Alt>P"/>
<accelerator action="<Alt>Left"/>
<accelerator action="<Alt>Right"/>
</ui>
'''
@ -416,9 +418,7 @@ class ViewManager:
self.tip_of_day_activate),
]
self._readonly_action_list = [
('SaveAs', gtk.STOCK_SAVE_AS, _('_Save As'), "<control><shift>s",
None, self.__save_as_activate),
self._readonly_action_list = [
('Export', 'gramps-export', _('_Export'), "<control>e", None,
self.export_data),
('Abandon', gtk.STOCK_REVERT_TO_SAVED,
@ -447,7 +447,11 @@ class ViewManager:
('<CONTROL>J', None, '<CONTROL>J',
"<CONTROL>J", None, self.__keypress),
('<Alt>N', None, '<Alt>N', "<Alt>N", None, self.__next_view),
('<Alt>P', None, '<Alt>P', "<Alt>P", None, self.__prev_view),
('<Alt>P', None, '<Alt>P', "<Alt>P", None, self.__prev_view),
('<Alt>Left', None, '<Alt>Left', "<Alt>Left", None,
self.__prev_view),
('<Alt>Right', None, '<Alt>Right', "<Alt>Right", None,
self.__next_view),
]
self._action_action_list = [
@ -566,13 +570,13 @@ class ViewManager:
if self.filter_menu.get_active() != Config.get(Config.FILTER):
self.filter_menu.set_active(Config.get(Config.FILTER))
def post_init_interface(self):
def post_init_interface(self, show_manager=True):
"""
Showing the main window is deferred so that
ArgHandler can work without it always shown
"""
self.window.show()
if not self.state.db.is_open():
if not self.state.db.is_open() and show_manager:
self.__open_activate(None)
def post_load_newdb(self, filename, filetype):
@ -1044,98 +1048,34 @@ class ViewManager:
if self.state.db.is_open():
self.db_loader.import_file()
self.__post_load()
def open_activate(self, path):
"""
Open and make a family tree active
"""
self.__read_recent_file(path)
def __open_activate(self, obj):
"""
Called when the Open button is clicked
Called when the Open button is clicked, opens the DbManager
"""
import DbManager
dialog = DbManager.DbManager(self.state, self.window)
value = dialog.run()
if value:
(filename, title) = value
self.read_file(filename, 'x-directory/normal')
self.db_loader.read_file(filename)
try:
os.chdir(os.path.dirname(filename))
except (IOError, OSError):
pass
self.__post_load_newdb(filename, 'x-directory/normal', title)
def read_file(self, filename, filetype):
"""
This method takes care of changing database, and loading the data.
This method should only return on success.
Returning on failure makes no sense, because we cannot recover,
since database has already beeen changed.
Therefore, any errors should raise exceptions.
On success, return with the disabled signals. The post-load routine
should enable signals, as well as finish up with other UI goodies.
"""
if os.path.exists(filename):
if not os.access(filename, os.W_OK):
mode = "r"
QuestionDialog.WarningDialog(_('Read only database'),
_('You do not have write access '
'to the selected file.'))
else:
mode = "w"
elif filetype == 'unknown':
QuestionDialog.WarningDialog(
_('Missing or Invalid database'),
_('%s could not be found.\n'
'It is possible that this file no longer exists '
'or has been moved.') % filename)
return False
else:
mode = 'w'
try:
dbclass = gen.db.dbdir.GrampsDBDir
except gen.db.exceptions.GrampsDbException, msg:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
_("This may be caused by an improper installation of GRAMPS.") +
"\n" + str(msg))
return
self.state.change_database(dbclass(Config.get(Config.TRANSACTIONS)))
self.state.db.disable_signals()
self.uistate.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
self.uistate.progress.show()
try:
self.state.db.load(filename, self.uistate.pulse_progressbar, mode)
self.state.db.set_save_path(filename)
try:
os.chdir(os.path.dirname(filename))
except (OSError, IOError):
print "could not change directory"
except Errors.DbError, msg:
QuestionDialog.DBErrorDialog(str(msg.value))
self.state.no_database()
except Exception:
LOG.error("Failed to open database.", exc_info=True)
return True
def __save_as_activate(self, obj):
"""
Called when the SaveAs button is clicked
"""
if self.state.db.is_open():
(filename, filetype) = self.db_loader.save_as()
self.__post_load_newdb(filename, filetype)
def __read_recent_file(self, filename):
"""
Called when the recent file is loaded
"""
if self.db_loader.read_file(filename, 'x-directory/normal'):
if self.db_loader.read_file(filename):
# Attempt to figure out the database title
path = os.path.join(filename, "name.txt")
try:

View File

@ -45,7 +45,6 @@ import gtk
#
#-------------------------------------------------------------------------
import ViewManager
import GrampsDb
import ArgHandler
import Config
import const
@ -249,10 +248,12 @@ class Gramps:
ah = ArgHandler.ArgHandler(state, self.vm, args)
if ah.need_gui():
retval = ah.handle_args()
self.vm.post_init_interface()
if retval:
filename, filetype = retval
self.vm.post_load_newdb(filename, filetype)
self.vm.post_init_interface(show_manager=False)
self.vm.open_activate(filename)
else:
self.vm.post_init_interface()
else:
ah.handle_args()
self.vm.post_init_interface()

View File

@ -46,7 +46,6 @@ import gtk.glade
# gramps modules
#
#-------------------------------------------------------------------------
import GrampsDb
import GrampsDbUtils
import Utils
import GrampsDisplay

View File

@ -45,7 +45,7 @@ import gtk
# Gramps Modules
#
#-------------------------------------------------------------------------
from GrampsDb._GrampsBSDDB import GrampsBSDDB
from GrampsDbUtils._GrampsBSDDB import GrampsBSDDB
from QuestionDialog import ErrorDialog
from Errors import HandleError
from BasicUtils import UpdateCallback