gramps/src/ReportOptions.py

606 lines
21 KiB
Python
Raw Normal View History

2004-12-22 07:26:37 +05:30
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2004 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
# Written by Alex Roitman
"""
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