Refactor various aspects of the report system.

svn: r9496
This commit is contained in:
Brian Matherly
2007-12-13 01:52:03 +00:00
parent 20e2ecfe50
commit 05575ad026
38 changed files with 663 additions and 502 deletions

View File

@@ -42,7 +42,6 @@ import gtk
#-------------------------------------------------------------------------
from BasicUtils import name_displayer
import BaseDoc
import Utils
import ManagedWindow
from _StyleComboBox import StyleComboBox
@@ -90,6 +89,8 @@ class BareReportDialog(ManagedWindow.ManagedWindow):
elif type(option_class) == InstanceType:
self.options = option_class
self.options.load_previous_values()
self.init_interface()
def build_window_key(self,obj):
@@ -153,8 +154,6 @@ class BareReportDialog(ManagedWindow.ManagedWindow):
self.notebook.set_border_width(6)
self.window.vbox.add(self.notebook)
self.setup_paper_frame()
self.setup_html_frame()
self.setup_report_options_frame()
self.setup_other_frames()
self.notebook.set_current_page(0)
@@ -429,14 +428,6 @@ class BareReportDialog(ManagedWindow.ManagedWindow):
def setup_format_frame(self):
"""Not used in bare report dialogs. Override in the subclass."""
pass
def setup_paper_frame(self):
"""Not used in bare report dialogs. Override in the subclass."""
pass
def setup_html_frame(self):
"""Not used in bare report dialogs. Override in the subclass."""
pass
#------------------------------------------------------------------------
#

View File

@@ -0,0 +1,302 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2007 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
#
#-------------------------------------------------------------------------
import os
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# GTK+ modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
from _ReportDialog import ReportDialog
from _FileEntry import FileEntry
from _TemplateParser import _template_map, _default_template, _user_template
from _PaperMenu import PaperFrame
#-------------------------------------------------------------------------
#
# ReportDialog class
#
#-------------------------------------------------------------------------
class DocReportDialog(ReportDialog):
"""
The DocReportDialog base class. This is a base class for generating
dialogs for docgen derived reports.
"""
def __init__(self,dbstate,uistate,person,option_class,name,trans_name):
"""Initialize a dialog to request that the user select options
for a basic *stand-alone* report."""
self.style_name = "default"
self.page_html_added = False
ReportDialog.__init__(self,dbstate,uistate,person,option_class,
name,trans_name)
# Allow for post processing of the format frame, since the
# show_all task calls events that may reset values
def init_interface(self):
ReportDialog.init_interface(self)
self.doc_type_changed(self.format_menu)
#------------------------------------------------------------------------
#
# Functions related to selecting/changing the current file format.
#
#------------------------------------------------------------------------
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
not the document requires table support, etc."""
raise NotImplementedError
def make_document(self):
"""Create a document of the type requested by the user.
"""
pstyle = self.paper_frame.get_paper_style()
self.doc = self.format(self.selected_style, pstyle, self.template_name)
self.options.set_document(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
formats for the report. It adjust the various dialog sections
to reflect the appropriate values for the currently selected
file format. For example, a HTML document doesn't need any
paper size/orientation options, but it does need a template
file. Those chances are made here."""
label = obj.get_printable()
if label:
self.print_report.set_label (label)
self.print_report.set_sensitive (True)
else:
self.print_report.set_label (_("Print a copy"))
self.print_report.set_sensitive (False)
# Is this to be a printed report or an electronic report
# (i.e. a set of web pages)
if self.page_html_added:
self.notebook.remove_page(0)
if obj.get_paper() == 1:
self.paper_label = gtk.Label('<b>%s</b>'%_("Paper Options"))
self.paper_label.set_use_markup(True)
self.notebook.insert_page(self.paper_frame,self.paper_label,0)
self.paper_frame.show_all()
else:
self.html_label = gtk.Label('<b>%s</b>' % _("HTML Options"))
self.html_label.set_use_markup(True)
self.notebook.insert_page(self.html_table,self.html_label,0)
self.html_table.show_all()
if not self.get_target_is_directory():
fname = self.target_fileentry.get_full_path(0)
(spath,ext) = os.path.splitext(fname)
ext_val = obj.get_ext()
if ext_val:
fname = spath + ext_val
else:
fname = spath
self.target_fileentry.set_filename(fname)
# Does this report format use styles?
if self.style_button:
self.style_button.set_sensitive(obj.get_styles())
self.style_menu.set_sensitive(obj.get_styles())
self.page_html_added = True
def setup_format_frame(self):
"""Set up the format frame of the dialog. This function
relies on the make_doc_menu() function to do all the hard
work."""
self.print_report = gtk.CheckButton (_("Print a copy"))
self.tbl.attach(self.print_report,2,4,self.col,self.col+1,
yoptions=gtk.SHRINK)
self.col += 1
self.make_doc_menu(self.options.handler.get_format_name())
self.format_menu.connect('changed',self.doc_type_changed)
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)
self.tbl.attach(self.format_menu,2,4,self.col,self.col+1,
yoptions=gtk.SHRINK)
self.col += 1
ext = self.format_menu.get_ext()
if ext == None:
ext = ""
else:
spath = self.get_default_directory()
if self.get_target_is_directory():
self.target_fileentry.set_filename(spath)
else:
base = self.get_default_basename()
spath = os.path.normpath("%s/%s%s" % (spath,base,ext))
self.target_fileentry.set_filename(spath)
def setup_report_options_frame(self):
self.paper_frame = PaperFrame(self.options.handler.get_paper_name(),
self.options.handler.get_orientation())
self.setup_html_frame()
ReportDialog.setup_report_options_frame(self)
def html_file_enable(self,obj):
active = obj.get_active()
text = unicode(obj.get_model()[active][0])
if _template_map.has_key(text):
if _template_map[text]:
self.html_fileentry.set_sensitive(0)
else:
self.html_fileentry.set_sensitive(1)
else:
self.html_fileentry.set_sensitive(0)
def setup_html_frame(self):
"""Set up the html frame of the dialog. This sole purpose of
this function is to grab a pointer for later use in the parse
html frame function."""
self.html_table = gtk.Table(3,3)
self.html_table.set_col_spacings(12)
self.html_table.set_row_spacings(6)
self.html_table.set_border_width(0)
label = gtk.Label("%s:" % _("Template"))
label.set_alignment(0.0,0.5)
self.html_table.attach(label, 1, 2, 1, 2, gtk.SHRINK|gtk.FILL,
yoptions=gtk.SHRINK)
self.template_combo = gtk.combo_box_new_text()
tlist = _template_map.keys()
tlist.sort()
template_name = self.options.handler.get_template_name()
self.template_combo.append_text(_default_template)
template_index = 1
active_index = 0
for template in tlist:
if template != _user_template:
self.template_combo.append_text(template)
if _template_map[template] == os.path.basename(template_name):
active_index = template_index
template_index = template_index + 1
self.template_combo.append_text(_user_template)
self.template_combo.connect('changed',self.html_file_enable)
self.html_table.attach(self.template_combo,2,3,1,2, yoptions=gtk.SHRINK)
label = gtk.Label("%s:" % _("User Template"))
label.set_alignment(0.0,0.5)
self.html_table.attach(label, 1, 2, 2, 3, gtk.SHRINK|gtk.FILL,
yoptions=gtk.SHRINK)
self.html_fileentry = FileEntry("HTML_Template",
_("Choose File"))
if template_name and not active_index:
active_index = template_index
user_template = template_name
self.html_fileentry.set_sensitive(True)
else:
user_template = ''
self.html_fileentry.set_sensitive(False)
if os.path.isfile(user_template):
self.html_fileentry.set_filename(user_template)
self.html_table.attach(self.html_fileentry,2,3,2,3, yoptions=gtk.SHRINK)
self.template_combo.set_active(active_index)
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_reference()
format_name = self.format_menu.get_clname()
self.options.handler.set_format_name(format_name)
def parse_html_frame(self):
"""Parse the html frame of the dialog. Save the user selected
html template name for later use. Note that this routine
retrieves a value whether or not the file entry box is
displayed on the screen. The subclass will know whether this
entry was enabled. This is for simplicity of programming."""
model = self.template_combo.get_model()
text = unicode(model[self.template_combo.get_active()][0])
if _template_map.has_key(text):
if text == _user_template:
self.template_name = self.html_fileentry.get_full_path(0)
else:
self.template_name = "%s%s%s" % (const.TEMPLATE_DIR,os.path.sep,
_template_map[text])
else:
self.template_name = ""
self.options.handler.set_template_name(self.template_name)
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Validate
the output file name before doing anything else. If there is
a file name, gather the options and create the report."""
# Is there a filename? This should also test file permissions, etc.
if not self.parse_target_frame():
self.window.run()
# Preparation
self.parse_format_frame()
self.parse_style_frame()
self.parse_html_frame()
self.options.handler.set_paper_name(self.paper_frame.get_paper_name())
self.options.handler.set_orientation(self.paper_frame.get_orientation())
self.parse_user_options()
# Create the output document.
self.make_document()
# Save options
self.options.handler.save_options()

View File

@@ -21,7 +21,7 @@
# $Id$
from _Constants import CATEGORY_DRAW
from _ReportDialog import ReportDialog
from _DocReportDialog import DocReportDialog
from _DrawFormatComboBox import DrawFormatComboBox
#-----------------------------------------------------------------------
@@ -29,14 +29,14 @@ from _DrawFormatComboBox import DrawFormatComboBox
# Drawing reports
#
#-----------------------------------------------------------------------
class DrawReportDialog(ReportDialog):
class DrawReportDialog(DocReportDialog):
"""A class of ReportDialog customized for drawing based reports."""
def __init__(self,dbstate,uistate,person,opt,name,translated_name):
"""Initialize a dialog to request that the user select options
for a basic drawing report. See the ReportDialog class for
more information."""
self.category = CATEGORY_DRAW
ReportDialog.__init__(self,dbstate,uistate,person,opt,
DocReportDialog.__init__(self,dbstate,uistate,person,opt,
name,translated_name)
#------------------------------------------------------------------------

View File

@@ -46,6 +46,7 @@ import BaseDoc
import Config
from _Constants import CATEGORY_GRAPHVIZ
from _ReportDialog import ReportDialog
from _PaperMenu import PaperFrame
#-------------------------------------------------------------------------------
#
@@ -514,11 +515,112 @@ class GraphvizReportDialog(ReportDialog):
for a graphiz report. See the ReportDialog class for
more information."""
self.category = CATEGORY_GRAPHVIZ
#TODO: Add custom options to "opt" first.
ReportDialog.__init__(self,dbstate,uistate,person,opt,
name,translated_name)
def init_interface(self):
ReportDialog.init_interface(self)
self.doc_type_changed(self.format_menu)
def setup_format_frame(self):
"""Set up the format frame of the dialog."""
self.print_report = gtk.CheckButton (_("Open with application"))
self.tbl.attach(self.print_report,2,4,self.col,self.col+1,
yoptions=gtk.SHRINK)
self.col += 1
def make_doc_menu(self,active=None):
"""Build a menu of document types that are appropriate for
a graphiz report."""
self.format_menu = GraphvizFormatComboBox()
self.format_menu.set(active)
self.format_menu.set(self.options.handler.get_format_name())
self.format_menu.connect('changed',self.doc_type_changed)
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)
self.tbl.attach(self.format_menu,2,4,self.col,self.col+1,
yoptions=gtk.SHRINK)
self.col += 1
ext = self.format_menu.get_ext()
if ext == None:
ext = ""
else:
spath = self.get_default_directory()
if self.get_target_is_directory():
self.target_fileentry.set_filename(spath)
else:
base = self.get_default_basename()
spath = os.path.normpath("%s/%s%s" % (spath,base,ext))
self.target_fileentry.set_filename(spath)
def setup_report_options_frame(self):
self.paper_label = gtk.Label('<b>%s</b>'%_("Paper Options"))
self.paper_label.set_use_markup(True)
self.paper_frame = PaperFrame(self.options.handler.get_paper_name(),
self.options.handler.get_orientation())
self.notebook.insert_page(self.paper_frame,self.paper_label,0)
self.paper_frame.show_all()
ReportDialog.setup_report_options_frame(self)
def doc_type_changed(self, obj):
"""This routine is called when the user selects a new file
formats for the report. It adjust the various dialog sections
to reflect the appropriate values for the currently selected
file format. For example, a HTML document doesn't need any
paper size/orientation options, but it does need a template
file. Those chances are made here."""
label = obj.get_printable()
if label:
self.print_report.set_label (label)
self.print_report.set_sensitive (True)
else:
self.print_report.set_label (_("Open with application"))
self.print_report.set_sensitive (False)
def make_document(self):
"""Create a document of the type requested by the user.
"""
pstyle = self.paper_frame.get_paper_style()
self.doc = self.format(None, pstyle, None)
self.options.set_document(self.doc)
if self.print_report.get_active():
self.doc.print_requested()
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Validate
the output file name before doing anything else. If there is
a file name, gather the options and create the report."""
# Is there a filename? This should also test file permissions, etc.
if not self.parse_target_frame():
self.window.run()
# Preparation
self.parse_format_frame()
self.parse_user_options()
self.options.handler.set_paper_name(self.paper_frame.get_paper_name())
self.options.handler.set_orientation(self.paper_frame.get_orientation())
# Create the output document.
self.make_document()
# Save options
self.options.handler.save_options()
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_reference()
format_name = self.format_menu.get_clname()
self.options.handler.set_format_name(format_name)
def setup_style_frame(self):
"""Required by ReportDialog:BareReportDialog"""
pass

View File

@@ -26,6 +26,7 @@
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import os
#-------------------------------------------------------------------------
#
@@ -60,12 +61,16 @@ except:
#-------------------------------------------------------------------------
paper_sizes = []
#-------------------------------------------------------------------------
#
# PaperComboBox
#
#-------------------------------------------------------------------------
class PaperComboBox(gtk.ComboBox):
def __init__(self):
gtk.ComboBox.__init__(self,model=None)
def set(self,mapping,default):
def __init__(self,default_name):
gtk.ComboBox.__init__(self)
self.store = gtk.ListStore(str)
self.set_model(self.store)
cell = gtk.CellRendererText()
@@ -75,10 +80,10 @@ class PaperComboBox(gtk.ComboBox):
index = 0
start_index = 0
for key in mapping:
for key in paper_sizes:
self.mapping[key.get_name()] = key
self.store.append(row=[key.get_name()])
if key.get_name() == default:
if key.get_name() == default_name:
start_index = index
index += 1
@@ -91,12 +96,16 @@ class PaperComboBox(gtk.ComboBox):
key = self.store[active][0]
return (self.mapping[key],key)
#-------------------------------------------------------------------------
#
# OrientationComboBox
#
#-------------------------------------------------------------------------
class OrientationComboBox(gtk.ComboBox):
def __init__(self):
gtk.ComboBox.__init__(self,model=None)
def set(self,default=0):
def __init__(self,default=BaseDoc.PAPER_PORTRAIT):
gtk.ComboBox.__init__(self)
self.store = gtk.ListStore(str)
self.set_model(self.store)
cell = gtk.CellRendererText()
@@ -111,6 +120,12 @@ class OrientationComboBox(gtk.ComboBox):
else:
self.set_active(1)
def set_value(self,value=0):
if value == BaseDoc.PAPER_PORTRAIT:
self.set_active(0)
else:
self.set_active(1)
def get_value(self):
active = self.get_active()
if active < 0:
@@ -122,29 +137,169 @@ class OrientationComboBox(gtk.ComboBox):
#-------------------------------------------------------------------------
#
# make_orientation_menu
# PaperFrame
#
#-------------------------------------------------------------------------
def make_orientation_menu(main_menu,value=0):
#-------------------------------------------------------------------------
class PaperFrame(gtk.HBox):
"""PaperFrame provides all the entry necessary to specify a paper style. """
def __init__(self,default_name,default_orientation):
gtk.HBox.__init__(self)
glade_file = os.path.join(const.GLADE_DIR, "paper_settings.glade")
glade_xml = gtk.glade.XML(glade_file, "paper_table", "gramps")
myMenu = gtk.Menu()
menuitem = gtk.MenuItem(_("Portrait"))
menuitem.set_data("i",BaseDoc.PAPER_PORTRAIT)
menuitem.show()
myMenu.append(menuitem)
self.paper_table = glade_xml.get_widget('paper_table')
menuitem = gtk.MenuItem(_("Landscape"))
menuitem.set_data("i",BaseDoc.PAPER_LANDSCAPE)
menuitem.show()
myMenu.append(menuitem)
# get all the widgets
widgets = ('pwidth', 'pheight', 'lmargin', 'rmargin', 'tmargin',
'bmargin', 'lunits1', 'lunits2', 'lunits3', 'lunits4',
'lunits5', 'lunits6', 'metric')
for w in widgets:
setattr(self, w, glade_xml.get_widget(w))
# insert custom widgets
self.papersize_menu = PaperComboBox(default_name)
self.orientation_menu = OrientationComboBox(default_orientation)
# connect all widgets
format_table = glade_xml.get_widget('format_table')
format_table.attach(self.papersize_menu, 1, 3, 0, 1,
yoptions=gtk.SHRINK)
format_table.attach(self.orientation_menu, 1, 3, 3, 4,
yoptions=gtk.SHRINK)
if value == BaseDoc.PAPER_PORTRAIT:
myMenu.set_active(0)
elif value == BaseDoc.PAPER_LANDSCAPE:
myMenu.set_active(1)
# connect signals
self.papersize_menu.connect('changed',self.size_changed)
self.metric.connect('toggled',self.units_changed)
main_menu.set_menu(myMenu)
# set initial values
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
self.paper_table.show_all()
self.add(self.paper_table)
def size_changed(self, obj):
"""Paper size combobox 'changed' callback."""
size, name = self.get_paper_size()
is_custom = name == _("Custom Size")
self.pwidth.set_sensitive(is_custom)
self.pheight.set_sensitive(is_custom)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % size.get_width())
self.pheight.set_text("%.2f" % size.get_height())
elif self.paper_unit == 'in.':
self.pwidth.set_text("%.2f" % size.get_width_inches())
self.pheight.set_text("%.2f" % size.get_height_inches())
else:
raise ValueError('Paper dimension unit "%s" is not allowed' %
self.paper_unit)
def units_changed(self, checkbox):
"""Metric checkbox 'toggled' callback."""
paper_size, paper_name = self.get_paper_size()
paper_margins = self.get_paper_margins()
if checkbox.get_active():
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
else:
self.paper_unit = 'in.'
self.paper_unit_multiplier = 2.54
self.lunits1.set_text(self.paper_unit)
self.lunits2.set_text(self.paper_unit)
self.lunits3.set_text(self.paper_unit)
self.lunits4.set_text(self.paper_unit)
self.lunits5.set_text(self.paper_unit)
self.lunits6.set_text(self.paper_unit)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % paper_size.get_width())
self.pheight.set_text("%.2f" % paper_size.get_height())
else:
self.pwidth.set_text("%.2f" % paper_size.get_width_inches())
self.pheight.set_text("%.2f" % paper_size.get_height_inches())
self.lmargin.set_text("%.2f" %
(paper_margins[0] / self.paper_unit_multiplier))
self.rmargin.set_text("%.2f" %
(paper_margins[1] / self.paper_unit_multiplier))
self.tmargin.set_text("%.2f" %
(paper_margins[2] / self.paper_unit_multiplier))
self.bmargin.set_text("%.2f" %
(paper_margins[3] / self.paper_unit_multiplier))
def get_paper_size(self):
"""Read and validate paper size values.
If needed update the dimensions from the width, height entries,
and worst case fallback to A4 size.
"""
papersize, papername = self.papersize_menu.get_value()
# FIXME it is wrong to use translatable text in comparison.
# How can we distinguish custom size though?
if papername == _('Custom Size'):
try:
h = float(unicode(self.pheight.get_text()))
w = float(unicode(self.pwidth.get_text()))
if h <= 1.0 or w <= 1.0:
papersize.set_height(29.7)
papersize.set_width(21.0)
else:
papersize.set_height(h * self.paper_unit_multiplier)
papersize.set_width(w * self.paper_unit_multiplier)
except:
papersize.set_height(29.7)
papersize.set_width(21.0)
return papersize, papername
def get_paper_margins(self):
"""Get and validate margin values from dialog entries.
Values returned in [cm].
"""
paper_margins = []
paper_margins.append(unicode(self.lmargin.get_text()))
paper_margins.append(unicode(self.rmargin.get_text()))
paper_margins.append(unicode(self.tmargin.get_text()))
paper_margins.append(unicode(self.bmargin.get_text()))
for i, margin in enumerate(paper_margins):
try:
paper_margins[i] = float(margin)
paper_margins[i] = paper_margins[i] * self.paper_unit_multiplier
paper_margins[i] = max(paper_margins[i], 0)
except:
paper_margins[i] = 2.54
return paper_margins
def get_paper_style(self):
paper_size, paper_name = self.get_paper_size()
paper_orientation = self.orientation_menu.get_value()
paper_margins = self.get_paper_margins()
pstyle = BaseDoc.PaperStyle(paper_size,
paper_orientation,
*paper_margins)
return pstyle
def get_paper_name(self):
paper_size, paper_name = self.get_paper_size()
return paper_name
def get_orientation(self):
return self.orientation_menu.get_value()
#-------------------------------------------------------------------------
#
# PageSizeParser

View File

@@ -87,8 +87,6 @@ class ReportDialog(BareReportDialog):
def init_interface(self):
BareReportDialog.init_interface(self)
if self.format_menu:
self.doc_type_changed(self.format_menu)
def setup_center_person(self):
pass
@@ -151,81 +149,6 @@ class ReportDialog(BareReportDialog):
his/her preferences."""
Config.set(Config.REPORT_DIRECTORY,value)
#------------------------------------------------------------------------
#
# Functions related to selecting/changing the current file format.
#
#------------------------------------------------------------------------
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
not the document requires table support, etc."""
return None
def make_document(self):
"""Create a document of the type requested by the user.
"""
pstyle = PaperStyle(self.paper_size,
self.paper_orientation,
*self.paper_margins)
self.doc = self.format(self.selected_style, pstyle, self.template_name)
self.options.set_document(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
formats for the report. It adjust the various dialog sections
to reflect the appropriate values for the currently selected
file format. For example, a HTML document doesn't need any
paper size/orientation options, but it does need a template
file. Those chances are made here."""
label = obj.get_printable()
if label:
self.print_report.set_label (label)
self.print_report.set_sensitive (True)
else:
self.print_report.set_label (_("Print a copy"))
self.print_report.set_sensitive (False)
# Is this to be a printed report or an electronic report
# (i.e. a set of web pages)
if self.page_html_added:
self.notebook.remove_page(0)
if obj.get_paper() == 1:
self.paper_label = gtk.Label('<b>%s</b>'%_("Paper Options"))
self.paper_label.set_use_markup(True)
self.notebook.insert_page(self.paper_table,self.paper_label,0)
self.paper_table.show_all()
else:
self.html_label = gtk.Label('<b>%s</b>' % _("HTML Options"))
self.html_label.set_use_markup(True)
self.notebook.insert_page(self.html_table,self.html_label,0)
self.html_table.show_all()
if not self.get_target_is_directory():
fname = self.target_fileentry.get_full_path(0)
(spath,ext) = os.path.splitext(fname)
ext_val = obj.get_ext()
if ext_val:
fname = spath + ext_val
else:
fname = spath
self.target_fileentry.set_filename(fname)
# Does this report format use styles?
if self.style_button:
self.style_button.set_sensitive(obj.get_styles())
self.style_menu.set_sensitive(obj.get_styles())
self.page_html_added = True
#------------------------------------------------------------------------
#
# Functions related to setting up the dialog window.
@@ -270,193 +193,6 @@ class ReportDialog(BareReportDialog):
self.target_fileentry.set_filename(spath)
self.target_fileentry.gtk_entry().set_position(len(spath))
def setup_format_frame(self):
"""Set up the format frame of the dialog. This function
relies on the make_doc_menu() function to do all the hard
work."""
self.print_report = gtk.CheckButton (_("Print a copy"))
self.tbl.attach(self.print_report,2,4,self.col,self.col+1,
yoptions=gtk.SHRINK)
self.col += 1
self.make_doc_menu(self.options.handler.get_format_name())
self.format_menu.connect('changed',self.doc_type_changed)
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)
self.tbl.attach(self.format_menu,2,4,self.col,self.col+1,
yoptions=gtk.SHRINK)
self.col += 1
ext = self.format_menu.get_ext()
if ext == None:
ext = ""
else:
spath = self.get_default_directory()
if self.get_target_is_directory():
self.target_fileentry.set_filename(spath)
else:
base = self.get_default_basename()
spath = os.path.normpath("%s/%s%s" % (spath,base,ext))
self.target_fileentry.set_filename(spath)
def size_changed(self, obj):
"""Paper size combobox 'changed' callback."""
size, name = self.get_paper_size()
is_custom = name == _("Custom Size")
self.pwidth.set_sensitive(is_custom)
self.pheight.set_sensitive(is_custom)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % size.get_width())
self.pheight.set_text("%.2f" % size.get_height())
elif self.paper_unit == 'in.':
self.pwidth.set_text("%.2f" % size.get_width_inches())
self.pheight.set_text("%.2f" % size.get_height_inches())
else:
raise ValueError('Paper dimension unit "%s" is not allowed' %
self.paper_unit)
def units_changed(self, checkbox):
"""Metric checkbox 'toggled' callback."""
paper_size, paper_name = self.get_paper_size()
paper_margins = self.get_paper_margins()
if checkbox.get_active():
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
else:
self.paper_unit = 'in.'
self.paper_unit_multiplier = 2.54
self.lunits1.set_text(self.paper_unit)
self.lunits2.set_text(self.paper_unit)
self.lunits3.set_text(self.paper_unit)
self.lunits4.set_text(self.paper_unit)
self.lunits5.set_text(self.paper_unit)
self.lunits6.set_text(self.paper_unit)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % paper_size.get_width())
self.pheight.set_text("%.2f" % paper_size.get_height())
else:
self.pwidth.set_text("%.2f" % paper_size.get_width_inches())
self.pheight.set_text("%.2f" % paper_size.get_height_inches())
self.lmargin.set_text("%.2f" %
(paper_margins[0] / self.paper_unit_multiplier))
self.rmargin.set_text("%.2f" %
(paper_margins[1] / self.paper_unit_multiplier))
self.tmargin.set_text("%.2f" %
(paper_margins[2] / self.paper_unit_multiplier))
self.bmargin.set_text("%.2f" %
(paper_margins[3] / self.paper_unit_multiplier))
def setup_paper_frame(self):
"""Set up the paper selection frame of the dialog."""
glade_file = os.path.join(const.GLADE_DIR, "paper_settings.glade")
glade_xml = gtk.glade.XML(glade_file, "paper_table", "gramps")
self.paper_table = glade_xml.get_widget('paper_table')
# get all the widgets
widgets = ('pwidth', 'pheight', 'lmargin', 'rmargin', 'tmargin',
'bmargin', 'lunits1', 'lunits2', 'lunits3', 'lunits4',
'lunits5', 'lunits6', 'metric')
for w in widgets:
setattr(self, w, glade_xml.get_widget(w))
# insert custom widgets
self.papersize_menu = PaperComboBox()
self.orientation_menu = OrientationComboBox()
format_table = glade_xml.get_widget('format_table')
format_table.attach(self.papersize_menu, 1, 3, 0, 1,
yoptions=gtk.SHRINK)
format_table.attach(self.orientation_menu, 1, 3, 3, 4,
yoptions=gtk.SHRINK)
# connect signals
self.papersize_menu.connect('changed',self.size_changed)
self.metric.connect('toggled',self.units_changed)
# set initial values
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
self.papersize_menu.set(paper_sizes,
self.options.handler.get_paper_name())
self.orientation_menu.set(self.options.handler.get_orientation())
def html_file_enable(self,obj):
active = obj.get_active()
text = unicode(obj.get_model()[active][0])
if _template_map.has_key(text):
if _template_map[text]:
self.html_fileentry.set_sensitive(0)
else:
self.html_fileentry.set_sensitive(1)
else:
self.html_fileentry.set_sensitive(0)
def setup_html_frame(self):
"""Set up the html frame of the dialog. This sole purpose of
this function is to grab a pointer for later use in the parse
html frame function."""
self.html_table = gtk.Table(3,3)
self.html_table.set_col_spacings(12)
self.html_table.set_row_spacings(6)
self.html_table.set_border_width(0)
label = gtk.Label("%s:" % _("Template"))
label.set_alignment(0.0,0.5)
self.html_table.attach(label, 1, 2, 1, 2, gtk.SHRINK|gtk.FILL,
yoptions=gtk.SHRINK)
self.template_combo = gtk.combo_box_new_text()
tlist = _template_map.keys()
tlist.sort()
template_name = self.options.handler.get_template_name()
self.template_combo.append_text(_default_template)
template_index = 1
active_index = 0
for template in tlist:
if template != _user_template:
self.template_combo.append_text(template)
if _template_map[template] == os.path.basename(template_name):
active_index = template_index
template_index = template_index + 1
self.template_combo.append_text(_user_template)
self.template_combo.connect('changed',self.html_file_enable)
self.html_table.attach(self.template_combo,2,3,1,2, yoptions=gtk.SHRINK)
label = gtk.Label("%s:" % _("User Template"))
label.set_alignment(0.0,0.5)
self.html_table.attach(label, 1, 2, 2, 3, gtk.SHRINK|gtk.FILL,
yoptions=gtk.SHRINK)
self.html_fileentry = FileEntry("HTML_Template",
_("Choose File"))
if template_name and not active_index:
active_index = template_index
user_template = template_name
self.html_fileentry.set_sensitive(True)
else:
user_template = ''
self.html_fileentry.set_sensitive(False)
if os.path.isfile(user_template):
self.html_fileentry.set_filename(user_template)
self.html_table.attach(self.html_fileentry,2,3,2,3, yoptions=gtk.SHRINK)
self.template_combo.set_active(active_index)
#------------------------------------------------------------------------
#
# Functions related to retrieving data from the dialog window
@@ -519,99 +255,6 @@ class ReportDialog(BareReportDialog):
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_reference()
format_name = self.format_menu.get_clname()
self.options.handler.set_format_name(format_name)
def get_paper_size(self):
"""Read and validate paper size values.
If needed update the dimensions from the width, height entries,
and worst case fallback to A4 size.
"""
papersize, papername = self.papersize_menu.get_value()
# FIXME it is wrong to use translatable text in comparison.
# How can we distinguish custom size though?
if papername == _('Custom Size'):
try:
h = float(unicode(self.pheight.get_text()))
w = float(unicode(self.pwidth.get_text()))
if h <= 1.0 or w <= 1.0:
papersize.set_height(29.7)
papersize.set_width(21.0)
else:
papersize.set_height(h * self.paper_unit_multiplier)
papersize.set_width(w * self.paper_unit_multiplier)
except:
papersize.set_height(29.7)
papersize.set_width(21.0)
return papersize, papername
def get_paper_margins(self):
"""Get and validate margin values from dialog entries.
Values returned in [cm].
"""
paper_margins = []
paper_margins.append(unicode(self.lmargin.get_text()))
paper_margins.append(unicode(self.rmargin.get_text()))
paper_margins.append(unicode(self.tmargin.get_text()))
paper_margins.append(unicode(self.bmargin.get_text()))
for i, margin in enumerate(paper_margins):
try:
paper_margins[i] = float(margin)
paper_margins[i] = paper_margins[i] * self.paper_unit_multiplier
paper_margins[i] = max(paper_margins[i], 0)
except:
paper_margins[i] = 2.54
return paper_margins
def parse_paper_frame(self):
"""Parse the paper frame of the dialog.
Save the user selected choices for later use.
"""
self.paper_size, paper_name = self.get_paper_size()
self.options.handler.set_paper_name(paper_name)
self.options.handler.set_paper(self.paper_size)
self.paper_orientation = self.orientation_menu.get_value()
self.options.handler.set_orientation(self.paper_orientation)
self.paper_margins = self.get_paper_margins()
def parse_html_frame(self):
"""Parse the html frame of the dialog. Save the user selected
html template name for later use. Note that this routine
retrieves a value whether or not the file entry box is
displayed on the screen. The subclass will know whether this
entry was enabled. This is for simplicity of programming."""
model = self.template_combo.get_model()
text = unicode(model[self.template_combo.get_active()][0])
if _template_map.has_key(text):
if text == _user_template:
self.template_name = self.html_fileentry.get_full_path(0)
else:
self.template_name = "%s%s%s" % (const.TEMPLATE_DIR,os.path.sep,
_template_map[text])
else:
self.template_name = ""
self.options.handler.set_template_name(self.template_name)
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Validate
the output file name before doing anything else. If there is
@@ -622,14 +265,8 @@ class ReportDialog(BareReportDialog):
self.window.run()
# Preparation
self.parse_format_frame()
self.parse_style_frame()
self.parse_paper_frame()
self.parse_html_frame()
self.parse_user_options()
# Create the output document.
self.make_document()
# Save options
self.options.handler.save_options()

View File

@@ -468,15 +468,19 @@ class ReportOptions(_Options.Options):
This is a base Options class for the reports. All reports' options
classes should derive from it.
"""
def __init__(self,name,person_id=None):
"""
Initializes the class, performing usual house-keeping tasks.
Subclasses MUST call this in their __init__() method.
"""
self.set_new_options()
self.handler = OptionHandler(name,self.options_dict,person_id)
self.name = name
self.person_id = person_id
self.options_dict = {}
self.options_help = {}
self.handler = None
def load_previous_values(self):
self.handler = OptionHandler(self.name,self.options_dict,self.person_id)
def make_default_style(self,default_style):
"""
@@ -560,6 +564,7 @@ class MenuReportOptions(MenuOptions,ReportOptions):
"""
def __init__(self,name,person_id=None):
MenuOptions.__init__(self)
ReportOptions.__init__(self,name, person_id)
MenuOptions.__init__(self)

View File

@@ -21,7 +21,7 @@
# $Id$
from _Constants import CATEGORY_TEXT
from _ReportDialog import ReportDialog
from _DocReportDialog import DocReportDialog
from _TextFormatComboBox import TextFormatComboBox
#-----------------------------------------------------------------------
@@ -29,7 +29,7 @@ from _TextFormatComboBox import TextFormatComboBox
# Textual reports
#
#-----------------------------------------------------------------------
class TextReportDialog(ReportDialog):
class TextReportDialog(DocReportDialog):
"""A class of ReportDialog customized for text based reports."""
def __init__(self,dbstate,uistate,person,options,name,translated_name):
@@ -37,7 +37,7 @@ class TextReportDialog(ReportDialog):
for a basic text report. See the ReportDialog class for more
information."""
self.category = CATEGORY_TEXT
ReportDialog.__init__(self,dbstate,uistate,person,options,
DocReportDialog.__init__(self,dbstate,uistate,person,options,
name,translated_name)
#------------------------------------------------------------------------