gramps/src/plugins/drawreport/AncestorTree.py
Gerald Britton e8f9c8422a Tweaks to graphical tree reports
svn: r16422
2011-01-21 14:30:14 +00:00

991 lines
36 KiB
Python

#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2007-2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant#
# Copyright (C) 2010 Craig J. Anderson
#
# 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: Ancestor2.py
"""Reports/Graphical Reports/Ancestor Tree"""
#------------------------------------------------------------------------
#
# python modules
#
#------------------------------------------------------------------------
import math
def log2(val):
"""
Calculate the log base 2 of a value.
"""
return int(math.log(val, 2))
X_INDEX = log2
from gen.ggettext import sgettext as _
#------------------------------------------------------------------------
#
# GRAMPS modules
#
#------------------------------------------------------------------------
#from Errors import ReportError
from gen.plug.menu import BooleanOption
from gen.plug.menu import NumberOption
from gen.plug.menu import StringOption
from gen.plug.menu import EnumeratedListOption
from gen.plug.menu import TextOption
from gen.plug.menu import PersonOption
from gen.plug.report import Report
from gen.plug.report import utils as ReportUtils
from gui.plug.report import MenuReportOptions
from gen.display.name import displayer as name_displayer
PT2CM = ReportUtils.pt2cm
#cm2pt = ReportUtils.cm2pt
#------------------------------------------------------------------------
#
# Constants
#
#------------------------------------------------------------------------
_BORN = _('short for born|b.')
_DIED = _('short for died|d.')
_MARR = _('short for married|m.')
from libtreebase import *
#------------------------------------------------------------------------
#
# Box classes
#
#------------------------------------------------------------------------
class AncestorBoxBase(BoxBase):
""" The base class for the two boxes used in this report """
def __init__(self, boxstr):
BoxBase.__init__(self)
self.boxstr = boxstr
def y_index(self, max_gen):
""" Calculate the column or generation that this person is in. """
x_level = self.level[0]
#Calculate which row in the column of people.
tmp_y = self.level[1] - (2**x_level)
#Calculate which row in the table (yes table) of people.
delta = (2**max_gen) // (2**(x_level))
return int((delta/2) + (tmp_y*delta))
class PersonBox(AncestorBoxBase):
"""
Calculates information about the box that will print on a page
"""
def __init__(self, level):
AncestorBoxBase.__init__(self, "AC2-box")
self.level = (X_INDEX(level), level)
class FamilyBox(AncestorBoxBase):
"""
Calculates information about the box that will print on a page
"""
def __init__(self, level):
AncestorBoxBase.__init__(self, "AC2-fam-box")
self.level = (X_INDEX(level)+1, level)
def y_index(self, max_gen):
""" Calculate the column or generation that this person is in. """
x_level = self.level[0] - 1
#Calculate which row in the column of people.
tmp_y = self.level[1] - (2**x_level)
#Calculate which row in the table (yes table) of people.
delta = (2**max_gen) // (2**(x_level))
return int((delta/2) + (tmp_y*delta))
#------------------------------------------------------------------------
#
# Line class
#
#------------------------------------------------------------------------
class Line(LineBase):
""" Our line class."""
def __init__(self, start):
LineBase.__init__(self, start)
self.linestr = 'AC2-line'
#------------------------------------------------------------------------
#
# Titles Class(es)
#
#------------------------------------------------------------------------
class TitleN(TitleBox):
"""No Title class for the report """
def __init__(self, doc):
TitleBox.__init__(self, doc, "None")
def calc_title(self, center):
"""Calculate the title of the report"""
return
class TitleA(TitleBox):
"""Title class for the report """
def __init__(self, doc):
TitleBox.__init__(self, doc, "AC2-Title")
def calc_title(self, center):
"""Calculate the title of the report"""
name = ""
if center is not None:
name = name_displayer.display(center)
self.text = _("Ancestor Graph for %s") % name
self.set_box_height_width()
#------------------------------------------------------------------------
#
# CalcItems (helper class to calculate text)
# make_ancestor_tree (main recursive functions)
#
#------------------------------------------------------------------------
class CalcItems(object):
def __init__(self, dbase):
__gui = GUIConnect()
#calculate the printed lines for each box
#display_repl = [] #Not used in this report
#str = ""
#if self.get_val('miss_val'):
# str = "_____"
self.__calc_l = CalcLines(dbase, [])
self.__blank_father = None
self.__blank_mother = None
main = self.__calc_l.calc_lines( None, None, __gui.get_val('dispf'))
secn = self.__calc_l.calc_lines( None, None, __gui.get_val('disp_sec'))
self.disp_father = __gui.get_val('dispf')
self.__blank_father = main
self.disp_mother = __gui.get_val('dispf')
self.__blank_mother = main
if __gui.get_val('dif_sec') == 1:
self.disp_father = __gui.get_val('disp_sec')
self.__blank_father = secn
elif __gui.get_val('dif_sec') == 2:
self.disp_mother = __gui.get_val('disp_sec')
self.__blank_mother = secn
self.disp_marr = [__gui.get_val('dispmarr')]
self.__blank_marriage = \
self.__calc_l.calc_lines(None, None, self.disp_marr)
def calc_person(self, index, indi_handle, fams_handle):
working_lines = ""
if index == 1 or index % 2 == 0: #The center person always uses main
if indi_handle == fams_handle == None:
working_lines = self.__blank_father
else:
working_lines = self.disp_father
else:
if indi_handle == fams_handle == None:
working_lines = self.__blank_mother
else:
working_lines = self.disp_mother
if indi_handle == fams_handle == None:
return working_lines
else:
return self.__calc_l.calc_lines(indi_handle, fams_handle,
working_lines)
def calc_marrage(self, indi_handle, fams_handle):
if indi_handle == fams_handle == None:
return self.__blank_marriage
else:
return self.__calc_l.calc_lines(indi_handle, fams_handle,
self.disp_marr)
class MakeAncestorTree(object):
"""
The main procedure to use recursion to make the tree based off of a person.
order of people inserted into Persons is important.
makes sure that order is done correctly.
"""
def __init__(self, dbase, canvas, max_gen, inc_marr, fill_out):
self.database = dbase
self.canvas = canvas
self.inlc_marr = inc_marr
self.max_generations = max_gen
self.fill_out = fill_out
self.calc_items = CalcItems(self.database)
def add_person_box(self, index, indi_handle, fams_handle):
""" Makes a person box and add that person into the Canvas. """
myself = PersonBox(index)
myself.text = self.calc_items.calc_person(
index, indi_handle, fams_handle)
self.canvas.add_box(myself)
return myself
def add_marriage_box(self, index, indi_handle, fams_handle):
""" Makes a marriage box and add that person into the Canvas. """
myself = FamilyBox(index)
#calculate the text.
myself.text = self.calc_items.calc_marrage(indi_handle, fams_handle)
self.canvas.add_box(myself)
def add_line(self, person, father, mother = None):
""" Adds the line connecting the boxes """
if father is None and mother is None:
return
line = Line(person)
if father:
line.add_to(father)
if mother:
line.add_to(mother)
self.canvas.add_line(line)
return line
def recurse(self, person_handle, family_handle, index):
""" traverse the ancestors recursively until either the end
of a line is found, or until we reach the maximum number of
generations that the user wants """
if log2(index) == self.max_generations:
return None
person = self.database.get_person_from_handle(person_handle)
if not person:
return self.__fill(index, None,
min(self.fill_out, self.max_generations-X_INDEX(index)-1)
)
parents_handle = person.get_main_parents_family_handle()
father = marrbox = mother = None
if parents_handle:
#note depth first
family = self.database.get_family_from_handle(parents_handle)
father = self.recurse(family.get_father_handle(), parents_handle,
index*2)
mybox = self.add_person_box(index, person_handle, family_handle)
if self.inlc_marr and (log2(index) + 2) <= self.max_generations:
marrbox = self.add_marriage_box(index,
family.get_father_handle(),
parents_handle)
mother = self.recurse(family.get_mother_handle(), parents_handle,
(index*2)+1)
self.add_line(mybox, father, mother)
else:
mybox = self.__fill(index, person_handle,
min(self.fill_out, self.max_generations-X_INDEX(index)-1)
)
#father = self.__fill(index *2, self.fill_out)
#mybox = self.add_person_box(index, person_handle, family_handle)
#if self.fill_out and self.inlc_marr and (log2(index) + 2) <
# self.max_generations:
# marrbox = self.add_marriage_box(index*2, None, None)
#mother = self.__fill(index *2+1, self.fill_out)
return mybox
def __fill(self, index, person_handle, max_fill):
""" Fills out the Ancestor tree as desired/needed.
this is an iterative apporach.
"""
if max_fill < 0:
return
##if X_INDEX(index) == self.max_generations:
## return None
###########################
#list of boxes
#for each generation (max_fill)
__BOXES = [None] * (max_fill+1)
__INDEX = [index]
__LINES = [None] * max_fill
#if __INFO[0][__FILL_AMOUNT] == max_fill or \
# X_INDEX(index) >= self.max_generations-1:
if max_fill == 0:
return self.add_person_box(index, None, None)
###########################
#Prime the pump
cur_gen = 1
#Cur_gen is the current Generation that we are working with
#use a bottom up iterative approach
while cur_gen > 0:
###########################
#Step 1. this level is blank. add our father
#if __INFO[cur_gen][__INDEX] == 0:
if len(__INDEX) == cur_gen:
__INDEX.append(__INDEX[cur_gen-1]*2)
#we will be adding a father here
if cur_gen < max_fill:
#But first, go to this father first if we can
cur_gen += 1
else:
#found our father. add him
__BOXES[cur_gen] = self.add_person_box(
__INDEX[cur_gen], None, None)
###########################
#Step 1.5. Dad has already been made.
elif __INDEX[cur_gen] %2 == 0:
###########################
#Step 2. add our kid
__BOXES[cur_gen-1] = self.add_person_box(
__INDEX[cur_gen-1],
person_handle if cur_gen == 1 else None,
None)
###########################
#Step 2.3. add our marriage
if self.inlc_marr and cur_gen <= max_fill+1:
self.add_marriage_box(__INDEX[cur_gen-1], None, None)
###########################
#Step 2.6. line part 1
__LINES[cur_gen-1] = self.add_line(__BOXES[cur_gen-1],
__BOXES[cur_gen])
#make sure there is a NEW int.
__INDEX.pop()
#not a refernce that will clobber dada info
__INDEX.append((__INDEX[cur_gen-1] *2) +1)
#__INDEX[cur_gen] +=1
if cur_gen < max_fill:
cur_gen += 1
else:
###########################
#Step 3. Now we can make Mom
__BOXES[cur_gen] = self.add_person_box(
__INDEX[cur_gen], None, None)
###########################
#Step 4. Father and Mother are done but only 1/2 line
else:
if cur_gen > 0:
###########################
#Step 2.6. line part 2
__LINES[cur_gen-1].add_to(__BOXES[cur_gen])
__INDEX.pop()
cur_gen -= 1
return __BOXES[0]
def start(self, person_id):
""" go ahead and make it happen """
center = self.database.get_person_from_gramps_id(person_id)
center_h = center.get_handle()
self.recurse(center_h, None, 1)
#------------------------------------------------------------------------
#
# Transform Classes
#
#------------------------------------------------------------------------
#------------------------------------------------------------------------
# Class rl_Transform
#------------------------------------------------------------------------
class RLTransform():
"""
setup all of the boxes on the canvas in for a left/right report
"""
def __init__(self, canvas, opts, max_generations, compress_tree):
self.canvas = canvas
self.rept_opts = opts
self.max_generations = max_generations
self.compress_tree = compress_tree
self.y_offset = self.rept_opts.littleoffset*2 + self.canvas.title.height
self.__last_y_level = 0
self.__y_level = 0
def __next_y(self, box):
""" boxes are already in top down (.y_cm) form so if we
set the box in the correct y level depending on compress_tree
"""
y_index = box.y_index(self.max_generations+1) -1
if self.compress_tree:
current_y = self.__y_level
if y_index > self.__last_y_level:
self.__last_y_level = y_index
self.__y_level += 1
current_y = self.__y_level
return current_y
else:
return y_index
def _place(self, box):
""" put the box in it's correct spot """
#1. cm_x
box.x_cm = self.rept_opts.littleoffset
box.x_cm += (box.level[0] *
(self.rept_opts.col_width + self.rept_opts.max_box_width))
#2. cm_y
box.y_cm = self.__next_y(box) * self.rept_opts.max_box_height
box.y_cm += self.y_offset
#if box.height < self.rept_opts.max_box_height:
# box.y_cm += ((self.rept_opts.max_box_height - box.height) /2)
def place(self):
""" step through boxes so they can be put in the right spot """
#prime the pump
self.__last_y_level = \
self.canvas.boxes[0].y_index(self.max_generations+1) -1
#go
for box in self.canvas.boxes:
self._place(box)
#------------------------------------------------------------------------
#
# class make_report
#
#------------------------------------------------------------------------
class MakeReport():
def __init__(self, dbase, doc, canvas,
font_normal, inlc_marr, compress_tree):
self.database = dbase
self.doc = doc
self.canvas = canvas
self.font_normal = font_normal
self.inlc_marr = inlc_marr
self.compress_tree = compress_tree
self.mother_ht = self.father_ht = 0
self.max_generations = 0
def get_height_width(self, box):
"""
obtain width information for each level (x)
obtain height information for each item
"""
self.canvas.set_box_height_width(box)
if box.width > self.doc.report_opts.max_box_width:
self.doc.report_opts.max_box_width = box.width #+ box.shadow
if box.level[1] > 0:
if box.level[1] % 2 == 0 and box.height > self.father_ht:
self.father_ht = box.height
elif box.level[1] % 2 == 1 and box.height > self.mother_ht:
self.mother_ht = box.height
tmp = log2(box.level[1])
if tmp > self.max_generations:
self.max_generations = tmp
def get_generations(self):
return self.max_generations
def start(self):
# 1.
#set the sizes for each box and get the max_generations.
self.father_ht = 0.0
self.mother_ht = 0.0
for box in self.canvas.boxes:
self.get_height_width(box)
if self.compress_tree and not self.inlc_marr:
self.doc.report_opts.max_box_height = \
min(self.father_ht, self.mother_ht)
else:
self.doc.report_opts.max_box_height = \
max(self.father_ht, self.mother_ht)
#At this point we know everything we need to make the report.
#Size of each column of people - self.rept_opt.box_width
#size of each column (or row) of lines - self.rept_opt.col_width
#size of each row - self.rept_opt.box_height
#go ahead and set it now.
for box in self.canvas.boxes:
box.width = self.doc.report_opts.max_box_width
# 2.
#setup the transform class to move around the boxes on the canvas
transform = RLTransform(self.canvas, self.doc.report_opts,
self.max_generations, self.compress_tree)
transform.place()
class GUIConnect():
""" This is a BORG object. There is ONLY one.
This give some common routines that EVERYONE can use like
get the value from a GUI variable
"""
__shared_state = {}
def __init__(self): #We are BORG!
self.__dict__ = self.__shared_state
def set__opts(self, options):
""" Set only once as we are BORG. """
self.__opts = options
def get_val(self, val):
""" Get a GUI value. """
return self.__opts.get_option_by_name(val).get_value()
def title_class(self, doc):
""" Return a class that holds the proper title based off of the
GUI options """
title_type = self.get_val('report_title')
return TitleA(doc) if title_type else TitleN(doc)
#------------------------------------------------------------------------
#
# AncestorTree
#
#------------------------------------------------------------------------
class AncestorTree2(Report):
def __init__(self, database, options_class):
"""
Create AncestorTree object that produces the report.
The arguments are:
database - the GRAMPS database instance
person - currently selected person
options_class - instance of the Options class for this report
This report needs the following parameters (class variables)
that come in the options class.
max_generations - Maximum number of generations to include.
pagebbg - Whether to include page breaks between generations.
dispf - Display format for the output box.
scale_report - Whether to scale the report to fit the width or all.
indblank - Whether to include blank pages.
compress - Whether to compress chart.
"""
Report.__init__(self, database, options_class)
self.connect = GUIConnect()
self.connect.set__opts(options_class.menu)
style_sheet = self.doc.get_style_sheet()
font_normal = style_sheet.get_paragraph_style("AC2-Normal").get_font()
self.doc.report_opts = ReportOptions(self.doc, font_normal)
self.canvas = Canvas(self.doc)
#make the tree into self.canvas
inlc_marr = self.connect.get_val('incmarr')
self.max_generations = self.connect.get_val('maxgen')
fillout = self.connect.get_val('fillout')
tree = MakeAncestorTree(database, self.canvas, self.max_generations,
inlc_marr, fillout)
tree.start(self.connect.get_val('pid'))
tree = None
#Title
title = self.connect.title_class(self.doc)
center = self.database.get_person_from_gramps_id(
self.connect.get_val('pid')
)
title.calc_title(center)
self.canvas.add_title(title)
#make the report as big as it wants to be.
compress = self.connect.get_val('compress')
report = MakeReport(database, self.doc, self.canvas, font_normal,
inlc_marr, compress)
report.start()
self.max_generations = report.get_generations() #already know
report = None
def begin_report(self):
"""
We have
1. a canvas in its full one-page size
2. a page that we wish to print on
scale up/down either or both of the above as needed/desired.
almost all of this should be moved into Canvas!
"""
if self.connect.get_val('use_note'):
note_box = NoteBox(self.doc, "AC2-fam-box",
self.connect.get_val('note_local'))
subst = SubstKeywords(self.database, None, None)
note_box.text = subst.replace_and_clean(
self.connect.get_val('note_disp'))
self.canvas.add_note(note_box)
one_page = self.connect.get_val('onepage')
scale_report = self.connect.get_val('scale_report')
scale = self.canvas.scale_report(one_page,
scale_report != 0, scale_report == 2)
if scale != 1:
self.scale_styles(scale)
def write_report(self):
one_page = self.connect.get_val('onepage')
#scale_report = self.connect.get_val('scale_report')
#inlc_marr = self.connect.get_val('incmarr')
inc_border = self.connect.get_val('inc_border')
incblank = self.connect.get_val('incblank')
prnnum = self.connect.get_val('prnnum')
#####################
#Setup page infomation
colsperpage = self.doc.get_usable_width()
colsperpage += self.doc.report_opts.col_width
colsperpage = int(colsperpage / (self.doc.report_opts.max_box_width +
self.doc.report_opts.col_width))
colsperpage = colsperpage or 1
#####################
#Vars
if prnnum:
page_num_box = PageNumberBox(self.doc, 'AC2-box')
#####################
#ok, everyone is now ready to print on the canvas. Paginate?
self.canvas.paginate(colsperpage, one_page)
#####################
#Yeah!!!
#lets finally make some pages!!!
#####################
for page in self.canvas.page_iter_gen(incblank):
self.doc.start_page()
#do we need to print a border?
if inc_border:
page.draw_border('AC2-line')
#Do we need to print the page number?
if prnnum:
page_num_box.display(page)
#Print the individual people and lines
page.display()
self.doc.end_page()
def scale_styles(self, scale):
"""
Scale the styles for this report.
"""
style_sheet = self.doc.get_style_sheet()
from gen.plug.docgen import GraphicsStyle
graph_style = style_sheet.get_draw_style("AC2-box")
graph_style.set_shadow(graph_style.get_shadow(),
graph_style.get_shadow_space() * scale)
graph_style.set_line_width(graph_style.get_line_width() * scale)
style_sheet.add_draw_style("AC2-box", graph_style)
graph_style = style_sheet.get_draw_style("AC2-fam-box")
graph_style.set_shadow(graph_style.get_shadow(),
graph_style.get_shadow_space() * scale)
graph_style.set_line_width(graph_style.get_line_width() * scale)
style_sheet.add_draw_style("AC2-fam-box", graph_style)
para_style = style_sheet.get_paragraph_style("AC2-Normal")
font = para_style.get_font()
font.set_size(font.get_size() * scale)
para_style.set_font(font)
style_sheet.add_paragraph_style("AC2-Normal", para_style)
para_style = style_sheet.get_paragraph_style("AC2-Title")
font = para_style.get_font()
font.set_size(font.get_size() * scale)
para_style.set_font(font)
style_sheet.add_paragraph_style("AC2-Title", para_style)
graph_style = GraphicsStyle()
width = graph_style.get_line_width()
width = width * scale
graph_style.set_line_width(width)
style_sheet.add_draw_style("AC2-line", graph_style)
self.doc.set_style_sheet(style_sheet)
#------------------------------------------------------------------------
#
# AncestorTreeOptions
#
#------------------------------------------------------------------------
class AncestorTree2Options(MenuReportOptions):
"""
Defines options and provides handling interface.
"""
def __init__(self, name, dbase):
MenuReportOptions.__init__(self, name, dbase)
def add_menu_options(self, menu):
category_name = _("Tree Options")
pid = PersonOption(_("Center Person"))
pid.set_help(_("The center person for the tree"))
menu.add_option(category_name, "pid", pid)
self.max_gen = NumberOption(_("Generations"), 10, 1, 50)
self.max_gen.set_help(_("The number of generations to include "
"in the tree"))
menu.add_option(category_name, "maxgen", self.max_gen)
self.fillout = EnumeratedListOption(_("Display unknown\ngenerations"),
0)
menu.add_option(category_name, "fillout", self.fillout)
self.max_gen.connect('value-changed', self.__fillout_vals)
self.__fillout_vals()
compress = BooleanOption(_('Co_mpress tree'), True)
compress.set_help(_("Whether to compress the tree."))
menu.add_option(category_name, "compress", compress)
#better to 'Show siblings of\nthe center person
#Spouse_disp = EnumeratedListOption(_("Show spouses of\nthe center "
# "person"), 0)
#Spouse_disp.add_item( 0, _("No. Do not show Spouses"))
#Spouse_disp.add_item( 1, _("Yes, and use the the Main Display Format"))
#Spouse_disp.add_item( 2, _("Yes, and use the the Secondary "
# "Display Format"))
#Spouse_disp.set_help(_("Show spouses of the center person?"))
#menu.add_option(category_name, "Spouse_disp", Spouse_disp)
category_name = _("Display")
disp = TextOption(_("Main\nDisplay Format"),
["$n","%s $b" % _BORN,"%s $d" %_DIED] )
disp.set_help(_("Display format for the output box."))
menu.add_option(category_name, "dispf", disp)
difMom = EnumeratedListOption(_("Use Main/Secondary\nDisplay "
"Format for"), 0)
difMom.add_item( 0, _("Everyone uses the Main Display format"))
difMom.add_item( 1, _("Mothers use Main, and Fathers use the "
"Secondary"))
difMom.add_item( 2, _("Fathers use Main, and Mothers use the "
"Secondary"))
difMom.set_help(_("Which Display format to use for Fathers and "
"Mothers"))
menu.add_option(category_name, "dif_sec", difMom)
#Will add when libsubstkeyword supports it.
#missing = EnumeratedListOption(_("Replace missing\nplaces\\dates \
# with"), 0)
#missing.add_item( 0, _("Does not display anything"))
#missing.add_item( 1, _("Displays '_____'"))
#missing.set_help(_("What will print when information is not known"))
#menu.add_option(category_name, "miss_val", missing)
category_name = _("Secondary")
dispMom = TextOption(_("Secondary\nDisplay Format"),
["$n","%s $b" % _BORN,
"%s $m" %_MARR,
"%s $d" %_DIED]
)
dispMom.set_help(_("Display format for the output box."))
menu.add_option(category_name, "disp_sec", dispMom)
incmarr = BooleanOption(_('Include Marriage information'), False)
incmarr.set_help(_("Whether to include marriage information in the "
"report."))
menu.add_option(category_name, "incmarr", incmarr)
marrdisp = StringOption(_("Marriage\nDisplay Format"), "%s $m" % _MARR)
marrdisp.set_help(_("Display format for the output box."))
menu.add_option(category_name, "dispmarr", marrdisp)
category_name = _("Print")
self.scale = EnumeratedListOption(_("Scale report to fit"), 0)
self.scale.add_item( 0, _("Do not scale report"))
self.scale.add_item( 1, _("Scale report to fit page width only"))
self.scale.add_item( 2, _("Scale report to fit the size of the page"))
self.scale.set_help(_("Whether to scale the report to fit a "
"specific size"))
menu.add_option(category_name, "scale_report", self.scale)
self.scale.connect('value-changed', self.__check_blank)
self.__onepage = BooleanOption(_('One page report'), True)
self.__onepage.set_help(_("Whether to scale the size of the page to "
"the size of the report."))
menu.add_option(category_name, "onepage", self.__onepage)
self.__onepage.connect('value-changed', self.__check_blank)
self.title = EnumeratedListOption(_("Report Title"), 0)
self.title.add_item( 0, "Do not print a Title")
self.title.add_item( 1, "Include Report Title")
menu.add_option(category_name, "report_title", self.title)
border = BooleanOption(_('Print a border'), True)
border.set_help(_("Whether to make a border around the report."))
menu.add_option(category_name, "inc_border", border)
prnnum = BooleanOption(_('Print Page Numbers'), False)
prnnum.set_help(_("Whether to print page numbers on each page."))
menu.add_option(category_name, "prnnum", prnnum)
self.__blank = BooleanOption(_('Include Blank Pages'), True)
self.__blank.set_help(_("Whether to include pages that are blank."))
menu.add_option(category_name, "incblank", self.__blank)
self.__check_blank()
category_name = _("Notes")
self.usenote = BooleanOption(_('Include a personal note'), False)
self.usenote.set_help(_("Whether to include a personalized note on "
"the report."))
menu.add_option(category_name, "use_note", self.usenote)
self.notedisp = TextOption(_("Note to add\nto the graph\n\n$T "
"inserts today's date"), [])
self.notedisp.set_help(_("Add a personal note"))
menu.add_option(category_name, "note_disp", self.notedisp)
locals = NoteType(0, 1)
notelocal = EnumeratedListOption(_("Note Location"), 0)
for num, text in locals.note_locals():
notelocal.add_item( num, text )
notelocal.set_help(_("Where to place a personal note."))
menu.add_option(category_name, "note_local", notelocal)
def __check_blank(self):
off = not self.__onepage.get_value() and (self.scale.get_value() != 2)
self.__blank.set_available( off )
def __fillout_vals(self):
max_gen = self.max_gen.get_value()
old_val = self.fillout.get_value()
item_list = []
item_list.append([0, _("No generations of empty boxes "
"for unknown ancestors") ])
if max_gen > 1:
item_list.append([1, _("One Generation of empty boxes "
"for unknown ancestors") ])
item_list.extend([itr, str(itr) +
_(" Generations of empty boxes for unknown ancestors")]
for itr in range(2, max_gen)
)
self.fillout.set_items(item_list)
if old_val+2 > len(item_list):
self.fillout.set_value(len(item_list) -2)
def make_default_style(self, default_style):
"""Make the default output style for the Ancestor Tree."""
from gen.plug.docgen import (FontStyle, ParagraphStyle, GraphicsStyle,
FONT_SANS_SERIF, PARA_ALIGN_CENTER)
## Paragraph Styles:
font = FontStyle()
font.set_size(9)
font.set_type_face(FONT_SANS_SERIF)
para_style = ParagraphStyle()
para_style.set_font(font)
para_style.set_description(_('The basic style used for the '
'text display.'))
default_style.add_paragraph_style("AC2-Normal", para_style)
box_shadow = PT2CM(font.get_size()) * .6
font = FontStyle()
font.set_size(16)
font.set_type_face(FONT_SANS_SERIF)
para_style = ParagraphStyle()
para_style.set_font(font)
para_style.set_alignment(PARA_ALIGN_CENTER)
para_style.set_description(_('The basic style used for the '
'title display.'))
default_style.add_paragraph_style("AC2-Title", para_style)
## Draw styles
graph_style = GraphicsStyle()
graph_style.set_paragraph_style("AC2-Normal")
graph_style.set_shadow(1, box_shadow) #shadow set by text size
graph_style.set_fill_color((255, 255, 255))
default_style.add_draw_style("AC2-box", graph_style)
graph_style = GraphicsStyle()
graph_style.set_paragraph_style("AC2-Normal")
#graph_style.set_shadow(0, PT2CM(9)) #shadow set by text size
graph_style.set_fill_color((255, 255, 255))
default_style.add_draw_style("AC2-fam-box", graph_style)
graph_style = GraphicsStyle()
graph_style.set_paragraph_style("AC2-Title")
graph_style.set_color((0, 0, 0))
graph_style.set_fill_color((255, 255, 255))
graph_style.set_line_width(0)
default_style.add_draw_style("AC2-Title", graph_style)
graph_style = GraphicsStyle()
default_style.add_draw_style("AC2-line", graph_style)
#=====================================
#But even if you should suffer for what is right, you are blessed.
#"Do not fear what they fear ; do not be frightened."
#Take Courage
#1 Peter 3:14