start work on new export manager

svn: r8834
This commit is contained in:
Benny Malengier 2007-08-18 21:13:30 +00:00
parent 1d65909cef
commit c0f14c9070
6 changed files with 444 additions and 10 deletions

View File

@ -1,3 +1,10 @@
2007-08-18 Benny Malengier <bm@cage.ugent.be>
* src/ExportAssistant.py: begin of new export manager based on gtk.Assistant...
* src/ManagedWindow.py : allow a gtk.Window to be a ManagedWindow itself
* src/ViewManager.py : temporarily hook calling new export assistant
* src/Makefile.am : Add ExportAssistant.py
* po/POTFILES.in : Add ExportAssistant.py
2007-08-18 Brian Matherly <brian@gramps-project.org>
* src/plugins/KinshipReport.py: Add kinship report
* src/plugins/Makefile.am: Add KinshipReport.py

View File

@ -19,6 +19,7 @@ src/DbManager.py
src/DdTargets.py
src/DisplayState.py
src/Errors.py
src/ExportAssistant.py
src/Exporter.py
src/FontScale.py
src/GrampsCfg.py

376
src/ExportAssistant.py Normal file
View File

@ -0,0 +1,376 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2004-2007 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Written by B.Malengier
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
import os
import sys
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
log = logging.getLogger(".ExportAssistant")
#-------------------------------------------------------------------------
#
# Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import const
import Config
from PluginUtils import export_list
import Utils
import ManagedWindow
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
_gramps_png = os.path.join(const.image_dir,"gramps.png")
_splash_jpg = os.path.join(const.image_dir,"splash.jpg")
#-------------------------------------------------------------------------
#
# ExportAssistant
#
#-------------------------------------------------------------------------
class ExportAssistant(gtk.Assistant, ManagedWindow.ManagedWindow) :
"""
This class creates a GTK assistant 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 assistant page.
The export formats and options are obtained from the plugins
"""
__gsignals__ = {"apply": "override", "cancel": "override",
"close": "override", "prepare": "override"}
def __init__(self,dbstate,uistate):
"""
Set up the assistant, and build all the possible assistant pages.
Some page elements are left empty, since their contents depends
on the user choices and on the success of the attempted save.
"""
self.dbstate = dbstate
self.uistate = uistate
#set up Assisant
gtk.Assistant.__init__(self)
self.set_title('test')
#set up ManagedWindow
self.top_title = _("Export Assistant")
ManagedWindow.ManagedWindow.__init__(self,uistate,[],
self.__class__)
self.set_window(self, None, self.top_title, isWindow=True)
if self.dbstate.active:
self.person = self.dbstate.get_active_person()
else:
self.person = self.dbstate.db.find_initial_person()
self.logo = gtk.gdk.pixbuf_new_from_file(_gramps_png)
self.splash = gtk.gdk.pixbuf_new_from_file(_splash_jpg)
self.obtain_export_formats()
self.previous_page = -1
#create the assistant pages
self.create_page_intro()
self.create_page_exporttypes()
self.create_page_options()
self.create_page_fileselect()
self.create_page_confirm()
self.create_page_progress()
self.create_page_summary()
#ManagedWindow show method
ManagedWindow.ManagedWindow.show(self)
def build_menu_names(self,obj):
''' Override ManagedWindow method
'''
return (self.top_title, None)
def create_page_intro(self):
''' Create the introduction page
'''
label = gtk.Label(self.get_intro_text())
label.set_line_wrap(True)
label.set_use_markup(True)
page = label
page.show_all()
self.append_page(page)
self.set_page_header_image(page, self.logo)
self.set_page_side_image(page, self.splash)
self.set_page_title(page, _('Saving your data'))
self.set_page_complete(page, True)
self.set_page_type(page, gtk.ASSISTANT_PAGE_INTRO)
def create_page_exporttypes(self):
''' Create the export type page
A Title label
A table of format radio buttons and their descriptions.
'''
self.format_buttons = []
box = gtk.VBox()
box.set_border_width(12)
box.set_spacing(12)
table = gtk.Table(2*len(self.exportformats),2)
table.set_row_spacings(6)
table.set_col_spacings(6)
tip = gtk.Tooltips()
group = None
for ix in range(len(self.exportformats)):
title = self.exportformats[ix][1]
description= self.exportformats[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)
tip.set_tip(button,description)
box.add(table)
page = box
page.show_all()
self.append_page(page)
self.set_page_header_image(page, self.logo)
self.set_page_title(page, _('Choose the format you want to export to'))
#there is always one radio button selected
self.set_page_complete(page, True)
self.set_page_type(page, gtk.ASSISTANT_PAGE_CONTENT)
def create_page_options(self):
pass
def create_page_fileselect(self):
self.chooser = gtk.FileChooserWidget(gtk.FILE_CHOOSER_ACTION_SAVE)
#add border
self.chooser.set_border_width(12)
#global files, ask before overwrite
self.chooser.set_local_only(False)
self.chooser.set_do_overwrite_confirmation(True)
folder, name = self.suggest_filename()
self.chooser.set_current_folder(folder)
self.chooser.set_current_name(name)
#connect changes in filechooser with check to mark page complete
self.chooser.connect("selection-changed", self.check_fileselect)
self.chooser.connect("key-release-event", self.check_fileselect)
#first selection does not give a selection-changed event, grab the button
self.chooser.connect("button-release-event", self.check_fileselect)
#Note, we can induce an exotic error, delete filename,
# do not release button, click forward. We expect user not to do this
# In case he does, recheck on confirmation page!
self.chooser.show_all()
page = self.chooser
self.append_page(page)
self.set_page_header_image(page, self.logo)
self.set_page_title(page, _('Select Save File'))
#see if page can be set as complete :
self.check_fileselect(page)
self.set_page_type(page, gtk.ASSISTANT_PAGE_CONTENT)
def check_fileselect(self, filechooser, event=None):
''' Given a filechooser, determine if it can be marked complete
in the Assistant
Used as normal callback and event callback.
'''
filename = filechooser.get_filename()
folder = filechooser.get_current_folder()
#the file must be valid, not a folder, and folder must be valid
if filename and filename.strip and Utils.find_folder(filename) == '' \
and folder and Utils.find_folder(folder):
#this page of the assistant is complete
self.set_page_complete(filechooser, True)
else :
self.set_page_complete(filechooser, False)
def create_page_confirm(self):
pass
def create_page_progress(self):
pass
def create_page_summary(self):
# Construct summary page
# As this is the last page needs to be of page_type
# gtk.ASSISTANT_PAGE_CONFIRM or gtk.ASSISTANT_PAGE_SUMMARY
label = gtk.Label('Thanks for using our Export Assistant!')
label.set_line_wrap(True)
label.set_use_markup(True)
label.show()
page = label
self.append_page(page)
self.set_page_header_image(page, self.logo)
self.set_page_title(page, _('Summary'))
self.set_page_side_image(page, self.splash)
self.set_page_type(page, gtk.ASSISTANT_PAGE_SUMMARY)
def do_apply(self):
pass
def do_cancel(self):
self.close()
def do_close(self):
self.close()
def do_prepare(self, page):
# prepare the next page, page_number is page we are on now
page_number = self.get_current_page()
page = self.get_nth_page(page_number)
if page_number == 1 :
# store the selected export type:
self.exporttype = self.get_selected_format_index()
# create the correct option page:
elif self.get_page_type(page) == gtk.ASSISTANT_PAGE_SUMMARY :
# The summary page, update the label and title
#determine success
success = True
if success:
conclusion_title = _('Your data has been saved')
conclusion_text = _(
'The copy of your data has been '
'successfully saved. You may press OK button '
'now to continue.\n\n'
'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. ')
#add test, what is dir
conclusion_text += '\n\n' + self.chooser.get_filename()
else:
conclusion_title = _('Saving failed'),
conclusion_text = _(
'There was an error while saving your data. '
'You may try starting the export again.\n\n'
'Note: your currently opened database is safe. '
'It was only '
'a copy of your data that failed to save.')
page.set_label(conclusion_text)
self.set_page_title(page, conclusion_title)
#remember the previous page
self.__previous_page = page_number
def close(self, *obj) :
#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 PluginMgr.export_list list
and from the locally defined exports (i.e. native export defined here).
"""
self.exportformats = [item for item in 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 '
'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 transfer it to a different program.\n\n'
'If you change your mind during this process, you '
'can safely press the Cancel button at any time and your '
'present database will still be intact.')
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
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]
# Suggested folder: try last export, then last import, then home.
default_dir = Config.get(Config.RECENT_EXPORT_DIR)
if len(default_dir)<=1:
default_dir = Config.get(Config.RECENT_IMPORT_DIR)
if len(default_dir)<=1:
default_dir = const.user_home
if ext == 'gramps':
new_filename = os.path.join(default_dir,'data.gramps')
elif ext == 'burn':
new_filename = os.path.basename(self.dbstate.db.get_save_path())
else:
new_filename = Utils.get_new_filename(ext,default_dir)
return (default_dir, os.path.split(new_filename)[1])

View File

@ -48,6 +48,7 @@ gdir_PYTHON = \
DdTargets.py\
DisplayState.py\
Errors.py\
ExportAssistant.py\
Exporter.py\
FontScale.py\
GrampsCfg.py\

View File

@ -310,6 +310,14 @@ class ManagedWindow:
# Proceed with the class.
...
@param uistate gramps uistate
@param track {list of parent windows, [] if the main GRAMPS window
is the parent}
@param obj The object that is used to id the managed window,
The inheriting object needs a method build_menu_names(self,obj)
which works on this obj and creates menu labels
"""
window_key = self.build_window_key(obj)
menu_label, submenu_label = self.build_menu_names(obj)
@ -345,10 +353,30 @@ class ManagedWindow:
# On the top level: we use gramps top window
self.parent_window = self.uistate.window
def set_window(self, window, title, text, msg=None):
set_titles(window, title, text, msg)
self.window = window
self.window.connect('delete-event', self.close)
def set_window(self, window, title, text, msg=None, isWindow=False):
'''
Set the window that is managed.
@param window if isWindow=False window must be a gtk.Window() object, otherwise None
@param title a label widget in which to write the title, None if not needed
@param text text to use as title of window and in title param
@param msg if not None, use msg as title of window instead of text
@param isWindow {if isWindow than self is the window
(so self inherits from gtk.Window and
from ManagedWindow.ManagedWindow)
if not isWindow, than window is the Window to manage,
and after this method self.window stores it.
}
'''
self.isWindow = isWindow
if self.isWindow :
set_titles(self, title, text, msg)
else :
set_titles(window, title, text, msg)
#closing the gtk.Window must also close ManagedWindow
self.window = window
self.window.connect('delete-event', self.close)
def build_menu_names(self, obj):
return ('Undefined Menu','Undefined Submenu')
@ -371,10 +399,16 @@ class ManagedWindow:
self.get_widget(button_name).connect('clicked', function)
def show(self):
assert self.window, "ManagedWindow: self.window does not exist!"
self.window.set_transient_for(self.parent_window)
self.opened = True
self.window.show_all()
if self.isWindow :
self.set_transient_for(self.parent_window)
self.opened = True
self.show_all()
else :
assert self.window, "ManagedWindow: self.window does not exist!"
self.window.set_transient_for(self.parent_window)
self.opened = True
self.window.show_all()
def close(self, *obj):
"""
@ -390,8 +424,11 @@ class ManagedWindow:
"""
Present window (unroll/unminimize/bring to top).
"""
assert self.window, "ManagedWindow: self.window does not exist!"
self.window.present()
if self.isWindow :
self.present(self)
else :
assert self.window, "ManagedWindow: self.window does not exist!"
self.window.present()
#-------------------------------------------------------------------------
#

View File

@ -110,6 +110,7 @@ UIDEFAULT = '''<ui>
<separator/>
<menuitem action="Import"/>
<menuitem action="Export"/>
<menuitem action="ExportNew"/>
<placeholder name="LocalExport"/>
<separator/>
<menuitem action="Abandon"/>
@ -362,6 +363,8 @@ class ViewManager:
None, self.save_as_activate),
('Export', 'gramps-export', _('_Export'), "<control>e", None,
self.export_data),
('ExportNew', 'gramps-export', _('_ExportNew'), None, None,
self.exportnew_data),
('Abandon', gtk.STOCK_REVERT_TO_SAVED,
_('_Abandon changes and quit'), None, None, self.abort),
('Reports', 'gramps-reports', _('_Reports'), None,
@ -1187,6 +1190,15 @@ class ViewManager:
import Exporter
Exporter.Exporter(self.state, self.uistate)
def exportnew_data(self, obj):
if self.state.db.db_is_open:
import ExportAssistant
try:
ExportAssistant.ExportAssistant(self.state, self.uistate)
except Errors.WindowActiveError:
return
def rebuild_report_and_tool_menus(self, tool_list, report_list):
self.build_tools_menu(tool_list)
self.build_report_menu(report_list)