Merge REP_OPT branch

svn: r3827
This commit is contained in:
Alex Roitman 2004-12-22 01:56:37 +00:00
parent c9e6a13a3d
commit a4f9849e8f
17 changed files with 2025 additions and 903 deletions

View File

@ -2,6 +2,33 @@
* src/docgen/AsciiDoc.py (reformat_para): Correctly check for
empty paragraph.
* src/ArgHandler.py: Pass category on to CL task.
* src/Report.py: Handle showing options centrally.
* src/plugins/BookReport.py: Handle showing options centrally.
* src/plugins/TimeLine.py: Handle showing options centrally.
* src/plugins/FtmStyleDescendants.py: Handle showing options centrally.
* various: Merge REP_OPT branch with HEAD.
2004-12-20 Alex Roitman <shura@alex.neuro.umn.edu>
* src/ArgHandler.py: Single out Book by category.
* src/Plugins.py: Use category to register cl report.
* src/Report.py: Support template; make template file selector modal;
change key for orientation.
* src/ReportOptions.py: Add get/save template support.
* src/plugins/BookReport.py: Reinstate command line mode.
* src/plugins/TimeLine.py: Clean up; add docstrings;
avoid possible conflicts with dialog's contents.
* src/plugins/FtmStyleDescendants.py: Convert to present scheme.
* src/ArgHandler.py: Remove name and category from options.
* src/Plugins.py: Remove name and category from options.
* src/Report.py: Remove name and category from options.
* src/gramps_main.py: Remove name and category from options.
* src/plugins/BookReport.py: Remove name and category from options.
* src/plugins/TimeLine.py: Remove name and category from options.
* src/plugins/FtmStyleDescendants.py: Remove name and category.
2004-12-19 Don Allingham <dallingham@users.sourceforge.net>
* src/DbPrompter.py: Add display messages during load
* src/GrampsBSDDB.py: Add display messages during load
@ -19,10 +46,46 @@
* src/gramps.glade: use gramps.png for loading message window
* src/gramps_main.py: remove delete_abandoned_photos calls
2004-12-19 Alex Roitman <shura@alex.neuro.umn.edu>
* src/ArgHandler.py: Switch to generic task CL function.
* src/Plugins.py: Change registration to use generic task functions.
* src/Report.py (report,write_book_item,cl_report): Add generic
functions.
* src/ReportOptions.py: Move doc-related options into OptionHandler.
* src/gramps_main.py (menu_report): Call report using new registration.
* src/plugins/BookReport.py: Use generic function for writing items.
* src/plugins/TimeLine.py: Use generic functions for all three modes.
2004-12-18 Alex Roitman <shura@alex.neuro.umn.edu>
* src/Report.py (BareReportDialog.__init__): Instantiate or assign
option_class, depending on the type.
2004-12-17 Alex Roitman <shura@alex.neuro.umn.edu>
* src/const.py.in: Add category-related constants.
* src/Plugins.py: Provide single registration for all report flavors.
* src/Report.py: Use new categories; serve the semi-common options.
* src/docgen/LPRDoc.py: Register "print" name with book and text.
* src/plugins/BookReport.py: Use single registration.
* src/plugins/FtmStyleDescendants.py: Properly use semi-common
options; Use correct id-search; Use single registration.
* src/plugins/TimeLine.py: Properly use semi-common options;
Use correct id-search; Use single registration.
* src/Report.py: Use orientation option. Allow writing book from cl.
* src/plugins/BookReport.py: Support for writing book from cl.
2004-12-16 Don Allingham <dallingham@users.sourceforge.net>
* src/PeopleModel.py: Fixed rebuild_display
* src/ReadXML.py: Fixed calendar handling
2004-12-16 Alex Roitman <shura@alex.neuro.umn.edu>
* src/Report.py: Fixes related to filter and max_gen/page_breaks --
the semi-common options.
* src/ReportOptions.py: Fixes related to filter.
* src/plugins/FtmStyleDescendants.py: Convert to new scheme.
* src/plugins/TimeLine.py: Transfer filter to this report for the
time being.
2004-12-16 Julio Sanchez <julio.sanchez@gmail.com>
* src/po/es.po: forward port of the Spanish translations in STABLE,
plus many new translations
@ -36,9 +99,38 @@
starting from the French version
* src/dates/Makefile.am: include Spanish date handler
2004-12-15 Alex Roitman <shura@alex.neuro.umn.edu>
* src/Plugins.py: Minor.
* src/Report.py: Numerous fixes of running/destroying dialogs;
Document report-specific options in Command Line.
* src/StyleEditor.py: Take care of modal dialog.
* src/gramps.glade: Take care of modal dialog.
* src/docgen/LPRDoc.py: Register with "print" name.
* src/plugins/BookReport.py: Numerous dialog fixes.
* src/plugins/TimeLine.py: Document report-specific options in CL.
* src/Plugins.py: Remove unneeded registration item.
* src/ReportOptions.py: Re-work generations/pagebreak options.
* src/Utils.py (get_type_converter_by_name,type_name):
Add functions.
* src/plugins/BookReport.py: Convert open/save to new system.
* src/plugins/TimeLine.py: Correct generations/pagebreak and
registration.
2004-12-14 Alex Roitman <shura@alex.neuro.umn.edu>
* src/Report.py: Self-documenting common options.
* src/ReportOptions.py: Minor fixes.
* src/plugins/BookReport.py: Minor fixes.
* src/plugins/TimeLine.py: Commnad line and options fixes.
2004-12-13 Tim Waugh <twaugh@redhat.com>
* src/plugins/Ancestors.py (generation): Avoid empty sections.
2004-12-13 Alex Roitman <shura@alex.neuro.umn.edu>
* src/ArgHandler.py: Minor improvements.
* src/Report.py: Add Command Line class.
* src/plugins/TimeLine.py: Factor out Command line class.
2004-12-09 Don Allingham <dallingham@users.sourceforge.net>
* src/GrampsBSDDB.py: add cursor routines
* src/GrampsDbBase.py: add cursor routines
@ -63,9 +155,17 @@
2004-12-07 Alex Roitman <shura@alex.neuro.umn.edu>
* src/data/Makefile.am: Replace dist_data_DATA with EXTRA_DIST.
* src/plugins/TimeLine.py: Get rid of dialog classes.
* src/plugins/BookReport.py: Minor fixes (still semi-broken).
* src/Report.py: Make dialogs modal.
2004-12-06 Alex Roitman <shura@alex.neuro.umn.edu>
* configure.in: bump up the version.
* src/plugins/TimeLine.py: Start Grand Report Unification.
* src/plugins/BookReport.py: Start Grand Report Unification.
* src/Report.py: Start Grand Report Unification.
2004-12-06 Don Allingham <dallingham@users.sourceforge.net>
* NEWS: minor update for 1.1.2 release
* Release: Version 1.1.2 "Confuse-a-cat" released.
@ -103,6 +203,14 @@
* src/gramps.glade: fixed spacing in message
* src/gramps_main.py: add disconnected filter
2004-12-03 Alex Roitman <shura@alex.neuro.umn.edu>
* src/ArgHandler.py: Minor.
* src/Plugins.py: Add clname to all report registrations.
* src/Report.py: Correct save_options order.
* src/Sort.py: Correct date comparison.
* src/Utils.py (get_type_converter): Correct type comparisons.
* src/plugins/TimeLine.py: Clean up command-line support.
2004-12-02 Don Allingham <dallingham@users.sourceforge.net>
* src/EditPerson.py: hide window while closing updating info
* src/FamilyView.py: Fix deleting of spouses and children
@ -111,9 +219,19 @@
* src/PeopleView.py: text clean up
* src/gramps_main.py: disable buttons while deleting a person
* src/plugins/TimeLine.py: Start on the command-line support.
* src/Plugins.py: Command line report registration.
* src/ArgHandler.py: Command line support.
* src/const.py.in: Add options for command line support.
2004-12-01 Alex Roitman <shura@alex.neuro.umn.edu>
* src/Report.py (on_center_person_change_clicked): Typo.
* src/plugins/TimeLine.py: Tweak to finish book support.
* src/plugins/BookReport.py: Fully support options.
* src/ReportOptions.py: Finish book support.
* src/Report.py: Finish book support.
2004-12-01 Don Allingham <dallingham@users.sourceforge.net>
* src/GenericFilter.py: use DateParser to parse dates.
@ -130,6 +248,12 @@
bug by using horrible and ugly hack; (build_backhistmenu,
build_fwdhistmenu): Use gramps IDs instead of handles in menus.
* src/plugins/TimeLine.py: Finish up describing arguments in
the doc string. Start working with Book item stuff -- still broken.
* src/plugins/BookReport.py: Start using new report options.
* src/ReportOptions.py: Add some book support.
* src/Report.py: Modify to support book.
2004-11-29 Don Allingham <dallingham@users.sourceforge.net>
* src/EditPerson.py: simpler way of handling patronymic names
based of LANG
@ -142,6 +266,10 @@
* src/DbPrompter.py (open_native): Add function.
* src/RecentFiles.py (remove_filename): Add function.
2004-11-28 Eero Tamminen <eerot@sf>
* src/plugins/TimeLine.py: put the TimeLine init var descriptions
into correct order in comments
2004-11-28 Alex Roitman <shura@alex.neuro.umn.edu>
* src/plugins/PatchNames.py: Typo.
* src/plugins/ChangeNames.py: Correct description.
@ -191,6 +319,15 @@
* src/DbPrompter.py: Support for recent-files.
* src/ArgHandler.py: Support for recent-files.
* src/Plugins.py: Add support for setting active menu element
in the doc menus.
* src/PaperMenu.py: Add name-based support for paper menu
selection. Fix orientation selection.
* src/Report.py: Add support paper, orientation, and style
persistent options.
* src/ReportOptions.py: Add support paper, orientation, and style
persistent options.
2004-11-24 Don Allingham <dallingham@users.sourceforge.net>
* src/GrampsDbBase.py: always use external thumbnails
* src/GrampsBSDDB.py: always use external thumbnails
@ -216,6 +353,16 @@
* src/RelLib.py: add support for Source key,value pairs
* src/gramps.glade: add support for Source key,value pairs
2004-11-22 Alex Roitman <shura@alex.neuro.umn.edu>
* src/ReportOptions.py: Add support for last-common options.
Move common defaults from OptionList to OptionListCollection. Adjust
parsing and saving of collection accordingly. Add OptionHandler()
class to support most of the common functionality across plugins.
* src/Report.py: Use new class for setting/getting options.
* src/plugins/TimeLine.py: Simplify the options class, since most
of the functionality is moved into ReportOptions.OptionHandler().
* src/Utils.py (get_type_converter): Add function.
2004-11-20 Don Allingham <dallingham@users.sourceforge.net>
* src/plugins/ChangeNames.py: Add a plugin to change capitalization
of family names
@ -440,6 +587,16 @@
2004-10-21 Don Allingham <dallingham@users.sourceforge.net>
* src/DateParser.py: fix dates of the format of JAN 2000
2004-10-21 Alex Roitman <shura@alex.neuro.umn.edu>
* src/ReportOptions.py: Add to CVS.
* src/Makefile.am: Shipt ReportOptions.py.
* src/Plugins.py: Change registration for book items.
* src/Report.py: Use new option class.
* src/Utils.py: Move pt2cm() here.
* src/const.py.in: Define report options XML filename.
* src/plugins/TimeLine.py: Use new class separation scheme.
* src/plugins/BookReport.py: Use new class separation scheme.
2004-10-19 Don Allingham <dallingham@users.sourceforge.net>
* src/GrampsCfg.py: eliminate unused options
* src/gramps.glade: eliminate unused options

View File

@ -48,6 +48,8 @@ import DbPrompter
import QuestionDialog
import GrampsGconfKeys
import RecentFiles
import Plugins
import Report
#-------------------------------------------------------------------------
#
@ -174,10 +176,14 @@ class ArgHandler:
self.exports.append((outfname,outformat))
elif o in ( '-a', '--action' ):
action = v
if action not in ( 'check', 'summary' ):
if action not in ( 'check', 'summary', 'report' ):
print "Unknown action: %s. Ignoring." % action
continue
self.actions.append(action)
options_str = ""
if opt_ix<len(options)-1 \
and options[opt_ix+1][0] in ( '-p', '--options' ):
options_str = options[opt_ix+1][1]
self.actions.append((action,options_str))
#-------------------------------------------------------------------------
#
@ -304,9 +310,11 @@ class ArgHandler:
print "Exporting: file %s, format %s." % expt
self.cl_export(expt[0],expt[1])
for action in self.actions:
for (action,options_str) in self.actions:
print "Performing action: %s." % action
self.cl_action(action)
if options_str:
print "Using options string: %s" % options_str
self.cl_action(action,options_str)
print "Cleaning up."
# remove import db after use
@ -489,7 +497,7 @@ class ArgHandler:
# Action handler
#
#-------------------------------------------------------------------------
def cl_action(self,action):
def cl_action(self,action,options_str):
"""
Command-line action routine. Try to perform specified action.
Any errors will cause the os._exit(1) call.
@ -508,6 +516,36 @@ class ArgHandler:
import Summary
text = Summary.build_report(self.parent.db,None)
print text
elif action == "report":
try:
options_str_dict = dict( [ tuple(chunk.split('='))
for chunk in options_str.split(',') ] )
except:
options_str_dict = {}
print "Ignoring invalid options string."
name = options_str_dict.pop('name',None)
if not name:
print "Report name not given. Please use name=reportname"
os._exit(1)
found = False
for item in Plugins._cl:
if name == item[0]:
category = item[1]
report_class = item[2]
options_class = item[3]
if category == const.CATEGORY_BOOK:
options_class(self.parent.db,name,category,options_str_dict)
else:
Report.cl_report(self.parent.db,name,category,
report_class,options_class,options_str_dict)
found = True
return
print "Unknown report name. Available names are:"
for item in Plugins._cl:
print " %s" % item[0]
else:
print "Unknown action: %s." % action
os._exit(1)

View File

@ -106,7 +106,8 @@ gdir_PYTHON = \
ArgHandler.py\
Exporter.py\
GrampsGconfKeys.py\
RecentFiles.py
RecentFiles.py\
ReportOptions.py
# Could use GNU make's ':=' syntax for nice wildcard use.
# If not using GNU make, then list all files individually

View File

@ -1,7 +1,7 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2003 Donald N. Allingham
# Copyright (C) 2000-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
@ -18,6 +18,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GNOME modules
@ -65,6 +67,7 @@ def make_paper_menu(main_menu,default=""):
name = paper.get_name()
menuitem = gtk.MenuItem(name)
menuitem.set_data("i",paper)
menuitem.set_data("label",name)
menuitem.show()
myMenu.append(menuitem)
if default == name:
@ -83,22 +86,23 @@ def make_orientation_menu(main_menu,value=0):
menuitem = gtk.MenuItem(_("Portrait"))
menuitem.set_data("i",BaseDoc.PAPER_PORTRAIT)
menuitem.show()
if value == BaseDoc.PAPER_PORTRAIT:
menuitem.select()
myMenu.append(menuitem)
menuitem = gtk.MenuItem(_("Landscape"))
menuitem.set_data("i",BaseDoc.PAPER_LANDSCAPE)
menuitem.show()
if value == BaseDoc.PAPER_LANDSCAPE:
menuitem.select()
myMenu.append(menuitem)
if value == BaseDoc.PAPER_PORTRAIT:
myMenu.set_active(0)
elif value == BaseDoc.PAPER_LANDSCAPE:
myMenu.set_active(1)
main_menu.set_menu(myMenu)
#-------------------------------------------------------------------------
#
# FilterParser
# PageSizeParser
#
#-------------------------------------------------------------------------
class PageSizeParser(handler.ContentHandler):

View File

@ -48,6 +48,7 @@ import os
import sys
import string
from re import compile
from gettext import gettext as _
#-------------------------------------------------------------------------
#
@ -58,10 +59,7 @@ import const
import Utils
import GrampsGconfKeys
import Errors
import gettext
_ = gettext.gettext
import Report
#-------------------------------------------------------------------------
#
@ -81,6 +79,7 @@ _bookdoc = []
_drawdoc = []
_failmsg = []
_bkitems = []
_cl = []
_status_up = None
#-------------------------------------------------------------------------
@ -529,23 +528,6 @@ def register_import(task, ffilter, mime=None, native_format=0):
if mime:
_imports.append((task, ffilter, mime, native_format))
def register_report(task, name,
category=_("Uncategorized"),
description=_unavailable,
status=_("Unknown"),
author_name=_("Unknown"),
author_email=_("Unknown")
):
"""Register a report with the plugin system"""
del_index = -1
for i in range(0,len(_reports)):
val = _reports[i]
if val[2] == name:
del_index = i
if del_index != -1:
del _reports[del_index]
_reports.append((task, category, name, description, status, author_name, author_email))
def register_tool(task, name,
category=_("Uncategorized"),
@ -566,41 +548,122 @@ def register_tool(task, name,
#-------------------------------------------------------------------------
#
# Text document registration
# Report registration
#
#-------------------------------------------------------------------------
def register_report(
name,
category,
report_class,
options_class,
modes,
translated_name,
status=_("Unknown"),
description=_unavailable,
author_name=_("Unknown"),
author_email=_("Unknown")
):
"""
Registers report for all possible flavors.
This function should be used to register report as a stand-alone,
book item, or command-line flavor in any combination of those.
The low-level functions (starting with '_') should not be used
on their own. Instead, this function will call them as needed.
"""
(junk,standalone_task) = divmod(modes,2**Report.MODE_GUI)
if standalone_task:
_register_standalone(report_class,options_class,translated_name,
category,description,
status,author_name,author_email)
(junk,book_item_task) = divmod(modes-standalone_task,2**Report.MODE_BKI)
if book_item_task:
book_item_category = const.book_categories[category]
_register_book_item(translated_name,book_item_category,
report_class,options_class,name)
(junk,command_line_task) = divmod(modes-standalone_task-book_item_task,
2**Report.MODE_CLI)
if command_line_task:
_register_cl_report(name,category,report_class,options_class)
def _register_standalone(report_class, options_class, name,
category=_("Uncategorized"),
description=_unavailable,
status=_("Unknown"),
author_name=_("Unknown"),
author_email=_("Unknown")
):
"""Register a report with the plugin system"""
del_index = -1
for i in range(0,len(_reports)):
val = _reports[i]
if val[2] == name:
del_index = i
if del_index != -1:
del _reports[del_index]
_reports.append((report_class, options_class,
category, name, description, status, author_name, author_email))
def _register_book_item(translated_name,category,report_class,option_class,name):
"""Register a book item"""
for n in _bkitems:
if n[0] == name:
return
_bkitems.append((translated_name,category,report_class,option_class,name))
def _register_cl_report(name,category,report_class,options_class):
for n in _cl:
if n[0] == name:
return
_cl.append((name,category,report_class,options_class))
#-------------------------------------------------------------------------
#
# Text document generator registration
#
#-------------------------------------------------------------------------
def register_text_doc(name,classref, table, paper, style, ext,
print_report_label = None):
print_report_label=None,clname=''):
"""Register a text document generator"""
for n in _textdoc:
if n[0] == name:
return
_textdoc.append((name,classref,table,paper,style,ext,print_report_label))
if not clname:
clname = ext[1:]
_textdoc.append((name,classref,table,paper,style,ext,print_report_label,clname))
#-------------------------------------------------------------------------
#
# Text document registration
# Book document generator registration
#
#-------------------------------------------------------------------------
def register_book_doc(name,classref, table, paper, style, ext):
def register_book_doc(name,classref, table, paper, style, ext, clname=''):
"""Register a text document generator"""
for n in _bookdoc:
if n[0] == name:
return
_bookdoc.append((name,classref,table,paper,style,ext))
if not clname:
clname = ext[1:]
_bookdoc.append((name,classref,table,paper,style,ext,clname))
#-------------------------------------------------------------------------
#
# Drawing document registration
# Drawing document generator registration
#
#-------------------------------------------------------------------------
def register_draw_doc(name,classref,paper,style, ext,
print_report_label = None):
print_report_label=None,clname=''):
"""Register a drawing document generator"""
for n in _drawdoc:
if n[0] == name:
return
_drawdoc.append((name,classref,paper,style,ext,print_report_label))
if not clname:
clname = ext[1:]
_drawdoc.append((name,classref,paper,style,ext,print_report_label,clname))
#-------------------------------------------------------------------------
#
@ -621,19 +684,6 @@ def relationship_class(db):
global _relcalc_class
return _relcalc_class(db)
#-------------------------------------------------------------------------
#
# Book item registration
#
#-------------------------------------------------------------------------
def register_book_item(name,category,options_dialog,write_book_item,options,style_name,style_file,make_default_style):
"""Register a book item"""
for n in _bkitems:
if n[0] == name:
return
_bkitems.append((name,category,options_dialog,write_book_item,options,style_name,style_file,make_default_style))
#-------------------------------------------------------------------------
#
# Image attributes
@ -687,7 +737,39 @@ def build_menu(top_menu,list,callback):
#
#-------------------------------------------------------------------------
def build_report_menu(top_menu,callback):
build_menu(top_menu,_reports,callback)
# build_menu(top_menu,_reports,callback)
#def build_menu(top_menu,list,callback):
report_menu = gtk.Menu()
report_menu.show()
hash_data = {}
for report in _reports:
standalone_category = const.standalone_categories[report[2]]
if hash_data.has_key(standalone_category):
hash_data[standalone_category].append(
(report[3],report[0],report[1],report[2]))
else:
hash_data[standalone_category] = [
(report[3],report[0],report[1],report[2])]
catlist = hash_data.keys()
catlist.sort()
for key in catlist:
entry = gtk.MenuItem(key)
entry.show()
report_menu.append(entry)
submenu = gtk.Menu()
submenu.show()
entry.set_submenu(submenu)
lst = hash_data[key]
lst.sort()
for name in lst:
subentry = gtk.MenuItem("%s..." % name[0])
subentry.show()
subentry.connect("activate",callback,Report.report,name[1],name[2],name[3],name[0])
submenu.append(subentry)
top_menu.set_submenu(report_menu)
#-------------------------------------------------------------------------
#
@ -702,16 +784,19 @@ def build_tools_menu(top_menu,callback):
# get_text_doc_menu
#
#-------------------------------------------------------------------------
def get_text_doc_menu(main_menu,tables,callback,obj=None):
def get_text_doc_menu(main_menu,tables,callback,obj=None,active=None):
index = 0
myMenu = gtk.Menu()
_textdoc.sort()
active_found = False
other_active = None
for item in _textdoc:
if tables and item[2] == 0:
continue
name = item[0]
menuitem = gtk.MenuItem(name)
menuitem.set_data("name",item[1])
menuitem.set_data("label",name)
menuitem.set_data("styles",item[4])
menuitem.set_data("paper",item[3])
menuitem.set_data("ext",item[5])
@ -721,28 +806,42 @@ def get_text_doc_menu(main_menu,tables,callback,obj=None):
menuitem.connect("activate",callback)
menuitem.show()
myMenu.append(menuitem)
if name == GrampsGconfKeys.get_output_preference():
if name == active:
myMenu.set_active(index)
callback(menuitem)
if callback:
callback(menuitem)
active_found = True
elif name == GrampsGconfKeys.get_output_preference():
other_active = index
other_item = menuitem
index = index + 1
if other_active and not active_found:
myMenu.set_active(index)
if callback:
callback(other_item)
main_menu.set_menu(myMenu)
#-------------------------------------------------------------------------
#
# get_text_doc_menu
# get_book_menu
#
#-------------------------------------------------------------------------
def get_book_menu(main_menu,tables,callback,obj=None):
def get_book_menu(main_menu,tables,callback,obj=None,active=None):
index = 0
myMenu = gtk.Menu()
_bookdoc.sort()
active_found = False
other_active = None
for item in _bookdoc:
if tables and item[2] == 0:
continue
name = item[0]
menuitem = gtk.MenuItem(name)
menuitem.set_data("name",item[1])
menuitem.set_data("label",name)
menuitem.set_data("styles",item[4])
menuitem.set_data("paper",item[3])
menuitem.set_data("ext",item[5])
@ -751,10 +850,20 @@ def get_book_menu(main_menu,tables,callback,obj=None):
menuitem.connect("activate",callback)
menuitem.show()
myMenu.append(menuitem)
if name == GrampsGconfKeys.get_output_preference():
if name == active:
myMenu.set_active(index)
callback(menuitem)
if callback:
callback(menuitem)
active_found = True
elif name == GrampsGconfKeys.get_output_preference():
other_active = index
other_item = menuitem
index = index + 1
if other_active and not active_found:
myMenu.set_active(index)
if callback:
callback(other_item)
main_menu.set_menu(myMenu)
#-------------------------------------------------------------------------
@ -771,7 +880,7 @@ def get_text_doc_list():
#-------------------------------------------------------------------------
#
# get_text_doc_list
# get_book_doc_list
#
#-------------------------------------------------------------------------
def get_book_doc_list():
@ -799,13 +908,16 @@ def get_draw_doc_list():
# get_draw_doc_menu
#
#-------------------------------------------------------------------------
def get_draw_doc_menu(main_menu,callback=None,obj=None):
def get_draw_doc_menu(main_menu,callback=None,obj=None,active=None):
index = 0
myMenu = gtk.Menu()
for (name,classref,paper,styles,ext,printable) in _drawdoc:
active_found = False
other_active = None
for (name,classref,paper,styles,ext,printable,clname) in _drawdoc:
menuitem = gtk.MenuItem(name)
menuitem.set_data("name",classref)
menuitem.set_data("label",name)
menuitem.set_data("styles",styles)
menuitem.set_data("paper",paper)
menuitem.set_data("ext",ext)
@ -815,11 +927,20 @@ def get_draw_doc_menu(main_menu,callback=None,obj=None):
menuitem.connect("activate",callback)
menuitem.show()
myMenu.append(menuitem)
if name == GrampsGconfKeys.get_goutput_preference():
if name == active:
myMenu.set_active(index)
if callback:
callback(menuitem)
if callback:
callback(menuitem)
active_found = True
elif name == GrampsGconfKeys.get_goutput_preference():
other_active = index
other_item = menuitem
index = index + 1
if other_active and not active_found:
myMenu.set_active(index)
if callback:
callback(other_item)
main_menu.set_menu(myMenu)
#-------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001 David R. Hampton
@ -32,7 +32,8 @@ __version__ = "$Revision$"
#
#-------------------------------------------------------------------------
import os
from gettext import gettext as _
from types import ClassType, InstanceType
#-------------------------------------------------------------------------
#
# GNOME/GTK modules
@ -55,8 +56,8 @@ import BaseDoc
import StyleEditor
import GrampsGconfKeys
import PaperMenu
import Errors
from gettext import gettext as _
from QuestionDialog import ErrorDialog, OptionDialog
#-------------------------------------------------------------------------
@ -71,7 +72,7 @@ except:
#-------------------------------------------------------------------------
#
#
# Constants
#
#-------------------------------------------------------------------------
_default_template = _("Default Template")
@ -81,6 +82,11 @@ _template_map = {
_user_template : None
}
# Modes for generating reports
MODE_GUI = 1 # Standalone report using GUI
MODE_BKI = 2 # Book Item interface using GUI
MODE_CLI = 4 # Command line interface (CLI)
#-------------------------------------------------------------------------
#
# Support for printing generated files
@ -193,16 +199,20 @@ class BareReportDialog:
frame_pad = 5
border_pad = 6
def __init__(self,database,person,options={}):
def __init__(self,database,person,option_class,name):
"""Initialize a dialog to request that the user select options
for a basic *bare* report."""
# Save info about who the report is about.
self.option_store = options
self.style_name = "default"
self.db = database
self.person = person
if type(option_class) == ClassType:
self.options = option_class(name)
elif type(option_class) == InstanceType:
self.options = option_class
self.report_name = name
self.init_interface()
def init_interface(self):
self.output_notebook = None
self.notebook_page = 1
self.pagecount_menu = None
@ -216,22 +226,28 @@ class BareReportDialog:
self.frames = {}
self.format_menu = None
self.style_button = None
self.style_name = self.options.handler.get_default_stylesheet_name()
(self.max_gen,self.page_breaks) = self.options.handler.get_report_generations()
try:
self.local_filters = self.options.get_report_filters(self.person)
except AttributeError:
self.local_filters = []
self.window = gtk.Dialog('GRAMPS')
self.window.set_has_separator(gtk.FALSE)
self.cancel = self.window.add_button(gtk.STOCK_CANCEL,1)
self.ok = self.window.add_button(gtk.STOCK_OK,0)
self.cancel = self.window.add_button(gtk.STOCK_CANCEL,False)
self.ok = self.window.add_button(gtk.STOCK_OK,True)
self.ok.connect('clicked',self.on_ok_clicked)
self.cancel.connect('clicked',self.on_cancel)
self.window.set_response_sensitive(0,gtk.TRUE)
self.window.set_response_sensitive(1,gtk.TRUE)
# self.window.set_response_sensitive(0,gtk.TRUE)
# self.window.set_response_sensitive(1,gtk.TRUE)
self.window.set_resize_mode(0)
# Build the list of widgets that are used to extend the Options
# frame and to create other frames
self.add_user_options()
# Set up and run the dialog. These calls are not in top down
@ -257,14 +273,9 @@ class BareReportDialog:
self.setup_other_frames()
self.window.show_all()
#------------------------------------------------------------------------
#
# Customization hooks for subclasses
#
#------------------------------------------------------------------------
def get_title(self):
"""The window title for this dialog."""
return('')
"""The window title for this dialog"""
return "%s - GRAMPS Book" % self.report_name
def get_header(self, name):
"""The header line to put at the top of the contents of the
@ -272,8 +283,14 @@ class BareReportDialog:
selected person. Most subclasses will customize this to give
some indication of what the report will be, i.e. 'Descendant
Report for %s'."""
return(name)
return _("%(report_name)s for GRAMPS Book") % {
'report_name' : self.report_name}
#------------------------------------------------------------------------
#
# Customization hooks for subclasses
#
#------------------------------------------------------------------------
def get_stylesheet_savefile(self):
"""Where should new styles for this report be saved? This is
the name of an XML file that will be located in the ~/.gramps
@ -325,7 +342,19 @@ class BareReportDialog:
It is called immediately before the window is displayed. All
calls to add_option or add_frame_option should be called in
this task."""
pass
try:
self.options.add_user_options(self)
except AttributeError:
pass
def parse_user_options(self):
"""Called to allow parsing of added widgets.
It is called when OK is pressed in a dialog.
All custom widgets should provide a parsing code here."""
try:
self.options.parse_user_options(self)
except AttributeError:
pass
def add_option(self,label_text,widget,tooltip=None):
"""Takes a text string and a Gtk Widget, and stores them to be
@ -362,16 +391,16 @@ class BareReportDialog:
# Functions to create a default output style.
#
#------------------------------------------------------------------------
def make_default_style(self):
"""Create the default style to be used by the associated report. This
routine is a default implementation and should be overridden."""
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SANS_SERIF,size=16,bold=1)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set_header_level(1)
para.set(pad=0.5)
self.default_style.add_style("Title",para)
# def make_default_style(self):
# """Create the default style to be used by the associated report. This
# routine is a default implementation and should be overridden."""
# font = BaseDoc.FontStyle()
# font.set(face=BaseDoc.FONT_SANS_SERIF,size=16,bold=1)
# para = BaseDoc.ParagraphStyle()
# para.set_font(font)
# para.set_header_level(1)
# para.set(pad=0.5)
# self.default_style.add_style("Title",para)
def build_style_menu(self,default=None):
"""Build a menu of style sets that are available for use in
@ -466,16 +495,17 @@ class BareReportDialog:
# Build the default style set for this report.
self.default_style = BaseDoc.StyleSheet()
self.make_default_style()
self.options.make_default_style(self.default_style)
# Build the initial list of available styles sets. This
# includes the default style set and any style sets saved from
# previous invocations of gramps.
self.style_sheet_list = BaseDoc.StyleSheetList(self.get_stylesheet_savefile(),
self.default_style)
self.style_sheet_list = BaseDoc.StyleSheetList(
self.options.handler.get_stylesheet_savefile(),
self.default_style)
# Now build the actual menu.
style = self.option_store.get('style',self.default_style.get_name())
style = self.options.handler.get_default_stylesheet_name()
self.build_style_menu(style)
def setup_report_options_frame(self):
@ -486,18 +516,16 @@ class BareReportDialog:
generations fields and the filter combo box are used in most
(but not all) dialog boxes."""
(use_gen, use_break) = self.get_report_generations()
local_filters = self.get_report_filters()
(em_label, extra_map, preset, em_tip) = self.get_report_extra_menu_info()
(et_label, string, et_tip) = self.get_report_extra_textbox_info()
row = 0
max_rows = 0
if use_gen:
max_rows = max_rows + 1
if use_break:
max_rows = max_rows + 1
if len(local_filters):
if self.max_gen:
max_rows = max_rows + 2
#if self.page_breaks:
# max_rows = max_rows + 1
if len(self.local_filters):
max_rows = max_rows + 1
if extra_map:
max_rows = max_rows + 1
@ -529,23 +557,24 @@ class BareReportDialog:
self.notebook.append_page(table,label)
row += 1
if len(local_filters):
if len(self.local_filters):
self.filter_combo = gtk.OptionMenu()
l = gtk.Label("%s:" % _("Filter"))
l.set_alignment(0.0,0.5)
table.attach(l,1,2,row,row+1,gtk.SHRINK|gtk.FILL,gtk.SHRINK|gtk.FILL)
table.attach(self.filter_combo,2,3,row,row+1,gtk.SHRINK|gtk.FILL,gtk.SHRINK|gtk.FILL)
menu = GenericFilter.build_filter_menu(local_filters,self.option_store.get('filter',''))
menu = GenericFilter.build_filter_menu(self.local_filters)
self.filter_combo.set_menu(menu)
self.filter_combo.set_history(self.options.handler.get_filter_number())
self.filter_menu = menu
row += 1
# Set up the generations spin and page break checkbox
if use_gen:
if self.max_gen:
self.generations_spinbox = gtk.SpinButton(digits=0)
self.generations_spinbox.set_numeric(1)
adjustment = gtk.Adjustment(use_gen,1,31,1,0)
adjustment = gtk.Adjustment(self.max_gen,1,31,1,0)
self.generations_spinbox.set_adjustment(adjustment)
adjustment.value_changed()
l = gtk.Label("%s:" % _("Generations"))
@ -554,11 +583,12 @@ class BareReportDialog:
table.attach(self.generations_spinbox,2,3,row,row+1,gtk.EXPAND|gtk.FILL,gtk.SHRINK|gtk.FILL)
row += 1
if use_break:
msg = _("Page break between generations")
self.pagebreak_checkbox = gtk.CheckButton(msg)
table.attach(self.pagebreak_checkbox,2,3,row,row+1)
row += 1
#if self.page_breaks:
msg = _("Page break between generations")
self.pagebreak_checkbox = gtk.CheckButton(msg)
self.pagebreak_checkbox.set_active(self.page_breaks)
table.attach(self.pagebreak_checkbox,2,3,row,row+1)
row += 1
# Now the "extra" option menu
if extra_map:
@ -662,7 +692,7 @@ class BareReportDialog:
item = self.style_menu.get_menu().get_active()
self.selected_style = item.get_data("d")
style_name = item.get_data('l')
self.option_store['style'] = style_name
self.options.handler.set_default_stylesheet_name(style_name)
def parse_report_options_frame(self):
"""Parse the report options frame of the dialog. Save the
@ -682,9 +712,12 @@ class BareReportDialog:
else:
self.pg_brk = 0
if self.max_gen or self.pg_brk:
self.options.handler.set_report_generations(self.max_gen,self.pg_brk)
if self.filter_combo:
self.filter = self.filter_menu.get_active().get_data("filter")
self.option_store['filter'] = self.filter.get_name()
self.options.handler.set_filter_number(self.filter_combo.get_history())
else:
self.filter = None
@ -712,7 +745,7 @@ class BareReportDialog:
#
#------------------------------------------------------------------------
def on_cancel(self,*obj):
self.window.destroy()
pass
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Parse all options
@ -722,16 +755,17 @@ class BareReportDialog:
self.parse_style_frame()
self.parse_report_options_frame()
self.parse_other_frames()
self.parse_user_options()
# Clean up the dialog object
self.window.destroy()
# Save options
self.options.handler.save_options()
def on_style_edit_clicked(self, *obj):
"""The user has clicked on the 'Edit Styles' button. Create a
style sheet editor object and let them play. When they are
done, the previous routine will be called to update the dialog
menu for selecting a style."""
StyleEditor.StyleListDisplay(self.style_sheet_list,self.build_style_menu)
StyleEditor.StyleListDisplay(self.style_sheet_list,self.build_style_menu,self.window)
def on_center_person_change_clicked(self,*obj):
import SelectPerson
@ -779,36 +813,50 @@ class ReportDialog(BareReportDialog):
dialog for a stand-alone report.
"""
def __init__(self,database,person,options={}):
def __init__(self,database,person,option_class,name=''):
"""Initialize a dialog to request that the user select options
for a basic *stand-alone* report."""
self.style_name = "default"
BareReportDialog.__init__(self,database,person,options)
BareReportDialog.__init__(self,database,person,option_class,name)
# Allow for post processing of the format frame, since the
# show_all task calls events that may reset values
def init_interface(self):
BareReportDialog.init_interface(self)
if self.format_menu:
self.doc_type_changed(self.format_menu.get_menu().get_active())
self.setup_post_process()
# def on_cancel(self,*obj):
# self.window.destroy()
def setup_post_process(self):
pass
def setup_center_person(self): pass
def setup_center_person(self):
pass
def get_title(self):
"""The window title for this dialog"""
name = self.report_name
category = const.standalone_categories[self.category]
return "%s - %s - GRAMPS" % (name,category)
def get_header(self, name):
"""The header line to put at the top of the contents of the
dialog box. By default this will just be the name of the
report for the selected person. """
return _("%(report_name)s for %(person_name)s") % {
'report_name' : self.report_name,
'person_name' : name}
#------------------------------------------------------------------------
#
# Customization hooks for subclasses
#
#------------------------------------------------------------------------
def get_target_browser_title(self):
"""The title of the window that will be created when the user
clicks the 'Browse' button in the 'Save As' File Entry
widget."""
return("%s - GRAMPS" % _("Save Report As"))
def get_target_is_directory(self):
"""Is the user being asked to input the name of a file or a
directory in the 'Save As' File Entry widget. This item
@ -858,7 +906,7 @@ class ReportDialog(BareReportDialog):
# Functions related to selecting/changing the current file format.
#
#------------------------------------------------------------------------
def make_doc_menu(self):
def make_doc_menu(self,active=None):
"""Build a menu of document types that are appropriate for
this report. This menu will be generated based upon the type
of document (text, draw, graph, etc. - a subclass), whether or
@ -866,8 +914,13 @@ class ReportDialog(BareReportDialog):
pass
def make_document(self):
"""Create a document of the type selected by the user."""
pass
"""Create a document of the type requested by the user."""
self.doc = self.format(self.selected_style,self.paper,
self.template_name,self.orien)
self.options.handler.doc = self.doc
if self.print_report.get_active ():
self.doc.print_requested ()
def doc_type_changed(self, obj):
"""This routine is called when the user selects a new file
@ -937,6 +990,7 @@ class ReportDialog(BareReportDialog):
if hid[-4:]==".xml":
hid = hid[0:-4]
self.target_fileentry = gnome.ui.FileEntry(hid,_("Save As"))
self.target_fileentry.set_modal(True)
if self.get_target_is_directory():
self.target_fileentry.set_directory_entry(1)
@ -965,7 +1019,7 @@ class ReportDialog(BareReportDialog):
self.col += 1
self.format_menu = gtk.OptionMenu()
self.make_doc_menu()
self.make_doc_menu(self.options.handler.get_format_name())
label = gtk.Label("%s:" % _("Output Format"))
label.set_alignment(0.0,0.5)
self.tbl.attach(label,1,2,self.col,self.col+1,gtk.SHRINK|gtk.FILL)
@ -1070,9 +1124,11 @@ class ReportDialog(BareReportDialog):
self.paper_table.attach(l,5,6,2,3,gtk.SHRINK|gtk.FILL)
PaperMenu.make_paper_menu(self.papersize_menu,
self.option_store.get('paper',GrampsGconfKeys.get_paper_preference()))
self.options.handler.get_paper_name()
)
PaperMenu.make_orientation_menu(self.orientation_menu,
self.option_store.get('orientation',BaseDoc.PAPER_PORTRAIT))
self.options.handler.get_orientation()
)
# The optional pagecount stuff.
if pagecount_map:
@ -1129,7 +1185,7 @@ class ReportDialog(BareReportDialog):
self.template_combo.set_popdown_strings(template_list)
self.template_combo.entry.set_editable(0)
def_template = self.option_store.get('default_template','')
def_template = ''
if def_template in template_list:
self.template_combo.entry.set_text(def_template)
self.template_combo.entry.connect('changed',self.html_file_enable)
@ -1139,8 +1195,9 @@ class ReportDialog(BareReportDialog):
l.set_alignment(0.0,0.5)
self.html_table.attach(l,1,2,2,3,gtk.SHRINK|gtk.FILL)
self.html_fileentry = gnome.ui.FileEntry("HTML_Template",_("Choose File"))
self.html_fileentry.set_modal(True)
self.html_fileentry.set_sensitive(0)
user_template = self.option_store.get('user_template','')
user_template = ''
if os.path.isfile(user_template):
self.html_fileentry.set_filename(user_template)
self.html_table.attach(self.html_fileentry,2,3,2,3)
@ -1178,12 +1235,15 @@ class ReportDialog(BareReportDialog):
return
self.set_default_directory(os.path.dirname(self.target_path) + os.sep)
self.options.handler.output = self.target_path
return 1
def parse_format_frame(self):
"""Parse the format frame of the dialog. Save the user
selected output format for later use."""
self.format = self.format_menu.get_menu().get_active().get_data("name")
format_name = self.format_menu.get_menu().get_active().get_data("label")
self.options.handler.set_format_name(format_name)
def parse_paper_frame(self):
"""Parse the paper frame of the dialog. Save the user
@ -1192,7 +1252,8 @@ class ReportDialog(BareReportDialog):
is displayed on the screen. The subclass will know which ones
it has enabled. This is for simplicity of programming."""
self.paper = self.papersize_menu.get_menu().get_active().get_data("i")
self.option_store['paper'] = self.paper.get_name()
paper_name = self.papersize_menu.get_menu().get_active().get_data("label")
self.options.handler.set_paper_name(paper_name)
if self.paper.get_height() <= 0 or self.paper.get_width() <= 0:
try:
@ -1210,7 +1271,7 @@ class ReportDialog(BareReportDialog):
self.paper.set_width(21.0)
self.orien = self.orientation_menu.get_menu().get_active().get_data("i")
self.option_store['orientation'] = self.orien
self.options.handler.set_orientation(self.orien)
if self.pagecount_menu == None:
self.pagecount = 0
@ -1228,14 +1289,11 @@ class ReportDialog(BareReportDialog):
if _template_map.has_key(text):
if text == _user_template:
self.template_name = self.html_fileentry.get_full_path(0)
self.option_store['default_template'] = text
self.option_store['user_template'] = ''
else:
self.template_name = "%s/%s" % (const.template_dir,_template_map[text])
self.option_store['default_template'] = text
self.option_store['user_template'] = self.template_name
else:
self.template_name = None
self.options.handler.set_template_name(self.template_name)
def on_ok_clicked(self, obj):
@ -1254,28 +1312,33 @@ class ReportDialog(BareReportDialog):
self.parse_html_frame()
self.parse_report_options_frame()
self.parse_other_frames()
self.parse_user_options()
# Create the output document.
self.make_document()
# Create the report object and product the report.
try:
self.make_report()
except (IOError,OSError),msg:
ErrorDialog(str(msg))
# # Create the report object and product the report.
# try:
# self.make_report()
# except (IOError,OSError),msg:
# ErrorDialog(str(msg))
# Save options
self.options.handler.save_options()
# Clean up the dialog object
self.window.destroy()
#self.window.destroy()
class TextReportDialog(ReportDialog):
"""A class of ReportDialog customized for text based reports."""
def __init__(self,database,person,options={}):
def __init__(self,database,person,options,name=''):
"""Initialize a dialog to request that the user select options
for a basic text report. See the ReportDialog class for more
information."""
ReportDialog.__init__(self,database,person, options)
self.category = const.CATEGORY_TEXT
ReportDialog.__init__(self,database,person,options,name)
#------------------------------------------------------------------------
#
@ -1293,60 +1356,46 @@ class TextReportDialog(ReportDialog):
# Functions related to selecting/changing the current file format.
#
#------------------------------------------------------------------------
def make_doc_menu(self):
def make_doc_menu(self,active=None):
"""Build a menu of document types that are appropriate for
this text report. This menu will be generated based upon
whether the document requires table support, etc."""
Plugins.get_text_doc_menu(self.format_menu, self.doc_uses_tables(),
self.doc_type_changed)
def make_document(self):
"""Create a document of the type requested by the user."""
self.doc = self.format(self.selected_style,self.paper,
self.template_name,self.orien)
if self.print_report.get_active ():
self.doc.print_requested ()
self.doc_type_changed, None, active)
#------------------------------------------------------------------------
#
# Functions related to creating the actual report document.
#
#------------------------------------------------------------------------
def make_report(self):
"""Create the contents of the report. This is a simple
default implementation suitable for testing. Is should be
overridden to produce a real report."""
self.doc.start_paragraph("Title")
title = "Basic Report for %s" % self.name
self.doc.write_text(title)
self.doc.end_paragraph()
# def make_report(self):
# """Create the contents of the report. This is a simple
# default implementation suitable for testing. Is should be
# overridden to produce a real report."""
# self.doc.start_paragraph("Title")
# title = "Basic Report for %s" % self.name
# self.doc.write_text(title)
# self.doc.end_paragraph()
class DrawReportDialog(ReportDialog):
"""A class of ReportDialog customized for drawing based reports."""
def __init__(self,database,person,opt={}):
def __init__(self,database,person,opt,name=''):
"""Initialize a dialog to request that the user select options
for a basic drawing report. See the ReportDialog class for
more information."""
ReportDialog.__init__(self,database,person,opt)
self.category = const.CATEGORY_DRAW
ReportDialog.__init__(self,database,person,opt,name)
#------------------------------------------------------------------------
#
# Functions related to selecting/changing the current file format.
#
#------------------------------------------------------------------------
def make_doc_menu(self):
def make_doc_menu(self,active=None):
"""Build a menu of document types that are appropriate for
this drawing report."""
Plugins.get_draw_doc_menu(self.format_menu,self.doc_type_changed)
def make_document(self):
"""Create a document of the type requested by the user."""
self.doc = self.format(self.selected_style,self.paper,
self.template_name,self.orien)
if self.print_report.get_active ():
self.doc.print_requested ()
Plugins.get_draw_doc_menu(self.format_menu,self.doc_type_changed,
None, active)
class TemplateParser(handler.ContentHandler):
"""
@ -1377,14 +1426,11 @@ class TemplateParser(handler.ContentHandler):
if tag == "template":
self.data[attrs['title']] = attrs['file']
#-----------------------------------------------------------------------
#
# Initialization
#
#-----------------------------------------------------------------------
try:
parser = make_parser()
gspath = const.template_dir
@ -1396,3 +1442,266 @@ try:
parser.parse("file://%s/templates.xml" % gspath)
except (IOError,OSError,SAXParseException):
pass
#------------------------------------------------------------------------
#
# Command-line report
#
#------------------------------------------------------------------------
class CommandLineReport:
"""
Provides a way to generate report from the command line.
"""
def __init__(self,database,name,category,option_class,options_str_dict):
self.database = database
self.category = category
self.option_class = option_class(name)
self.show = options_str_dict.pop('show',None)
self.options_str_dict = options_str_dict
self.init_options()
self.parse_option_str()
self.show_options()
def init_options(self):
self.options_dict = {
'of' : self.option_class.handler.report_name,
'off' : self.option_class.handler.get_format_name(),
'style' : self.option_class.handler.get_default_stylesheet_name(),
'papers' : self.option_class.handler.get_paper_name(),
'papero' : self.option_class.handler.get_orientation(),
'template' : self.option_class.handler.get_orientation(),
'id' : ''
}
self.options_help = {
'of' : ["=filename","Output file name. MANDATORY"],
'off' : ["=format","Output file format."],
'style' : ["=name","Style name."],
'papers' : ["=name","Paper size name."],
'papero' : ["=num","Paper orientation number."],
'template' : ["=name","Template name (HTML only)."],
'id' : ["=ID","Gramps ID of a central person. MANDATORY"],
'filter' : ["=num","Filter number."],
'max_gen' : ["=num","Number generations to follow."],
'page_breaks': ["=0/1","Page break between generations."],
}
# Add report-specific options
for key in self.option_class.handler.options_dict.keys():
if key not in self.options_dict.keys():
self.options_dict[key] = self.option_class.handler.options_dict[key]
# Add help for report-specific options
for key in self.option_class.options_help.keys():
if key not in self.options_help.keys():
self.options_help[key] = self.option_class.options_help[key]
def parse_option_str(self):
for opt in self.options_str_dict.keys():
if opt in self.options_dict.keys():
converter = Utils.get_type_converter(self.options_dict[opt])
self.options_dict[opt] = converter(self.options_str_dict[opt])
self.option_class.handler.options_dict[opt] = self.options_dict[opt]
else:
print "Ignoring unknown option: %s" % opt
person_id = self.options_dict['id']
self.person = self.database.get_person_from_gramps_id(person_id)
id_list = []
for person_handle in self.database.get_person_handles():
person = self.database.get_person_from_handle(person_handle)
id_list.append("%s\t%s" % (person.get_gramps_id(),
person.get_primary_name().get_name()))
self.options_help['id'].append(id_list)
self.options_help['id'].append(False)
if self.options_dict.has_key('filter'):
filter_num = self.options_dict['filter']
self.filters = self.option_class.get_report_filters(self.person)
self.option_class.handler.set_filter_number(filter_num)
filt_list = [ filt.get_name() for filt in self.filters ]
cust_filt_list = [ filt2.get_name() for filt2 in
GenericFilter.CustomFilters.get_filters() ]
filt_list.extend(cust_filt_list)
self.options_help['filter'].append(filt_list)
self.options_help['filter'].append(True)
if self.options_dict.has_key('max_gen'):
max_gen = self.options_dict['max_gen']
page_breaks = self.options_dict['page_breaks']
self.option_class.handler.set_report_generations(max_gen,page_breaks)
self.options_help['max_gen'].append("Whatever Number You Wish")
self.options_help['page_breaks'].append([
"No page break","Page break"])
self.options_help['page_breaks'].append(True)
self.option_class.handler.output = self.options_dict['of']
self.options_help['of'].append(os.path.expanduser("~/whatever_name"))
if self.category == const.CATEGORY_TEXT:
for item in Plugins._textdoc:
if item[7] == self.options_dict['off']:
self.format = item[1]
self.options_help['off'].append(
[ item[7] for item in Plugins._textdoc ]
)
self.options_help['off'].append(False)
elif self.category == const.CATEGORY_DRAW:
for item in Plugins._drawdoc:
if item[6] == self.options_dict['off']:
self.format = item[1]
self.options_help['off'].append(
[ item[6] for item in Plugins._drawdoc ]
)
self.options_help['off'].append(False)
elif self.category == const.CATEGORY_BOOK:
for item in Plugins._bookdoc:
if item[6] == self.options_dict['off']:
self.format = item[1]
self.options_help['off'].append(
[ item[6] for item in Plugins._bookdoc ]
)
self.options_help['off'].append(False)
else:
self.format = None
for paper in PaperMenu.paper_sizes:
if paper.get_name() == self.options_dict['papers']:
self.paper = paper
self.options_help['papers'].append(
[ paper.get_name() for paper in PaperMenu.paper_sizes
if paper.get_name() != 'Custom Size' ] )
self.options_help['papers'].append(False)
self.orien = self.options_dict['papero']
self.options_help['papero'].append([
"%d\tPortrait" % BaseDoc.PAPER_PORTRAIT,
"%d\tLandscape" % BaseDoc.PAPER_LANDSCAPE ] )
self.options_help['papero'].append(False)
self.template_name = self.options_dict['template']
self.options_help['template'].append(os.path.expanduser("~/whatever_name"))
if self.category in (const.CATEGORY_TEXT,const.CATEGORY_DRAW):
default_style = BaseDoc.StyleSheet()
self.option_class.make_default_style(default_style)
# Read all style sheets available for this item
style_file = self.option_class.handler.get_stylesheet_savefile()
self.style_list = BaseDoc.StyleSheetList(style_file,default_style)
# Get the selected stylesheet
style_name = self.option_class.handler.get_default_stylesheet_name()
self.selected_style = self.style_list.get_style_sheet(style_name)
self.options_help['style'].append(
self.style_list.get_style_names() )
self.options_help['style'].append(False)
def show_options(self):
if not self.show:
return
elif self.show == 'all':
print " Available options:"
for key in self.options_dict.keys():
print " %s" % key
print " Use 'show=option' to see description and acceptable values"
elif self.show in self.options_dict.keys():
print ' %s%s\t%s' % (self.show,
self.options_help[self.show][0],
self.options_help[self.show][1])
print " Available values are:"
vals = self.options_help[self.show][2]
if type(vals) in [list,tuple]:
if self.options_help[self.show][3]:
for num in range(len(vals)):
print " %d\t%s" % (num,vals[num])
else:
for val in vals:
print " %s" % val
else:
print " %s" % self.options_help[self.show][2]
else:
self.show = None
#------------------------------------------------------------------------
#
# Generic task functions for reports
#
#------------------------------------------------------------------------
# Standalone GUI report generic task
def report(database,person,report_class,options_class,category,name):
"""
report - task starts the report. The plugin system requires that the
task be in the format of task that takes a database and a person as
its arguments.
"""
if category == const.CATEGORY_TEXT:
dialog_class = TextReportDialog
elif category == const.CATEGORY_DRAW:
dialog_class = DrawReportDialog
elif category == const.CATEGORY_BOOK:
report_class(database,person)
return
else:
dialog_class = ReportDialog
dialog = dialog_class(database,person,options_class,name)
response = dialog.window.run()
if response == True:
try:
MyReport = report_class(dialog.db,dialog.person,dialog.options)
MyReport.write_report()
except Errors.FilterError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except Errors.ReportError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except:
import DisplayTrace
DisplayTrace.DisplayTrace()
dialog.window.destroy()
# Book item generic task
def write_book_item(database,person,report_class,options_class):
"""Write the Timeline Graph using options set.
All user dialog has already been handled and the output file opened."""
try:
if options_class.handler.get_person_id():
person = database.get_person_from_gramps_id(options_class.handler.get_person_id())
return report_class(database,person,options_class)
except Errors.ReportError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except Errors.FilterError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except:
import DisplayTrace
DisplayTrace.DisplayTrace()
# Command-line generic task
def cl_report(database,name,category,report_class,options_class,options_str_dict):
clr = CommandLineReport(database,name,category,options_class,options_str_dict)
# Exit here if show option was given
if clr.show:
return
# write report
try:
clr.option_class.handler.doc = clr.format(
clr.selected_style,clr.paper,clr.template_name,clr.orien)
MyReport = report_class(database, clr.person, clr.option_class)
MyReport.write_report()
except:
import DisplayTrace
DisplayTrace.DisplayTrace()

View File

@ -0,0 +1,605 @@
#
# 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
"""
Report option handling, including saving and parsing.
"""
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
import os
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# SAX interface
#
#-------------------------------------------------------------------------
try:
from xml.sax import make_parser,handler,SAXParseException
except:
from _xmlplus.sax import make_parser,handler,SAXParseException
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import const
import GrampsGconfKeys
import Utils
import BaseDoc
#-------------------------------------------------------------------------
#
# List of options for a single report
#
#-------------------------------------------------------------------------
class OptionList:
"""
Implements a set of options to parse and store for a given report.
"""
def __init__(self):
self.options = {}
self.style_name = None
self.paper_name = None
self.orientation = None
self.template_name = None
self.format_name = None
def set_options(self,options):
"""
Sets the whole bunch of options for the OptionList.
options: list of options to set.
"""
self.options = options
def get_options(self):
"""
Returns the whole bunch of options for the OptionList.
"""
return self.options
def set_option(self,name,value):
"""
Sets a particular option in the OptionList.
name: name of the option to set.
value: value of the option to set.
"""
self.options[name] = value
def remove_option(self,name):
"""
Removes a particular option from the OptionList.
name: name of the option to remove.
"""
if self.options.has_key(name):
del self.options[name]
def get_option(self,name):
"""
Returns the value of a particular option in the OptionList.
"""
return self.options.get(name,None)
def set_style_name(self,style_name):
"""
Sets the style name for the OptionList.
style_name: name of the style to set.
"""
self.style_name = style_name
def get_style_name(self):
"""
Returns the style name of the OptionList.
"""
return self.style_name
def set_paper_name(self,paper_name):
"""
Sets the paper name for the OptionList.
style_name: name of the paper to set.
"""
self.paper_name = paper_name
def get_paper_name(self):
"""
Returns the paper name of the OptionList.
"""
return self.paper_name
def set_orientation(self,orientation):
"""
Sets the orientation for the OptionList.
orientation: orientation to set.
"""
self.orientation = orientation
def get_orientation(self):
"""
Returns the orientation for the OptionList.
"""
return self.orientation
def set_template_name(self,template_name):
"""
Sets the template name for the OptionList.
template_name: name of the template to set.
"""
self.template_name = template_name
def get_template_name(self):
"""
Returns the template name of the OptionList.
"""
return self.template_name
def set_format_name(self,format_name):
"""
Sets the format name for the OptionList.
format_name: name of the format to set.
"""
self.format_name = format_name
def get_format_name(self):
"""
Returns the format name of the OptionList.
"""
return self.format_name
#-------------------------------------------------------------------------
#
# Collection of option lists
#
#-------------------------------------------------------------------------
class OptionListCollection:
# Default values for common options
default_style_name = "default"
default_paper_name = GrampsGconfKeys.get_paper_preference()
default_template_name = ""
default_orientation = BaseDoc.PAPER_PORTRAIT
default_format_name = _('Print...')
def __init__(self,filename=None):
"""
Creates an OptionListCollection instance from the list defined
in the specified file.
filename: XML file that contains option definitions
"""
if not filename or not os.path.isfile(filename):
filename = const.report_options
self.file = os.path.expanduser(filename)
self.last_paper_name = self.default_paper_name
self.last_orientation = self.default_orientation
self.last_template_name = self.default_template_name
self.last_format_name = self.default_format_name
self.option_list_map = {}
self.parse()
def get_option_list_map(self):
"""
Returns the map of reports names to option lists.
"""
return self.option_list_map
def get_option_list(self,name):
"""
Returns the option_list associated with the report name
name: name associated with the desired report.
"""
return self.option_list_map.get(name,None)
def get_report_names(self):
"Returns a list of all the report names in the OptionListCollection"
return self.option_list_map.keys()
def set_option_list(self,name,option_list):
"""
Adds or replaces an option_list in the OptionListCollection.
name: name assocated with the report to add or replace.
option_list: option_list
"""
self.option_list_map[name] = option_list
def set_last_paper_name(self,paper_name):
"""
Sets the last paper name used for the any report in this collection.
paper_name: name of the paper to set.
"""
self.last_paper_name = paper_name
def get_last_paper_name(self):
"""
Returns the last paper name used for the any report in this collection.
"""
return self.last_paper_name
def set_last_orientation(self,orientation):
"""
Sets the last orientation used for the any report in this collection.
orientation: orientation to set.
"""
self.last_orientation = orientation
def get_last_orientation(self):
"""
Returns the last orientation used for the any report in this collection.
"""
return self.last_orientation
def set_last_template_name(self,template_name):
"""
Sets the last template used for the any report in this collection.
template_name: name of the style to set.
"""
self.last_template_name = template_name
def get_last_template_name(self):
"""
Returns the last template used for the any report in this collection.
"""
return self.last_template_name
def set_last_format_name(self,format_name):
"""
Sets the last format used for the any report in this collection.
format_name: name of the format to set.
"""
self.last_format_name = format_name
def get_last_format_name(self):
"""
Returns the last format used for the any report in this collection.
"""
return self.last_format_name
def save(self):
"""
Saves the current OptionListCollection to the associated file.
"""
f = open(self.file,"w")
f.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
f.write('<reportoptions>\n')
f.write('<last-common>\n')
if self.get_last_paper_name() != self.default_paper_name:
f.write(' <paper name="%s"/>\n' % self.get_last_paper_name() )
if self.get_last_template_name() != self.default_template_name:
f.write(' <template name="%s"/>\n' % self.get_last_template_name() )
if self.get_last_format_name() != self.default_format_name:
f.write(' <format name="%s"/>\n' % self.get_last_format_name() )
if self.get_last_orientation() != self.default_orientation:
f.write(' <orientation value="%d"/>\n' % self.get_last_orientation() )
f.write('</last-common>\n')
for report_name in self.get_report_names():
option_list = self.get_option_list(report_name)
f.write('<report name="%s">\n' % report_name)
options = option_list.get_options()
for option_name in options.keys():
if type(options[option_name]) in (type(list()),type(tuple())):
f.write(' <option name="%s" value="" length="%d">\n' % (
option_name, len(options[option_name]) ) )
for list_index in range(len(options[option_name])):
f.write(' <listitem number="%d" value="%s"/>\n' % (
list_index, options[option_name][list_index]) )
f.write(' </option>\n')
else:
f.write(' <option name="%s" value="%s"/>\n' % (
option_name,options[option_name]) )
if option_list.get_style_name() \
and option_list.get_style_name() != self.default_style_name:
f.write(' <style name="%s"/>\n' % option_list.get_style_name() )
if option_list.get_paper_name() \
and option_list.get_paper_name() != self.default_paper_name:
f.write(' <paper name="%s"/>\n' % option_list.get_paper_name() )
if option_list.get_template_name() \
and option_list.get_template_name() != self.default_template_name:
f.write(' <template name="%s"/>\n' % option_list.get_template_name() )
if option_list.get_format_name() \
and option_list.get_format_name() != self.default_format_name:
f.write(' <format name="%s"/>\n' % option_list.get_format_name() )
if option_list.get_orientation() \
and option_list.get_orientation() != self.default_orientation:
f.write(' <orientation value="%d"/>\n' % option_list.get_orientation() )
f.write('</report>\n')
f.write('</reportoptions>\n')
f.close()
def parse(self):
"""
Loads the OptionList from the associated file, if it exists.
"""
try:
p = make_parser()
p.setContentHandler(OptionParser(self))
p.parse('file://' + self.file)
except (IOError,OSError,SAXParseException):
pass
#-------------------------------------------------------------------------
#
# OptionParser
#
#-------------------------------------------------------------------------
class OptionParser(handler.ContentHandler):
"""
SAX parsing class for the OptionListCollection XML file.
"""
def __init__(self,collection):
"""
Creates a OptionParser class that populates the passed collection.
collection: BookList to be loaded from the file.
"""
handler.ContentHandler.__init__(self)
self.collection = collection
self.rname = None
self.option_list = None
self.oname = None
self.o = None
self.an_o = None
self.common = False
def startElement(self,tag,attrs):
"""
Overridden class that handles the start of a XML element
"""
if tag == "report":
self.rname = attrs['name']
self.option_list = OptionList()
self.o = {}
elif tag == "last-common":
self.common = True
elif tag == "option":
self.oname = attrs['name']
if attrs.has_key('length'):
self.an_o = []
else:
self.an_o = attrs['value']
elif tag == "listitem":
self.an_o.append(attrs['value'])
elif tag == "style":
self.option_list.set_style_name(attrs['name'])
elif tag == "paper":
if self.common:
self.collection.set_last_paper_name(attrs['name'])
else:
self.option_list.set_paper_name(attrs['name'])
elif tag == "template":
if self.common:
self.collection.set_last_template_name(attrs['name'])
else:
self.option_list.set_template_name(attrs['name'])
elif tag == "format":
if self.common:
self.collection.set_last_format_name(attrs['name'])
else:
self.option_list.set_format_name(attrs['name'])
elif tag == "orientation":
if self.common:
self.collection.set_last_orientation(int(attrs['value']))
else:
self.option_list.set_orientation(int(attrs['value']))
def endElement(self,tag):
"Overridden class that handles the end of a XML element"
if tag == "option":
self.o[self.oname] = self.an_o
elif tag == "report":
self.option_list.set_options(self.o)
self.collection.set_option_list(self.rname,self.option_list)
elif tag == "last-common":
self.common = False
#-------------------------------------------------------------------------
#
# Class handling options for plugins
#
#-------------------------------------------------------------------------
class OptionHandler:
"""
Implements handling of the options for the plugins.
"""
def __init__(self,report_name,options_dict,person_id=None):
self.report_name = report_name
self.default_options_dict = options_dict.copy()
self.options_dict = options_dict
# These are needed for running reports.
# We will not need to save/retreive them, just keep around.
self.doc = None
self.output = None
self.newpage = False
# Retrieve our options from whole collection
self.option_list_collection = OptionListCollection()
self.style_name = self.option_list_collection.default_style_name
self.paper_name = self.option_list_collection.get_last_paper_name()
self.orientation = self.option_list_collection.get_last_orientation()
self.template_name = self.option_list_collection.get_last_template_name()
self.format_name = self.option_list_collection.get_last_format_name()
self.saved_option_list = self.option_list_collection.get_option_list(report_name)
self.person_id = person_id
# Whatever was found should override the defaults
if self.saved_option_list:
self.set_options()
else:
# If nothing was found, set up the option list
self.saved_option_list = OptionList()
self.option_list_collection.set_option_list(report_name,self.saved_option_list)
def set_options(self):
"""
Sets options to be used in this plugin according to the passed
options dictionary.
Dictionary values are all strings, since they were read from XML.
Here we need to convert them to the needed types. We use default
values to determine the type.
"""
# First we set options_dict values based on the saved options
options = self.saved_option_list.get_options()
for option_name in options.keys():
try:
converter = Utils.get_type_converter(self.options_dict[option_name])
self.options_dict[option_name] = converter(options[option_name])
except ValueError:
pass
# Then we set common options from whatever was found
if self.saved_option_list.get_style_name():
self.style_name = self.saved_option_list.get_style_name()
if self.saved_option_list.get_orientation():
self.orientation = self.saved_option_list.get_orientation()
if self.saved_option_list.get_template_name():
self.template_name = self.saved_option_list.get_template_name()
if self.saved_option_list.get_paper_name():
self.paper_name = self.saved_option_list.get_paper_name()
if self.saved_option_list.get_format_name():
self.format_name = self.saved_option_list.get_format_name()
def save_options(self):
"""
Saves options to file.
We need to only store non-default options. Therefore, we remove all
options whose values are the defaults prior to saving. Also, we save
the present common options as the last-common for this collection.
"""
# First we save options from options_dict
for option_name in self.options_dict.keys():
if self.options_dict[option_name] == self.default_options_dict[option_name]:
self.saved_option_list.remove_option(option_name)
else:
self.saved_option_list.set_option(option_name,self.options_dict[option_name])
# Then we save common options
self.saved_option_list.set_style_name(self.style_name)
self.saved_option_list.set_orientation(self.orientation)
self.saved_option_list.set_template_name(self.template_name)
self.saved_option_list.set_paper_name(self.paper_name)
self.saved_option_list.set_format_name(self.format_name)
self.option_list_collection.set_option_list(self.report_name,self.saved_option_list)
# Then save last-common options from the current selection
self.option_list_collection.set_last_orientation(self.orientation)
self.option_list_collection.set_last_template_name(self.template_name)
self.option_list_collection.set_last_paper_name(self.paper_name)
self.option_list_collection.set_last_format_name(self.format_name)
# Finally, save the whole collection into file
self.option_list_collection.save()
def get_report_generations(self):
if self.default_options_dict.has_key('max_gen'):
max_gen = self.options_dict.get('max_gen',
self.default_options_dict['max_gen'])
page_breaks = self.options_dict.get('page_breaks',
self.default_options_dict['page_breaks'])
return (max_gen,page_breaks)
else:
return (0,0)
def set_report_generations(self,max_gen,page_breaks):
self.options_dict['max_gen'] = max_gen
self.options_dict['page_breaks'] = page_breaks
def get_stylesheet_savefile(self):
"""Where to save user defined styles for this report."""
return "%s.xml" % self.report_name
def get_default_stylesheet_name(self):
return self.style_name
def set_default_stylesheet_name(self,style_name):
self.style_name = style_name
def get_filter_number(self):
try:
return self.options_dict.get('filter',
self.default_options_dict['filter'])
except KeyError:
return None
def set_filter_number(self,val):
self.options_dict['filter'] = val
def get_format_name(self):
return self.format_name
def set_format_name(self,format_name):
self.format_name = format_name
def get_paper_name(self):
return self.paper_name
def set_paper_name(self,paper_name):
self.paper_name = paper_name
def get_template_name(self):
return self.template_name
def set_template_name(self,template_name):
self.template_name = template_name
def get_orientation(self):
return self.orientation
def set_orientation(self,orientation):
self.orientation = orientation
def get_person_id(self):
return self.person_id
def set_person_id(self,val):
self.person_id = val

View File

@ -93,7 +93,7 @@ class Sort:
else:
date2 = Date.Date()
val = date1.is_equal(date2)
val = cmp(date1,date2)
if val == 0:
return self.by_last_name(first_id,second_id)
return val

View File

@ -52,7 +52,7 @@ class StyleListDisplay:
add, edit, and delete styles from a StyleSheet.
"""
def __init__(self,stylesheetlist,callback):
def __init__(self,stylesheetlist,callback,parent_window):
"""
Creates a StyleListDisplay object that displays the styles in the
StyleSheet.
@ -64,8 +64,9 @@ class StyleListDisplay:
self.sheetlist = stylesheetlist
self.top = gtk.glade.XML(const.stylesFile,"styles","gramps")
self.window = self.top.get_widget('styles')
Utils.set_titles(self.top.get_widget('styles'),
Utils.set_titles(self.window,
self.top.get_widget('title'),
_('Document Styles'))
@ -85,6 +86,10 @@ class StyleListDisplay:
self.list = ListModel.ListModel(self.top.get_widget("list"),
[('Style',-1,10)],)
self.redraw()
if parent_window:
self.window.set_transient_for(parent_window)
response = self.window.run()
self.window.destroy()
def redraw(self):
"""Redraws the list of styles that are current available"""
@ -106,8 +111,8 @@ class StyleListDisplay:
StyleEditor("New Style",style,self)
def on_ok_clicked(self,obj):
"""Called with the OK button is clicked; Calls the callback task, then
saves the stylesheet, and destroys the window."""
"""Called with the OK button is clicked; Calls the callback task,
then saves the stylesheet."""
self.callback()
try:
self.sheetlist.save()
@ -117,7 +122,6 @@ class StyleListDisplay:
except:
import DisplayTrace
DisplayTrace.DisplayTrace()
Utils.destroy_passed_object(obj)
def on_button_press(self,obj,event):
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:

View File

@ -488,6 +488,14 @@ def roman(num):
else:
return '?'
#-------------------------------------------------------------------------
#
# Convert points to cm
#
#-------------------------------------------------------------------------
def pt2cm(val):
return (float(val)/28.3465)
#-------------------------------------------------------------------------
#
# Change label apperance
@ -662,3 +670,48 @@ def get_new_filename(ext,folder='~/'):
while os.path.isfile(os.path.expanduser(_NEW_NAME_PATTERN % (folder,ix,ext) )):
ix = ix + 1
return os.path.expanduser(_NEW_NAME_PATTERN % (folder,ix,ext))
def get_type_converter(val):
"""
Returns function that converts strings into the type of val.
"""
val_type = type(val)
if val_type in (str,unicode):
return unicode
elif val_type == int:
return int
elif val_type == float:
return float
elif val_type in (list,tuple):
return list
def type_name(val):
"""
Returns the name the type of val.
Only numbers and strings are supported.
The rest becomes strings (unicode).
"""
val_type = type(val)
if val_type == int:
return 'int'
elif val_type == float:
return 'float'
elif val_type in (str,unicode):
return 'unicode'
return 'unicode'
def get_type_converter_by_name(val_str):
"""
Returns function that converts strings into the type given by val_str.
Only numbers and strings are supported.
The rest becomes strings (unicode).
"""
if val_str == 'int':
return int
elif val_str == 'float':
return float
elif val_str in ('str','unicode'):
return unicode
return unicode

View File

@ -78,6 +78,7 @@ caution_xpm = "%s/caution.png" % rootDir
system_filters = "%s/system_filters.xml" % rootDir
custom_filters = "~/.gramps/custom_filters.xml"
report_options = "~/.gramps/report_options.xml"
icon = "%s/gramps.png" % rootDir
logo = "%s/logo.png" % rootDir
gladeFile = "%s/gramps.glade" % rootDir
@ -151,10 +152,11 @@ unknown = _("unknown")
# (longName, shortName, type , default, flags, descrip , argDescrip)
popt_table = [
("import", 'i', str, None, 0, "Import file", "FILENAME"),
("output", 'o', str, None, 0, "Write file", "FILENAME"),
("format", 'f', str, None, 0, 'Specify format', "FORMAT"),
("action", 'a', str, None, 0, 'Specify action', "ACTION"),
("import", 'i', str, None, 0, "Import file", "FILENAME"),
("output", 'o', str, None, 0, "Write file", "FILENAME"),
("format", 'f', str, None, 0, 'Specify format', "FORMAT"),
("action", 'a', str, None, 0, 'Specify action', "ACTION"),
("options", 'p', str, None, 0, 'Specify options', "OPTIONS_STRING"),
]
longopts = [
@ -190,9 +192,10 @@ longopts = [
"output=",
"format=",
"action=",
"options=",
]
shortopts = "i:o:f:a:?"
shortopts = "i:o:f:a:p:?"
#-------------------------------------------------------------------------
#
@ -886,3 +889,23 @@ notes_formats = [
]
CATEGORY_TEXT = 0
CATEGORY_DRAW = 1
CATEGORY_CODE = 2
CATEGORY_WEB = 3
CATEGORY_VIEW = 4
CATEGORY_BOOK = 5
standalone_categories = {
CATEGORY_TEXT : _("Text Reports"),
CATEGORY_DRAW : _("Graphical Reports"),
CATEGORY_CODE : _("Code-generating Reports"),
CATEGORY_WEB : _("Web Page"),
CATEGORY_VIEW : _("View"),
CATEGORY_BOOK : _("Book Reports"),
}
book_categories = {
CATEGORY_TEXT : _("Text"),
CATEGORY_DRAW : _("Graphics"),
}

View File

@ -1167,8 +1167,10 @@ Plugins.register_text_doc(
table=1,
paper=1,
style=1,
ext=""
)
ext="",
print_report_label=None,
clname='print')
Plugins.register_book_doc(
_("Print..."),
@ -1176,11 +1178,14 @@ Plugins.register_book_doc(
1,
1,
1,
"")
"",
'print')
Plugins.register_draw_doc(
_("Print..."),
LPRDoc,
1,
1,
"");
"",
None,
'print')

View File

@ -21044,7 +21044,7 @@ Other</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="modal">False</property>
<property name="default_width">400</property>
<property name="default_height">300</property>
<property name="resizable">True</property>
@ -21078,7 +21078,6 @@ Other</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">0</property>
<signal name="clicked" handler="destroy_passed_object" object="styles"/>
</widget>
</child>

View File

@ -1691,10 +1691,10 @@ class Gramps:
def on_preferences_activate(self,obj):
GrampsCfg.display_preferences_box(self.db)
def menu_report(self,obj,task):
def menu_report(self,obj,task,report_class,options_class,category,name):
"""Call the report plugin selected from the menus"""
if self.active_person:
task(self.db,self.active_person)
task(self.db,self.active_person,report_class,options_class,category,name)
def menu_tools(self,obj,task):
"""Call the tool plugin selected from the menus"""

View File

@ -1,7 +1,6 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
#
# Copyright (C) 2003-2004 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
@ -21,10 +20,8 @@
# $Id$
#
# Written by Alex Roitman,
# largely based on the BaseDoc classes by Don Allingham
#
#-------------------------------------------------------------------------
#
@ -32,6 +29,7 @@
#
#-------------------------------------------------------------------------
import os
from gettext import gettext as _
#-------------------------------------------------------------------------
#
@ -43,13 +41,6 @@ try:
except:
from _xmlplus.sax import make_parser,handler,SAXParseException
#-------------------------------------------------------------------------
#
# internationalization
#
#-------------------------------------------------------------------------
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
@ -70,8 +61,9 @@ import ListModel
import Plugins
import Report
import BaseDoc
from QuestionDialog import WarningDialog
import ReportOptions
#------------------------------------------------------------------------
#
# Book Item class
@ -103,9 +95,8 @@ class BookItem:
self.name = ""
self.category = ""
self.dialog = None
self.write_item = None
self.options = []
self.option_class = None
self.style_file = ""
self.style_name = "default"
self.make_default_style = None
@ -122,12 +113,9 @@ class BookItem:
if item[0] == name:
self.name = item[0]
self.category = item[1]
self.dialog = item[2]
self.write_item = item[3]
self.options = list(item[4])
self.style_name = item[5]
self.style_file = item[6]
self.make_default_style = item[7]
self.write_item = item[2]
self.item_name = item[4]
self.option_class = item[3](self.item_name)
def get_name(self):
"""
@ -141,32 +129,12 @@ class BookItem:
"""
return self.category
def get_dialog(self):
"""
Returns the callable cofigurator dialog.
"""
return self.dialog
def get_write_item(self):
"""
Returns the report-writing function of the item.
"""
return self.write_item
def set_options(self,options):
"""
Sets the options for the item.
options: list of options to set.
"""
self.options = options
def get_options(self):
"""
Returns the list of options for the item.
"""
return self.options
def set_style_name(self,style_name):
"""
Sets the style name for the item.
@ -312,7 +280,7 @@ class BookList:
BookList is loaded from a specified XML file if it exists.
"""
def __init__(self,file):
def __init__(self,filename):
"""
Creates a new BookList from the books that may be defined in the
specified file.
@ -321,7 +289,7 @@ class BookList:
"""
self.bookmap = {}
self.file = os.path.expanduser("~/.gramps/" + file)
self.file = os.path.expanduser("~/.gramps/" + filename)
self.parse()
def delete_book(self,name):
@ -374,18 +342,23 @@ class BookList:
f.write('<book name="%s" database="%s">\n' % (name,dbname) )
for item in book.get_item_list():
f.write(' <item name="%s">\n' % item.get_name() )
options = item.get_options()
for opt_index in range(len(options)):
if type(options[opt_index]) == type([]):
f.write(' <option number="%d" value="" length="%d">\n' % (
opt_index, len(options[opt_index]) ) )
for list_index in range(len(options[opt_index])):
f.write(' <listitem number="%d" value="%s"/>\n' % (
list_index, options[opt_index][list_index]) )
option_handler = item.option_class.handler
for option_name in option_handler.options_dict.keys():
option_value = option_handler.options_dict[option_name]
if type(option_value) in (list,tuple):
f.write(' <option name="%s" length="%d">\n' % (
option_name, len(option_value) ) )
for list_index in range(len(option_value)):
option_type = Utils.type_name(option_value[list_index])
f.write(' <listitem number="%d" type="%s" value="%s"/>\n' % (
list_index, option_type, option_value[list_index]) )
f.write(' </option>\n')
else:
f.write(' <option number="%d" value="%s"/>\n' % (
opt_index,options[opt_index]) )
option_type = Utils.type_name(option_value)
f.write(' <option name="%s" type="%s" value="%s"/>\n' % (
option_name,option_type,option_value) )
f.write(' <person gramps_id="%s"/>\n' %
option_handler.get_person_id() )
f.write(' <style name="%s"/>\n' % item.get_style_name() )
f.write(' </item>\n')
f.write('</book>\n')
@ -404,6 +377,7 @@ class BookList:
except (IOError,OSError,SAXParseException):
pass
#-------------------------------------------------------------------------
#
# BookParser
@ -425,8 +399,10 @@ class BookParser(handler.ContentHandler):
self.b = None
self.i = None
self.o = None
self.an_o = None
self.an_o_name = None
self.an_o_value = None
self.s = None
self.p = None
self.bname = None
self.iname = None
@ -442,23 +418,29 @@ class BookParser(handler.ContentHandler):
self.b.set_dbname(self.dbname)
elif tag == "item":
self.i = BookItem(attrs['name'])
self.o = []
self.o = {}
elif tag == "option":
self.an_o_name = attrs['name']
if attrs.has_key('length'):
self.an_o = []
self.an_o_value = []
else:
self.an_o = attrs['value']
converter = Utils.get_type_converter_by_name(attrs['type'])
self.an_o_value = converter(attrs['value'])
elif tag == "listitem":
self.an_o.append(attrs['value'])
converter = Utils.get_type_converter_by_name(attrs['type'])
self.an_o_value.append(converter(attrs['value']))
elif tag == "style":
self.s = attrs['name']
elif tag == "person":
self.p = attrs['gramps_id']
def endElement(self,tag):
"Overridden class that handles the end of a XML element"
if tag == "option":
self.o.append(self.an_o)
self.o[self.an_o_name] = self.an_o_value
elif tag == "item":
self.i.set_options(self.o)
self.i.option_class.handler.options_dict.update(self.o)
self.i.option_class.handler.set_person_id(self.p)
self.i.set_style_name(self.s)
self.b.append_item(self.i)
elif tag == "book":
@ -476,15 +458,17 @@ class BookListDisplay:
Allows the user to select and/or delete a book from the list.
"""
def __init__(self,booklist,nodelete=0):
def __init__(self,booklist,nodelete=0,dosave=0):
"""
Creates a BookListDisplay object that displays the books in BookList.
booklist: books that are displayed
nodelete: if not 0 then the Delete button is hidden
dosave: if 1 then the book list is saved on hitting OK
"""
self.booklist = booklist
self.dosave = dosave
base = os.path.dirname(__file__)
glade_file = os.path.join(base,"book.glade")
self.xml = gtk.glade.XML(glade_file,"booklist","gramps")
@ -531,7 +515,8 @@ class BookListDisplay:
if iter:
data = self.blist.get_data(iter,[0])
self.selection = self.booklist.get_book(data[0])
self.booklist.save()
if self.dosave:
self.booklist.save()
def on_booklist_delete_clicked(self,obj):
"""
@ -550,6 +535,31 @@ class BookListDisplay:
def on_booklist_cancel_clicked(self,obj):
pass
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class BookOptions:
"""
Defines options and provides handling interface.
"""
def __init__(self,name,person_id=None):
# Options specific for this report
self.options_dict = {
'bookname' : '',
}
self.options_help = {
'bookname' : ("=name","Name of the book. MANDATORY",
BookList('books.xml').get_book_names(),
False),
}
self.handler = ReportOptions.OptionHandler(name,
self.options_dict,person_id)
#-------------------------------------------------------------------------
#
# Book creation dialog
@ -668,10 +678,11 @@ class BookReportSelector:
for saved_item in book.get_item_list():
name = saved_item.get_name()
item = BookItem(name)
options = saved_item.get_options()
if not same_db or not options[0]:
options[0] = self.person.get_handle()
item.set_options(options)
item.option_class = saved_item.option_class
person_id = item.option_class.handler.get_person_id()
if not same_db or not person_id:
person_id = self.person.get_gramps_id()
item.option_class.handler.set_person_id(person_id)
item.set_style_name(saved_item.get_style_name())
self.book.append_item(item)
@ -679,7 +690,7 @@ class BookReportSelector:
if data[1] == _("Title"):
data.append(_("Not Applicable"))
else:
pname = self.db.get_person_from_handle(options[0])
pname = self.db.get_person_from_gramps_id(person_id)
data.append(pname.get_primary_name().get_regular_name())
self.bk_model.add(data)
@ -699,10 +710,10 @@ class BookReportSelector:
data.append(self.person.get_primary_name().get_regular_name())
self.bk_model.add(data)
item = BookItem(data[0])
options = item.get_options()
if not options[0]:
options[0] = self.person.get_handle()
item.set_options(options)
person_id = item.option_class.handler.get_person_id()
if not person_id:
person_id = self.person.get_gramps_id()
item.option_class.handler.set_person_id(person_id)
self.book.append_item(item)
def on_remove_clicked(self,obj):
@ -761,17 +772,14 @@ class BookReportSelector:
data = self.bk_model.get_data(iter,range(self.bk_ncols))
row = self.bk_model.get_selected_row()
item = self.book.get_item(row)
options_dialog = item.get_dialog()
options = item.get_options()
style_name = item.get_style_name()
opt_dlg = options_dialog(self.db,self.person,options,style_name)
opt_dlg.window.destroy()
if opt_dlg.person and data[1] != _("Title"):
option_class = item.option_class
item_dialog = BookItemDialog(self.db,option_class,data[0])
response = item_dialog.window.run()
if response == True and item_dialog.person and data[1] != _("Title"):
self.bk_model.model.set_value(iter,2,
opt_dlg.person.get_primary_name().get_regular_name())
item.set_options(opt_dlg.options)
item.set_style_name(opt_dlg.style_name)
self.book.set_item(row,item)
item_dialog.person.get_primary_name().get_regular_name())
self.book.set_item(row,item)
item_dialog.window.destroy()
def bk_button_press(self,obj,event):
"""
@ -852,7 +860,7 @@ class BookReportSelector:
Run final BookReportDialog with the current book.
"""
if self.book.item_list:
BookReportDialog(self.db,self.person,self.book)
BookReportDialog(self.db,self.person,self.book,BookOptions)
self.top.destroy()
def on_save_clicked(self,obj):
@ -871,20 +879,56 @@ class BookReportSelector:
Run the BookListDisplay dialog to present the choice of books to open.
"""
self.book_list = BookList(self.file)
booklistdisplay = BookListDisplay(self.book_list,1)
booklistdisplay = BookListDisplay(self.book_list,1,0)
booklistdisplay.top.destroy()
book = booklistdisplay.selection
if book:
self.open_book(book)
self.name_entry.set_text(book.get_name())
def on_edit_clicked(self,obj):
"""
Run the BookListDisplay dialog to present the choice of books to delete.
"""
self.book_list = BookList(self.file)
booklistdisplay = BookListDisplay(self.book_list)
booklistdisplay = BookListDisplay(self.book_list,0,1)
booklistdisplay.top.destroy()
#------------------------------------------------------------------------
#
# Book Item Options dialog
#
#------------------------------------------------------------------------
class BookItemDialog(Report.BareReportDialog):
"""
This class overrides the interface methods common for different reports
in a way specific for this report. This is a book item dialog.
"""
def __init__(self,database,option_class,name=''):
self.database = database
self.option_class = option_class
self.person = self.database.get_person_from_gramps_id(self.option_class.handler.get_person_id())
self.new_person = None
Report.BareReportDialog.__init__(self,database,self.person,option_class,name)
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Parse all options
and close the window."""
# Preparation
self.parse_style_frame()
self.parse_report_options_frame()
self.parse_user_options()
if self.new_person:
self.person = self.new_person
self.option_class.handler.set_person_id(self.person.get_gramps_id())
self.options.handler.save_options()
#------------------------------------------------------------------------
#
# The final dialog - paper, format, target, etc.
@ -897,8 +941,9 @@ class BookReportDialog(Report.ReportDialog):
Creates a dialog selecting target, format, and paper/HTML options.
"""
def __init__(self,database,person,book):
Report.BareReportDialog.__init__(self,database,person)
def __init__(self,database,person,book,options):
self.options = options
Report.BareReportDialog.__init__(self,database,person,options,'book')
self.book = book
self.database = database
self.person = person
@ -907,21 +952,29 @@ class BookReportDialog(Report.ReportDialog):
for item in self.book.get_item_list():
# Set up default style
default_style = BaseDoc.StyleSheet()
make_default_style = item.get_make_default_style()
make_default_style = item.option_class.make_default_style
make_default_style(default_style)
# Read all style sheets available for this item
style_file = item.get_style_file()
style_file = item.option_class.handler.get_stylesheet_savefile()
style_list = BaseDoc.StyleSheetList(style_file,default_style)
# Get the selected stylesheet
style_name = item.get_style_name()
style_name = item.option_class.handler.get_default_stylesheet_name()
style_sheet = style_list.get_style_sheet(style_name)
for this_style_name in style_sheet.get_names():
self.selected_style.add_style(
this_style_name,style_sheet.get_style(this_style_name))
response = self.window.run()
if response == True:
try:
self.make_report()
except (IOError,OSError),msg:
ErrorDialog(str(msg))
self.window.destroy()
def setup_style_frame(self): pass
def setup_report_options_frame(self): pass
def setup_other_frames(self): pass
@ -942,12 +995,12 @@ class BookReportDialog(Report.ReportDialog):
"""Needed solely for forming sane filename for the output."""
return "book.xml"
def make_doc_menu(self):
def make_doc_menu(self,active=None):
"""Build a menu of document types that are appropriate for
this text report. This menu will be generated based upon
whether the document requires table support, etc."""
Plugins.get_book_menu(self.format_menu, self.doc_uses_tables(),
self.doc_type_changed)
self.doc_type_changed,None,active)
def make_document(self):
"""Create a document of the type requested by the user."""
@ -957,13 +1010,13 @@ class BookReportDialog(Report.ReportDialog):
self.rptlist = []
newpage = 0
for item in self.book.get_item_list():
write_book_item = item.get_write_item()
options = item.get_options()
if write_book_item:
obj = write_book_item(self.database,self.person,
self.doc,options,newpage)
self.rptlist.append(obj)
newpage = 1
item.option_class.handler.doc = self.doc
item.option_class.handler.newpage = newpage
report_class = item.get_write_item()
obj = Report.write_book_item(self.database,self.person,
report_class,item.option_class)
self.rptlist.append(obj)
newpage = 1
self.doc.open(self.target_path)
def make_report(self):
@ -977,24 +1030,76 @@ class BookReportDialog(Report.ReportDialog):
#------------------------------------------------------------------------
#
# Function to register the overall book report
# Function to write books from command line
#
#------------------------------------------------------------------------
def report(database,person):
BookReportSelector(database,person)
def cl_report(database,name,category,options_str_dict):
clr = Report.CommandLineReport(database,name,category,BookOptions,options_str_dict)
# Exit here if show option was given
if clr.show:
return
book_list = BookList('books.xml')
book_name = clr.options_dict['bookname']
book = book_list.get_book(book_name)
selected_style = BaseDoc.StyleSheet()
for item in book.get_item_list():
# Set up default style
default_style = BaseDoc.StyleSheet()
make_default_style = item.option_class.make_default_style
make_default_style(default_style)
# Read all style sheets available for this item
style_file = item.option_class.handler.get_stylesheet_savefile()
style_list = BaseDoc.StyleSheetList(style_file,default_style)
# Get the selected stylesheet
style_name = item.option_class.handler.get_default_stylesheet_name()
style_sheet = style_list.get_style_sheet(style_name)
for this_style_name in style_sheet.get_names():
selected_style.add_style(
this_style_name,style_sheet.get_style(this_style_name))
# write report
try:
doc = clr.format(selected_style,clr.paper,clr.template_name,clr.orien)
rptlist = []
newpage = 0
for item in book.get_item_list():
item.option_class.handler.doc = doc
item.option_class.handler.newpage = newpage
report_class = item.get_write_item()
obj = Report.write_book_item(database,clr.person,
report_class,item.option_class)
rptlist.append(obj)
newpage = 1
doc.open(clr.option_class.handler.output)
doc.init()
for item in rptlist:
item.write_report()
doc.close()
except:
import DisplayTrace
DisplayTrace.DisplayTrace()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
Plugins.register_report(
report,
_("Book Report"),
category=_("Books"),
status=(_("Unstable")),
description=_("Creates a book containing several reports."),
author_name="Alex Roitman",
author_email="shura@alex.neuro.umn.edu"
name = 'book',
category = const.CATEGORY_BOOK,
report_class = BookReportSelector,
options_class = cl_report,
modes = Report.MODE_GUI | Report.MODE_CLI,
translated_name = _("Book Report"),
status = _("Beta"),
description = _("Creates a book containing several reports."),
author_name = "Alex Roitman",
author_email = "shura@alex.neuro.umn.edu"
)

View File

@ -33,6 +33,7 @@
import os
import string
import cStringIO
from gettext import gettext as _
#------------------------------------------------------------------------
#
@ -44,8 +45,17 @@ import BaseDoc
import RelLib
import Errors
import Utils
import ReportOptions
from QuestionDialog import ErrorDialog
from gettext import gettext as _
import DateHandler
import const
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
dd = DateHandler.create_display()
#------------------------------------------------------------------------
#
@ -54,16 +64,47 @@ from gettext import gettext as _
#------------------------------------------------------------------------
class FtmDescendantReport(Report.Report):
def __init__(self,database,person,max,pgbrk,doc,output,newpage=0):
self.anc_map = {}
self.gen_map = {}
def __init__(self,database,person,options_class):
"""
Creates the Ftm-Style Descendant object that produces the report.
The arguments are:
database - the GRAMPS database instance
person - currently selected person
options_class - instance of the Options class for this report
This report needs the following parameters (class variables)
that come in the options class.
max_gen - Maximum number of generations to include.
pg_breaks - Whether to include page breaks between generations.
document - BaseDoc instance for the output file. Any class derived
from BaseDoc may be used
output - name of the output file.
None if report is not a standalone, in which case
somebody must take care of opening and initializing report
prior to writing.
newpage - if True, newpage is made before writing a report
"""
self.database = database
self.start = person
self.max_generations = max
self.pgbrk = pgbrk
self.doc = doc
self.options_class = options_class
self.anc_map = {}
self.gen_map = {}
(self.max_generations,self.pgbrk) \
= options_class.handler.get_report_generations()
self.doc = options_class.handler.doc
output = options_class.handler.output
self.newpage = options_class.handler.newpage
self.setup()
self.newpage = newpage
if output:
self.standalone = 1
self.doc.open(output)
@ -482,7 +523,7 @@ class FtmDescendantReport(Report.Report):
self.doc.write_text(base.get_title())
for item in [ base.get_author(), base.get_publication_info(), base.get_abbreviation(),
srcref.get_date().get_date(),]:
dd.display(srcref.get_date()),]:
if item:
self.doc.write_text('; %s' % item)
@ -991,7 +1032,7 @@ class FtmDescendantReport(Report.Report):
self.doc.end_row()
if not first:
self.doc.end_table()
self.doc.end_table()
first = 1
@ -1448,244 +1489,89 @@ class FtmDescendantReport(Report.Report):
#
#
#------------------------------------------------------------------------
def _make_default_style(default_style):
"""Make the default output style for the FTM Style Descendant report."""
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SANS_SERIF,size=16,bold=1,italic=1)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set_header_level(1)
para.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
para.set(pad=0.5)
para.set_description(_('The style used for the title of the page.'))
default_style.add_style("FTD-Title",para)
class FtmDescendantOptions:
"""
Defines options and provides handling interface.
"""
def __init__(self,name,person_id=None):
# Options specific for this report
self.options_dict = {}
self.options_help = {}
# Semi-common options that should be enabled for this report
self.enable_dict = {
'max_gen' : 10,
'page_breaks' : 0,
}
self.options_dict.update(self.enable_dict)
self.handler = ReportOptions.OptionHandler(name,
self.options_dict,person_id)
def make_default_style(self,default_style):
"""Make the default output style for the FTM Style Descendant report."""
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SANS_SERIF,size=16,bold=1,italic=1)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set_header_level(1)
para.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
para.set(pad=0.5)
para.set_description(_('The style used for the title of the page.'))
default_style.add_style("FTD-Title",para)
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SANS_SERIF,size=14,italic=1)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set_header_level(2)
para.set(pad=0.5)
para.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
para.set_description(_('The style used for the generation header.'))
default_style.add_style("FTD-Generation",para)
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SANS_SERIF,size=14,italic=1)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set_header_level(2)
para.set(pad=0.5)
para.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
para.set_description(_('The style used for the generation header.'))
default_style.add_style("FTD-Generation",para)
para = BaseDoc.ParagraphStyle()
para.set(first_indent=-1.0,lmargin=1.0,pad=0.25)
para.set_description(_('The basic style used for the text display.'))
default_style.add_style("FTD-Entry",para)
para = BaseDoc.ParagraphStyle()
para.set(first_indent=-1.0,lmargin=1.0,pad=0.25)
para.set_description(_('The basic style used for the text display.'))
default_style.add_style("FTD-Entry",para)
para = BaseDoc.ParagraphStyle()
para.set(lmargin=1.0,pad=0.05)
para.set_description(_('The basic style used for the text display.'))
default_style.add_style("FTD-Details",para)
para = BaseDoc.ParagraphStyle()
para.set(lmargin=1.0,pad=0.05)
para.set_description(_('The basic style used for the text display.'))
default_style.add_style("FTD-Details",para)
para = BaseDoc.ParagraphStyle()
para.set(lmargin=0.0,pad=0.05)
para.set_description(_('The style used for numbering children.'))
default_style.add_style("FTD-Child-Num",para)
para = BaseDoc.ParagraphStyle()
para.set(lmargin=0.0,pad=0.05)
para.set_description(_('The style used for numbering children.'))
default_style.add_style("FTD-Child-Num",para)
para = BaseDoc.ParagraphStyle()
para.set(lmargin=1.0,pad=0.25)
para.set_description(_('The basic style used for the text display.'))
default_style.add_style("FTD-SubEntry",para)
para = BaseDoc.ParagraphStyle()
para.set(pad=0.05)
para.set_description(_('The basic style used for the text display.'))
default_style.add_style("FTD-Endnotes",para)
para = BaseDoc.ParagraphStyle()
para.set(lmargin=1.0,pad=0.25)
para.set_description(_('The basic style used for the text display.'))
default_style.add_style("FTD-SubEntry",para)
#------------------------------------------------------------------------
#
# Dialog for a standalone report
#
#------------------------------------------------------------------------
class FtmDescendantReportDialog(Report.TextReportDialog):
report_options = {}
def __init__(self,database,person):
Report.TextReportDialog.__init__(self,database,person,self.report_options)
#------------------------------------------------------------------------
#
# Customization hooks
#
#------------------------------------------------------------------------
def get_title(self):
"""The window title for this dialog"""
return "%s - %s - GRAMPS" % (_("FTM Style Descendant Report"),_("Text Reports"))
def get_header(self, name):
"""The header line at the top of the dialog contents"""
return _("FTM Style Descendant Report for %s") % name
def get_target_browser_title(self):
"""The title of the window created when the 'browse' button is
clicked in the 'Save As' frame."""
return _("Save FTM Style Descendant Report")
def get_stylesheet_savefile(self):
"""Where to save styles for this report."""
return "ftm_descendant_report.xml"
def make_default_style(self):
_make_default_style(self.default_style)
def make_report(self):
"""Create the object that will produce the FTM Style Descendant Report.
All user dialog has already been handled and the output file
opened."""
try:
MyReport = FtmDescendantReport(self.db, self.person,
self.max_gen, self.pg_brk, self.doc, self.target_path)
MyReport.write_report()
except Errors.ReportError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except Errors.FilterError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except:
import DisplayTrace
DisplayTrace.DisplayTrace()
#------------------------------------------------------------------------
#
# Standalone report function
#
#------------------------------------------------------------------------
def report(database,person):
FtmDescendantReportDialog(database,person)
#------------------------------------------------------------------------
#
# Set up sane defaults for the book_item
#
#------------------------------------------------------------------------
_style_file = "ftm_descendant_report.xml"
_style_name = "default"
_person_handle = ""
_max_gen = 10
_pg_brk = 0
_options = ( _person_handle, _max_gen, _pg_brk )
#------------------------------------------------------------------------
#
# Book Item Options dialog
#
#------------------------------------------------------------------------
class FtmDescendantBareReportDialog(Report.BareReportDialog):
def __init__(self,database,person,opt,stl):
self.options = opt
self.db = database
if self.options[0]:
self.person = self.db.get_person_from_handle(self.options[0])
else:
self.person = person
self.style_name = stl
Report.BareReportDialog.__init__(self,database,self.person)
self.max_gen = int(self.options[1])
self.pg_brk = int(self.options[2])
self.new_person = None
self.generations_spinbox.set_value(self.max_gen)
self.pagebreak_checkbox.set_active(self.pg_brk)
self.window.run()
#------------------------------------------------------------------------
#
# Customization hooks
#
#------------------------------------------------------------------------
def get_title(self):
"""The window title for this dialog"""
return "%s - GRAMPS Book" % (_("FTM Style Descendant Report"))
def get_header(self, name):
"""The header line at the top of the dialog contents"""
return _("FTM Style Descendant Report for GRAMPS Book")
def get_stylesheet_savefile(self):
"""Where to save styles for this report."""
return _style_file
def make_default_style(self):
_make_default_style(self.default_style)
def on_cancel(self, obj):
pass
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Parse all options
and close the window."""
# Preparation
self.parse_style_frame()
self.parse_report_options_frame()
if self.new_person:
self.person = self.new_person
self.options = ( self.person.get_handle(), self.max_gen, self.pg_brk )
self.style_name = self.selected_style.get_name()
#------------------------------------------------------------------------
#
# Function to write Book Item
#
#------------------------------------------------------------------------
def write_book_item(database,person,doc,options,newpage=0):
"""Write the FTM Style Descendant Report options set.
All user dialog has already been handled and the output file opened."""
try:
if options[0]:
person = database.get_person_from_handle(options[0])
max_gen = int(options[1])
pg_brk = int(options[2])
return FtmDescendantReport(database, person, max_gen,
pg_brk, doc, None, newpage )
except Errors.ReportError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except Errors.FilterError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except:
import DisplayTrace
DisplayTrace.DisplayTrace()
para = BaseDoc.ParagraphStyle()
para.set(pad=0.05)
para.set_description(_('The basic style used for the text display.'))
default_style.add_style("FTD-Endnotes",para)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
from Plugins import register_report, register_book_item
from Plugins import register_report
register_report(
report,
_("FTM Style Descendant Report"),
category=_("Text Reports"),
status=(_("Beta")),
name = 'ftm_descendant_report',
category = const.CATEGORY_TEXT,
report_class = FtmDescendantReport,
options_class = FtmDescendantOptions,
modes = Report.MODE_GUI | Report.MODE_BKI | Report.MODE_CLI,
translated_name = _("FTM Style Descendant Report"),
status = _("Beta"),
description= _("Produces a textual descendant report similar to Family Tree Maker."),
author_name="Alex Roitman",
author_email="shura@alex.neuro.umn.edu"
)
# (name,category,options_dialog,write_book_item,options,style_name,style_file,make_default_style)
register_book_item(
_("FTM Style Descendant Report"),
_("Text"),
FtmDescendantBareReportDialog,
write_book_item,
_options,
_style_name,
_style_file,
_make_default_style
)

View File

@ -30,6 +30,7 @@ Timeline report
#
#------------------------------------------------------------------------
import os
from gettext import gettext as _
#------------------------------------------------------------------------
#
@ -50,9 +51,9 @@ import GenericFilter
import Errors
import Date
import Sort
import ReportOptions
from QuestionDialog import ErrorDialog
from gettext import gettext as _
import const
#------------------------------------------------------------------------
#
@ -61,31 +62,59 @@ from gettext import gettext as _
#------------------------------------------------------------------------
class TimeLine:
def __init__(self,database,person,filter,title,sort_func,document,output,newpage=0):
def __init__(self,database,person,options_class):
"""
Creates the Timeline object that produces the report. This class
is used by the TimelineDialog class. The arguments are:
Creates the Timeline object that produces the report.
The arguments are:
database - the GRAMPS database instance
person - currently selected person
options_class - instance of the Options class for this report
This report needs the following parameters (class variables)
that come in the options class.
filter - Filter to be applied to the people of the database.
The option class carries its number, and the function
returning the list of filters.
title - Title of the report displayed on top
sort_func - function used to sort entries, that returns -1/0/1
when given two personal handles (like cmp).
The option class carries its number, and the function
returning the list of sort functions.
document - BaseDoc instance for the output file. Any class derived
from BaseDoc may be used
output - name of the output file.
None if report is not a standalone, in which case
somebody must take care of opening and initializing report
prior to writing.
newpage - if True, newpage is made before writing a report
database - the GRAMPS database
person - currently selected person
output - name of the output file
document - BaseDoc instance for the output file. Any class derived
from BaseDoc may be used.
filter - filtering function selected by the TimeLineDialog
class.
"""
self.d = document
self.filter = filter
self.db = database
self.person = person
self.output = output
self.title = title
self.sort_func = sort_func
self.newpage = newpage
self.options_class = options_class
filter_num = options_class.handler.get_filter_number()
filters = options_class.get_report_filters(person)
self.filter = filters[filter_num]
self.title = options_class.handler.options_dict['title']
sort_func_num = options_class.handler.options_dict['sortby']
sort_functions = options_class.get_sort_functions(Sort.Sort(database))
self.sort_func = sort_functions[sort_func_num][1]
self.d = options_class.handler.doc
self.output = options_class.handler.output
self.newpage = options_class.handler.newpage
self.setup()
if output:
if self.output:
self.standalone = 1
self.d.open(output)
self.d.open(self.output)
self.d.init()
else:
self.standalone = 0
@ -168,7 +197,7 @@ class TimeLine:
font = self.d.style_list['TLG-Name'].get_font()
incr = pt2cm(font.get_size())
incr = Utils.pt2cm(font.get_size())
pad = incr*.75
x1,x2,y1,y2 = (0,0,0,0)
@ -267,7 +296,7 @@ class TimeLine:
self.d.center_text('TLG-title',self.title,width/2.0,0)
label_y = self.header - (pt2cm(normal_font.get_size())*1.2)
label_y = self.header - (Utils.pt2cm(normal_font.get_size())*1.2)
top_y = self.header
bottom_y = self.d.get_usable_height()
@ -330,373 +359,156 @@ class TimeLine:
p = self.db.get_person_from_handle(p_id)
n = p.get_primary_name().get_name()
size = max(self.d.string_width(font,n),size)
return pt2cm(size)
return Utils.pt2cm(size)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def _make_default_style(default_style):
"""Make the default output style for the Timeline report."""
f = BaseDoc.FontStyle()
f.set_size(10)
f.set_type_face(BaseDoc.FONT_SANS_SERIF)
p = BaseDoc.ParagraphStyle()
p.set_font(f)
p.set_description(_("The style used for the person's name."))
default_style.add_style("TLG-Name",p)
class TimeLineOptions:
f = BaseDoc.FontStyle()
f.set_size(8)
f.set_type_face(BaseDoc.FONT_SANS_SERIF)
p = BaseDoc.ParagraphStyle()
p.set_font(f)
p.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
p.set_description(_("The style used for the year labels."))
default_style.add_style("TLG-Label",p)
"""
Defines options and provides handling interface.
"""
f = BaseDoc.FontStyle()
f.set_size(14)
f.set_type_face(BaseDoc.FONT_SANS_SERIF)
p = BaseDoc.ParagraphStyle()
p.set_font(f)
p.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
p.set_description(_("The style used for the title of the page."))
default_style.add_style("TLG-Title",p)
def __init__(self,name,person_id=None):
# Options specific for this report
self.options_dict = {
'sortby' : 0,
'title' : '',
}
self.options_help = {
'sortby' : ("=num","Number of a sorting function",
[item[0] for item in
self.get_sort_functions(Sort.Sort(None))],
True),
'title' : ("=str","Title string for the report",
"Whatever String You Wish"),
}
#------------------------------------------------------------------------
#
# Builds filter list for this report
#
#------------------------------------------------------------------------
def _get_report_filters(person):
"""Set up the list of possible content filters."""
# Semi-common options that should be enabled for this report
self.enable_dict = {
'filter' : 0,
}
name = person.get_primary_name().get_name()
all = GenericFilter.GenericFilter()
all.set_name(_("Entire Database"))
all.add_rule(GenericFilter.Everyone([]))
self.options_dict.update(self.enable_dict)
self.handler = ReportOptions.OptionHandler(name,
self.options_dict,person_id)
des = GenericFilter.GenericFilter()
des.set_name(_("Descendants of %s") % name)
des.add_rule(GenericFilter.IsDescendantOf([person.get_handle(),1]))
def make_default_style(self,default_style):
"""Make the default output style for the Timeline report."""
f = BaseDoc.FontStyle()
f.set_size(10)
f.set_type_face(BaseDoc.FONT_SANS_SERIF)
p = BaseDoc.ParagraphStyle()
p.set_font(f)
p.set_description(_("The style used for the person's name."))
default_style.add_style("TLG-Name",p)
ans = GenericFilter.GenericFilter()
ans.set_name(_("Ancestors of %s") % name)
ans.add_rule(GenericFilter.IsAncestorOf([person.get_handle(),1]))
f = BaseDoc.FontStyle()
f.set_size(8)
f.set_type_face(BaseDoc.FONT_SANS_SERIF)
p = BaseDoc.ParagraphStyle()
p.set_font(f)
p.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
p.set_description(_("The style used for the year labels."))
default_style.add_style("TLG-Label",p)
com = GenericFilter.GenericFilter()
com.set_name(_("People with common ancestor with %s") % name)
com.add_rule(GenericFilter.HasCommonAncestorWith([person.get_handle()]))
return [all,des,ans,com]
#------------------------------------------------------------------------
#
# Builds list of sorting functions for this report
#
#------------------------------------------------------------------------
def _get_sort_functions(sort):
return [
(_("Birth Date"),sort.by_birthdate),
(_("Name"),sort.by_last_name),
]
#------------------------------------------------------------------------
#
# TimeLineDialog
#
#------------------------------------------------------------------------
class TimeLineDialog(Report.DrawReportDialog):
report_options = {}
def __init__(self,database,person):
self.database = database
Report.DrawReportDialog.__init__(self,database,person,self.report_options)
def get_title(self):
"""The window title for this dialog"""
return "%s - %s - GRAMPS" % (_("Timeline Graph"),
_("Graphical Reports"))
def get_header(self, name):
"""The header line at the top of the dialog contents."""
return _("Timeline Graph for %s") % name
def get_stylesheet_savefile(self):
"""Where to save user defined styles for this report."""
return _style_file
def get_target_browser_title(self):
"""The title of the window created when the 'browse' button is
clicked in the 'Save As' frame."""
return _("Timeline File")
def get_report_generations(self):
"""No generation options."""
return (0, 0)
f = BaseDoc.FontStyle()
f.set_size(14)
f.set_type_face(BaseDoc.FONT_SANS_SERIF)
p = BaseDoc.ParagraphStyle()
p.set_font(f)
p.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
p.set_description(_("The style used for the title of the page."))
default_style.add_style("TLG-Title",p)
def add_user_options(self):
"""
Override the base class add_user_options task to add a menu that allows
the user to select the sort method.
"""
self.sort_style = gtk.OptionMenu()
self.sort_menu = gtk.Menu()
sort_functions = _get_sort_functions(Sort.Sort(self.database))
for item in sort_functions:
menuitem = gtk.MenuItem(item[0])
menuitem.set_data('sort',item[1])
menuitem.show()
self.sort_menu.append(menuitem)
self.sort_style.set_menu(self.sort_menu)
self.add_option(_('Sort by'),self.sort_style)
self.title_box = gtk.Entry()
self.title_box.set_text(self.get_header(self.person.get_primary_name().get_name()))
self.title_box.show()
self.add_option(_('Title'),self.title_box)
def get_report_filters(self):
return _get_report_filters(self.person)
def make_default_style(self):
_make_default_style(self.default_style)
def make_report(self):
title = unicode(self.title_box.get_text())
sort_func = self.sort_menu.get_active().get_data('sort')
try:
MyReport = TimeLine(self.db, self.person,
self.filter, title, sort_func, self.doc, self.target_path)
MyReport.write_report()
except Errors.FilterError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except Errors.ReportError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except:
import DisplayTrace
DisplayTrace.DisplayTrace()
#------------------------------------------------------------------------
#
# point to centimeter convertion
#
#------------------------------------------------------------------------
def pt2cm(val):
return (float(val)/28.3465)
#------------------------------------------------------------------------
#
# entry point
#
#------------------------------------------------------------------------
def report(database,person):
"""
report - task starts the report. The plugin system requires that the
task be in the format of task that takes a database and a person as
its arguments.
"""
TimeLineDialog(database,person)
def get_description():
"""
get_description - returns a descriptive name for the report. The plugin
system uses this to provide a description in the report selector.
"""
return _("Generates a timeline graph.")
#------------------------------------------------------------------------
#
# Set up sane defaults for the book_item
#
#------------------------------------------------------------------------
_style_file = "timeline.xml"
_style_name = "default"
_person_handle = ""
_filter_num = 0
_sort_func_num = 0
_title_str = ""
_options = ( _person_handle, _filter_num, _sort_func_num, _title_str )
#------------------------------------------------------------------------
#
# Book Item Options dialog
#
#------------------------------------------------------------------------
class TimeLineBareDialog(Report.BareReportDialog):
def __init__(self,database,person,opt,stl):
self.options = opt
self.db = database
if self.options[0]:
self.person = self.db.get_person_from_handle(self.options[0])
def get_report_filters(self,person):
"""Set up the list of possible content filters."""
if person:
name = person.get_primary_name().get_name()
handle = person.get_handle()
else:
self.person = person
self.style_name = stl
name = 'PERSON'
handle = ''
Report.BareReportDialog.__init__(self,database,self.person)
all = GenericFilter.GenericFilter()
all.set_name(_("Entire Database"))
all.add_rule(GenericFilter.Everyone([]))
self.filter_num = int(self.options[1])
self.sort_func_num = int(self.options[2])
self.title_str = self.options[3]
self.new_person = None
des = GenericFilter.GenericFilter()
des.set_name(_("Descendants of %s") % name)
des.add_rule(GenericFilter.IsDescendantOf([handle,1]))
self.filter_combo.set_history(self.filter_num)
self.sort_style.set_history(self.sort_func_num)
self.title_box.set_text(self.title_str)
ans = GenericFilter.GenericFilter()
ans.set_name(_("Ancestors of %s") % name)
ans.add_rule(GenericFilter.IsAncestorOf([handle,1]))
self.window.run()
com = GenericFilter.GenericFilter()
com.set_name(_("People with common ancestor with %s") % name)
com.add_rule(GenericFilter.HasCommonAncestorWith([handle]))
#------------------------------------------------------------------------
#
# Customization hooks
#
#------------------------------------------------------------------------
def get_title(self):
"""The window title for this dialog"""
return "%s - GRAMPS Book" % (_("Timeline Graph"))
return [all,des,ans,com]
def get_header(self, name):
"""The header line at the top of the dialog contents"""
return _("Timeline Graph for GRAMPS Book")
def get_sort_functions(self,sort):
return [
(_("Birth Date"),sort.by_birthdate),
(_("Name"),sort.by_last_name),
]
def get_stylesheet_savefile(self):
"""Where to save styles for this report."""
return _style_file
def get_report_generations(self):
"""No generations, no page breaks."""
return (0, 0)
def add_user_options(self):
def add_user_options(self,dialog):
"""
Override the base class add_user_options task to add a menu that allows
the user to select the sort method.
"""
self.sort_style = gtk.OptionMenu()
sort_style = gtk.OptionMenu()
self.sort_menu = gtk.Menu()
sort_functions = _get_sort_functions(Sort.Sort(self.db))
for item in sort_functions:
sort_functions = self.get_sort_functions(Sort.Sort(dialog.db))
for item_index in range(len(sort_functions)):
item = sort_functions[item_index]
menuitem = gtk.MenuItem(item[0])
menuitem.set_data('sort',item[1])
menuitem.set_data('index',item_index)
menuitem.show()
self.sort_menu.append(menuitem)
self.sort_style.set_menu(self.sort_menu)
self.add_option(_('Sort by'),self.sort_style)
sort_style.set_menu(self.sort_menu)
sort_style.set_history(self.options_dict['sortby'])
dialog.add_option(_('Sort by'),sort_style)
self.title_box = gtk.Entry()
if self.options_dict['title']:
self.title_box.set_text(self.options_dict['title'])
else:
self.title_box.set_text(dialog.get_header(dialog.person.get_primary_name().get_name()))
self.title_box.show()
self.add_option(_('Title'),self.title_box)
dialog.add_option(_('Title'),self.title_box)
def make_default_style(self):
_make_default_style(self.default_style)
def get_report_filters(self):
return _get_report_filters(self.person)
def on_cancel(self, obj):
pass
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Parse all options
and close the window."""
# Preparation
self.parse_style_frame()
if self.new_person:
self.person = self.new_person
self.filter_num = self.filter_combo.get_history()
self.sort_func_num = self.sort_style.get_history()
self.title_str = unicode(self.title_box.get_text())
self.options = ( self.person.get_handle(), self.filter_num,
self.sort_func_num, self.title_str )
self.style_name = self.selected_style.get_name()
def parse_user_options(self,dialog):
"""
Parses the custom options that we have added.
"""
self.options_dict['title'] = unicode(self.title_box.get_text())
self.options_dict['sortby'] = self.sort_menu.get_active().get_data('index')
#------------------------------------------------------------------------
#
# Function to write Book Item
#
#
#------------------------------------------------------------------------
def write_book_item(database,person,doc,options,newpage=0):
"""Write the Timeline Graph using options set.
All user dialog has already been handled and the output file opened."""
try:
if options[0]:
person = database.get_person_from_handle(options[0])
filter_num = int(options[1])
filters = _get_report_filters(person)
afilter = filters[filter_num]
sort_func_num = int(options[2])
sort_functions = _get_sort_functions(Sort.Sort(database))
sort_func = sort_functions[sort_func_num][1]
title_str = options[3]
return TimeLine(database, person,
afilter, title_str, sort_func, doc, None, newpage )
except Errors.ReportError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except Errors.FilterError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
except:
import DisplayTrace
DisplayTrace.DisplayTrace()
#------------------------------------------------------------------------
#
# Register the TimeLine report with the plugin system. The register_report
# task of the Plugins module takes the following arguments.
#
# task - function that starts the task
# name - Name of the report
# status - alpha/beta/production
# category - Category entry in the menu system.
# author_name - Name of the author
# author_email - Author's email address
# description - function that returns the description of the report
#
#------------------------------------------------------------------------
from Plugins import register_report, register_book_item
from Plugins import register_report
register_report(
task=report,
name=_("Timeline Graph"),
status=(_("Beta")),
category=_("Graphical Reports"),
author_name="Donald N. Allingham",
author_email="dallingham@users.sourceforge.net",
description=get_description()
)
# (name,category,options_dialog,write_book_item,options,style_name,style_file,make_default_style)
register_book_item(
_("Timeline Graph"),
_("Graphics"),
TimeLineBareDialog,
write_book_item,
_options,
_style_name,
_style_file,
_make_default_style
name = 'timeline',
category = const.CATEGORY_DRAW,
report_class = TimeLine,
options_class = TimeLineOptions,
modes = Report.MODE_GUI | Report.MODE_BKI | Report.MODE_CLI,
translated_name = _("Timeline Graph"),
status = _("Beta"),
author_name = "Donald N. Allingham",
author_email = "dallingham@users.sourceforge.net",
description = _("Generates a timeline graph.")
)