From dc9f03b6c0c577f217da1cd4681bb0f5998ab940 Mon Sep 17 00:00:00 2001 From: Benny Malengier Date: Fri, 28 Dec 2007 15:09:01 +0000 Subject: [PATCH] 2007-12-28 Benny Malengier * 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 --- ChangeLog | 25 ++ po/POTFILES.in | 8 +- src/ArgHandler.py | 385 ++++++++--------- src/DbLoader.py | 162 +------- src/DbManager.py | 243 +++++++---- src/GrampsDb/Makefile.am | 26 -- src/GrampsDb/_GrampsDbFactories.py | 89 ---- src/GrampsDb/_GrampsGEDDB.py | 97 ----- src/GrampsDb/_GrampsInMemDB.py | 392 ------------------ src/GrampsDb/_GrampsXMLDB.py | 100 ----- src/GrampsDb/__init__.py | 46 -- src/GrampsDbUtils/Makefile.am | 3 + .../_GrampsBSDDB.py | 62 ++- src/GrampsDbUtils/_GrampsDbWRFactories.py | 29 +- .../_GrampsDbWriteXML.py | 0 src/GrampsDbUtils/_WriteGrdb.py | 2 +- src/GrampsDbUtils/_WriteXML.py | 17 +- src/GrampsDbUtils/__init__.py | 5 +- src/GrampsDbUtils/importdbdir.py | 288 +++++++++++++ src/Makefile.am | 1 - src/ObjectSelector/_ObjectSelectorWindow.py | 58 --- src/RecentFiles.py | 4 +- src/ViewManager.py | 100 +---- src/gramps_main.py | 7 +- src/plugins/Checkpoint.py | 1 - src/plugins/ReadGrdb.py | 2 +- 26 files changed, 760 insertions(+), 1392 deletions(-) delete mode 100644 src/GrampsDb/Makefile.am delete mode 100644 src/GrampsDb/_GrampsDbFactories.py delete mode 100644 src/GrampsDb/_GrampsGEDDB.py delete mode 100644 src/GrampsDb/_GrampsInMemDB.py delete mode 100644 src/GrampsDb/_GrampsXMLDB.py delete mode 100644 src/GrampsDb/__init__.py rename src/{GrampsDb => GrampsDbUtils}/_GrampsBSDDB.py (99%) rename src/{GrampsDb => GrampsDbUtils}/_GrampsDbWriteXML.py (100%) create mode 100644 src/GrampsDbUtils/importdbdir.py diff --git a/ChangeLog b/ChangeLog index 6d78a0ff6..e03294c60 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2007-12-28 Benny Malengier + * 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 * src/ReportBase/_GraphvizReportDialog.py * src/plugins/GVFamilyLines.py diff --git a/po/POTFILES.in b/po/POTFILES.in index 4f0345945..5f4937d00 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -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 diff --git a/src/ArgHandler.py b/src/ArgHandler.py index c5ea2635a..9ec358933 100644 --- a/src/ArgHandler.py +++ b/src/ArgHandler.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 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. diff --git a/src/DbLoader.py b/src/DbLoader.py index cf5d212c2..17b6862fa 100644 --- a/src/DbLoader.py +++ b/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() diff --git a/src/DbManager.py b/src/DbManager.py index f4ebc7dde..e4cafca19 100644 --- a/src/DbManager.py +++ b/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): """ diff --git a/src/GrampsDb/Makefile.am b/src/GrampsDb/Makefile.am deleted file mode 100644 index b4de6eb11..000000000 --- a/src/GrampsDb/Makefile.am +++ /dev/null @@ -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)); diff --git a/src/GrampsDb/_GrampsDbFactories.py b/src/GrampsDb/_GrampsDbFactories.py deleted file mode 100644 index 1358269cf..000000000 --- a/src/GrampsDb/_GrampsDbFactories.py +++ /dev/null @@ -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 - - - - diff --git a/src/GrampsDb/_GrampsGEDDB.py b/src/GrampsDb/_GrampsGEDDB.py deleted file mode 100644 index e91a7835c..000000000 --- a/src/GrampsDb/_GrampsGEDDB.py +++ /dev/null @@ -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) diff --git a/src/GrampsDb/_GrampsInMemDB.py b/src/GrampsDb/_GrampsInMemDB.py deleted file mode 100644 index 9155ecd6b..000000000 --- a/src/GrampsDb/_GrampsInMemDB.py +++ /dev/null @@ -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) diff --git a/src/GrampsDb/_GrampsXMLDB.py b/src/GrampsDb/_GrampsXMLDB.py deleted file mode 100644 index b36218cfa..000000000 --- a/src/GrampsDb/_GrampsXMLDB.py +++ /dev/null @@ -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) diff --git a/src/GrampsDb/__init__.py b/src/GrampsDb/__init__.py deleted file mode 100644 index 862af6f6b..000000000 --- a/src/GrampsDb/__init__.py +++ /dev/null @@ -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 - - diff --git a/src/GrampsDbUtils/Makefile.am b/src/GrampsDbUtils/Makefile.am index ae8995406..b4e5055c0 100644 --- a/src/GrampsDbUtils/Makefile.am +++ b/src/GrampsDbUtils/Makefile.am @@ -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\ diff --git a/src/GrampsDb/_GrampsBSDDB.py b/src/GrampsDbUtils/_GrampsBSDDB.py similarity index 99% rename from src/GrampsDb/_GrampsBSDDB.py rename to src/GrampsDbUtils/_GrampsBSDDB.py index 6334a0b65..09c9b060d 100644 --- a/src/GrampsDb/_GrampsBSDDB.py +++ b/src/GrampsDbUtils/_GrampsBSDDB.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 diff --git a/src/GrampsDbUtils/_GrampsDbWRFactories.py b/src/GrampsDbUtils/_GrampsDbWRFactories.py index 8cc7aa922..c87698b24 100644 --- a/src/GrampsDbUtils/_GrampsDbWRFactories.py +++ b/src/GrampsDbUtils/_GrampsDbWRFactories.py @@ -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 diff --git a/src/GrampsDb/_GrampsDbWriteXML.py b/src/GrampsDbUtils/_GrampsDbWriteXML.py similarity index 100% rename from src/GrampsDb/_GrampsDbWriteXML.py rename to src/GrampsDbUtils/_GrampsDbWriteXML.py diff --git a/src/GrampsDbUtils/_WriteGrdb.py b/src/GrampsDbUtils/_WriteGrdb.py index 03ce22f38..c0dae55a2 100644 --- a/src/GrampsDbUtils/_WriteGrdb.py +++ b/src/GrampsDbUtils/_WriteGrdb.py @@ -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 diff --git a/src/GrampsDbUtils/_WriteXML.py b/src/GrampsDbUtils/_WriteXML.py index a26023524..819ffb167 100644 --- a/src/GrampsDbUtils/_WriteXML.py +++ b/src/GrampsDbUtils/_WriteXML.py @@ -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' diff --git a/src/GrampsDbUtils/__init__.py b/src/GrampsDbUtils/__init__.py index 3c74a4cb7..53a2231e2 100644 --- a/src/GrampsDbUtils/__init__.py +++ b/src/GrampsDbUtils/__init__.py @@ -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 - diff --git a/src/GrampsDbUtils/importdbdir.py b/src/GrampsDbUtils/importdbdir.py new file mode 100644 index 000000000..c18a42415 --- /dev/null +++ b/src/GrampsDbUtils/importdbdir.py @@ -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 \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am index 2870b9d07..2d6abb438 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,6 @@ SUBDIRS = \ Filters \ FilterEditor \ gen \ - GrampsDb \ GrampsDbUtils \ GrampsLocale \ Merge \ diff --git a/src/ObjectSelector/_ObjectSelectorWindow.py b/src/ObjectSelector/_ObjectSelectorWindow.py index de7b45c66..5fe247bea 100644 --- a/src/ObjectSelector/_ObjectSelectorWindow.py +++ b/src/ObjectSelector/_ObjectSelectorWindow.py @@ -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') diff --git a/src/RecentFiles.py b/src/RecentFiles.py index 079302203..4d087c86c 100644 --- a/src/RecentFiles.py +++ b/src/RecentFiles.py @@ -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. """ diff --git a/src/ViewManager.py b/src/ViewManager.py index c5abab75c..e99dd3f33 100644 --- a/src/ViewManager.py +++ b/src/ViewManager.py @@ -186,6 +186,8 @@ UIDEFAULT = ''' + + ''' @@ -416,9 +418,7 @@ class ViewManager: self.tip_of_day_activate), ] - self._readonly_action_list = [ - ('SaveAs', gtk.STOCK_SAVE_AS, _('_Save As'), "s", - None, self.__save_as_activate), + self._readonly_action_list = [ ('Export', 'gramps-export', _('_Export'), "e", None, self.export_data), ('Abandon', gtk.STOCK_REVERT_TO_SAVED, @@ -447,7 +447,11 @@ class ViewManager: ('J', None, 'J', "J", None, self.__keypress), ('N', None, 'N', "N", None, self.__next_view), - ('P', None, 'P', "P", None, self.__prev_view), + ('P', None, 'P', "P", None, self.__prev_view), + ('Left', None, 'Left', "Left", None, + self.__prev_view), + ('Right', None, 'Right', "Right", None, + self.__next_view), ] self._action_action_list = [ @@ -566,13 +570,13 @@ class ViewManager: if self.filter_menu.get_active() != Config.get(Config.FILTER): self.filter_menu.set_active(Config.get(Config.FILTER)) - def post_init_interface(self): + def post_init_interface(self, show_manager=True): """ Showing the main window is deferred so that ArgHandler can work without it always shown """ self.window.show() - if not self.state.db.is_open(): + if not self.state.db.is_open() and show_manager: self.__open_activate(None) def post_load_newdb(self, filename, filetype): @@ -1044,98 +1048,34 @@ class ViewManager: if self.state.db.is_open(): self.db_loader.import_file() self.__post_load() - + + def open_activate(self, path): + """ + Open and make a family tree active + """ + self.__read_recent_file(path) + def __open_activate(self, obj): """ - Called when the Open button is clicked + Called when the Open button is clicked, opens the DbManager """ import DbManager dialog = DbManager.DbManager(self.state, self.window) value = dialog.run() if value: (filename, title) = value - self.read_file(filename, 'x-directory/normal') + self.db_loader.read_file(filename) try: os.chdir(os.path.dirname(filename)) except (IOError, OSError): pass self.__post_load_newdb(filename, 'x-directory/normal', title) - def read_file(self, filename, filetype): - """ - This method takes care of changing database, and loading the data. - - This method should only return on success. - Returning on failure makes no sense, because we cannot recover, - since database has already beeen changed. - Therefore, any errors should raise exceptions. - - On success, return with the disabled signals. The post-load routine - should enable signals, as well as finish up with other UI goodies. - """ - - if os.path.exists(filename): - if not os.access(filename, os.W_OK): - mode = "r" - QuestionDialog.WarningDialog(_('Read only database'), - _('You do not have write access ' - 'to the selected file.')) - else: - mode = "w" - elif filetype == 'unknown': - QuestionDialog.WarningDialog( - _('Missing or Invalid database'), - _('%s could not be found.\n' - 'It is possible that this file no longer exists ' - 'or has been moved.') % filename) - return False - else: - mode = 'w' - - try: - dbclass = gen.db.dbdir.GrampsDBDir - except gen.db.exceptions.GrampsDbException, msg: - QuestionDialog.ErrorDialog( - _("Could not open file: %s") % filename, - _("This may be caused by an improper installation of GRAMPS.") + - "\n" + str(msg)) - return - - self.state.change_database(dbclass(Config.get(Config.TRANSACTIONS))) - self.state.db.disable_signals() - - self.uistate.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) - self.uistate.progress.show() - - try: - self.state.db.load(filename, self.uistate.pulse_progressbar, mode) - self.state.db.set_save_path(filename) - try: - os.chdir(os.path.dirname(filename)) - except (OSError, IOError): - print "could not change directory" - except Errors.DbError, msg: - QuestionDialog.DBErrorDialog(str(msg.value)) - self.state.no_database() - except Exception: - LOG.error("Failed to open database.", exc_info=True) - - return True - - def __save_as_activate(self, obj): - """ - Called when the SaveAs button is clicked - """ - if self.state.db.is_open(): - (filename, filetype) = self.db_loader.save_as() - self.__post_load_newdb(filename, filetype) - def __read_recent_file(self, filename): """ Called when the recent file is loaded """ - if self.db_loader.read_file(filename, 'x-directory/normal'): - + if self.db_loader.read_file(filename): # Attempt to figure out the database title path = os.path.join(filename, "name.txt") try: diff --git a/src/gramps_main.py b/src/gramps_main.py index 273c028d7..35e12e58b 100644 --- a/src/gramps_main.py +++ b/src/gramps_main.py @@ -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() diff --git a/src/plugins/Checkpoint.py b/src/plugins/Checkpoint.py index f773e6a44..da1f11ab6 100644 --- a/src/plugins/Checkpoint.py +++ b/src/plugins/Checkpoint.py @@ -46,7 +46,6 @@ import gtk.glade # gramps modules # #------------------------------------------------------------------------- -import GrampsDb import GrampsDbUtils import Utils import GrampsDisplay diff --git a/src/plugins/ReadGrdb.py b/src/plugins/ReadGrdb.py index ad22b9208..aa907cb76 100644 --- a/src/plugins/ReadGrdb.py +++ b/src/plugins/ReadGrdb.py @@ -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