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:
parent
5ea0cd4b3e
commit
dc9f03b6c0
25
ChangeLog
25
ChangeLog
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
162
src/DbLoader.py
162
src/DbLoader.py
@ -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()
|
||||
|
243
src/DbManager.py
243
src/DbManager.py
@ -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):
|
||||
"""
|
||||
|
@ -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));
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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)
|
@ -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)
|
@ -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)
|
@ -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
|
||||
|
||||
|
@ -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\
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
||||
|
288
src/GrampsDbUtils/importdbdir.py
Normal file
288
src/GrampsDbUtils/importdbdir.py
Normal 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
|
@ -10,7 +10,6 @@ SUBDIRS = \
|
||||
Filters \
|
||||
FilterEditor \
|
||||
gen \
|
||||
GrampsDb \
|
||||
GrampsDbUtils \
|
||||
GrampsLocale \
|
||||
Merge \
|
||||
|
@ -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')
|
||||
|
@ -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.
|
||||
"""
|
||||
|
@ -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>
|
||||
'''
|
||||
|
||||
@ -417,8 +419,6 @@ class ViewManager:
|
||||
]
|
||||
|
||||
self._readonly_action_list = [
|
||||
('SaveAs', gtk.STOCK_SAVE_AS, _('_Save As'), "<control><shift>s",
|
||||
None, self.__save_as_activate),
|
||||
('Export', 'gramps-export', _('_Export'), "<control>e", None,
|
||||
self.export_data),
|
||||
('Abandon', gtk.STOCK_REVERT_TO_SAVED,
|
||||
@ -448,6 +448,10 @@ class ViewManager:
|
||||
"<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>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):
|
||||
@ -1045,97 +1049,33 @@ class ViewManager:
|
||||
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:
|
||||
|
@ -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()
|
||||
|
@ -46,7 +46,6 @@ import gtk.glade
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import GrampsDb
|
||||
import GrampsDbUtils
|
||||
import Utils
|
||||
import GrampsDisplay
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user