2004-07-09 23:49:47 +05:30
|
|
|
#
|
|
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
|
|
#
|
|
|
|
# Copyright (C) 2004 Donald N. Allingham
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#
|
|
|
|
|
|
|
|
# $Id$
|
|
|
|
|
|
|
|
#
|
|
|
|
# Written by Alex Roitman, 2004
|
|
|
|
#
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Python modules
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
import os
|
|
|
|
import shutil
|
|
|
|
from gettext import gettext as _
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Gnome modules
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
import gtk
|
|
|
|
import gnome
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# gramps modules
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
import const
|
|
|
|
import Utils
|
|
|
|
import Plugins
|
|
|
|
import QuestionDialog
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Exporter
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
class Exporter:
|
|
|
|
"""
|
|
|
|
This class creates Gnome Druid to guide the user through the various
|
|
|
|
Save as/Export options. The overall goal is to keep things simple by
|
|
|
|
presenting few choice options on each druid page.
|
|
|
|
|
|
|
|
The export formats and options are obtained from the plugins, with the
|
|
|
|
exception of a native save. Native save as just copies file to another
|
|
|
|
name.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self,parent,parent_window):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Set up the window, the druid, and build all the druid's pages.
|
|
|
|
Some page elements are left empty, since their contents depends
|
|
|
|
on the user choices and on the success of the attempted save.
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
self.parent = parent
|
|
|
|
self.parent_window = parent_window
|
2004-07-11 05:01:28 +05:30
|
|
|
if self.parent.active_person:
|
2004-07-11 11:33:07 +05:30
|
|
|
self.person = self.parent.active_person
|
2004-07-11 05:01:28 +05:30
|
|
|
else:
|
2004-07-11 11:33:07 +05:30
|
|
|
self.person = self.parent.find_initial_person()
|
2004-07-09 23:49:47 +05:30
|
|
|
|
|
|
|
self.build_exports()
|
2004-07-10 04:31:19 +05:30
|
|
|
self.confirm_label = gtk.Label()
|
2004-07-13 02:59:15 +05:30
|
|
|
self.extra_pages = []
|
2004-07-10 04:31:19 +05:30
|
|
|
|
2004-07-09 23:49:47 +05:30
|
|
|
self.w = gtk.Window()
|
|
|
|
|
|
|
|
self.fg_color = gtk.gdk.color_parse('#7d684a')
|
|
|
|
self.bg_color = gtk.gdk.color_parse('#e1dbc5')
|
|
|
|
self.logo = gtk.gdk.pixbuf_new_from_file("%s/gramps.png" % const.rootDir)
|
|
|
|
self.splash = gtk.gdk.pixbuf_new_from_file("%s/splash.jpg" % const.rootDir)
|
|
|
|
|
2004-07-11 11:33:07 +05:30
|
|
|
self.d = gnome.ui.Druid()
|
|
|
|
self.w.add(self.d)
|
|
|
|
self.d.add(self.build_info_page())
|
|
|
|
self.d.add(self.build_format_page())
|
|
|
|
self.file_sel_page = self.build_file_sel_page()
|
|
|
|
self.d.add(self.file_sel_page)
|
|
|
|
self.d.add(self.build_confirm_page())
|
2004-07-09 23:49:47 +05:30
|
|
|
self.last_page = self.build_last_page()
|
2004-07-11 11:33:07 +05:30
|
|
|
self.d.add(self.last_page)
|
2004-07-09 23:49:47 +05:30
|
|
|
|
2004-07-11 11:33:07 +05:30
|
|
|
self.d.set_show_help(gtk.TRUE)
|
|
|
|
self.d.connect('cancel',self.close)
|
|
|
|
self.d.connect('help',self.help)
|
2004-07-09 23:49:47 +05:30
|
|
|
self.w.connect("destroy_event",self.close)
|
|
|
|
self.w.set_transient_for(self.parent_window)
|
|
|
|
|
|
|
|
self.w.show_all()
|
|
|
|
|
|
|
|
def close(self,obj,obj2=None):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Close and delete handler.
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
self.w.destroy()
|
|
|
|
|
|
|
|
def help(self,obj):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Help handler.
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
#FIXME: point to the correct section when it exists
|
|
|
|
gnome.help_display('gramps-manual','index')
|
|
|
|
|
|
|
|
def build_info_page(self):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Build initial druid page with the overall information about the process.
|
|
|
|
This is a static page, nothing fun here :-)
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
p = gnome.ui.DruidPageEdge(0)
|
|
|
|
p.set_title(_('Saving your data'))
|
|
|
|
p.set_title_color(self.fg_color)
|
|
|
|
p.set_bg_color(self.bg_color)
|
|
|
|
p.set_logo(self.logo)
|
|
|
|
p.set_watermark(self.splash)
|
|
|
|
p.set_text(_('Under normal circumstances, GRAMPS does not require you '
|
|
|
|
'to directly save your changes. All changes you make are '
|
|
|
|
'immediately saved to the database.\n\n'
|
|
|
|
'This process will help you save a copy of your data '
|
|
|
|
'in any of the several formats supported by GRAMPS. '
|
|
|
|
'This can be used to make a copy of your data, backup '
|
|
|
|
'your data, or convert it to a format that will allow '
|
|
|
|
'you to trasnfer it to a different program.\n\n'
|
|
|
|
'If you change your mind during this process, you '
|
2004-07-14 07:14:04 +05:30
|
|
|
'can safely press the Cancel button at any time and your '
|
2004-07-09 23:49:47 +05:30
|
|
|
'present database will still be intact.'))
|
|
|
|
return p
|
|
|
|
|
|
|
|
def build_last_page(self):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Build the last druid page. The actual text will be added after the
|
|
|
|
save is performed and the success status us known.
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
p = gnome.ui.DruidPageEdge(1)
|
|
|
|
p.set_title_color(self.fg_color)
|
|
|
|
p.set_bg_color(self.bg_color)
|
|
|
|
p.set_logo(self.logo)
|
|
|
|
p.set_watermark(self.splash)
|
|
|
|
p.connect('finish',self.close)
|
|
|
|
return p
|
|
|
|
|
2004-07-10 04:31:19 +05:30
|
|
|
def build_confirm_page(self):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Build a save confirmation page. Setting up the actual label
|
|
|
|
text is deferred until the page is being prepared. This
|
|
|
|
is necessary, because no choice is made by the user when this
|
|
|
|
page is set up.
|
|
|
|
"""
|
2004-07-10 04:31:19 +05:30
|
|
|
p = gnome.ui.DruidPageStandard()
|
|
|
|
p.set_title(_('Final save confirmation'))
|
|
|
|
p.set_title_foreground(self.fg_color)
|
|
|
|
p.set_background(self.bg_color)
|
|
|
|
p.set_logo(self.logo)
|
|
|
|
|
|
|
|
p.append_item("",self.confirm_label,"")
|
|
|
|
|
|
|
|
p.connect('prepare',self.build_confirm_label)
|
|
|
|
p.connect('next',self.save)
|
|
|
|
return p
|
|
|
|
|
|
|
|
def build_confirm_label(self,obj,obj2):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Build the text of the confirmation label. This should query
|
|
|
|
the selected options (format, filename) and present the summary
|
|
|
|
of the proposed action.
|
|
|
|
"""
|
2004-07-10 04:31:19 +05:30
|
|
|
filename = self.chooser.get_filename()
|
|
|
|
name = os.path.split(filename)[1]
|
|
|
|
folder = os.path.split(filename)[0]
|
2004-07-11 05:01:28 +05:30
|
|
|
ix = self.get_selected_format_index()
|
|
|
|
format = self.exports[ix][1].replace('_','')
|
2004-07-10 04:31:19 +05:30
|
|
|
|
|
|
|
self.confirm_label.set_text(
|
|
|
|
_('The data will be saved as follows:\n\n'
|
|
|
|
'Format:\t%s\nName:\t%s\nFolder:\t%s\n\n'
|
|
|
|
'Press Forward to proceed, Cancel to abort, or Back to '
|
|
|
|
'revisit your options.') % (format, name, folder))
|
|
|
|
self.confirm_label.set_line_wrap(gtk.TRUE)
|
|
|
|
|
2004-07-09 23:49:47 +05:30
|
|
|
def save(self,obj,obj2):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Perform the actual Save As/Export operation.
|
|
|
|
Depending on the success status, set the text for the final page.
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
filename = self.chooser.get_filename()
|
2004-07-11 05:01:28 +05:30
|
|
|
ix = self.get_selected_format_index()
|
2004-07-11 11:33:07 +05:30
|
|
|
if self.exports[ix][3]:
|
|
|
|
success = self.exports[ix][0](self.parent.db,filename,self.person,
|
|
|
|
self.option_box_instance)
|
|
|
|
else:
|
|
|
|
success = self.exports[ix][0](self.parent.db,filename,self.person)
|
2004-07-09 23:49:47 +05:30
|
|
|
if success:
|
|
|
|
self.last_page.set_title(_('Your data has been saved'))
|
2004-07-11 05:01:28 +05:30
|
|
|
self.last_page.set_text(_('The copy of your data has been '
|
|
|
|
'successfully saved. You may press Apply button '
|
2004-07-10 04:31:19 +05:30
|
|
|
'now to continue.\n\n'
|
2004-07-11 05:01:28 +05:30
|
|
|
'Note: the database currently opened in your GRAMPS '
|
|
|
|
'window is NOT the file you have just saved. '
|
|
|
|
'Future editing of the currently opened database will '
|
|
|
|
'not alter the copy you have just made. '))
|
2004-07-09 23:49:47 +05:30
|
|
|
else:
|
|
|
|
self.last_page.set_title(_('Saving failed'))
|
|
|
|
self.last_page.set_text(_('There was an error '
|
2004-07-10 04:31:19 +05:30
|
|
|
'while saving your data. Please go back and try again.\n\n'
|
2004-07-14 07:14:04 +05:30
|
|
|
'Note: your currently opened database is safe. It was only '
|
|
|
|
'a copy of your data that failed to save.'))
|
2004-07-09 23:49:47 +05:30
|
|
|
|
|
|
|
def build_format_page(self):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Build a page with the table of format radio buttons and
|
|
|
|
their descriptions.
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
self.format_buttons = []
|
|
|
|
|
|
|
|
p = gnome.ui.DruidPageStandard()
|
|
|
|
p.set_title(_('Choosing the format to save'))
|
|
|
|
p.set_title_foreground(self.fg_color)
|
|
|
|
p.set_background(self.bg_color)
|
|
|
|
p.set_logo(self.logo)
|
|
|
|
|
|
|
|
box = gtk.VBox()
|
|
|
|
box.set_spacing(12)
|
|
|
|
p.append_item("",box,"")
|
|
|
|
|
|
|
|
table = gtk.Table(2*len(self.exports),2)
|
|
|
|
table.set_row_spacings(6)
|
|
|
|
table.set_col_spacings(6)
|
|
|
|
|
|
|
|
group = None
|
|
|
|
for ix in range(len(self.exports)):
|
|
|
|
title = self.exports[ix][1]
|
|
|
|
description= self.exports[ix][2]
|
|
|
|
|
|
|
|
button = gtk.RadioButton(group,title)
|
|
|
|
if not group:
|
|
|
|
group = button
|
|
|
|
self.format_buttons.append(button)
|
|
|
|
table.attach(button,0,2,2*ix,2*ix+1)
|
|
|
|
label = gtk.Label(description)
|
|
|
|
label.set_line_wrap(gtk.TRUE)
|
2004-07-13 02:59:15 +05:30
|
|
|
label.set_alignment(0,0.5)
|
|
|
|
table.attach(label,1,2,2*ix+1,2*ix+2,xpadding=24)
|
2004-07-09 23:49:47 +05:30
|
|
|
|
|
|
|
box.add(table)
|
|
|
|
box.show_all()
|
2004-07-11 11:33:07 +05:30
|
|
|
p.connect('next',self.build_options)
|
2004-07-09 23:49:47 +05:30
|
|
|
return p
|
|
|
|
|
2004-07-11 11:33:07 +05:30
|
|
|
def build_options(self,obj,obj2):
|
2004-07-13 02:59:15 +05:30
|
|
|
"""
|
|
|
|
Build an extra page with the options specific for the chosen format.
|
|
|
|
If there's already a page (or pages) for this format in
|
|
|
|
self.empty_pages then do nothing, otherwise add a page.
|
|
|
|
|
|
|
|
If the chosen format does not have options then remove all
|
|
|
|
extra pages that are already there (from previous user passes
|
|
|
|
through the druid).
|
|
|
|
"""
|
2004-07-11 11:33:07 +05:30
|
|
|
ix = self.get_selected_format_index()
|
|
|
|
if self.exports[ix][3]:
|
|
|
|
title = self.exports[ix][3][0]
|
2004-07-13 02:59:15 +05:30
|
|
|
for (ep_ix,ep) in self.extra_pages:
|
|
|
|
if ep_ix == ix:
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
ep.destroy()
|
|
|
|
self.extra_pages.remove((ep_ix,ep))
|
|
|
|
|
2004-07-11 11:33:07 +05:30
|
|
|
option_box_class = self.exports[ix][3][1]
|
|
|
|
self.option_box_instance = option_box_class(self.person)
|
|
|
|
|
|
|
|
p = gnome.ui.DruidPageStandard()
|
|
|
|
p.set_title(title)
|
|
|
|
p.set_title_foreground(self.fg_color)
|
|
|
|
p.set_background(self.bg_color)
|
|
|
|
p.set_logo(self.logo)
|
|
|
|
p.append_item("",self.option_box_instance.get_option_box(),"")
|
2004-07-13 02:59:15 +05:30
|
|
|
self.extra_pages.append((ix,p))
|
2004-07-11 11:33:07 +05:30
|
|
|
self.d.insert_page(self.file_sel_page,p)
|
|
|
|
p.show_all()
|
2004-07-13 02:59:15 +05:30
|
|
|
else:
|
|
|
|
for (ep_ix,ep) in self.extra_pages:
|
|
|
|
ep.destroy()
|
|
|
|
self.extra_pages = []
|
2004-07-11 11:33:07 +05:30
|
|
|
|
2004-07-09 23:49:47 +05:30
|
|
|
def build_file_sel_page(self):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Build a druid page embedding the FileChooserWidget.
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
p = gnome.ui.DruidPageStandard()
|
|
|
|
p.set_title(_('Selecting the file name'))
|
|
|
|
p.set_title_foreground(self.fg_color)
|
|
|
|
p.set_background(self.bg_color)
|
|
|
|
p.set_logo(self.logo)
|
|
|
|
|
|
|
|
self.chooser = gtk.FileChooserWidget(gtk.FILE_CHOOSER_ACTION_SAVE)
|
|
|
|
p.append_item("",self.chooser,"")
|
2004-07-13 19:17:37 +05:30
|
|
|
# Dirty hack to enable proper EXPAND and FILL properties of the chooser
|
|
|
|
parent = self.chooser.get_parent()
|
|
|
|
parent.set_child_packing(self.chooser,1,1,0,gtk.PACK_START)
|
|
|
|
gradnparent = parent.get_parent()
|
|
|
|
gradnparent.set_child_packing(parent,1,1,0,gtk.PACK_START)
|
2004-07-11 05:01:28 +05:30
|
|
|
p.connect('prepare',self.suggest_filename)
|
2004-07-09 23:49:47 +05:30
|
|
|
return p
|
|
|
|
|
2004-07-11 05:01:28 +05:30
|
|
|
def suggest_filename(self,obj,obj2):
|
|
|
|
"""
|
|
|
|
Prepare suggested filename and set it in the file chooser.
|
|
|
|
"""
|
|
|
|
ix = self.get_selected_format_index()
|
|
|
|
ext = self.exports[ix][4]
|
|
|
|
if ext == 'gramps':
|
|
|
|
new_filename = os.path.expanduser('~/data.gramps')
|
|
|
|
else:
|
|
|
|
new_filename = Utils.get_new_filename(ext)
|
|
|
|
self.chooser.set_filename(new_filename)
|
|
|
|
self.chooser.set_current_name(os.path.split(new_filename)[1])
|
|
|
|
|
|
|
|
def get_selected_format_index(self):
|
|
|
|
"""
|
|
|
|
Query the format radiobuttons and return the index number
|
|
|
|
of the selected one.
|
|
|
|
"""
|
|
|
|
for ix in range(len(self.format_buttons)):
|
|
|
|
button = self.format_buttons[ix]
|
|
|
|
if button.get_active():
|
|
|
|
return ix
|
|
|
|
else:
|
|
|
|
return 0
|
|
|
|
|
2004-07-11 11:33:07 +05:30
|
|
|
def native_export(self,database,filename,person):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
Native database export. For now, just stupid copying of the present
|
|
|
|
grdb file under another name. In the future, filter and other
|
|
|
|
options may be added.
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
try:
|
|
|
|
shutil.copyfile(database.get_save_path(),filename)
|
|
|
|
return 1
|
|
|
|
except IOError, msg:
|
|
|
|
QuestionDialog.ErrorDialog( _("Could not write file: %s") % filename,
|
|
|
|
_('System message was: %s') % msg )
|
|
|
|
return 0
|
|
|
|
|
|
|
|
def build_exports(self):
|
2004-07-11 05:01:28 +05:30
|
|
|
"""
|
|
|
|
This method builds its own list of available exports.
|
|
|
|
The list is built from the Plugins._exports list
|
|
|
|
and from the locally defined exports (i.e. native export defined here).
|
|
|
|
"""
|
2004-07-09 23:49:47 +05:30
|
|
|
native_title = _('GRAMPS _GRDB database')
|
|
|
|
native_description =_('The GRAMPS GRDB database is a format '
|
|
|
|
'that GRAMPS uses to store information. '
|
|
|
|
'Selecting this option will allow you to '
|
|
|
|
'make a copy of the current database.')
|
|
|
|
native_config = None
|
|
|
|
native_ext = 'grdb'
|
|
|
|
native_export = self.native_export
|
|
|
|
|
|
|
|
self.exports = [ (native_export,native_title,native_description,
|
|
|
|
native_config,native_ext) ]
|
|
|
|
self.exports = self.exports + [ item for item in Plugins._exports ]
|