~ubuntu-branches/ubuntu/trusty/gramps/trusty-proposed

« back to all changes in this revision

Viewing changes to src/plugins/textreport/EndOfLineReport.py

  • Committer: Package Import Robot
  • Author(s): Ross Gammon
  • Date: 2014-02-03 17:28:04 UTC
  • mfrom: (39.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20140203172804-76y7nwxiw92zhlnj
Tags: 4.0.3+dfsg-1
* New upstream release (Closes: #720858)
* To-do notes improved and made persistent (Closes: #680692)
* Applied patch to setup.py to fix resource path problem
* Applied patch to disable the optional HTML View & prevent a crash
* Remove sourceless javascript files (Closes: #736436)
* Gramps uses Bat Mitzva internally (Closes: #502532)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#
2
 
# Gramps - a GTK+/GNOME based genealogy program
3
 
#
4
 
# Copyright (C) 2007-2008 Brian G. Matherly
5
 
# Copyright (C) 2010       Jakim Friant
6
 
#
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.
11
 
#
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.
16
 
#
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
20
 
#
21
 
 
22
 
# $Id: EndOfLineReport.py 18915 2012-02-17 16:51:40Z romjerome $
23
 
 
24
 
"""Reports/Text Reports/End of Line Report"""
25
 
 
26
 
#------------------------------------------------------------------------
27
 
#
28
 
# python modules
29
 
#
30
 
#------------------------------------------------------------------------
31
 
import copy
32
 
from gen.ggettext import gettext as _
33
 
 
34
 
#------------------------------------------------------------------------
35
 
#
36
 
# gramps modules
37
 
#
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,
43
 
                            PARA_ALIGN_CENTER)
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
48
 
import DateHandler
49
 
 
50
 
#------------------------------------------------------------------------
51
 
#
52
 
# EndOfLineReport
53
 
#
54
 
#------------------------------------------------------------------------
55
 
class EndOfLineReport(Report):
56
 
 
57
 
    def __init__(self, database, options, user):
58
 
        """
59
 
        Create the EndOfLineReport object that produces the report.
60
 
        
61
 
        The arguments are:
62
 
 
63
 
        database        - the GRAMPS database instance
64
 
        options         - instance of the Options class for this report
65
 
        user            - a gen.user.User() instance
66
 
 
67
 
        This report needs the following parameters (class variables)
68
 
        that come in the options class.
69
 
        name_format   - Preferred format to display names
70
 
 
71
 
        """
72
 
        Report.__init__(self, database, options, user)
73
 
        menu = options.menu
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 )
78
 
 
79
 
        # Copy the global NameDisplay so that we don't change application 
80
 
        # defaults.
81
 
        self._name_display = copy.deepcopy(global_name_display)
82
 
        name_format = menu.get_option_by_name("name_format").get_value()
83
 
        if name_format != 0:
84
 
            self._name_display.set_default_format(name_format)
85
 
 
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]
94
 
        #
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
97
 
        # pedigree.
98
 
        #
99
 
        # eol_map is populated by get_eol() which calls itself recursively.
100
 
        self.eol_map = {}
101
 
        self.get_eol(self.center_person, 1, [])
102
 
        
103
 
    def get_eol(self, person, gen, pedigree):
104
 
        """
105
 
        Recursively find the end of the line for each person
106
 
        """
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()
111
 
        
112
 
        if person_handle in pedigree:
113
 
            # This is a severe error!
114
 
            # It indicates a loop in ancestry: A -> B -> A
115
 
            person_is_eol = True
116
 
        elif not families:
117
 
            person_is_eol = True
118
 
        else:
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()
123
 
                if father_handle: 
124
 
                    father = self.database.get_person_from_handle(father_handle)
125
 
                    self.get_eol(father, gen+1, new_pedigree)
126
 
                if mother_handle:
127
 
                    mother = self.database.get_person_from_handle(mother_handle)
128
 
                    self.get_eol(mother, gen+1, new_pedigree)
129
 
            
130
 
                if not father_handle or not mother_handle:
131
 
                    person_is_eol = True
132
 
                
133
 
        if person_is_eol:
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 )
140
 
 
141
 
    def write_report(self):
142
 
        """
143
 
        The routine the actually creates the report. At this point, the document
144
 
        is opened and ready for writing.
145
 
        """
146
 
        pname = self._name_display.display(self.center_person)
147
 
        
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()
154
 
        
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()
160
 
        
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)
167
 
        self.doc.end_table()
168
 
 
169
 
    def write_generation_row(self, generation):
170
 
        """
171
 
        Write out a row in the table showing the generation.
172
 
        """
173
 
        self.doc.start_row()
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()
178
 
        self.doc.end_cell()
179
 
        self.doc.end_row()
180
 
        
181
 
    def write_person_row(self, person_handle):
182
 
        """
183
 
        Write a row in the table with information about the given person.
184
 
        """
185
 
        person = self.database.get_person_from_handle(person_handle)
186
 
 
187
 
        name = self._name_display.display(person)
188
 
        mark = ReportUtils.get_person_mark(self.database, person)
189
 
        birth_date = ""
190
 
        birth_ref = person.get_birth_ref()
191
 
        if birth_ref:
192
 
            event = self.database.get_event_from_handle(birth_ref.ref)
193
 
            birth_date = DateHandler.get_date( event )
194
 
        
195
 
        death_date = ""
196
 
        death_ref = person.get_death_ref()
197
 
        if 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 }
203
 
        
204
 
        self.doc.start_row()
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()
210
 
        self.doc.end_cell()
211
 
        self.doc.end_row()
212
 
        
213
 
    def write_pedigree_row(self, pedigree):
214
 
        """
215
 
        Write a row in the table with with the person's family line.
216
 
        
217
 
        pedigree is an array containing the names of the people in the pedigree
218
 
        """
219
 
        names = []
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)
224
 
        self.doc.start_row()
225
 
        self.doc.start_cell('EOL-TableCell')
226
 
        self.doc.end_cell()
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()
231
 
        self.doc.end_cell()
232
 
        self.doc.end_row()
233
 
 
234
 
#------------------------------------------------------------------------
235
 
#
236
 
# EndOfLineOptions
237
 
#
238
 
#------------------------------------------------------------------------
239
 
class EndOfLineOptions(MenuReportOptions):
240
 
    """
241
 
    Defines options and provides handling interface.
242
 
    """
243
 
 
244
 
    def __init__(self, name, dbase):
245
 
        MenuReportOptions.__init__(self, name, dbase)
246
 
        
247
 
    def add_menu_options(self, menu):
248
 
        """
249
 
        Add options to the menu for the End of Line report.
250
 
        """
251
 
        category_name = _("Report Options")
252
 
        
253
 
        pid = PersonOption(_("Center Person"))
254
 
        pid.set_help(_("The center person for the report"))
255
 
        menu.add_option(category_name, "pid", pid)
256
 
 
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)
266
 
 
267
 
 
268
 
    def make_default_style(self, default_style):
269
 
        """Make the default output style for the End of Line Report."""
270
 
        # Paragraph Styles
271
 
        f = FontStyle()
272
 
        f.set_size(16)
273
 
        f.set_type_face(FONT_SANS_SERIF)
274
 
        f.set_bold(1)
275
 
        p = ParagraphStyle()
276
 
        p.set_header_level(1)
277
 
        p.set_bottom_border(1)
278
 
        p.set_bottom_margin(ReportUtils.pt2cm(8))
279
 
        p.set_font(f)
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)
283
 
        
284
 
        font = FontStyle()
285
 
        font.set(face=FONT_SANS_SERIF, size=12, italic=1)
286
 
        p = ParagraphStyle()
287
 
        p.set_bottom_margin(ReportUtils.pt2cm(6))
288
 
        p.set_font(font)
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)
292
 
        
293
 
        font = FontStyle()
294
 
        font.set_size(10)
295
 
        p = ParagraphStyle()
296
 
        p.set_font(font)
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)
301
 
        
302
 
        font = FontStyle()
303
 
        font.set_size(12)
304
 
        font.set_italic(True)
305
 
        p = ParagraphStyle()
306
 
        p.set_font(font)
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)
310
 
        
311
 
        font = FontStyle()
312
 
        font.set_size(8)
313
 
        p = ParagraphStyle()
314
 
        p.set_font(font)
315
 
        p.set_top_margin(0)
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)
319
 
        
320
 
        #Table Styles
321
 
        cell = TableCellStyle()
322
 
        default_style.add_cell_style('EOL-TableCell', cell)
323
 
        
324
 
        cell = TableCellStyle()
325
 
        cell.set_bottom_border(1)
326
 
        default_style.add_cell_style('EOL_GenerationCell', cell)
327
 
 
328
 
        table = TableStyle()
329
 
        table.set_width(100)
330
 
        table.set_columns(2)
331
 
        table.set_column_width(0, 10)
332
 
        table.set_column_width(1, 90)
333
 
        default_style.add_table_style('EOL-Table', table)