2
# Gramps - a GTK+/GNOME based genealogy program
4
# Copyright (C) 2007-2008 Brian G. Matherly
5
# Copyright (C) 2010 Jakim Friant
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 2 of the License, or
10
# (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, write to the Free Software
19
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
# $Id: EndOfLineReport.py 18915 2012-02-17 16:51:40Z romjerome $
24
"""Reports/Text Reports/End of Line Report"""
26
#------------------------------------------------------------------------
30
#------------------------------------------------------------------------
32
from gen.ggettext import gettext as _
34
#------------------------------------------------------------------------
38
#------------------------------------------------------------------------
39
from gen.display.name import displayer as global_name_display
40
from Errors import ReportError
41
from gen.plug.docgen import (IndexMark, FontStyle, ParagraphStyle, TableStyle,
42
TableCellStyle, FONT_SANS_SERIF, INDEX_TYPE_TOC,
44
from gen.plug.menu import (PersonOption, EnumeratedListOption)
45
from gen.plug.report import Report
46
from gen.plug.report import utils as ReportUtils
47
from gen.plug.report import MenuReportOptions
50
#------------------------------------------------------------------------
54
#------------------------------------------------------------------------
55
class EndOfLineReport(Report):
57
def __init__(self, database, options, user):
59
Create the EndOfLineReport object that produces the report.
63
database - the GRAMPS database instance
64
options - instance of the Options class for this report
65
user - a gen.user.User() instance
67
This report needs the following parameters (class variables)
68
that come in the options class.
69
name_format - Preferred format to display names
72
Report.__init__(self, database, options, user)
74
pid = menu.get_option_by_name('pid').get_value()
75
self.center_person = database.get_person_from_gramps_id(pid)
76
if (self.center_person == None) :
77
raise ReportError(_("Person %s is not in the Database") % pid )
79
# Copy the global NameDisplay so that we don't change application
81
self._name_display = copy.deepcopy(global_name_display)
82
name_format = menu.get_option_by_name("name_format").get_value()
84
self._name_display.set_default_format(name_format)
86
# eol_map is a map whose:
87
# keys are the generations of the people
88
# values are a map whose:
89
# keys are person handles
90
# values are an array whose:
91
# elements are an array of ancestor person handles that link
92
# the eol person handle to the person or interest
93
# eol_map[generation][person_handle][pedigree_idx][ancestor_handle_idx]
95
# There is an array of pedigrees because one person could show up twice
96
# in one generation (descendants marrying). Most people only have one
99
# eol_map is populated by get_eol() which calls itself recursively.
101
self.get_eol(self.center_person, 1, [])
103
def get_eol(self, person, gen, pedigree):
105
Recursively find the end of the line for each person
107
person_handle = person.get_handle()
108
new_pedigree = list(pedigree) + [person_handle]
109
person_is_eol = False
110
families = person.get_parent_family_handle_list()
112
if person_handle in pedigree:
113
# This is a severe error!
114
# It indicates a loop in ancestry: A -> B -> A
119
for family_handle in families:
120
family = self.database.get_family_from_handle(family_handle)
121
father_handle = family.get_father_handle()
122
mother_handle = family.get_mother_handle()
124
father = self.database.get_person_from_handle(father_handle)
125
self.get_eol(father, gen+1, new_pedigree)
127
mother = self.database.get_person_from_handle(mother_handle)
128
self.get_eol(mother, gen+1, new_pedigree)
130
if not father_handle or not mother_handle:
134
# This person is the end of a line
135
if gen not in self.eol_map:
136
self.eol_map[gen] = {}
137
if person_handle not in self.eol_map[gen]:
138
self.eol_map[gen][person_handle] = []
139
self.eol_map[gen][person_handle].append( new_pedigree )
141
def write_report(self):
143
The routine the actually creates the report. At this point, the document
144
is opened and ready for writing.
146
pname = self._name_display.display(self.center_person)
148
self.doc.start_paragraph("EOL-Title")
149
# feature request 2356: avoid genitive form
150
title = _("End of Line Report for %s") % pname
151
mark = IndexMark(title, INDEX_TYPE_TOC, 1)
152
self.doc.write_text(title, mark)
153
self.doc.end_paragraph()
155
self.doc.start_paragraph("EOL-Subtitle")
156
# feature request 2356: avoid genitive form
157
title = _("All the ancestors of %s who are missing a parent") % pname
158
self.doc.write_text(title)
159
self.doc.end_paragraph()
161
self.doc.start_table('EolTable','EOL-Table')
162
for generation, handles in self.eol_map.iteritems():
163
self.write_generation_row(generation)
164
for person_handle, pedigrees in handles.iteritems():
165
self.write_person_row(person_handle)
166
map(self.write_pedigree_row, pedigrees)
169
def write_generation_row(self, generation):
171
Write out a row in the table showing the generation.
174
self.doc.start_cell('EOL_GenerationCell', 2)
175
self.doc.start_paragraph('EOL-Generation')
176
self.doc.write_text( _("Generation %d") % generation )
177
self.doc.end_paragraph()
181
def write_person_row(self, person_handle):
183
Write a row in the table with information about the given person.
185
person = self.database.get_person_from_handle(person_handle)
187
name = self._name_display.display(person)
188
mark = ReportUtils.get_person_mark(self.database, person)
190
birth_ref = person.get_birth_ref()
192
event = self.database.get_event_from_handle(birth_ref.ref)
193
birth_date = DateHandler.get_date( event )
196
death_ref = person.get_death_ref()
198
event = self.database.get_event_from_handle(death_ref.ref)
199
death_date = DateHandler.get_date( event )
200
dates = _(" (%(birth_date)s - %(death_date)s)") % {
201
'birth_date' : birth_date,
202
'death_date' : death_date }
205
self.doc.start_cell('EOL-TableCell', 2)
206
self.doc.start_paragraph('EOL-Normal')
207
self.doc.write_text(name, mark)
208
self.doc.write_text(dates)
209
self.doc.end_paragraph()
213
def write_pedigree_row(self, pedigree):
215
Write a row in the table with with the person's family line.
217
pedigree is an array containing the names of the people in the pedigree
220
for person_handle in pedigree:
221
person = self.database.get_person_from_handle(person_handle)
222
names.append(self._name_display.display(person))
223
text = " -- ".join(names)
225
self.doc.start_cell('EOL-TableCell')
227
self.doc.start_cell('EOL-TableCell')
228
self.doc.start_paragraph('EOL-Pedigree')
229
self.doc.write_text(text)
230
self.doc.end_paragraph()
234
#------------------------------------------------------------------------
238
#------------------------------------------------------------------------
239
class EndOfLineOptions(MenuReportOptions):
241
Defines options and provides handling interface.
244
def __init__(self, name, dbase):
245
MenuReportOptions.__init__(self, name, dbase)
247
def add_menu_options(self, menu):
249
Add options to the menu for the End of Line report.
251
category_name = _("Report Options")
253
pid = PersonOption(_("Center Person"))
254
pid.set_help(_("The center person for the report"))
255
menu.add_option(category_name, "pid", pid)
257
# We must figure out the value of the first option before we can
258
# create the EnumeratedListOption
259
fmt_list = global_name_display.get_name_format()
260
name_format = EnumeratedListOption(_("Name format"), 0)
261
name_format.add_item(0, _("Default"))
262
for num, name, fmt_str, act in fmt_list:
263
name_format.add_item(num, name)
264
name_format.set_help(_("Select the format to display names"))
265
menu.add_option(category_name, "name_format", name_format)
268
def make_default_style(self, default_style):
269
"""Make the default output style for the End of Line Report."""
273
f.set_type_face(FONT_SANS_SERIF)
276
p.set_header_level(1)
277
p.set_bottom_border(1)
278
p.set_bottom_margin(ReportUtils.pt2cm(8))
280
p.set_alignment(PARA_ALIGN_CENTER)
281
p.set_description(_("The style used for the title of the page."))
282
default_style.add_paragraph_style("EOL-Title", p)
285
font.set(face=FONT_SANS_SERIF, size=12, italic=1)
287
p.set_bottom_margin(ReportUtils.pt2cm(6))
289
p.set_alignment(PARA_ALIGN_CENTER)
290
p.set_description(_('The style used for the section headers.'))
291
default_style.add_paragraph_style("EOL-Subtitle", p)
297
p.set_top_margin(ReportUtils.pt2cm(6))
298
p.set_bottom_margin(ReportUtils.pt2cm(6))
299
p.set_description(_('The basic style used for the text display.'))
300
default_style.add_paragraph_style("EOL-Normal", p)
304
font.set_italic(True)
307
p.set_top_margin(ReportUtils.pt2cm(6))
308
p.set_description(_('The basic style used for generation headings.'))
309
default_style.add_paragraph_style("EOL-Generation", p)
316
p.set_bottom_margin(ReportUtils.pt2cm(6))
317
p.set_description(_('The basic style used for the text display.'))
318
default_style.add_paragraph_style("EOL-Pedigree", p)
321
cell = TableCellStyle()
322
default_style.add_cell_style('EOL-TableCell', cell)
324
cell = TableCellStyle()
325
cell.set_bottom_border(1)
326
default_style.add_cell_style('EOL_GenerationCell', cell)
331
table.set_column_width(0, 10)
332
table.set_column_width(1, 90)
333
default_style.add_table_style('EOL-Table', table)