2006-05-31 06:18:07 +05:30
|
|
|
#
|
|
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
|
|
#
|
|
|
|
# Copyright (C) 2001-2006 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
|
|
|
|
#
|
|
|
|
|
2006-05-31 11:27:55 +05:30
|
|
|
# $Id$
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2006-05-31 23:56:50 +05:30
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Python modules
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
2006-05-31 08:11:46 +05:30
|
|
|
import os
|
2006-07-05 05:08:51 +05:30
|
|
|
from gettext import gettext as _
|
|
|
|
|
2006-06-02 06:10:54 +05:30
|
|
|
import logging
|
2006-07-05 05:08:51 +05:30
|
|
|
|
2006-06-02 06:10:54 +05:30
|
|
|
log = logging.getLogger(".")
|
2006-05-31 23:56:50 +05:30
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# GTK+ modules
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
2006-05-31 08:11:46 +05:30
|
|
|
import gtk
|
|
|
|
|
2006-05-31 23:56:50 +05:30
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# GRAMPS modules
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
2006-05-31 08:11:46 +05:30
|
|
|
import Config
|
|
|
|
import Errors
|
2006-07-05 05:08:51 +05:30
|
|
|
import Utils
|
|
|
|
import const
|
|
|
|
|
2007-05-15 09:47:12 +05:30
|
|
|
from QuestionDialog import ErrorDialog, OptionDialog, RunDatabaseRepair
|
2006-05-31 08:11:46 +05:30
|
|
|
|
|
|
|
from _Constants import CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK, \
|
|
|
|
CATEGORY_VIEW, CATEGORY_CODE, CATEGORY_WEB, standalone_categories
|
2006-05-31 06:18:07 +05:30
|
|
|
from _BareReportDialog import BareReportDialog
|
2006-05-31 08:11:46 +05:30
|
|
|
from _FileEntry import FileEntry
|
|
|
|
from _PaperMenu import PaperComboBox, OrientationComboBox, paper_sizes
|
|
|
|
from _TemplateParser import _template_map, _default_template, _user_template
|
2007-02-25 02:45:21 +05:30
|
|
|
from BaseDoc import PaperStyle
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2006-05-31 23:56:50 +05:30
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# ReportDialog class
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
2006-05-31 06:18:07 +05:30
|
|
|
class ReportDialog(BareReportDialog):
|
|
|
|
"""
|
|
|
|
The ReportDialog base class. This is a base class for generating
|
|
|
|
customized dialogs to solicit options for a report. It cannot be
|
|
|
|
used as is, but it can be easily sub-classed to create a functional
|
|
|
|
dialog for a stand-alone report.
|
|
|
|
"""
|
|
|
|
|
2006-05-31 23:56:50 +05:30
|
|
|
def __init__(self,dbstate,uistate,person,option_class,name,trans_name):
|
2006-05-31 06:18:07 +05:30
|
|
|
"""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
|
2006-05-31 23:56:50 +05:30
|
|
|
BareReportDialog.__init__(self,dbstate,uistate,person,option_class,
|
|
|
|
name,trans_name)
|
2006-05-31 06:18:07 +05:30
|
|
|
|
|
|
|
# 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)
|
|
|
|
self.setup_post_process()
|
|
|
|
|
|
|
|
def setup_post_process(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def setup_center_person(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def get_title(self):
|
|
|
|
"""The window title for this dialog"""
|
|
|
|
name = self.report_name
|
|
|
|
category = 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. """
|
2006-10-10 05:39:24 +05:30
|
|
|
if name.strip():
|
|
|
|
return _("%(report_name)s for %(person_name)s") % {
|
|
|
|
'report_name' : self.report_name,
|
|
|
|
'person_name' : name}
|
|
|
|
else:
|
2006-11-03 22:35:24 +05:30
|
|
|
# No need to translate report_name, it is already translated
|
|
|
|
return self.report_name
|
2006-05-31 06:18:07 +05:30
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Customization hooks for subclasses
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
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
|
|
|
|
currently only selects the Filename/Directory prompt, and
|
|
|
|
whether or not the browser accepts filenames. In the future it
|
|
|
|
may also control checking of the selected filename."""
|
|
|
|
return None
|
|
|
|
|
|
|
|
def get_default_basename(self):
|
|
|
|
"""What should the default name be?
|
|
|
|
"""
|
|
|
|
spath = self.options.handler.get_stylesheet_savefile()
|
|
|
|
return spath.split('.')[0]
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Functions related getting/setting the default directory for a dialog.
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
def get_default_directory(self):
|
|
|
|
"""Get the name of the directory to which the target dialog
|
|
|
|
box should default. This value can be set in the preferences
|
|
|
|
panel."""
|
|
|
|
return Config.get(Config.REPORT_DIRECTORY)
|
|
|
|
|
|
|
|
def set_default_directory(self, value):
|
|
|
|
"""Save the name of the current directory, so that any future
|
|
|
|
reports will default to the most recently used directory.
|
|
|
|
This also changes the directory name that will appear in the
|
|
|
|
preferences panel, but does not change the preference in disk.
|
|
|
|
This means that the last directory used will only be
|
|
|
|
remembered for this session of gramps unless the user saves
|
|
|
|
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):
|
2007-09-17 00:28:24 +05:30
|
|
|
"""Create a document of the type requested by the user.
|
|
|
|
"""
|
2007-09-18 00:18:29 +05:30
|
|
|
pstyle = PaperStyle(self.paper_size,
|
|
|
|
self.paper_orientation,
|
|
|
|
*self.paper_margins)
|
|
|
|
|
2007-09-17 00:28:24 +05:30
|
|
|
self.doc = self.format(self.selected_style, pstyle, self.template_name)
|
|
|
|
|
2006-05-31 06:18:07 +05:30
|
|
|
self.options.set_document(self.doc)
|
2007-09-17 00:28:24 +05:30
|
|
|
|
|
|
|
if self.print_report.get_active():
|
|
|
|
self.doc.print_requested()
|
2006-05-31 06:18:07 +05:30
|
|
|
|
|
|
|
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
|
2007-08-26 19:35:34 +05:30
|
|
|
else:
|
2006-05-31 06:18:07 +05:30
|
|
|
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.
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
def setup_target_frame(self):
|
|
|
|
"""Set up the target frame of the dialog. This function
|
|
|
|
relies on several target_xxx() customization functions to
|
|
|
|
determine whether the target is a directory or file, what the
|
|
|
|
title of any browser window should be, and what default
|
|
|
|
directory should be used."""
|
|
|
|
|
|
|
|
# Save Frame
|
|
|
|
|
|
|
|
label = gtk.Label("<b>%s</b>" % _('Document Options'))
|
|
|
|
label.set_use_markup(1)
|
|
|
|
label.set_alignment(0.0,0.5)
|
|
|
|
self.tbl.set_border_width(12)
|
|
|
|
self.tbl.attach(label, 0, 4, self.col, self.col+1, gtk.FILL)
|
|
|
|
self.col += 1
|
|
|
|
|
|
|
|
hid = self.get_stylesheet_savefile()
|
|
|
|
if hid[-4:]==".xml":
|
|
|
|
hid = hid[0:-4]
|
|
|
|
self.target_fileentry = FileEntry(hid,_("Save As"))
|
|
|
|
|
|
|
|
if self.get_target_is_directory():
|
|
|
|
self.target_fileentry.set_directory_entry(1)
|
|
|
|
self.doc_label = gtk.Label("%s:" % _("Directory"))
|
|
|
|
else:
|
|
|
|
self.doc_label = gtk.Label("%s:" % _("Filename"))
|
|
|
|
self.doc_label.set_alignment(0.0,0.5)
|
|
|
|
|
|
|
|
self.tbl.attach(self.doc_label, 1, 2, self.col, self.col+1,
|
|
|
|
xoptions=gtk.SHRINK|gtk.FILL,yoptions=gtk.SHRINK)
|
|
|
|
self.tbl.attach(self.target_fileentry, 2, 4, self.col, self.col+1,
|
|
|
|
xoptions=gtk.EXPAND|gtk.FILL,yoptions=gtk.SHRINK)
|
|
|
|
self.col += 1
|
|
|
|
|
|
|
|
spath = self.get_default_directory()
|
|
|
|
|
|
|
|
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 setup_output_notebook(self):
|
2007-09-16 03:21:44 +05:30
|
|
|
"""Set up the output notebook of the dialog.
|
|
|
|
|
|
|
|
This sole purpose of this function is to grab a pointer for later
|
|
|
|
use in the callback from when the file format is changed.
|
|
|
|
|
|
|
|
"""
|
2006-05-31 06:18:07 +05:30
|
|
|
pass
|
|
|
|
|
2007-09-16 03:21:44 +05:30
|
|
|
def size_changed(self, obj):
|
|
|
|
"""Paper size combobox 'changed' callback."""
|
2007-09-18 00:18:29 +05:30
|
|
|
size, name = self.get_paper_size()
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-16 03:21:44 +05:30
|
|
|
is_custom = name == _("Custom Size")
|
|
|
|
self.pwidth.set_sensitive(is_custom)
|
|
|
|
self.pheight.set_sensitive(is_custom)
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-18 00:18:29 +05:30
|
|
|
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)
|
2007-01-18 08:35:26 +05:30
|
|
|
|
2007-09-18 00:18:29 +05:30
|
|
|
def units_changed(self, checkbox):
|
2007-09-16 03:21:44 +05:30
|
|
|
"""Metric checkbox 'toggled' callback."""
|
2007-09-18 00:18:29 +05:30
|
|
|
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
|
2007-01-18 08:35:26 +05:30
|
|
|
else:
|
2007-09-18 00:18:29 +05:30
|
|
|
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))
|
2007-01-18 08:35:26 +05:30
|
|
|
|
2006-05-31 06:18:07 +05:30
|
|
|
def setup_paper_frame(self):
|
2007-03-27 17:34:07 +05:30
|
|
|
"""Set up the paper selection frame of the dialog."""
|
2007-09-16 03:21:44 +05:30
|
|
|
glade_file = os.path.join(const.GLADE_DIR, "paper_settings.glade")
|
|
|
|
glade_xml = gtk.glade.XML(glade_file, "paper_table", "gramps")
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-16 03:21:44 +05:30
|
|
|
self.paper_table = glade_xml.get_widget('paper_table')
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-16 03:21:44 +05:30
|
|
|
# get all the widgets
|
|
|
|
widgets = ('pwidth', 'pheight', 'lmargin', 'rmargin', 'tmargin',
|
|
|
|
'bmargin', 'lunits1', 'lunits2', 'lunits3', 'lunits4',
|
|
|
|
'lunits5', 'lunits6', 'metric')
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-16 03:21:44 +05:30
|
|
|
for w in widgets:
|
|
|
|
setattr(self, w, glade_xml.get_widget(w))
|
2007-01-18 08:35:26 +05:30
|
|
|
|
2007-09-16 03:21:44 +05:30
|
|
|
# insert custom widgets
|
|
|
|
self.papersize_menu = PaperComboBox()
|
|
|
|
self.orientation_menu = OrientationComboBox()
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-16 03:21:44 +05:30
|
|
|
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)
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-16 03:21:44 +05:30
|
|
|
# connect signals
|
|
|
|
self.papersize_menu.connect('changed',self.size_changed)
|
|
|
|
self.metric.connect('toggled',self.units_changed)
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-16 03:21:44 +05:30
|
|
|
# set initial values
|
2007-09-18 00:18:29 +05:30
|
|
|
self.paper_unit = 'cm'
|
|
|
|
self.paper_unit_multiplier = 1.0
|
2006-05-31 08:11:46 +05:30
|
|
|
self.papersize_menu.set(paper_sizes,
|
2006-05-31 06:18:07 +05:30
|
|
|
self.options.handler.get_paper_name())
|
|
|
|
self.orientation_menu.set(self.options.handler.get_orientation())
|
2007-09-16 03:21:44 +05:30
|
|
|
|
2006-05-31 06:18:07 +05:30
|
|
|
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)
|
2007-05-16 07:39:04 +05:30
|
|
|
self.html_table.attach(label, 1, 2, 1, 2, gtk.SHRINK|gtk.FILL,
|
|
|
|
yoptions=gtk.SHRINK)
|
2006-05-31 06:18:07 +05:30
|
|
|
|
|
|
|
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)
|
2007-02-15 08:44:03 +05:30
|
|
|
if _template_map[template] == os.path.basename(template_name):
|
2006-05-31 06:18:07 +05:30
|
|
|
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)
|
|
|
|
|
2007-05-16 07:39:04 +05:30
|
|
|
self.html_table.attach(self.template_combo,2,3,1,2, yoptions=gtk.SHRINK)
|
2006-05-31 06:18:07 +05:30
|
|
|
label = gtk.Label("%s:" % _("User Template"))
|
|
|
|
label.set_alignment(0.0,0.5)
|
2007-05-16 07:39:04 +05:30
|
|
|
self.html_table.attach(label, 1, 2, 2, 3, gtk.SHRINK|gtk.FILL,
|
|
|
|
yoptions=gtk.SHRINK)
|
2006-05-31 06:18:07 +05:30
|
|
|
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)
|
2007-05-16 07:39:04 +05:30
|
|
|
self.html_table.attach(self.html_fileentry,2,3,2,3, yoptions=gtk.SHRINK)
|
2006-05-31 06:18:07 +05:30
|
|
|
self.template_combo.set_active(active_index)
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Functions related to retrieving data from the dialog window
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
def parse_target_frame(self):
|
|
|
|
"""Parse the target frame of the dialog. If the target
|
|
|
|
filename is empty this routine returns a special value of None
|
|
|
|
to tell the calling routine to give up. This function also
|
|
|
|
saves the current directory so that any future reports will
|
|
|
|
default to the most recently used directory."""
|
|
|
|
self.target_path = self.target_fileentry.get_full_path(0)
|
|
|
|
if not self.target_path:
|
|
|
|
return None
|
|
|
|
|
|
|
|
# First we check whether the selected path exists
|
|
|
|
if os.path.exists(self.target_path):
|
|
|
|
|
|
|
|
# selected path is an existing dir and we need a dir
|
|
|
|
if os.path.isdir(self.target_path) \
|
|
|
|
and self.get_target_is_directory():
|
|
|
|
|
|
|
|
# check whether the dir has rwx permissions
|
|
|
|
if not os.access(self.target_path,os.R_OK|os.W_OK|os.X_OK):
|
|
|
|
ErrorDialog(_('Permission problem'),
|
|
|
|
_("You do not have permission to write "
|
|
|
|
"under the directory %s\n\n"
|
|
|
|
"Please select another directory or correct "
|
|
|
|
"the permissions." % self.target_path)
|
|
|
|
)
|
|
|
|
return None
|
|
|
|
|
|
|
|
# selected path is an exsting file and we need a file
|
|
|
|
if os.path.isfile(self.target_path) \
|
|
|
|
and not self.get_target_is_directory():
|
|
|
|
a = OptionDialog(_('File already exists'),
|
|
|
|
_('You can choose to either overwrite the '
|
|
|
|
'file, or change the selected filename.'),
|
|
|
|
_('_Overwrite'),None,
|
|
|
|
_('_Change filename'),None)
|
|
|
|
|
|
|
|
if a.get_response() == gtk.RESPONSE_YES:
|
|
|
|
return None
|
|
|
|
|
|
|
|
# selected path does not exist yet
|
|
|
|
else:
|
|
|
|
# we will need to create the file/dir
|
|
|
|
# need to make sure we can create in the parent dir
|
|
|
|
parent_dir = os.path.dirname(os.path.normpath(self.target_path))
|
|
|
|
if not os.access(parent_dir,os.W_OK):
|
|
|
|
ErrorDialog(_('Permission problem'),
|
|
|
|
_("You do not have permission to create "
|
|
|
|
"%s\n\n"
|
|
|
|
"Please select another path or correct "
|
|
|
|
"the permissions." % self.target_path)
|
|
|
|
)
|
|
|
|
return None
|
|
|
|
|
|
|
|
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_reference()
|
|
|
|
format_name = self.format_menu.get_clname()
|
|
|
|
self.options.handler.set_format_name(format_name)
|
|
|
|
|
2007-09-18 00:18:29 +05:30
|
|
|
def get_paper_size(self):
|
|
|
|
"""Read and validate paper size values.
|
2007-09-16 03:04:12 +05:30
|
|
|
|
2007-09-18 00:18:29 +05:30
|
|
|
If needed update the dimensions from the width, height entries,
|
|
|
|
and worst case fallback to A4 size.
|
2007-09-16 03:04:12 +05:30
|
|
|
|
|
|
|
"""
|
2007-09-18 00:18:29 +05:30
|
|
|
papersize, papername = self.papersize_menu.get_value()
|
2007-01-18 08:35:26 +05:30
|
|
|
|
2007-09-18 00:18:29 +05:30
|
|
|
# FIXME it is wrong to use translatable text in comparison.
|
|
|
|
# How can we distinguish custom size though?
|
|
|
|
if papername == _('Custom Size'):
|
2006-05-31 06:18:07 +05:30
|
|
|
try:
|
|
|
|
h = float(unicode(self.pheight.get_text()))
|
|
|
|
w = float(unicode(self.pwidth.get_text()))
|
|
|
|
|
|
|
|
if h <= 1.0 or w <= 1.0:
|
2007-09-18 00:18:29 +05:30
|
|
|
papersize.set_height(29.7)
|
|
|
|
papersize.set_width(21.0)
|
2006-05-31 06:18:07 +05:30
|
|
|
else:
|
2007-09-18 00:18:29 +05:30
|
|
|
papersize.set_height(h * self.paper_unit_multiplier)
|
|
|
|
papersize.set_width(w * self.paper_unit_multiplier)
|
2006-05-31 06:18:07 +05:30
|
|
|
except:
|
2007-09-18 00:18:29 +05:30
|
|
|
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.
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-18 00:18:29 +05:30
|
|
|
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()))
|
2007-09-17 00:28:24 +05:30
|
|
|
|
2007-09-18 00:18:29 +05:30
|
|
|
for i, margin in enumerate(paper_margins):
|
2007-09-17 00:28:24 +05:30
|
|
|
try:
|
2007-09-18 00:18:29 +05:30
|
|
|
paper_margins[i] = float(margin)
|
|
|
|
paper_margins[i] = paper_margins[i] * self.paper_unit_multiplier
|
|
|
|
paper_margins[i] = max(paper_margins[i], 0)
|
2007-09-17 00:28:24 +05:30
|
|
|
except:
|
|
|
|
self.paper_margins[i] = 2.54
|
|
|
|
|
2007-09-18 00:18:29 +05:30
|
|
|
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()
|
2006-05-31 06:18:07 +05:30
|
|
|
|
2007-09-18 00:18:29 +05:30
|
|
|
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()
|
|
|
|
|
2006-05-31 06:18:07 +05:30
|
|
|
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:
|
2007-09-08 11:24:02 +05:30
|
|
|
self.template_name = "%s%s%s" % (const.TEMPLATE_DIR,os.path.sep,
|
2006-05-31 23:56:50 +05:30
|
|
|
_template_map[text])
|
2006-05-31 06:18:07 +05:30
|
|
|
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_paper_frame()
|
|
|
|
self.parse_html_frame()
|
|
|
|
self.parse_user_options()
|
|
|
|
|
|
|
|
# Create the output document.
|
|
|
|
self.make_document()
|
|
|
|
|
|
|
|
# Save options
|
|
|
|
self.options.handler.save_options()
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Generic task function a standalone GUI report
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
2006-05-31 23:56:50 +05:30
|
|
|
def report(dbstate,uistate,person,report_class,options_class,
|
2006-06-17 02:56:44 +05:30
|
|
|
trans_name,name,category, require_active):
|
2006-05-31 06:18:07 +05:30
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
|
|
|
|
2006-06-17 02:56:44 +05:30
|
|
|
if require_active and not person:
|
|
|
|
ErrorDialog(
|
|
|
|
_('Active person has not been set'),
|
|
|
|
_('You must select an active person for this report to work '
|
|
|
|
'properly.'))
|
|
|
|
return
|
|
|
|
|
2006-05-31 06:18:07 +05:30
|
|
|
if category == CATEGORY_TEXT:
|
2006-05-31 08:11:46 +05:30
|
|
|
from _TextReportDialog import TextReportDialog
|
2006-05-31 06:18:07 +05:30
|
|
|
dialog_class = TextReportDialog
|
|
|
|
elif category == CATEGORY_DRAW:
|
2006-05-31 08:11:46 +05:30
|
|
|
from _DrawReportDialog import DrawReportDialog
|
2006-05-31 06:18:07 +05:30
|
|
|
dialog_class = DrawReportDialog
|
2006-06-02 06:10:54 +05:30
|
|
|
elif category in (CATEGORY_BOOK,CATEGORY_CODE,CATEGORY_VIEW,CATEGORY_WEB):
|
2006-06-01 04:30:22 +05:30
|
|
|
try:
|
|
|
|
report_class(dbstate,uistate,person)
|
|
|
|
except Errors.WindowActiveError:
|
|
|
|
pass
|
|
|
|
return
|
2006-05-31 06:18:07 +05:30
|
|
|
else:
|
|
|
|
dialog_class = ReportDialog
|
|
|
|
|
2006-05-31 23:56:50 +05:30
|
|
|
dialog = dialog_class(dbstate,uistate,person,options_class,name,trans_name)
|
2007-01-01 05:26:14 +05:30
|
|
|
|
|
|
|
while True:
|
|
|
|
response = dialog.window.run()
|
|
|
|
if response == gtk.RESPONSE_OK:
|
2007-08-26 19:35:34 +05:30
|
|
|
dialog.close()
|
2007-01-01 05:26:14 +05:30
|
|
|
try:
|
|
|
|
MyReport = report_class(dialog.db,dialog.person,dialog.options)
|
|
|
|
MyReport.doc.init()
|
|
|
|
MyReport.begin_report()
|
|
|
|
MyReport.write_report()
|
|
|
|
MyReport.end_report()
|
|
|
|
except Errors.FilterError, msg:
|
|
|
|
(m1,m2) = msg.messages()
|
|
|
|
ErrorDialog(m1,m2)
|
|
|
|
except IOError, msg:
|
|
|
|
ErrorDialog(_("Report could not be created"),str(msg))
|
|
|
|
except Errors.ReportError, msg:
|
|
|
|
(m1,m2) = msg.messages()
|
|
|
|
ErrorDialog(m1,m2)
|
|
|
|
except Errors.DatabaseError,msg:
|
|
|
|
ErrorDialog(_("Report could not be created"),str(msg))
|
2007-05-15 09:47:12 +05:30
|
|
|
except AttributeError,msg:
|
2007-06-23 19:58:13 +05:30
|
|
|
if str(msg).startswith("'NoneType' object has no attribute"):
|
|
|
|
# "'NoneType' object has no attribute ..." usually means
|
2007-06-22 18:49:52 +05:30
|
|
|
# database corruption
|
|
|
|
RunDatabaseRepair(str(msg))
|
|
|
|
else:
|
|
|
|
raise
|
2007-01-01 05:26:14 +05:30
|
|
|
except:
|
|
|
|
log.error("Failed to run report.", exc_info=True)
|
|
|
|
break
|
2007-08-26 19:35:34 +05:30
|
|
|
elif (response == gtk.RESPONSE_DELETE_EVENT or
|
|
|
|
response == gtk.RESPONSE_CANCEL):
|
|
|
|
dialog.close()
|
2007-01-01 05:26:14 +05:30
|
|
|
break
|