gramps/src/ReportBase/_CommandLineReport.py

402 lines
16 KiB
Python

#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2007 Donald N. Allingham
# Copyright (C) 2008 Lukasz Rymarczyk
# Copyright (C) 2008 Raphael Ackermann
# Copyright (C) 2008 Brian G. Matherly
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import sys
import logging
log = logging.getLogger(".")
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
import gen
import Utils
import BaseDoc
from BasicUtils import name_displayer
from ReportBase import CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK, \
CATEGORY_GRAPHVIZ
from _PaperMenu import paper_sizes
import os
import const
#------------------------------------------------------------------------
#
# Private Functions
#
#------------------------------------------------------------------------
def _validate_options(options, dbase):
"""
Validate all options by making sure that their values are consistent with
the database.
menu: The Menu class
dbase: the database the options will be applied to
"""
if not hasattr(options, "menu"):
return
menu = options.menu
for name in menu.get_all_option_names():
option = menu.get_option_by_name(name)
if isinstance(option, gen.plug.menu.PersonOption):
pid = option.get_value()
person = dbase.get_person_from_gramps_id(pid)
if not person:
person = dbase.get_default_person()
if not person:
phandle = dbase.get_person_handles()[0]
person = dbase.get_person_from_handle(phandle)
if not person:
print "Please specify a person"
if person:
option.set_value(person.get_gramps_id())
elif isinstance(option, gen.plug.menu.FamilyOption):
fid = option.get_value()
family = dbase.get_family_from_gramps_id(fid)
if not family:
person = dbase.get_default_person()
family_list = person.get_family_handle_list()
if family_list:
family_handle = family_list[0]
else:
family_handle = dbase.get_family_handles()[0]
family = dbase.get_family_from_handle(family_handle)
option.set_value(family.get_gramps_id())
#------------------------------------------------------------------------
#
# Command-line report
#
#------------------------------------------------------------------------
class CommandLineReport:
"""
Provide a way to generate report from the command line.
"""
def __init__(self, database, name, category, option_class, options_str_dict,
noopt=False):
self.database = database
self.category = category
self.format = None
self.option_class = option_class(name, database)
self.option_class.load_previous_values()
_validate_options(self.option_class, database)
self.show = options_str_dict.pop('show', None)
self.options_str_dict = options_str_dict
self.init_standard_options(noopt)
self.init_report_options()
self.parse_options()
self.show_options()
def init_standard_options(self, noopt):
"""
Initialize the options that are hard-coded into the report system.
"""
pmgr = gen.plug.PluginManager.get_instance()
_textdoc_list = pmgr.get_text_doc_list()
_drawdoc_list = pmgr.get_draw_doc_list()
_bookdoc_list = pmgr.get_book_doc_list()
self.options_dict = {
'of' : self.option_class.handler.module_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_template_name(),
}
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).", ""],
}
if noopt:
return
self.options_help['of'][2] = os.path.join(const.USER_HOME,
"whatever_name")
if self.category == CATEGORY_TEXT:
self.options_help['off'][2] = \
[ item[6] for item in _textdoc_list ]
elif self.category == CATEGORY_DRAW:
self.options_help['off'][2] = \
[ item[6] for item in _drawdoc_list ]
elif self.category == CATEGORY_BOOK:
self.options_help['off'][2] = \
[ item[6] for item in _bookdoc_list ]
else:
self.options_help['off'][2] = "NA"
self.options_help['papers'][2] = \
[ paper.get_name() for paper in paper_sizes
if paper.get_name() != _("Custom Size") ]
self.options_help['papero'][2] = [
"%d\tPortrait" % BaseDoc.PAPER_PORTRAIT,
"%d\tLandscape" % BaseDoc.PAPER_LANDSCAPE ]
self.options_help['template'][2] = os.path.join(const.USER_HOME,
"whatever_name")
if self.category in (CATEGORY_TEXT, 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)
self.options_help['style'][2] = self.style_list.get_style_names()
def init_report_options(self):
"""
Initialize the options that are defined by each report.
"""
if not hasattr(self.option_class, "menu"):
return
menu = self.option_class.menu
for name in menu.get_all_option_names():
option = menu.get_option_by_name(name)
self.options_dict[name] = option.get_value()
self.options_help[name] = [ "", option.get_help() ]
if isinstance(option, gen.plug.menu.PersonOption):
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(),
name_displayer.display(person)))
self.options_help[name].append(id_list)
elif isinstance(option, gen.plug.menu.FamilyOption):
id_list = []
for fhandle in self.database.get_family_handles():
family = self.database.get_family_from_handle(fhandle)
mname = ""
fname = ""
mhandle = family.get_mother_handle()
if mhandle:
mother = self.database.get_person_from_handle(mhandle)
if mother:
mname = name_displayer.display(mother)
fhandle = family.get_father_handle()
if fhandle:
father = self.database.get_person_from_handle(fhandle)
if father:
fname = name_displayer.display(father)
text = "%s:\t%s, %s" % \
(family.get_gramps_id(), fname, mname)
id_list.append(text)
self.options_help[name].append(id_list)
elif isinstance(option, gen.plug.menu.NoteOption):
id_list = []
for nhandle in self.database.get_note_handles():
note = self.database.get_note_from_handle(nhandle)
id_list.append(note.get_gramps_id())
self.options_help[name].append(id_list)
elif isinstance(option, gen.plug.menu.MediaOption):
id_list = []
for mhandle in self.database.get_media_object_handles():
mobject = self.database.get_object_from_handle(mhandle)
id_list.append(mobject.get_gramps_id())
self.options_help[name].append(id_list)
elif isinstance(option, gen.plug.menu.PersonListOption):
self.options_help[name].append("")
elif isinstance(option, gen.plug.menu.NumberOption):
self.options_help[name].append("A number")
elif isinstance(option, gen.plug.menu.BooleanOption):
self.options_help[name].append(["0\tno", "1\tyes"])
elif isinstance(option, gen.plug.menu.DestinationOption):
self.options_help[name].append("A file system path")
elif isinstance(option, gen.plug.menu.StringOption):
self.options_help[name].append("Any text")
elif isinstance(option, gen.plug.menu.TextOption):
self.options_help[name].append("Any text")
elif isinstance(option, gen.plug.menu.EnumeratedListOption):
ilist = []
for (value, description) in option.get_items():
ilist.append("%s\t%s" % (value, description))
self.options_help[name].append(ilist)
else:
print "Unknown option: ", option
def parse_options(self):
"""
Load the options that the user has entered.
"""
if not hasattr(self.option_class, "menu"):
return
menu = self.option_class.menu
menu_opt_names = menu.get_all_option_names()
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]
if opt in menu_opt_names:
option = menu.get_option_by_name(opt)
option.set_value(self.options_dict[opt])
else:
print "Ignoring unknown option: %s" % opt
self.option_class.handler.output = self.options_dict['of']
pmgr = gen.plug.PluginManager.get_instance()
if self.category == CATEGORY_TEXT:
for item in pmgr.get_text_doc_list():
if item[7] == self.options_dict['off']:
self.format = item[1]
if self.format is None:
# Pick the first one as the default.
self.format = pmgr.get_text_doc_list()[0][1]
elif self.category == CATEGORY_DRAW:
for item in pmgr.get_draw_doc_list():
if item[6] == self.options_dict['off']:
self.format = item[1]
if self.format is None:
# Pick the first one as the default.
self.format = pmgr.get_draw_doc_list()[0][1]
elif self.category == CATEGORY_BOOK:
for item in pmgr.get_book_doc_list():
if item[6] == self.options_dict['off']:
self.format = item[1]
if self.format is None:
# Pick the first one as the default.
self.format = pmgr.get_book_doc_list()[0][1]
else:
self.format = None
for paper in paper_sizes:
if paper.get_name() == self.options_dict['papers']:
self.paper = paper
self.option_class.handler.set_paper(self.paper)
self.orien = self.options_dict['papero']
self.template_name = self.options_dict['template']
if self.category in (CATEGORY_TEXT, 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)
def show_options(self):
"""
Print available options on the CLI.
"""
if not self.show:
return
elif self.show == 'all':
print " Available options:"
for key in self.options_dict.keys():
if key in self.options_dict.keys():
# Make the output nicer to read, assume that tab has 8 spaces
if len(key) < 10:
print " %s\t\t%s (%s)" % (key,
self.options_help[key][1],
self.options_help[key][0])
else:
print " %s\t%s (%s)" % (key,
self.options_help[key][1],
self.options_help[key][0])
else:
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 isinstance(vals, (list, tuple)):
for val in vals:
print " %s" % val
else:
print " %s" % self.options_help[self.show][2]
else:
#there was a show option given, but the option is invalid
print ("option %s not valid. Use 'show=all' to see all valid "
"options." % self.show)
#------------------------------------------------------------------------
#
# Command-line report 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:
if category in [CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK, \
CATEGORY_GRAPHVIZ]:
clr.option_class.handler.doc = clr.format(
clr.selected_style,
BaseDoc.PaperStyle(clr.paper,clr.orien),
clr.template_name)
MyReport = report_class(database, clr.option_class)
MyReport.doc.init()
MyReport.begin_report()
MyReport.write_report()
MyReport.end_report()
except:
log.error("Failed to write report.", exc_info=True)