Refactor export plugin framework. All importers and exporters are now plugins.

svn: r11243
This commit is contained in:
Brian Matherly 2008-11-04 04:12:51 +00:00
parent b51caa5844
commit 2e9a488e3e
45 changed files with 746 additions and 1387 deletions

View File

@ -204,12 +204,6 @@ src/GrampsDbUtils/_GedcomStageOne.py
#src/GrampsDbUtils/_GedcomLex.py
src/GrampsDbUtils/_GedcomParse.py
src/GrampsDbUtils/_GedcomTokens.py
src/GrampsDbUtils/_GrampsDbWriteXML.py
src/GrampsDbUtils/_GrampsDbWRFactories.py
src/GrampsDbUtils/_ReadGedcom.py
src/GrampsDbUtils/_ReadXML.py
src/GrampsDbUtils/_WriteGedcom.py
src/GrampsDbUtils/_WriteXML.py
src/GrampsDbUtils/__init__.py
# GrampsLocale package
@ -242,12 +236,11 @@ src/Selectors/_SelectorFactory.py
src/Selectors/__init__.py
# plugins directory
src/plugins/AgeOnDate.py
src/plugins/all_events.py
src/plugins/all_relations.py
src/plugins/siblings.py
src/plugins/AgeOnDate.py
src/plugins/AncestorTree.py
src/plugins/AncestorReport.py
src/plugins/AncestorTree.py
src/plugins/BookReport.py
src/plugins/CalculateEstimatedDates.py
src/plugins/Calendar.py
@ -267,9 +260,15 @@ src/plugins/EndOfLineReport.py
src/plugins/Eval.py
src/plugins/EventCmp.py
src/plugins/EventNames.py
src/plugins/ExportCSV.py
src/plugins/ExportCd.py
src/plugins/ExportCsv.py
src/plugins/ExportFtree.py
src/plugins/ExportGedcom.py
src/plugins/ExportGeneWeb.py
src/plugins/ExportPkg.py
src/plugins/ExportVCalendar.py
src/plugins/ExportVCard.py
src/plugins/ExportXml.py
src/plugins/ExtractCity.py
src/plugins/FamilyGroup.py
src/plugins/FanChart.py
@ -278,11 +277,14 @@ src/plugins/FindDupes.py
src/plugins/GVFamilyLines.py
src/plugins/GVHourGlass.py
src/plugins/GVRelGraph.py
src/plugins/ImportCSV.py
src/plugins/ImportCsv.py
src/plugins/ImportGedcom.py
src/plugins/ImportGeneWeb.py
src/plugins/ImportGpkg.py
src/plugins/ImportGrdb.py
src/plugins/ImportProGen.py
src/plugins/ImportvCard.py
src/plugins/ImportXml.py
src/plugins/IndivComplete.py
src/plugins/KinshipReport.py
src/plugins/Leak.py
@ -297,6 +299,7 @@ src/plugins/OwnerEditor.py
src/plugins/PatchNames.py
src/plugins/PlaceReport.py
src/plugins/Rebuild.py
src/plugins/RebuildRefMap.py
src/plugins/References.py
src/plugins/RelCalc.py
src/plugins/rel_da.py
@ -315,6 +318,7 @@ src/plugins/rel_pl.py
src/plugins/RemoveUnused.py
src/plugins/ReorderIds.py
src/plugins/SameSurnames.py
src/plugins/siblings.py
src/plugins/SimpleBookTitle.py
src/plugins/SoundGen.py
src/plugins/StatisticsChart.py
@ -322,11 +326,6 @@ src/plugins/Summary.py
src/plugins/TimeLine.py
src/plugins/Verify.py
src/plugins/WebCal.py
src/plugins/WriteCD.py
src/plugins/WriteFtree.py
src/plugins/WriteGeneWeb.py
src/plugins/WritePkg.py
src/plugins/RebuildRefMap.py
# PluginUtils package
src/PluginUtils/_GuiOptions.py
@ -337,6 +336,7 @@ src/PluginUtils/_Tool.py
src/gen/utils/dbutils.py
src/gen/utils/progressmon.py
src/gen/plug/__init__.py
src/gen/plug/_export.py
src/gen/plug/_import.py
src/gen/plug/_manager.py
src/gen/plug/_plugin.py
@ -693,7 +693,6 @@ src/widgets/validatedmaskedentry.py
# Glade files
#
src/docgen/gtkprintpreview.glade
src/GrampsDbUtils/gedcomimport.glade
src/glade/edit_person.glade
src/glade/gramps.glade
src/glade/mergedata.glade
@ -703,14 +702,12 @@ src/glade/scratchpad.glade
src/glade/paper_settings.glade
src/plugins/NotRelated.glade
src/plugins/book.glade
src/plugins/cdexport.glade
src/plugins/changenames.glade
src/plugins/changetype.glade
src/plugins/csvexport.glade
src/plugins/desbrowse.glade
src/plugins/eval.glade
src/plugins/eventcmp.glade
src/plugins/genewebexport.glade
src/plugins/ImportGedcom.glade
src/plugins/leak.glade
src/plugins/merge.glade
src/plugins/ownereditor.glade
@ -719,10 +716,12 @@ src/plugins/relcalc.glade
src/plugins/soundex.glade
src/plugins/summary.glade
src/plugins/unused.glade
src/plugins/vcalendarexport.glade
src/plugins/vcardexport.glade
src/plugins/ExportCsv.glade
src/plugins/ExportFtree.glade
src/plugins/ExportGeneWeb.glade
src/plugins/ExportVCard.glade
src/plugins/ExportVCalendar.glade
src/plugins/verify.glade
src/plugins/writeftree.glade
#
# Files to extract from and then merge into
#

View File

@ -45,13 +45,9 @@ import logging
#
#-------------------------------------------------------------------------
import const
import GrampsDbUtils
import Mime
from QuestionDialog import ErrorDialog
import Config
import RecentFiles
import Utils
import gen.db.exceptions as GX
import gen
from DbManager import CLIDbManager, NAME_FILE, find_locker_name
@ -59,10 +55,6 @@ from PluginUtils import Tool
from gen.plug import PluginManager
from ReportBase import CATEGORY_BOOK, CATEGORY_CODE, cl_report
IMPORT_TYPES = (const.APP_GRAMPS_XML, const.APP_GEDCOM,
const.APP_GRAMPS_PKG, const.APP_GENEWEB,
const.APP_GRAMPS)
_help = """
Usage: gramps.py [OPTION...]
--load-modules=MODULE1,MODULE2,... Dynamic modules to load
@ -74,7 +66,7 @@ Help options
Application options
-O, --open=FAMILY_TREE Open family tree
-i, --import=FILENAME Import file
-o, --output=FILENAME Write file
-e, --export=FILENAME Export file
-f, --format=FORMAT Specify format
-a, --action=ACTION Specify action
-p, --options=OPTIONS_STRING Specify options
@ -96,7 +88,7 @@ class ArgHandler:
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, --output=FILE : filename to export.
-e, --export=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
@ -148,11 +140,9 @@ class ArgHandler:
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')
-f to indicate format
4/ -e, export a family tree in required format, optionally provide
-f to indicate format
5/ -a, --action: An action (possible: 'check', 'summary', 'report',
'tool')
6/ -u, --force-unlock: A locked database can be unlocked by given this
@ -187,84 +177,19 @@ class ArgHandler:
for opt_ix in range(len(options)):
option, value = options[opt_ix]
if option in ( '-O', '--open'):
self.handle_open_option(value)
self.__handle_open_option(value)
elif option in ( '-i', '--import'):
fname = value
fullpath = os.path.abspath(os.path.expanduser(fname))
format = None
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',
'gramps-pkg',
'grdb',
'geneweb'):
print "Invalid format: %s" % format
print "Ignoring input file: %s" % fname
continue
elif ftype == const.APP_GEDCOM:
format = 'gedcom'
elif ftype == const.APP_GRAMPS_PKG:
format = 'gramps-pkg'
elif ftype == const.APP_GRAMPS_XML:
format = 'gramps-xml'
elif ftype == const.APP_GRAMPS:
format = 'grdb'
elif ftype == const.APP_GENEWEB:
format = 'geneweb'
else:
print 'Unrecognized type: "%s" for input file: %s' \
% (ftype,fname)
print "Ignoring input file: %s" % fname
continue
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? (yes/no) ')
if answer.upper() in ('Y','YES'):
print "Will overwrite the existing file: %s" % fullpath
else:
print "Will skip the output file: %s" % fullpath
continue
if opt_ix < len(options)-1 \
and options[opt_ix+1][0] in ( '-f', '--format'):
outformat = options[opt_ix+1][1]
if outformat not in ('gedcom',
'gramps-xml',
'gramps-pkg',
'grdb',
'iso',
'wft',
'geneweb'):
print "Invalid format for output: %s" % outformat
print "Ignoring output file: %s" % outfname
continue
elif outfname[-3:].upper() == "GED":
outformat = 'gedcom'
elif outfname[-4:].upper() == "GPKG":
outformat = 'gramps-pkg'
elif outfname[-3:].upper() == "WFT":
outformat = 'wft'
elif outfname[-2:].upper() == "GW":
outformat = 'geneweb'
elif outfname[-6:].upper() == "GRAMPS":
outformat = 'gramps-xml'
elif outfname[-4:].upper() == "GRDB":
outformat = 'grdb'
else:
print "Unrecognized format for output file %s" % outfname
print "Ignoring output file: %s" % outfname
continue
self.exports.append((fullpath, outformat))
if opt_ix < len(options) - 1 \
and options[opt_ix + 1][0] in ( '-f', '--format'):
format = options[opt_ix + 1][1]
self.__handle_import_option(value, format)
elif option in ( '-e', '--export' ):
format = None
if opt_ix < len(options) - 1 \
and options[opt_ix + 1][0] in ( '-f', '--format'):
format = options[opt_ix + 1][1]
self.__handle_export_option(value, format)
elif option in ( '-a', '--action' ):
action = value
if action not in ( 'check', 'summary', 'report', 'tool' ):
@ -287,26 +212,11 @@ class ArgHandler:
elif option in ('-u', '--force-unlock'):
self.force_unlock = True
def handle_open_option(self, value):
def __handle_open_option(self, value):
"""
Handle the "-O" or "--open" option.
"""
db_path = None
# First, check if this is the name of a family tree
data = self.dbman.family_tree(value)
if data is not None:
# This is a known database name. Use it.
db_path, ftype, title = data
else:
# This is not a known database name.
# Check if the user provided a db path instead.
fullpath = os.path.abspath(os.path.expanduser(value))
if os.path.isdir(fullpath):
# The user provided a directory. Check if it is a valid tree.
name_file_path = os.path.join(fullpath, NAME_FILE)
if os.path.isfile(name_file_path):
db_path = fullpath
db_path = self.__deduce_db_path(value)
if db_path:
# We have a potential database path.
@ -319,7 +229,95 @@ class ArgHandler:
print _("If gedcom, gramps-xml or grdb, use the -i option to "
"import into a family tree instead")
sys.exit(0)
def __handle_import_option(self, value, format):
"""
Handle the "-i" or "--import" option.
"""
fname = value
fullpath = os.path.abspath(os.path.expanduser(fname))
if not os.path.exists(fullpath):
print 'Import file not found.'
print "Ignoring import file: %s" % fname
return
if format is None:
# Guess the file format based on the file extension.
# This will get the lower case extension without a period,
# or an empty string.
format = os.path.splitext(fname)[-1][1:].lower()
pmgr = PluginManager.get_instance()
plugin_found = False
for plugin in pmgr.get_import_plugins():
if format == plugin.get_extension():
plugin_found = True
if plugin_found:
self.imports.append((fname, format))
else:
print 'Unrecognized type: "%s" for import file: %s' \
% (format, fname)
print "Ignoring import file: %s" % fname
def __handle_export_option(self, value, format):
"""
Handle the "-e" or "--export" option.
"""
fname = value
fullpath = os.path.abspath(os.path.expanduser(fname))
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? (yes/no) ')
if answer.upper() in ('Y','YES'):
print "Will overwrite the existing file: %s" % fullpath
else:
print "Will skip the output file: %s" % fullpath
return
if format is None:
# Guess the file format based on the file extension.
# This will get the lower case extension without a period,
# or an empty string.
format = os.path.splitext(fname)[-1][1:].lower()
pmgr = PluginManager.get_instance()
plugin_found = False
for plugin in pmgr.get_export_plugins():
if format == plugin.get_extension():
plugin_found = True
if plugin_found:
self.exports.append((fullpath, format))
else:
print "Unrecognized format for export file %s" % fname
print "Ignoring export file: %s" % fname
def __deduce_db_path(self, db_name_or_path):
"""
Attempt to find a database path for the given parameter.
@return: The path to a Gramps DB
or None if a database can not be deduced.
"""
# First, check if this is the name of a family tree
db_path = self.dbman.get_family_tree_path(db_name_or_path)
if db_path is None:
# This is not a known database name.
# Check if the user provided a db path instead.
fullpath = os.path.abspath(os.path.expanduser(db_name_or_path))
if os.path.isdir(fullpath):
# The user provided a directory. Check if it is a valid tree.
name_file_path = os.path.join(fullpath, NAME_FILE)
if os.path.isfile(name_file_path):
db_path = fullpath
return db_path
#-------------------------------------------------------------------------
# Determine the need for GUI
#-------------------------------------------------------------------------
@ -358,80 +356,47 @@ class ArgHandler:
for name, dirname in self.dbman.family_tree_list():
print dirname, ', with name ', name
sys.exit(0)
if self.list_more:
print 'GRAMPS Family Trees:'
list = self.dbman.family_tree_summary()
for dict in list:
summary_list = self.dbman.family_tree_summary()
for summary in summary_list:
print "Family Tree \"%s\":" % dict["Family tree"]
for item in dict:
for item in summary:
if item != "Family tree":
print " %s: %s" % (item, dict[item])
sys.exit(0)
if self.help:
print _help
sys.exit(0)
if self.open_gui:
# Filename was given as gramps FILENAME.
# Open a session with that file. Forget the rest of given arguments
success = False
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 is const.APP_FAMTREE:
success = True
pass
elif filetype in IMPORT_TYPES:
# Say the type outloud
if filetype == const.APP_GRAMPS:
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"
elif filetype == const.APP_GRAMPS_PKG:
print "Type: GRAMPS XML package"
# First check if a Gramps database was provided
# (either a database path or a database name)
db_path = self.__deduce_db_path(self.open_gui)
filename, filetype, name = self.dbman.import_new_db(filetype,
filename, None)
success = True
else:
#see if not just a name of a database is given
data = self.dbman.family_tree(self.open_gui)
if data is not None:
filename, filetype = data[0], data[1]
success = True
else:
ErrorDialog(
_("Could not open file: %s") % filename,
_('Not a valid Family tree given to open\n\n'
))
print "Exiting..."
sys.exit(0)
if success:
if not db_path:
# Apparently it is not a database. See if it is a file that
# can be imported.
db_path, title = self.dbman.import_new_db(self.open_gui, None)
if db_path:
# Test if not locked or problematic
if not self.__check_db(filename, self.force_unlock):
if not self.__check_db(db_path, self.force_unlock):
sys.exit(0)
# Add the file to the recent items
path = os.path.join(filename, "name.txt")
path = os.path.join(db_path, "name.txt")
try:
ifile = open(path)
title = ifile.readline().strip()
ifile.close()
except:
title = filename
RecentFiles.recent_files(filename, title)
title = db_path
RecentFiles.recent_files(db_path, title)
else:
sys.exit(1)
return (filename, filetype)
return db_path
if self.open:
# Family Tree to open was given. Open it
@ -496,7 +461,7 @@ class ArgHandler:
os.path.isfile(os.path.join(filename, "name.txt")) and \
self.__check_db(filename):
self.vm.db_loader.read_file(filename)
return (filename, const.APP_FAMTREE)
return filename
def __check_db(self, dbpath, force_unlock = False):
# Test if not locked or problematic
@ -521,88 +486,12 @@ class ArgHandler:
Command-line import routine. Try to import filename using the format.
Any errors will cause the sys.exit(1) call.
"""
if format == 'grdb':
#2.x database
filename = os.path.normpath(os.path.abspath(filename))
try:
GrampsDbUtils.gramps_db_reader_factory(const.APP_GRAMPS)(
self.state.db,filename,empty)
except GX.GrampsDbException, e:
print "%s" % e.value
sys.exit(1)
except:
print "Error importing %s" % filename
sys.exit(1)
elif format == 'gedcom':
filename = os.path.normpath(os.path.abspath(filename))
filename = Utils.get_unicode_path(filename)
try:
# Cheating here to use default encoding
from GrampsDbUtils._ReadGedcom import import2
import2(self.state.db, filename, None, "", False)
except:
print "Error importing %s" % filename
sys.exit(1)
elif format == 'gramps-xml':
try:
GrampsDbUtils.gramps_db_reader_factory(const.APP_GRAMPS_XML)(
self.state.db,filename,None,self.cl)
except:
print "Error importing %s" % filename
sys.exit(1)
elif format == 'geneweb':
import ImportGeneWeb
filename = os.path.normpath(os.path.abspath(filename))
try:
ImportGeneWeb.importData(self.state.db, filename, None)
except:
print "Error importing %s" % filename
sys.exit(1)
elif format == 'gramps-pkg':
tmpdir_path = Utils.get_empty_tempdir("imp_gpkgdir")
try:
import tarfile
archive = tarfile.open(filename)
for tarinfo in archive:
archive.extract(tarinfo, tmpdir_path)
archive.close()
except tarfile.ReadError, msg:
print "Error reading archive:", msg
sys.exit(1)
except tarfile.CompressionError, msg:
print "Error uncompressing archive:", msg
sys.exit(1)
except:
print "Error extracting into %s" % tmpdir_path
sys.exit(1)
dbname = os.path.join(tmpdir_path, const.XMLFILE)
try:
GrampsDbUtils.gramps_db_reader_factory(const.APP_GRAMPS_XML)(
self.state.db,dbname,None)
except:
print "Error importing %s" % filename
sys.exit(1)
# Clean up tempdir after ourselves
# THIS HAS BEEN CHANGED, because now we want to keep images
# stay after the import is over. Just delete the XML file.
##jgs:FIXME for how long? just for debug? or this session?
## must not be forever, since re-exec of this routine
## clears dirfiles without asking
## & expands nre tarball possibly overwriting subdirs
##
## if only debugging, could do Utils.rm_tempdir here
## in any case, no real harm (exc. space) to leave stuff here
## until next exec of this, which will discard all old stuff
os.remove(dbname)
## files = os.listdir(tmpdir_path)
## for fn in files:
## os.remove(os.path.join(tmpdir_path,fn))
## os.rmdir(tmpdir_path)
else:
print "Invalid format: %s" % format
sys.exit(1)
pmgr = PluginManager.get_instance()
for plugin in pmgr.get_import_plugins():
if format == plugin.get_extension():
import_function = plugin.get_import_function()
import_function(self.state.db, filename, None)
if not self.cl:
if self.imp_db_path:
return self.vm.open_activate(self.imp_db_path)
@ -620,71 +509,11 @@ class ArgHandler:
Try to write into filename using the format.
Any errors will cause the sys.exit(1) call.
"""
filename = os.path.abspath(os.path.expanduser(filename))
if format == 'grdb':
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)
elif format == 'gramps-xml':
filename = os.path.normpath(os.path.abspath(filename))
if filename:
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)
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)
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)
ret = writer.export_data()
print "... finished writing %s" % filename
except:
print "Error exporting %s" % filename
sys.exit(1)
elif format == 'geneweb':
import WriteGeneWeb
try:
writer = WriteGeneWeb.GeneWebWriter(self.state.db,
None, 1, filename)
ret = writer.export_data()
print "... finished writing %s" % filename
except:
print "Error exporting %s" % filename
sys.exit(1)
else:
print "Invalid format: %s" % format
sys.exit(1)
pmgr = PluginManager.get_instance()
for plugin in pmgr.get_export_plugins():
if format == plugin.get_extension():
export_function = plugin.get_export_function()
export_function(self.state.db, filename)
#-------------------------------------------------------------------------
#
@ -777,5 +606,3 @@ class ArgHandler:
print "Unknown action: %s." % action
sys.exit(1)
def empty(val):
pass

View File

@ -56,30 +56,13 @@ import gobject
#-------------------------------------------------------------------------
import const
import Config
import Mime
import gen.db
import GrampsDbUtils
import Utils
from gen.plug import PluginManager
from QuestionDialog import (DBErrorDialog, ErrorDialog, QuestionDialog2,
WarningDialog)
import Errors
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
#connection between main mime type, name, and list of alternative mime types
_KNOWN_FORMATS = {
const.APP_GRAMPS : [_('GRAMPS (grdb)'), []],
const.APP_GRAMPS_XML : [_('GRAMPS XML'), []],
const.APP_GEDCOM : [_('GEDCOM'), []],
}
OPEN_FORMATS = [const.APP_GRAMPS_XML, const.APP_GEDCOM]
#-------------------------------------------------------------------------
#
# DbLoader class
@ -110,39 +93,27 @@ class DbLoader:
pmgr = PluginManager.get_instance()
choose_db_dialog = gtk.FileChooserDialog(_('GRAMPS: Import database'),
import_dialog = gtk.FileChooserDialog(_('GRAMPS: Import database'),
self.uistate.window,
gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
'gramps-import', gtk.RESPONSE_OK))
choose_db_dialog.set_local_only(False)
import_dialog.set_local_only(False)
# Always add automatic (match all files) filter
add_all_files_filter(choose_db_dialog) # *
add_xml_filter(choose_db_dialog) # .gramps
add_gedcom_filter(choose_db_dialog) # .ged
add_all_files_filter(import_dialog) # *
format_list = OPEN_FORMATS[:]
# Add more data type selections if opening existing db
# Add more file type selections for available importers
for plugin in pmgr.get_import_plugins():
mime_types = plugin.get_mime_types()
mime_filter = gtk.FileFilter()
mime_filter.set_name(plugin.get_name())
for mime_type in mime_types:
mime_filter.add_mime_type(mime_type)
format_name = plugin.get_name()
file_filter = gtk.FileFilter()
name = "%s (.%s)" % (plugin.get_name(), plugin.get_extension())
file_filter.set_name(name)
file_filter.add_pattern("*.%s" % plugin.get_extension())
file_filter.add_pattern(plugin.get_extension().capitalize())
import_dialog.add_filter(file_filter)
choose_db_dialog.add_filter(mime_filter)
# There might be multiple entries in mime_types
# Add only formats not already in list, so user don't get confused
# with multiple entries
if not mime_types[0] in format_list:
format_list.append(mime_types[0])
_KNOWN_FORMATS[mime_types[0]] = [format_name, mime_types[1:]]
(box, type_selector) = format_maker(format_list)
choose_db_dialog.set_extra_widget(box)
(box, type_selector) = format_maker()
import_dialog.set_extra_widget(box)
# Suggested folder: try last open file, import, then last export,
# then home.
@ -150,43 +121,31 @@ class DbLoader:
if len(default_dir)<=1:
default_dir = get_default_dir()
choose_db_dialog.set_current_folder(default_dir)
import_dialog.set_current_folder(default_dir)
while True:
response = choose_db_dialog.run()
response = import_dialog.run()
if response == gtk.RESPONSE_CANCEL:
break
elif response == gtk.RESPONSE_OK:
filename = Utils.get_unicode_path(choose_db_dialog.get_filename())
filename = Utils.get_unicode_path(import_dialog.get_filename())
if self.check_errors(filename):
# displays errors if any
continue
# Do not allow importing from the currently open file
if filename == self.dbstate.db.full_name:
ErrorDialog(_("Cannot import from current file"))
continue
filetype = type_selector.get_value()
if filetype == 'auto':
try:
filetype = Mime.get_type(filename)
except RuntimeError, msg:
ErrorDialog(_("Could not open file: %s") % filename,
str(msg))
continue
# First we try our best formats
if filetype in OPEN_FORMATS or filetype in _KNOWN_FORMATS:
importer = GrampsDbUtils.gramps_db_reader_factory(filetype)
self.do_import(choose_db_dialog, importer, filename)
return True
(the_path, the_file) = os.path.split(filename)
Config.set(Config.RECENT_IMPORT_DIR, the_path)
# Then we try all the known plugins
extension = type_selector.get_value()
if extension == 'auto':
# Guess the file format based on the file extension.
# This will get the lower case extension without a period,
# or an empty string.
extension = os.path.splitext(filename)[-1][1:].lower()
for plugin in pmgr.get_import_plugins():
if filetype in plugin.get_mime():
self.do_import(choose_db_dialog,
print plugin.get_extension()
if extension == plugin.get_extension():
self.do_import(import_dialog,
plugin.get_import_function(),
filename)
return True
@ -196,9 +155,9 @@ class DbLoader:
_("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)
'GRAMPS package, and GEDCOM.') % extension)
choose_db_dialog.destroy()
import_dialog.destroy()
return False
def check_errors(self, filename):
@ -218,16 +177,14 @@ class DbLoader:
return True
elif os.path.isdir(filename):
ErrorDialog(
_('Cannot open database'),
_('The selected file is a directory, not '
'a file.\nA GRAMPS database must be a file.'))
_('Cannot open file'),
_('The selected file is a directory, not a file.\n'))
return True
elif os.path.exists(filename):
if not os.access(filename, os.R_OK):
ErrorDialog(
_('Cannot open database'),
_('You do not have read access to the selected '
'file.'))
_('Cannot open file'),
_('You do not have read access to the selected file.'))
return True
else:
try:
@ -236,7 +193,7 @@ class DbLoader:
os.remove(filename)
except IOError:
ErrorDialog(
_('Cannot create database'),
_('Cannot create file'),
_('You do not have write access to the selected file.'))
return True
@ -361,34 +318,6 @@ def add_all_files_filter(chooser):
mime_filter.add_pattern('*')
chooser.add_filter(mime_filter)
def add_gramps_files_filter(chooser):
"""
Add an all-GRAMPS filter to the file chooser dialog.
"""
mime_filter = gtk.FileFilter()
mime_filter.set_name(_('All GRAMPS files'))
for fmt in OPEN_FORMATS:
mime_filter.add_mime_type(fmt)
chooser.add_filter(mime_filter)
def add_xml_filter(chooser):
"""
Add a GRAMPS XML filter to the file chooser dialog.
"""
mime_filter = gtk.FileFilter()
mime_filter.set_name(_('GRAMPS XML databases'))
mime_filter.add_mime_type(const.APP_GRAMPS_XML)
chooser.add_filter(mime_filter)
def add_gedcom_filter(chooser):
"""
Add a GEDCOM filter to the file chooser dialog.
"""
mime_filter = gtk.FileFilter()
mime_filter.set_name(_('GEDCOM files'))
mime_filter.add_mime_type(const.APP_GEDCOM)
chooser.add_filter(mime_filter)
#-------------------------------------------------------------------------
#
# Format selectors: explictly set the format of the file
@ -417,7 +346,7 @@ class GrampsFormatWidget(gtk.ComboBox):
return None
return self.format_list[active][0]
def format_maker(formats):
def format_maker():
"""
A factory function making format selection widgets.
@ -425,10 +354,11 @@ def format_maker(formats):
The auto selection is always added as the first one.
The returned box contains both the label and the selector.
"""
pmgr = PluginManager.get_instance()
format_list = [ ('auto', _('Automatically detected')) ]
for format in formats:
if format in _KNOWN_FORMATS:
format_list.append( (format, _KNOWN_FORMATS[format][0]) )
for plugin in pmgr.get_import_plugins():
format_list.append( (plugin.get_extension(), plugin.get_name()) )
type_selector = GrampsFormatWidget()
type_selector.set(format_list)

View File

@ -69,14 +69,12 @@ import pango
import const
from QuestionDialog import ErrorDialog, QuestionDialog
import gen.db
from gen.plug import PluginManager
import GrampsDbUtils
import Config
import Mime
from DdTargets import DdTargets
import RecentFiles
IMPORT_TYPES = (const.APP_GRAMPS_XML, const.APP_GEDCOM,
const.APP_GRAMPS_PKG, const.APP_GENEWEB,
const.APP_GRAMPS)
_RETURN = gtk.gdk.keyval_from_name("Return")
_KP_ENTER = gtk.gdk.keyval_from_name("KP_Enter")
@ -208,14 +206,14 @@ class CLIDbManager:
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
def get_family_tree_path(self, name):
"""
Given a name, return None if name not existing or the path to the
database if it is a known database name.
"""
for data in self.current_names:
if data[0] == name:
return data[1], 'x-directory/normal', name
return data[1]
return None
def family_tree_list(self):
@ -269,37 +267,39 @@ class CLIDbManager:
"""
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))
def import_new_db(self, filename, callback):
"""
Attempt to import the provided file into a new database.
A new database will only be created if an appropriate importer was
found.
@return: A tuple of (new_path, name) for the new database
or (None, None) if no import was performed.
"""
pmgr = PluginManager.get_instance()
(name, ext) = os.path.splitext(os.path.basename(filename))
format = ext[1:].lower()
# create the database
new_path, name = self._create_new_db(name)
for plugin in pmgr.get_import_plugins():
if format == plugin.get_extension():
# 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()
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
new_path, name = self._create_new_db(name)
# Create a new database
self.__start_cursor(_("Importing data..."))
dbclass = gen.db.GrampsDBDir
dbase = dbclass()
dbase.load(new_path, callback)
import_function = plugin.get_import_function()
import_function(dbase, filename, callback)
# finish up
self.__end_cursor()
dbase.close()
return new_path, name
return None, None
def is_locked(self, dbpath):
"""
@ -929,13 +929,9 @@ class DbManager(CLIDbManager):
drag_value = drag_value.strip()
# deterimine the mime type. If it is one that we are interested in,
# we process it
filetype = Mime.get_type(drag_value)
fname, type, title = self.import_new_db(filetype, drag_value[7:],
None)
fname, title = self.import_new_db(drag_value[7:], None)
return fname, type, title
return fname, title
def drag_motion(wid, context, xpos, ypos, time_stamp):
"""
@ -1099,7 +1095,11 @@ def check_out(dbase, rev, path, callback):
)
return
rdr = GrampsDbUtils.gramps_db_reader_factory(const.APP_GRAMPS_XML)
pmgr = PluginManager.get_instance()
for plugin in pmgr.get_import_plugins():
if plugin.get_extension() == "gramps":
rdr = plugin.get_import_function()
xml_file = os.path.join(path, ARCHIVE)
rdr(dbase, xml_file, callback)
os.unlink(xml_file)

View File

@ -131,7 +131,8 @@ class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
self.logo = gtk.gdk.pixbuf_new_from_file(_gramps_png)
self.splash = gtk.gdk.pixbuf_new_from_file(_splash_jpg)
self.obtain_export_formats()
pmgr = PluginManager.get_instance()
self.__exporters = pmgr.get_export_plugins()
self.__previous_page = -1
@ -191,7 +192,7 @@ class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
box.set_border_width(12)
box.set_spacing(12)
table = gtk.Table(2*len(self.exportformats),2)
table = gtk.Table(2*len(self.__exporters),2)
table.set_row_spacings(6)
table.set_col_spacings(6)
@ -200,9 +201,9 @@ class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
group = None
recent_type = Config.get(Config.RECENT_EXPORT_TYPE)
for ix in range(len(self.exportformats)):
title = self.exportformats[ix][1]
description= self.exportformats[ix][2]
for ix in range(len(self.__exporters)):
title = self.__exporters[ix].get_name()
description= self.__exporters[ix].get_description()
button = gtk.RadioButton(group,title)
if not group:
@ -248,7 +249,7 @@ class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
if pagenumber == _ExportAssistant_pages['exporttypes'] :
#decide if options need to be shown:
ix = self.get_selected_format_index()
if self.exportformats[ix][3]:
if self.__exporters[ix].get_config():
return pagenumber + 1
else :
# no options needed
@ -260,12 +261,15 @@ class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
"""This method gets the option page, and fills it with the options."""
option = self.get_selected_format_index()
vbox = self.get_nth_page(_ExportAssistant_pages['options'])
self.set_page_title(vbox, self.exportformats[option][3][0])
(config_title, config_box_class) = self.__exporters[option].get_config()
self.set_page_title(vbox, config_title)
# remove present content of the vbox
vbox.foreach(vbox.remove)
# add new content
option_box_class = self.exportformats[option][3][1]
self.option_box_instance = option_box_class(self.person)
if config_box_class:
self.option_box_instance = config_box_class(self.person)
else:
self.option_box_instance = None
box = self.option_box_instance.get_option_box()
vbox.add(box)
vbox.show_all()
@ -430,7 +434,7 @@ class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
# The confirm page with apply button
# Present user with what will happen
ix = self.get_selected_format_index()
format = self.exportformats[ix][1].replace('_','')
format = self.__exporters[ix].get_name()
#Allow for exotic error: file is still not correct
self.check_fileselect(self.chooser, show=False)
@ -505,18 +509,7 @@ class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
#clean up ManagedWindow menu, then destroy window, bring forward parent
ManagedWindow.ManagedWindow.close(self,*obj)
def obtain_export_formats(self):
"""
This method builds its own list of available exports.
The list is built from the list of exporters in the PluginManager and
from the locally defined exports (i.e. native export defined here).
"""
pmgr = PluginManager.get_instance()
self.exportformats = [item for item in pmgr.get_export_list()]
def get_intro_text(self):
return _('Under normal circumstances, GRAMPS does not require you '
'to directly save your changes. All changes you make are '
@ -546,7 +539,7 @@ class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
def suggest_filename(self):
"""Prepare suggested filename and set it in the file chooser."""
ix = self.get_selected_format_index()
ext = self.exportformats[ix][4]
ext = self.__exporters[ix].get_extension()
# Suggested folder: try last export, then last import, then home.
default_dir = Config.get(Config.RECENT_EXPORT_DIR)
@ -575,15 +568,11 @@ class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
Config.set(Config.RECENT_EXPORT_DIR, os.path.split(filename)[0])
ix = self.get_selected_format_index()
Config.set(Config.RECENT_EXPORT_TYPE, ix)
if self.exportformats[ix][3]:
success = self.exportformats[ix][0](self.dbstate.db,
filename,self.person,
self.option_box_instance,
self.callback)
else:
success = self.exportformats[ix][0](self.dbstate.db,
filename,self.person,
self.callback)
export_function = self.__exporters[ix].get_export_function()
success = export_function(self.dbstate.db,
filename,
self.option_box_instance,
self.callback)
return success
def pre_save(self,page):

View File

@ -14,22 +14,11 @@ pkgdata_PYTHON = \
_GedcomStageOne.py\
_GedcomTokens.py\
_GedcomUtils.py\
_GrampsDbWRFactories.py\
_GrampsDbWriteXML.py\
__init__.py\
_ReadGedcom.py\
_ReadXML.py\
_WriteGedcom.py\
_WriteXML.py
__init__.py
pkgpyexecdir = @pkgpyexecdir@/GrampsDbUtils
pkgpythondir = @pkgpythondir@/GrampsDbUtils
GLADEFILES = \
gedcomimport.glade
dist_pkgdata_DATA = $(GLADEFILES)
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo

View File

@ -79,7 +79,6 @@ def add_to_list(table, key, value):
Add the value to the table entry associated with key. If the entry
does not exist, it is added.
"""
print type(table)
if key in table:
table[key].append(value)
else:

View File

@ -1,77 +0,0 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2004-2007 Donald N. Allingham
# Copyright (C) 2008 Brian G. Matherly
#
# 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:_GrampsDbWRFactories.py 9912 2008-01-22 09:17:46Z acraphae $
"""
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 a Gedcom reader
> GrampsDb.gramps_db_reader_factory(db_type = const.APP_GEDCOM)
"""
import const
import logging
log = logging.getLogger(".GrampDb")
from gen.db import GrampsDbException
from gen.plug import PluginManager
def gramps_db_reader_factory(db_type):
"""Factory class for obtaining a Gramps database importer.
@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:
import _ReadXML as ReadXML
md = ReadXML.importData
elif db_type == const.APP_GEDCOM:
import _ReadGedcom as ReadGedcom
md = ReadGedcom.importData
else:
#see if registered importer
found = False
pmgr = PluginManager.get_instance()
for plugin in pmgr.get_import_plugins():
if db_type in plugin.get_mime_types():
print "Found import plugin for %s" % plugin.get_name()
found = True
md = plugin.get_import_function()
break
if not found:
raise GrampsDbException("Attempt to create a database "
"reader for unknown format: "
"db_type = %s" % (str(db_type)))
return md

View File

@ -1,149 +0,0 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2008 Robert Cheramy <robert@cheramy.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Contains the interface to allow a database to get written using
GRAMPS' XML file format.
"""
#-------------------------------------------------------------------------
#
# load standard python libraries
#
#-------------------------------------------------------------------------
import shutil
import os
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# load GRAMPS libraries
#
#-------------------------------------------------------------------------
import const
from QuestionDialog import ErrorDialog
import GrampsDbUtils
import ExportOptions
from gen.db.exceptions import GrampsDbWriteFailure
import gen.proxy
#-------------------------------------------------------------------------
#
# Attempt to load the GZIP library. Some version of python do not seem
# to be compiled with this available.
#
#-------------------------------------------------------------------------
try:
import gzip
_gzip_ok = 1
except:
_gzip_ok = 0
#-------------------------------------------------------------------------
#
# export_data
#
#-------------------------------------------------------------------------
def export_data(database, filename, person, option_box, callback=None):
"""
Call the XML writer with the syntax expected by the export plugin.
"""
if os.path.isfile(filename):
try:
shutil.copyfile(filename, filename + ".bak")
shutil.copystat(filename, filename + ".bak")
except:
pass
compress = _gzip_ok == 1
option_box.parse_options()
if option_box.private:
database = gen.proxy.PrivateProxyDb(database)
if option_box.restrict:
database = gen.proxy.LivingProxyDb(
database, gen.proxy.LivingProxyDb.MODE_INCLUDE_LAST_NAME_ONLY)
# Apply the Person Filter
if not option_box.cfilter.is_empty():
database = gen.proxy.FilterProxyDb(database, option_box.cfilter)
# Apply the Note Filter
if not option_box.nfilter.is_empty():
database = gen.proxy.FilterProxyDb(
database, note_filter=option_box.nfilter)
# Apply the ReferencedProxyDb to remove any objects not referenced
# after any of the other proxies have been applied
if option_box.unlinked:
database = gen.proxy.ReferencedProxyDb(database)
g = XmlWriter(database, callback, 0, compress)
return g.write(filename)
#-------------------------------------------------------------------------
#
# XmlWriter
#
#-------------------------------------------------------------------------
class XmlWriter(GrampsDbUtils.GrampsDbXmlWriter):
"""
Writes a database to the XML file.
"""
def __init__(self, dbase, callback, strip_photos, compress=1):
GrampsDbUtils.GrampsDbXmlWriter.__init__(
self, dbase, strip_photos, compress, const.VERSION, callback)
def write(self, filename):
"""
Write the database to the specified file.
"""
ret = 0 #False
try:
ret = GrampsDbUtils.GrampsDbXmlWriter.write(self, filename)
except GrampsDbWriteFailure, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1, m2)
return ret
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
TITLE = _('GRAMPS _XML database')
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'
from gen.plug import PluginManager
pmgr = PluginManager.get_instance()
pmgr.register_export(export_data, TITLE, DESCRIPTION, CONFIG, FILENAME)

View File

@ -22,28 +22,12 @@
"""
This package implements additions to the the GrampsDb database.
This package should be used for code that extended GrampsDb but also
depends on Gtk.
A number of importers and exporters are provided to convert between
the different backend formats.
To obtain a class that implements readers use the gramps_db_reader_factory
method. For information on using this factory see the
_GrampsDbUtilsFactories.py file comments.
"""
from _GedcomInfo import (personalConstantEvents, familyConstantEvents,
personalConstantAttributes)
from _GrampsDbWRFactories import gramps_db_reader_factory
from _GedcomParse import GedcomParser
from _WriteGedcom import GedcomWriter
from _GrampsDbWriteXML import GrampsDbXmlWriter
from _WriteXML import XmlWriter
import _Backup as Backup

View File

@ -1,34 +0,0 @@
#!/usr/bin/env python
import unittest
from test import test_util as tu
par = tu.path_append_parent()
###
class Test1(unittest.TestCase):
"""Test imports which are buried within functions
otherwise they may not get timely test coverage
NB: if any test fails, check imports within that module
"""
def test1a_buried_imports(self):
import sys
self.assertTrue(par in sys.path,
"par %r has to be in path!" % par)
ilist = (
"_WriteXML",
"_WriteGedcom",
"_ReadXML",
"_ReadGedcom",
)
for m in ilist:
try:
mod = __import__(m)
except ImportError:
mod = None
self.assertTrue(mod, "try import of module %r" % m)
if __name__ == "__main__":
unittest.main()
#===eof===

View File

@ -1,57 +0,0 @@
"""gedwrite_breakup_test tests the breakup function in GedcomWrite"""
import unittest as U
from test.test_util import msg, path_append_parent
path_append_parent();
import _WriteGedcom as WG
class Test1(U.TestCase):
def test1a_common(s):
#txt, limit, [split-results]
L=4
dat = (
##0123456
("a", L, ["a",]),
("abc", L, ["abc",]),
("abcd", L, ["abcd",]),
("abcde", L, ["abcd","e"]),
("1234567", L, ["1234","567"]),
("12345678", L, ["1234","5678"]),
("123456789", L, ["1234","5678", "9"]),
)
for (t,l,r) in dat:
g = WG.breakup(t,l)
s.assertEquals(g,r, msg(g,r, "breakup(%r,%d) results" % (t,l)))
def test1b_spaces(s):
#txt, limit, [split-results]
L=4
dat = (
##0123456
("a b ", L, ["a b ",]),
(" a b", L, [" a b",]),
("asdf g", L, ["asd", "f g"]),
(" z", L, [" ", "z"]),
(" z", L, [" ", " z"]),
(" A", 2, [" ", " ", " ", "A"]),
)
for (t,l,r) in dat:
g = WG.breakup(t,l)
s.assertEquals(g,r, msg(g,r, "breakup(%r,%d) results" % (t,l)))
def test1c_unusual(s):
#just documenting behavior for unlikely input
#txt, limit, [split-results]
dat = (
##0123456
("", 4, []),
("xyz", 1, ["x", "y", "z"]),
)
for (t,l,r) in dat:
g = WG.breakup(t,l)
s.assertEquals(g,r, msg(g,r, "breakup(%r,%d) results" % (t,l)))
s.assertRaises(ValueError, WG.breakup, "xy",0)
if __name__ == "__main__":
U.main()
#===eof===

View File

@ -133,7 +133,7 @@ class PluginStatus(ManagedWindow.ManagedWindow):
data = model.get_value(node, 3)
name = model.get_value(node, 1)
if data:
PluginTrace(self.uistate, self.track, data, name)
PluginTrace(self.uistate, [], data, name)
def build_menu_names(self, obj):
return (self.title, "")

View File

@ -10,6 +10,7 @@ pkgdatadir = $(datadir)/@PACKAGE@/gen/plug
pkgdata_PYTHON = \
__init__.py \
_export.py \
_import.py \
_manager.py \
_plugin.py

View File

@ -24,5 +24,6 @@ The "plug" package for handling plugins in Gramps.
from _plugin import Plugin
from _manager import PluginManager
from _import import ImportPlugin
from _export import ExportPlugin
__all__ = [ "menu", Plugin, PluginManager, ImportPlugin ]
__all__ = [ "menu", Plugin, PluginManager, ImportPlugin, ExportPlugin ]

102
src/gen/plug/_export.py Normal file
View File

@ -0,0 +1,102 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008 Brian G. Matherly
#
# 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 provides the Plugin class for export plugins.
"""
from gen.plug import Plugin
class ExportPlugin(Plugin):
"""
This class represents a plugin for exporting data from Gramps
"""
def __init__(self, name, description, export_function,
extension, config=None):
"""
@param name: A friendly name to call this plugin.
Example: "GEDCOM Export"
@type name: string
@param description: An short description of the plugin.
Example: "This plugin will export a GEDCOM file from database"
@type description: string
@param export_function: A function to call to perform the export.
The function must take the form:
def export_function(database, filename, option_box, callback):
where:
"db" is a Gramps database to import the data into
"filename" is the file that the data will be exported to
"callback" is a callable object that takes two parameters.
The first parameter is a progress indicator.
The second parameter is a text string.
@type export_function: callable
@param extension: The extension for the output file.
Example: "ged"
@type extension: str
@param config: Options for the exporter
@type config: tuple (??,??)
@return: nothing
"""
Plugin.__init__(self, name, description)
self.__name = name
self.__export_func = export_function
self.__extension = extension
self.__config = config
def get_module_name(self):
"""
Get the name of the module that this plugin lives in.
@return: a string representing the name of the module for this plugin
"""
return self.__export_func.__module__
def get_name(self):
"""
Get the short name for this plugins.
@return: str
"""
return self.__name
def get_export_function(self):
"""
Get the import function for this plugins.
@return: the callable import_function passed into __init__
"""
return self.__export_func
def get_extension(self):
"""
Get the file extension for the export file.
@return: str
"""
return self.__extension
def get_config(self):
"""
Get the config.
@return: (??,??)
"""
return self.__config

View File

@ -29,7 +29,7 @@ class ImportPlugin(Plugin):
"""
This class represents a plugin for importing data into Gramps
"""
def __init__(self, name, description, import_function, mime_types=None):
def __init__(self, name, description, import_function, extension):
"""
@param name: A friendly name to call this plugin.
Example: "GEDCOM Import"
@ -47,14 +47,14 @@ class ImportPlugin(Plugin):
The first parameter is a progress indicator.
The second parameter is a text string.
@type import_function: callable
@param mime_types: A list of mime types that apply to the file type.
Example: "['application/x-gramps']"
@type mime_types: [str] (list of strings)
@param extension: The extension for the files imported by this plugin.
Example: "ged"
@type extension: str
@return: nothing
"""
Plugin.__init__(self, name, description)
self.__import_func = import_function
self.__mime_types = mime_types
self.__extension = extension
def get_module_name(self):
"""
@ -72,10 +72,10 @@ class ImportPlugin(Plugin):
"""
return self.__import_func
def get_mime_types(self):
def get_extension(self):
"""
Get the list of mime types that apply to the import file.
Get the extension for the files imported by this plugin.
@return: [str] (list of strings)
@return: str
"""
return self.__mime_types
return self.__extension

View File

@ -93,8 +93,8 @@ class PluginManager(gen.utils.Callback):
self.__report_list = []
self.__quick_report_list = []
self.__tool_list = []
self.__export_list = []
self.__import_plugins = []
self.__export_plugins = []
self.__attempt_list = []
self.__loaddir_list = []
self.__textdoc_list = []
@ -257,10 +257,6 @@ class PluginManager(gen.utils.Callback):
""" Return the list of command line tool plugins. """
return self.__cli_tool_list
def get_export_list(self):
""" Return the list of export plugins. """
return self.__export_list
def get_module_description(self, module):
""" Given a module name, return the module description. """
return self.__mod2text.get(module, '')
@ -274,6 +270,9 @@ class PluginManager(gen.utils.Callback):
if isinstance(plugin, gen.plug.ImportPlugin):
self.__import_plugins.append(plugin)
self.__mod2text[plugin.get_module_name()] = plugin.get_description()
if isinstance(plugin, gen.plug.ExportPlugin):
self.__export_plugins.append(plugin)
self.__mod2text[plugin.get_module_name()] = plugin.get_description()
def get_import_plugins(self):
"""
@ -282,24 +281,14 @@ class PluginManager(gen.utils.Callback):
@return: [gen.plug.ImportPlugin] (a list of ImportPlugin instances)
"""
return self.__import_plugins
def register_export(self, export_data, title, description='', config=None,
filename=''):
"""
Register an export filter, taking the task, file filter,
and the list of patterns for the filename matching.
"""
if description and filename:
del_index = -1
for i in range(0, len(self.__export_list)):
if self.__export_list[i][1] == title:
del_index = i
if del_index != -1:
del self.__export_list[del_index]
self.__export_list.append(
(export_data, title, description, config, filename))
self.__mod2text[export_data.__module__] = description
def get_export_plugins(self):
"""
Get the list of export plugins.
@return: [gen.plug.ExportPlugin] (a list of ExportPlugin instances)
"""
return self.__export_plugins
def register_tool(self, name, category, tool_class, options_class,
modes, translated_name, status=_("Unknown"),
@ -545,8 +534,8 @@ class PluginManager(gen.utils.Callback):
for filename, junk in self.__failmsg_list
]
self.__export_list[:] = [ item for item in self.__export_list
if item[0].__module__ not in failed_module_names ][:]
self.__export_plugins[:] = [ item for item in self.__export_plugins
if item.get_module_name not in failed_module_names ][:]
self.__import_plugins[:] = [ item for item in self.__import_plugins
if item.get_module_name not in failed_module_names ][:]
self.__tool_list[:] = [ item for item in self.__tool_list

View File

@ -275,9 +275,8 @@ class Gramps:
# we may need to change the order of operation
ah = ArgHandler.ArgHandler(state, self.vm, args)
if ah.need_gui():
retval = ah.handle_args()
if retval:
filename, filetype = retval
filename = ah.handle_args()
if filename:
self.vm.post_init_interface(show_manager=False)
self.vm.open_activate(filename)
else:

View File

@ -73,10 +73,10 @@ except:
# GRAMPS modules
#
#-------------------------------------------------------------------------
from GrampsDbUtils import XmlWriter
from ExportXml import XmlWriter
from Utils import media_path_full
from QuestionDialog import ErrorDialog, MissingMediaDialog
from gen.plug import PluginManager
from gen.plug import PluginManager, ExportPlugin
_title_string = _("Export to CD")
@ -85,7 +85,7 @@ _title_string = _("Export to CD")
# writeData
#
#-------------------------------------------------------------------------
def writeData(database, filename, person, option_box=None, callback=None):
def writeData(database, filename, option_box=None, callback=None):
writer = PackageWriter(database, filename, callback)
return writer.export()
@ -299,13 +299,15 @@ class PackageWriter:
# Register the plugin
#
#-------------------------------------------------------------------------
_title = _('_Export to CD (portable XML)')
_description = _('Exporting to CD copies all your data and media '
'object files to the CD Creator. You may later burn the CD '
'with this data, and that copy will be completely portable '
'across different machines and binary architectures.')
_config = None
_filename = 'burn'
_description = _('Exporting to CD copies all your data and media object files '
'to the CD Creator. You may later burn the CD with this data, '
'and that copy will be completely portable across different '
'machines and binary architectures.')
pmgr = PluginManager.get_instance()
pmgr.register_export(writeData, _title, _description, _config, _filename)
plugin = ExportPlugin(name = _('_Export to CD (portable XML)'),
description = _description,
export_function = writeData,
extension = "burn",
config = None )
pmgr.register_plugin(plugin)

View File

@ -57,9 +57,9 @@ log = logging.getLogger(".ExportCSV")
import gen.lib
from Filters import GenericFilter, Rules, build_filter_menu
import Utils
import Errors
from QuestionDialog import ErrorDialog
from gen.plug import PluginManager
from gen.plug import PluginManager, ExportPlugin
import gen.proxy
import DateHandler
#-------------------------------------------------------------------------
@ -67,8 +67,8 @@ import DateHandler
# The function that does the exporting
#
#-------------------------------------------------------------------------
def exportData(database,filename,person, option_box,callback=None):
gw = CSVWriter(database,person,0,filename, option_box,callback)
def exportData(database, filename, option_box=None, callback=None):
gw = CSVWriter(database, filename, option_box, callback)
return gw.export_data()
#-------------------------------------------------------------------------
@ -166,15 +166,12 @@ class CSVWriterOptionBox:
"""
def __init__(self,person):
self.person = person
def get_option_box(self):
self.include_individuals = 1
self.include_marriages = 1
self.include_children = 1
glade_file = "%s/csvexport.glade" % os.path.dirname(__file__)
if not os.path.isfile(glade_file):
glade_file = "plugins/csvexport.glade"
def get_option_box(self):
glade_file = os.path.join(os.path.dirname(__file__), "ExportCsv.glade")
self.topDialog = glade.XML(glade_file,"csvExport","gramps")
filter_obj = self.topDialog.get_widget("filter")
@ -229,12 +226,9 @@ class CSVWriterOptionBox:
#
#-------------------------------------------------------------------------
class CSVWriter:
def __init__(self,database,person,cl=0,filename="",
option_box=None,callback=None):
def __init__(self, database, filename, option_box=None, callback=None):
self.db = database
self.person = person
self.option_box = option_box
self.cl = cl
self.filename = filename
self.callback = callback
if callable(self.callback): # callback is really callable
@ -250,7 +244,9 @@ class CSVWriter:
self.person_ids = {}
if not option_box:
self.cl_setup()
self.include_individuals = 1
self.include_marriages = 1
self.include_children = 1
else:
self.option_box.parse_options()
@ -258,48 +254,9 @@ class CSVWriter:
self.include_marriages = self.option_box.include_marriages
self.include_children = self.option_box.include_children
if self.option_box.cfilter is None:
for p in self.db.get_person_handles(sort_handles=False):
self.plist[p] = 1
else:
try:
for p in self.option_box.cfilter.apply(self.db,
self.db.get_person_handles(sort_handles=False)):
self.plist[p] = 1
except Errors.FilterError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
return
if not option_box.cfilter.is_empty():
self.db = gen.proxy.FilterProxyDb(self.db, option_box.cfilter)
# get the families for which these people are spouses:
self.flist = {}
for key in self.plist:
p = self.db.get_person_from_handle(key)
for family_handle in p.get_family_handle_list():
self.flist[family_handle] = 1
# now add the families for which these people are a child:
family_handles = self.db.get_family_handles()
for family_handle in family_handles:
family = self.db.get_family_from_handle(family_handle)
for child_ref in family.get_child_ref_list():
child_handle = child_ref.ref
if child_handle in self.plist.keys():
self.flist[family_handle] = 1
def update_empty(self):
pass
def update_real(self):
self.count += 1
newval = int(100*self.count/self.total)
if newval != self.oldval:
self.callback(newval)
self.oldval = newval
def cl_setup(self):
self.include_individuals = 0
self.include_marriages = 0
self.include_children = 0
for p in self.db.get_person_handles(sort_handles=False):
self.plist[p] = 1
# get the families for which these people are spouses:
@ -316,6 +273,16 @@ class CSVWriter:
child_handle = child_ref.ref
if child_handle in self.plist.keys():
self.flist[family_handle] = 1
def update_empty(self):
pass
def update_real(self):
self.count += 1
newval = int(100*self.count/self.total)
if newval != self.oldval:
self.callback(newval)
self.oldval = newval
def writeln(self):
self.g.writerow([])
@ -497,13 +464,17 @@ class CSVWriter:
#-------------------------------------------------------------------------
#
# Register all of the plugins
# Register the plugin
#
#-------------------------------------------------------------------------
_title = _('Comma _Separated Values Spreadsheet (CSV)')
_name = _('Comma _Separated Values Spreadsheet (CSV)')
_description = _('CSV is a common spreadsheet format.')
_config = (_('CSV spreadsheet options'),CSVWriterOptionBox)
_filename = 'csv'
pmgr = PluginManager.get_instance()
pmgr.register_export(exportData,_title,_description,_config,_filename)
plugin = ExportPlugin(name = _name,
description = _description,
export_function = exportData,
extension = "csv",
config = _config )
pmgr.register_plugin(plugin)

View File

@ -29,7 +29,6 @@
#
#-------------------------------------------------------------------------
import os
from cStringIO import StringIO
from gettext import gettext as _
#------------------------------------------------------------------------
@ -56,15 +55,15 @@ import Utils
from Filters import GenericFilter, Rules, build_filter_menu
import Errors
from QuestionDialog import ErrorDialog
from gen.plug import PluginManager
from gen.plug import PluginManager, ExportPlugin
#-------------------------------------------------------------------------
#
# writeData
#
#-------------------------------------------------------------------------
def writeData(database, filename, person, option_box, callback=None):
writer = FtreeWriter(database, person, 0, filename, option_box, callback)
def writeData(database, filename, option_box=None, callback=None):
writer = FtreeWriter(database, filename, option_box, callback)
return writer.export_data()
class FtreeWriterOptionBox:
@ -74,11 +73,11 @@ class FtreeWriterOptionBox:
"""
def __init__(self, person):
self.person = person
self.restrict = True
def get_option_box(self):
self.restrict = True
base = os.path.dirname(__file__)
glade_file = "%s/%s" % (base,"writeftree.glade")
glade_file = os.path.join(os.path.dirname(__file__),
"ExportFtree.glade")
self.top = glade.XML(glade_file, "top", "gramps")
@ -133,12 +132,10 @@ class FtreeWriterOptionBox:
#-------------------------------------------------------------------------
class FtreeWriter:
def __init__(self, database, person, cl=0, filename="", option_box=None,
def __init__(self, database, filename="", option_box=None,
callback = None):
self.db = database
self.person = person
self.option_box = option_box
self.cl = cl
self.filename = filename
self.callback = callback
if callable(self.callback): # callback is really callable
@ -303,15 +300,17 @@ def get_name(name, count):
else:
return "%s %s%s, %s" % (name.first_name, name.surname, val, name.suffix)
#-------------------------------------------------------------------------
#------------------------------------------------------------------------
#
# Register the plugin
# Register with the plugin system
#
#-------------------------------------------------------------------------
_title = _('_Web Family Tree')
_description = _('Web Family Tree format.')
#------------------------------------------------------------------------
_config = (_('Web Family Tree export options'), FtreeWriterOptionBox)
_filename = 'wft'
pmgr = PluginManager.get_instance()
pmgr.register_export(writeData, _title, _description, _config,_filename)
plugin = ExportPlugin(name = _('_Web Family Tree'),
description = _('Web Family Tree format.'),
export_function = writeData,
extension = "wft",
config = _config )
pmgr.register_plugin(plugin)

View File

@ -40,13 +40,14 @@ import time
#-------------------------------------------------------------------------
import gen.lib
import const
import _GedcomInfo as GedcomInfo
import GrampsDbUtils._GedcomInfo as GedcomInfo
import Errors
import ExportOptions
import BasicUtils
from Utils import media_path_full
import gen.proxy
from QuestionDialog import ErrorDialog
from gen.plug import PluginManager, ExportPlugin
#-------------------------------------------------------------------------
#
@ -306,12 +307,11 @@ class GedcomWriter(BasicUtils.UpdateCallback):
so that it can provide visual feedback via a progress bar if needed.
"""
def __init__(self, database, person, cmd_line=0,
def __init__(self, database, cmd_line=0,
option_box=None, callback=None):
BasicUtils.UpdateCallback.__init__(self, callback)
self.dbase = database
self.person = person
self.cmd_line = cmd_line
self.dirname = None
self.gedcom_file = None
@ -1502,14 +1502,13 @@ class GedcomWriter(BasicUtils.UpdateCallback):
#
#
#-------------------------------------------------------------------------
def export_data(database, filename, person, option_box, callback=None):
def export_data(database, filename, option_box=None, callback=None):
"""
External interface used to register with the plugin system.
"""
ret = False
try:
ged_write = GedcomWriter(database, person, 0,
option_box, callback)
ged_write = GedcomWriter(database, 0, option_box, callback)
ret = ged_write.write_gedcom_file(filename)
except IOError, msg:
msg2 = _("Could not create %s") % filename
@ -1520,17 +1519,19 @@ def export_data(database, filename, person, option_box, callback=None):
ErrorDialog(_("Could not create %s") % filename)
return ret
#-------------------------------------------------------------------------
#------------------------------------------------------------------------
#
# Register with the plugin system
#
#
#-------------------------------------------------------------------------
TITLE = _('GE_DCOM')
DESCRIPTION = _('GEDCOM is used to transfer data between genealogy programs. '
#------------------------------------------------------------------------
_description = _('GEDCOM is used to transfer data between genealogy programs. '
'Most genealogy software will accept a GEDCOM file as input.')
CONFIG = (_('GEDCOM export options'), ExportOptions.WriterOptionBox)
FILENAME = 'ged'
_config = (_('GEDCOM export options'), ExportOptions.WriterOptionBox)
from gen.plug import PluginManager
pmgr = PluginManager.get_instance()
pmgr.register_export(export_data, TITLE, DESCRIPTION, CONFIG, FILENAME)
plugin = ExportPlugin(name = _('GE_DCOM'),
description = _description,
export_function = export_data,
extension = "ged",
config = _config )
pmgr.register_plugin(plugin)

View File

@ -55,9 +55,8 @@ import gen.lib
from Filters import GenericFilter, Rules, build_filter_menu
#import const
import Utils
import Errors
from QuestionDialog import ErrorDialog
from gen.plug import PluginManager
from gen.plug import PluginManager, ExportPlugin
#-------------------------------------------------------------------------
#
@ -77,9 +76,8 @@ class GeneWebWriterOptionBox:
self.restrict = 1
self.private = 1
glade_file = "%s/genewebexport.glade" % os.path.dirname(__file__)
if not os.path.isfile(glade_file):
glade_file = "plugins/genewebexport.glade"
glade_file = os.path.join(os.path.dirname(__file__),
"ExportGeneWeb.glade")
self.topDialog = glade.XML(glade_file, "genewebExport", "gramps")
self.topDialog.signal_autoconnect({
@ -154,12 +152,10 @@ class GeneWebWriterOptionBox:
self.images_path = ""
class GeneWebWriter:
def __init__(self, database, person, cl=0, filename="", option_box=None,
def __init__(self, database, filename="", option_box=None,
callback=None):
self.db = database
self.person = person
self.option_box = option_box
self.cl = cl
self.filename = filename
self.callback = callback
if callable(self.callback): # callback is really callable
@ -175,7 +171,10 @@ class GeneWebWriter:
self.person_ids = {}
if not option_box:
self.cl_setup()
self.restrict = 0
self.private = 0
self.copy = 0
self.images = 0
else:
self.option_box.parse_options()
@ -188,23 +187,17 @@ class GeneWebWriter:
self.images = self.option_box.images
self.images_path = self.option_box.images_path
if self.option_box.cfilter is None:
for p in self.db.get_person_handles(sort_handles=False):
self.plist[p] = 1
else:
try:
for p in self.option_box.cfilter.apply(self.db, self.db.get_person_handles(sort_handles=False)):
self.plist[p] = 1
except Errors.FilterError, msg:
(m1, m2) = msg.messages()
ErrorDialog(m1, m2)
return
if not option_box.cfilter.is_empty():
self.db = gen.proxy.FilterProxyDb(self.db, option_box.cfilter)
self.flist = {}
for key in self.plist:
p = self.db.get_person_from_handle(key)
for family_handle in p.get_family_handle_list():
self.flist[family_handle] = 1
for p in self.db.get_person_handles(sort_handles=False):
self.plist[p] = 1
self.flist = {}
for key in self.plist:
p = self.db.get_person_from_handle(key)
for family_handle in p.get_family_handle_list():
self.flist[family_handle] = 1
# remove families that dont contain father AND mother
# because GeneWeb requires both to be present
@ -229,22 +222,6 @@ class GeneWebWriter:
self.callback(newval)
self.oldval = newval
def cl_setup(self):
self.restrict = 0
self.private = 0
self.copy = 0
self.images = 0
for p in self.db.get_person_handles(sort_handles=False):
self.plist[p] = 1
self.flist = {}
for key in self.plist:
p = self.db.get_person_from_handle(key)
for family_handle in p.get_family_handle_list():
self.flist[family_handle] = 1
def writeln(self, text):
self.g.write(self.iso8859('%s\n' % (text)))
@ -389,7 +366,7 @@ class GeneWebWriter:
note = ""
for notehandle in notelist:
noteobj = self.db.get_note_from_handle(notehandle)
note += noteobj.get(False)
note += noteobj.get()
note += " "
if note and note != "":
@ -629,19 +606,22 @@ class GeneWebWriter:
#
#
#-------------------------------------------------------------------------
def exportData(database,filename,person, option_box,callback=None):
gw = GeneWebWriter(database,person,0,filename, option_box,callback)
def exportData(database, filename, option_box=None, callback=None):
gw = GeneWebWriter(database, filename, option_box, callback)
return gw.export_data()
#-------------------------------------------------------------------------
#------------------------------------------------------------------------
#
# Register with the plugin system
#
#
#-------------------------------------------------------------------------
_title = _('_GeneWeb')
#------------------------------------------------------------------------
_description = _('GeneWeb is a web based genealogy program.')
_config = (_('GeneWeb export options'), GeneWebWriterOptionBox)
_filename = 'gw'
pmgr = PluginManager.get_instance()
pmgr.register_export(exportData, _title, _description, _config, _filename)
plugin = ExportPlugin(name = _('_GeneWeb'),
description = _description,
export_function = exportData,
extension = "gw",
config = _config )
pmgr.register_plugin(plugin)

View File

@ -60,8 +60,8 @@ import gtk
# GRAMPS modules
#
#-------------------------------------------------------------------------
from GrampsDbUtils import XmlWriter
from gen.plug import PluginManager
from ExportXml import XmlWriter
from gen.plug import PluginManager, ExportPlugin
import Utils
#-------------------------------------------------------------------------
@ -69,29 +69,30 @@ import Utils
# writeData
#
#-------------------------------------------------------------------------
def writeData(database, filename, person, option_box, callback=None):
option_box.parse_options()
if option_box.private:
database = gen.proxy.PrivateProxyDb(database)
if option_box.restrict:
database = gen.proxy.LivingProxyDb(
database, gen.proxy.LivingProxyDb.MODE_INCLUDE_LAST_NAME_ONLY)
# Apply the Person Filter
if not option_box.cfilter.is_empty():
database = gen.proxy.FilterProxyDb(database, option_box.cfilter)
# Apply the Note Filter
if not option_box.nfilter.is_empty():
database = gen.proxy.FilterProxyDb(
database, note_filter=option_box.nfilter)
def writeData(database, filename, option_box=None, callback=None):
if option_box:
option_box.parse_options()
# Apply the ReferencedProxyDb to remove any objects not referenced
# after any of the other proxies have been applied
if option_box.unlinked:
database = gen.proxy.ReferencedProxyDb(database)
if option_box.private:
database = gen.proxy.PrivateProxyDb(database)
if option_box.restrict:
database = gen.proxy.LivingProxyDb(
database, gen.proxy.LivingProxyDb.MODE_INCLUDE_LAST_NAME_ONLY)
# Apply the Person Filter
if not option_box.cfilter.is_empty():
database = gen.proxy.FilterProxyDb(database, option_box.cfilter)
# Apply the Note Filter
if not option_box.nfilter.is_empty():
database = gen.proxy.FilterProxyDb(
database, note_filter=option_box.nfilter)
# Apply the ReferencedProxyDb to remove any objects not referenced
# after any of the other proxies have been applied
if option_box.unlinked:
database = gen.proxy.ReferencedProxyDb(database)
writer = PackageWriter(database, filename, callback)
return writer.export()
@ -225,17 +226,20 @@ class PackageWriter:
g.close()
return True
#-------------------------------------------------------------------------
#------------------------------------------------------------------------
#
# Register the plugin
# Register with the plugin system
#
#-------------------------------------------------------------------------
_title = _('GRAM_PS package (portable XML)')
#------------------------------------------------------------------------
_description = _('GRAMPS package is an archived XML database together '
'with the media object files.')
_config = (_('GRAMPS package export options'), ExportOptions.WriterOptionBox)
_filename = 'gpkg'
pmgr = PluginManager.get_instance()
pmgr.register_export(writeData, _title, _description, _config, _filename)
plugin = ExportPlugin(name = _('GRAM_PS package (portable XML)'),
description = _description,
export_function = writeData,
extension = "gpkg",
config = _config )
pmgr.register_plugin(plugin)

View File

@ -59,7 +59,7 @@ import Utils
from gen.lib import Date, EventType
import Errors
from QuestionDialog import ErrorDialog
from gen.plug import PluginManager
from gen.plug import PluginManager, ExportPlugin
#-------------------------------------------------------------------------
#
@ -75,9 +75,9 @@ class CalendarWriterOptionBox:
def __init__(self, person):
self.person = person
glade_file = "%s/vcalendarexport.glade" % os.path.dirname(__file__)
if not os.path.isfile(glade_file):
glade_file = "plugins/vcalendarexport.glade"
glade_file = os.path.join(os.path.dirname(__file__),
"ExportVCalendar.glade")
self.topDialog = glade.XML(glade_file, "calendarExport", "gramps")
self.copy = 0
self.filter_menu = gtk.Menu()
@ -128,10 +128,9 @@ class CalendarWriterOptionBox:
class CalendarWriter:
def __init__(self, database, person, cl=0, filename="", option_box=None,
def __init__(self, database, cl=0, filename="", option_box=None,
callback=None):
self.db = database
self.person = person
self.option_box = option_box
self.cl = cl
self.filename = filename
@ -342,19 +341,22 @@ class CalendarWriter:
#
#
#-------------------------------------------------------------------------
def exportData(database, filename, person, option_box, callback=None):
cw = CalendarWriter(database, person, 0, filename, option_box, callback)
def exportData(database, filename, option_box=None, callback=None):
cw = CalendarWriter(database, 0, filename, option_box, callback)
return cw.export_data(filename)
#-------------------------------------------------------------------------
#------------------------------------------------------------------------
#
# Register with the plugin system
#
#
#-------------------------------------------------------------------------
_title = _('vC_alendar')
#------------------------------------------------------------------------
_description = _('vCalendar is used in many calendaring and pim applications.')
_config = (_('vCalendar export options'), CalendarWriterOptionBox)
_filename = 'vcs'
pmgr = PluginManager.get_instance()
pmgr.register_export(exportData, _title, _description, _config, _filename)
plugin = ExportPlugin(name = _('vC_alendar'),
description = _description,
export_function = exportData,
extension = "vcs",
config = _config )
pmgr.register_plugin(plugin)

View File

@ -56,7 +56,7 @@ from Filters import GenericFilter, Rules, build_filter_menu
from gen.lib import Date
import Errors
from QuestionDialog import ErrorDialog
from gen.plug import PluginManager
from gen.plug import PluginManager, ExportPlugin
#-------------------------------------------------------------------------
#
@ -74,9 +74,8 @@ class CardWriterOptionBox:
def get_option_box(self):
glade_file = "%s/vcardexport.glade" % os.path.dirname(__file__)
if not os.path.isfile(glade_file):
glade_file = "plugins/vcardexport.glade"
glade_file = os.path.join(os.path.dirname(__file__),
"ExportVCard.glade")
self.topDialog = glade.XML(glade_file,"vcardExport","gramps")
@ -125,10 +124,9 @@ class CardWriterOptionBox:
self.cfilter = self.filter_menu.get_active().get_data("filter")
class CardWriter:
def __init__(self, database, person, cl=0, filename="", option_box=None,
def __init__(self, database, cl=0, filename="", option_box=None,
callback=None):
self.db = database
self.person = person
self.option_box = option_box
self.cl = cl
self.filename = filename
@ -258,19 +256,22 @@ class CardWriter:
#
#
#-------------------------------------------------------------------------
def exportData(database, filename, person, option_box, callback=None):
cw = CardWriter(database, person, 0, filename, option_box, callback)
def exportData(database, filename, option_box=None, callback=None):
cw = CardWriter(database, 0, filename, option_box, callback)
return cw.export_data(filename)
#-------------------------------------------------------------------------
#------------------------------------------------------------------------
#
# Register with the plugin system
#
#
#-------------------------------------------------------------------------
_title = _('_vCard')
#------------------------------------------------------------------------
_description = _('vCard is used in many addressbook and pim applications.')
_config = (_('vCard export options'), CardWriterOptionBox)
_filename = 'vcf'
pmgr = PluginManager.get_instance()
pmgr.register_export(exportData, _title, _description, _config, _filename)
plugin = ExportPlugin(name = _('_vCard'),
description = _description,
export_function = exportData,
extension = "vcf",
config = _config )
pmgr.register_plugin(plugin)

View File

@ -2,6 +2,9 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2008 Robert Cheramy <robert@cheramy.net>
#
# 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
@ -23,8 +26,6 @@
"""
Contains the interface to allow a database to get written using
GRAMPS' XML file format.
This module contains all that is needed for xml write, however it does not
provide the export plugin functionality. That is provided in _WriteXML.py
"""
#-------------------------------------------------------------------------
@ -33,11 +34,13 @@ provide the export plugin functionality. That is provided in _WriteXML.py
#
#-------------------------------------------------------------------------
import time
import shutil
import os
import codecs
from xml.sax.saxutils import escape
from gettext import gettext as _
#------------------------------------------------------------------------
#
# Set up logging
@ -51,10 +54,14 @@ log = logging.getLogger(".WriteXML")
# load GRAMPS libraries
#
#-------------------------------------------------------------------------
import gen.lib
from BasicUtils import UpdateCallback
from gen.db.exceptions import GrampsDbWriteFailure
import const
from QuestionDialog import ErrorDialog
import ExportOptions
import gen.proxy
from gen.plug import PluginManager, ExportPlugin
#-------------------------------------------------------------------------
#
@ -76,15 +83,6 @@ strip_dict = dict.fromkeys(range(9)+range(12,20))
def escxml(d):
return escape(d, { '"' : '&quot;' } )
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def quick_write(database, filename, version="unknown"):
g = GrampsDbXmlWriter(database,0,1,version)
g.write(filename)
#-------------------------------------------------------------------------
#
#
@ -1131,8 +1129,90 @@ def conf_priv(obj):
#-------------------------------------------------------------------------
#
#
# export_data
#
#-------------------------------------------------------------------------
def export_data(database, filename, option_box=None, callback=None):
"""
Call the XML writer with the syntax expected by the export plugin.
"""
if os.path.isfile(filename):
try:
shutil.copyfile(filename, filename + ".bak")
shutil.copystat(filename, filename + ".bak")
except:
pass
# Don't export a writer for plugins, that is the task of _WriteXML.py
compress = _gzip_ok == 1
if option_box:
option_box.parse_options()
if option_box.private:
database = gen.proxy.PrivateProxyDb(database)
if option_box.restrict:
database = gen.proxy.LivingProxyDb(
database, gen.proxy.LivingProxyDb.MODE_INCLUDE_LAST_NAME_ONLY)
# Apply the Person Filter
if not option_box.cfilter.is_empty():
database = gen.proxy.FilterProxyDb(database, option_box.cfilter)
# Apply the Note Filter
if not option_box.nfilter.is_empty():
database = gen.proxy.FilterProxyDb(
database, note_filter=option_box.nfilter)
# Apply the ReferencedProxyDb to remove any objects not referenced
# after any of the other proxies have been applied
if option_box.unlinked:
database = gen.proxy.ReferencedProxyDb(database)
g = XmlWriter(database, callback, 0, compress)
return g.write(filename)
#-------------------------------------------------------------------------
#
# XmlWriter
#
#-------------------------------------------------------------------------
class XmlWriter(GrampsDbXmlWriter):
"""
Writes a database to the XML file.
"""
def __init__(self, dbase, callback, strip_photos, compress=1):
GrampsDbXmlWriter.__init__(
self, dbase, strip_photos, compress, const.VERSION, callback)
def write(self, filename):
"""
Write the database to the specified file.
"""
ret = 0 #False
try:
ret = GrampsDbXmlWriter.write(self, filename)
except GrampsDbWriteFailure, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1, m2)
return ret
#------------------------------------------------------------------------
#
# Register with the plugin system
#
#------------------------------------------------------------------------
_description = _('Exporting to CD copies all your data and media object files '
'to the CD Creator. You may later burn the CD with this data, '
'and that copy will be completely portable across different '
'machines and binary architectures.')
_config = (_('GRAMPS XML export options'), ExportOptions.WriterOptionBox)
pmgr = PluginManager.get_instance()
plugin = ExportPlugin(name = _('GRAMPS _XML database'),
description = _description,
export_function = export_data,
extension = "gramps",
config = _config )
pmgr.register_plugin(plugin)

View File

@ -796,5 +796,5 @@ pmgr = PluginManager.get_instance()
plugin = ImportPlugin(name = _('CSV Spreadheet'),
description = _("Import data from CSV files"),
import_function = importData,
mime_types = [_mime_type, _mime_type_rfc_4180])
extension = "csv")
pmgr.register_plugin(plugin)

View File

@ -639,7 +639,7 @@
<child>
<widget class="GtkLabel" id="label18">
<property name="visible">True</property>
<property name="label" translatable="yes">This GEDCOM file has identified itself as using ANSEL encoding. Sometimes, this is in error. If the imported data contains unusual characters, undo the import, and override the character set by selecting a different encoding below.</property>
<property name="label" translatable="yes">This GEDCOM file has identified itself as using ANSEL enconding. Sometimes, this is in error. If the imported data contains unusual characters, undo the import, and override the character set by selecting a different encoding below.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>

View File

@ -45,9 +45,10 @@ LOG = logging.getLogger(".GedcomImport")
#
#------------------------------------------------------------------------
import Errors
from _GedcomParse import GedcomParser
from _GedcomStageOne import StageOne
from GrampsDbUtils._GedcomParse import GedcomParser
from GrampsDbUtils._GedcomStageOne import StageOne
from QuestionDialog import ErrorDialog, DBErrorDialog
from gen.plug import PluginManager, ImportPlugin
try:
import Config
@ -61,7 +62,7 @@ except ImportError:
# importData
#
#-------------------------------------------------------------------------
def importData(database, filename, callback=None, use_trans=False):
def importData(database, filename, callback=None):
"""
Try to handle ANSEL encoded files that are not really ANSEL encoded
"""
@ -83,7 +84,8 @@ def importData(database, filename, callback=None, use_trans=False):
ifile.close()
if not gramps and ansel:
glade_file = "%s/gedcomimport.glade" % os.path.dirname(__file__)
glade_file = os.path.join(os.path.dirname(__file__),
"ImportGedcom.glade")
top = glade.XML(glade_file, 'encoding','gramps')
code = top.get_widget('codeset')
code.set_active(0)
@ -94,17 +96,6 @@ def importData(database, filename, callback=None, use_trans=False):
dialog.destroy()
else:
code_set = ""
import2(database, filename, callback, code_set, use_trans)
#-------------------------------------------------------------------------
#
# import2
#
#-------------------------------------------------------------------------
def import2(database, filename, callback, code_set, use_trans):
"""
Import the gedcom file.
"""
assert(isinstance(code_set, basestring))
@ -126,13 +117,10 @@ def import2(database, filename, callback, code_set, use_trans):
_("%s could not be imported") % filename + "\n" + str(msg))
return
if database.get_number_of_people() == 0:
use_trans = False
try:
read_only = database.readonly
database.readonly = False
gedparse.parse_gedcom_file(use_trans)
gedparse.parse_gedcom_file(False)
database.readonly = read_only
ifile.close()
except IOError, msg:
@ -146,3 +134,17 @@ def import2(database, filename, callback, code_set, use_trans):
ErrorDialog(_('Error reading GEDCOM file'), str(msg))
return
#------------------------------------------------------------------------
#
# Register with the plugin system
#
#------------------------------------------------------------------------
_description = _('GEDCOM is used to transfer data between genealogy programs. '
'Most genealogy software will accept a GEDCOM file as input.')
pmgr = PluginManager.get_instance()
plugin = ImportPlugin(name = _('GE_DCOM'),
description = _description,
import_function = importData,
extension = "ged" )
pmgr.register_plugin(plugin)

View File

@ -47,7 +47,6 @@ log = logging.getLogger(".ImportGeneWeb")
#-------------------------------------------------------------------------
import Errors
import gen.lib
import const
from QuestionDialog import ErrorDialog
from gen.plug import PluginManager, ImportPlugin
from htmlentitydefs import name2codepoint
@ -926,5 +925,5 @@ pmgr = PluginManager.get_instance()
plugin = ImportPlugin(name = _('GeneWeb'),
description = _("Import data from GeneWeb files"),
import_function = importData,
mime_types = [const.APP_GENEWEB])
extension = "gw")
pmgr.register_plugin(plugin)

View File

@ -47,7 +47,7 @@ log = logging.getLogger(".ReadPkg")
#
#-------------------------------------------------------------------------
import const
from GrampsDbUtils import gramps_db_reader_factory
import ImportXml
from QuestionDialog import ErrorDialog, WarningDialog
import Utils
from gen.plug import PluginManager, ImportPlugin
@ -93,7 +93,7 @@ def impData(database, name, cb=None):
imp_db_name = os.path.join(tmpdir_path, const.XMLFILE)
importer = gramps_db_reader_factory(const.APP_GRAMPS_XML)
importer = ImportXml.importData
info = importer(database, imp_db_name, cb)
newmediapath = database.get_mediapath()
#import of gpkg should not change media path as all media has new paths!
@ -146,5 +146,5 @@ pmgr = PluginManager.get_instance()
plugin = ImportPlugin(name = _('GRAMPS package'),
description = _("Import data from GRAMPS packages"),
import_function = impData,
mime_types = ['application/x-gramps-package'])
extension = "gpkg")
pmgr.register_plugin(plugin)

View File

@ -2687,5 +2687,5 @@ plugin = ImportPlugin(name = _('GRAMPS 2.x database'),
description = _("Import data from GRAMPS 2.x "
"database files"),
import_function = importData,
mime_types = ['application/x-gramps'])
extension = "grdb")
pmgr.register_plugin(plugin)

View File

@ -1218,5 +1218,5 @@ pmgr = PluginManager.get_instance()
plugin = ImportPlugin(name = _('Pro-Gen'),
description = _("Import data from Pro-Gen files"),
import_function = _importData,
mime_types = ["application/x-progen"])
extension = "def")
pmgr.register_plugin(plugin)

View File

@ -160,7 +160,11 @@ class VCardParser:
self.person = gen.lib.Person()
def set_nick_name(self, fields, data):
self.person.set_nick_name(data)
if self.person is not None:
attr = gen.lib.Attribute()
attr.set_type(gen.lib.AttributeType.NICKNAME)
attr.set_value(data)
self.person.add_attribute(attr)
def add_name(self, fields, data):
data_fields = data.split(";")
@ -170,7 +174,7 @@ class VCardParser:
name.set_first_name(data_fields[1])
if data_fields[2]:
name.set_first_name(data_fields[1]+" "+data_fields[2])
name.set_prefix(data_fields[3])
name.set_surname_prefix(data_fields[3])
name.set_suffix(data_fields[4])
self.person.set_primary_name(name)
@ -200,7 +204,10 @@ class VCardParser:
event = gen.lib.Event()
event.set_type(gen.lib.EventType(gen.lib.EventType.BIRTH))
self.db.add_event(event,self.trans)
self.person.set_birth_handle(event.get_handle())
event_ref = gen.lib.EventRef()
event_ref.set_reference_handle(event.get_handle())
self.person.set_birth_ref(event_ref)
def add_url(self, fields, data):
url = gen.lib.Url()
@ -216,5 +223,5 @@ pmgr = PluginManager.get_instance()
plugin = ImportPlugin(name = _('vCard'),
description = _("Import data from vCard files"),
import_function = importData,
mime_types = ["text/x-vcard", "text/x-vcalendar"])
extension = "vcf")
pmgr.register_plugin(plugin)

View File

@ -46,8 +46,9 @@ from BasicUtils import name_displayer
from gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY, EVENT_KEY,
MEDIA_KEY, PLACE_KEY, REPOSITORY_KEY, NOTE_KEY)
from BasicUtils import UpdateCallback
import _GrampsDbWriteXML
import ExportXml
import const
from gen.plug import PluginManager, ImportPlugin
#-------------------------------------------------------------------------
#
@ -2443,7 +2444,7 @@ def version_is_valid(filename, cli):
"""
parser = VersionParser(filename)
if parser.get_xmlns_version() > _GrampsDbWriteXML.XML_VERSION:
if parser.get_xmlns_version() > ExportXml.XML_VERSION:
msg = _("The .gramps file you are importing was made by version %s of "
"GRAMPS, while you are running an older version %s. "
"The file will not be imported. Please upgrade to the latest "
@ -2457,3 +2458,18 @@ def version_is_valid(filename, cli):
return False
return True
#------------------------------------------------------------------------
#
# Register with the plugin system
#
#------------------------------------------------------------------------
pmgr = PluginManager.get_instance()
plugin = ImportPlugin(name = _('GRAMPS _XML database'),
description = _('The GRAMPS XML database is a text '
'version of a family tree. It is '
'read-write compatible with the '
'present GRAMPS database format.'),
import_function = importData,
extension = "gramps" )
pmgr.register_plugin(plugin)

View File

@ -30,9 +30,15 @@ pkgdata_PYTHON = \
Eval.py\
EventCmp.py\
EventNames.py\
ExportCSV.py\
ExportCd.py\
ExportCsv.py\
ExportFtree.py\
ExportGedcom.py\
ExportGeneweb.py\
ExportPkg.py\
ExportVCalendar.py\
ExportVCard.py\
ExportXml.py\
ExtractCity.py\
FamilyGroup.py\
FanChart.py\
@ -42,10 +48,13 @@ pkgdata_PYTHON = \
GVHourGlass.py\
GVRelGraph.py\
ImportCSV.py\
ImportGedcom.py\
ImportGeneWeb.py\
ImportGpkg.py\
ImportGrdb.py\
ImportProGen.py\
ImportvCard.py\
ImportXml.py\
IndivComplete.py\
KinshipReport.py\
Leak.py\
@ -89,10 +98,7 @@ pkgdata_PYTHON = \
TimeLine.py\
Verify.py\
WebCal.py\
WriteFtree.py\
WriteGeneWeb.py\
WritePkg.py\
WriteCD.py
WriteFtree.py
# DateParserDisplayTest.py\
# DumpGenderStats.py\
@ -104,28 +110,28 @@ pkgpyexecdir = @pkgpyexecdir@/plugins
pkgpythondir = @pkgpythondir@/plugins
GLADEFILES = \
NotRelated.glade\
changetype.glade\
csvexport.glade\
desbrowse.glade\
eventcmp.glade\
merge.glade\
patchnames.glade\
book.glade\
changenames.glade\
changetype.glade\
desbrowse.glade\
eval.glade\
eventcmp.glade\
ExportCsv.glade\
ExportFtree.glade\
ExportGeneWeb.glade\
ExportVCalendar.glade\
ExportVCard.glade\
ImportGedcom.glade\
leak.glade\
merge.glade\
NotRelated.glade\
ownereditor.glade\
patchnames.glade\
relcalc.glade\
soundex.glade\
summary.glade\
verify.glade\
cdexport.glade\
eval.glade\
leak.glade\
book.glade\
ownereditor.glade\
writeftree.glade\
genewebexport.glade\
vcardexport.glade\
vcalendarexport.glade\
unused.glade
unused.glade\
verify.glade
GRAPHICS =

View File

@ -1,189 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkDialog" id="packageExport">
<property name="visible">True</property>
<property name="title" translatable="yes"></property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">True</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">8</property>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="cancel">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="response_id">0</property>
<signal name="clicked" handler="destroy_passed_object" object="packageExport"/>
</widget>
</child>
<child>
<widget class="GtkButton" id="ok">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="response_id">-5</property>
<signal name="clicked" handler="on_ok_clicked" object="packageExport"/>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">2</property>
<child>
<widget class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="stock">gtk-cdrom</property>
<property name="icon_size">4</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">_Export to CD</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-help</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="response_id">-11</property>
<signal name="clicked" handler="on_help_clicked" last_modification_time="Tue, 02 Dec 2003 02:04:37 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="border_width">12</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">12</property>
<child>
<widget class="GtkLabel" id="title">
<property name="visible">True</property>
<property name="label" translatable="yes"></property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_CENTER</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">6</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Exporting to a CD will not immediately write the CD. It will prepare the nautilus-cd-burner so that you can burn the CD from nautilus.
After exporting, go to the &lt;b&gt;burn:///&lt;/b&gt; directory in nautilus and select the Write to CD button.</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@ -42,20 +42,6 @@ class FactoryTest(unittest.TestCase):
self.assertRaises(GrampsDb.GrampsDbException, GrampsDb.gramps_db_factory, "gibberish")
def test_gramps_db_reader_factory(self):
"""Test that gramps_db_reader_factory returns the correct method."""
md = GrampsDb.gramps_db_reader_factory(db_type = const.app_gramps)
assert callable(md), "Returned method is %s " % str(md)
md = GrampsDb.gramps_db_reader_factory(db_type = const.app_gramps_xml)
assert callable(md), "Returned method is %s " % str(md)
md = GrampsDb.gramps_db_reader_factory(db_type = const.app_gedcom)
assert callable(md), "Returned method is %s " % str(md)
self.assertRaises(GrampsDb.GrampsDbException, GrampsDb.gramps_db_reader_factory, "gibberish")
class ReferenceMapTest (GrampsDbBaseTest):