4011: "reports" should have a "no private information" button

This commit is contained in:
Paul Franklin 2014-07-26 09:52:30 -07:00
parent 0aaa7f316d
commit a3c13cdecc

View File

@ -6,7 +6,7 @@
# Copyright (C) 2009-2010 Gary Burton # Copyright (C) 2009-2010 Gary Burton
# Contribution 2009 by Bob Ham <rah@bash.sh> # Contribution 2009 by Bob Ham <rah@bash.sh>
# Copyright (C) 2010 Jakim Friant # Copyright (C) 2010 Jakim Friant
# Copyright (C) 2011-2013 Paul Franklin # Copyright (C) 2011-2014 Paul Franklin
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -79,22 +79,17 @@ _COLORS = [ { 'name' : _("B&W outline"), 'value' : "outline" },
# class FamilyLinesOptions(MenuReportOptions) # class FamilyLinesOptions(MenuReportOptions)
# - this class is created when the report dialog comes up # - this class is created when the report dialog comes up
# - all configuration controls for the report are created here # - all configuration controls for the report are created here
# - see src/ReportBase/_ReportOptions.py for more information
# #
# class FamilyLinesReport(Report) # class FamilyLinesReport(Report)
# - this class is created only after the user clicks on "OK" # - this class is created only after the user clicks on "OK"
# - the actual report generation is done by this class # - the actual report generation is done by this class
# - see src/ReportBase/_Report.py for more information
#
# Likely to be of additional interest is register_report() at the
# very bottom of this file.
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
class FamilyLinesOptions(MenuReportOptions): class FamilyLinesOptions(MenuReportOptions):
""" """
Defines all of the controls necessary Defines all of the controls necessary
to configure the FamilyLines reports. to configure the FamilyLines report.
""" """
def __init__(self, name, dbase): def __init__(self, name, dbase):
self.limit_parents = None self.limit_parents = None
@ -107,20 +102,29 @@ class FamilyLinesOptions(MenuReportOptions):
def add_menu_options(self, menu): def add_menu_options(self, menu):
# -------------------------------- # ---------------------
category_name = _('People of Interest') category_name = _('Report Options')
add_option = partial(menu.add_option, category_name) add_option = partial(menu.add_option, category_name)
# -------------------------------- # ---------------------
person_list = PersonListOption(_('People of interest'))
person_list.set_help(_('People of interest are used as a starting '
'point when determining "family lines".'))
add_option('gidlist', person_list)
stdoptions.add_name_format_option(menu, category_name) stdoptions.add_name_format_option(menu, category_name)
followpar = BooleanOption( color = EnumeratedListOption(_("Graph coloring"), "filled")
_('Follow parents to determine family lines'), True) for i in range(len(_COLORS)):
color.add_item(_COLORS[i]["value"], _COLORS[i]["name"])
color.set_help(_("Males will be shown with blue, females "
"with red, unless otherwise set above for filled. "
"If the sex of an individual "
"is unknown it will be shown with gray."))
add_option("color", color)
use_roundedcorners = BooleanOption(_('Use rounded corners'), False)
use_roundedcorners.set_help(_('Use rounded corners to differentiate '
'between women and men.'))
add_option("useroundedcorners", use_roundedcorners)
followpar = BooleanOption(_('Follow parents to determine '
'"family lines"'), True)
followpar.set_help(_('Parents and their ancestors will be ' followpar.set_help(_('Parents and their ancestors will be '
'considered when determining "family lines".')) 'considered when determining "family lines".'))
add_option('followpar', followpar) add_option('followpar', followpar)
@ -131,16 +135,95 @@ class FamilyLinesOptions(MenuReportOptions):
'determining "family lines".')) 'determining "family lines".'))
add_option('followchild', followchild) add_option('followchild', followchild)
remove_extra_people = BooleanOption( remove_extra_people = BooleanOption(_('Try to remove extra '
_('Try to remove extra people and families'), True) 'people and families'), True)
remove_extra_people.set_help(_('People and families not directly ' remove_extra_people.set_help(_('People and families not directly '
'related to people of interest will ' 'related to people of interest will '
'be removed when determining ' 'be removed when determining '
'"family lines".')) '"family lines".'))
add_option('removeextra', remove_extra_people) add_option('removeextra', remove_extra_people)
stdoptions.add_private_data_option(menu, category_name, default=False)
stdoptions.add_localization_option(menu, category_name) stdoptions.add_localization_option(menu, category_name)
# --------------------------------
add_option = partial(menu.add_option, _('People of Interest'))
# --------------------------------
person_list = PersonListOption(_('People of interest'))
person_list.set_help(_('People of interest are used as a starting '
'point when determining "family lines".'))
add_option('gidlist', person_list)
self.limit_parents = BooleanOption(_('Limit the number of ancestors'),
False)
self.limit_parents.set_help(_('Whether to '
'limit the number of ancestors.'))
add_option('limitparents', self.limit_parents)
self.limit_parents.connect('value-changed', self.limit_changed)
self.max_parents = NumberOption('', 50, 10, 9999)
self.max_parents.set_help(_('The maximum number '
'of ancestors to include.'))
add_option('maxparents', self.max_parents)
self.limit_children = BooleanOption(_('Limit the number '
'of descendants'),
False)
self.limit_children.set_help(_('Whether to '
'limit the number of descendants.'))
add_option('limitchildren', self.limit_children)
self.limit_children.connect('value-changed', self.limit_changed)
self.max_children = NumberOption('', 50, 10, 9999)
self.max_children.set_help(_('The maximum number '
'of descendants to include.'))
add_option('maxchildren', self.max_children)
# --------------------
add_option = partial(menu.add_option, _('Include'))
# --------------------
self.include_dates = BooleanOption(_('Include dates'), True)
self.include_dates.set_help(_('Whether to include dates for people '
'and families.'))
add_option('incdates', self.include_dates)
self.include_dates.connect('value-changed', self.include_dates_changed)
self.justyears = BooleanOption(_("Limit dates to years only"), False)
self.justyears.set_help(_("Prints just dates' year, neither "
"month or day nor date approximation "
"or interval are shown."))
add_option("justyears", self.justyears)
include_places = BooleanOption(_('Include places'), True)
include_places.set_help(_('Whether to include placenames for people '
'and families.'))
add_option('incplaces', include_places)
include_num_children = BooleanOption(_('Include the number of '
'children'), True)
include_num_children.set_help(_('Whether to include the number of '
'children for families with more '
'than 1 child.'))
add_option('incchildcnt', include_num_children)
self.include_images = BooleanOption(_('Include '
'thumbnail images of people'),
True)
self.include_images.set_help(_('Whether to '
'include thumbnail images of people.'))
add_option('incimages', self.include_images)
self.include_images.connect('value-changed', self.images_changed)
self.image_location = EnumeratedListOption(_('Thumbnail location'), 0)
self.image_location.add_item(0, _('Above the name'))
self.image_location.add_item(1, _('Beside the name'))
self.image_location.set_help(_('Where the thumbnail image '
'should appear relative to the name'))
add_option('imageonside', self.image_location)
# ---------------------------- # ----------------------------
add_option = partial(menu.add_option, _('Family Colors')) add_option = partial(menu.add_option, _('Family Colors'))
# ---------------------------- # ----------------------------
@ -170,97 +253,6 @@ class FamilyLinesOptions(MenuReportOptions):
color_family.set_help(_('The color to use to display families.')) color_family.set_help(_('The color to use to display families.'))
add_option('colorfamilies', color_family) add_option('colorfamilies', color_family)
self.limit_parents = BooleanOption(_('Limit the number of ancestors'),
False)
self.limit_parents.set_help(_('Whether to '
'limit the number of ancestors.'))
add_option('limitparents', self.limit_parents)
self.limit_parents.connect('value-changed', self.limit_changed)
self.max_parents = NumberOption('', 50, 10, 9999)
self.max_parents.set_help(_('The maximum number '
'of ancestors to include.'))
add_option('maxparents', self.max_parents)
self.limit_children = BooleanOption(_('Limit the number '
'of descendants'),
False)
self.limit_children.set_help(_('Whether to '
'limit the number of descendants.'))
add_option('limitchildren', self.limit_children)
self.limit_children.connect('value-changed', self.limit_changed)
self.max_children = NumberOption('', 50, 10, 9999)
self.max_children.set_help(_('The maximum number '
'of descendants to include.'))
add_option('maxchildren', self.max_children)
# --------------------
add_option = partial(menu.add_option, _('Images'))
# --------------------
self.include_images = BooleanOption(_('Include '
'thumbnail images of people'),
True)
self.include_images.set_help(_('Whether to '
'include thumbnail images of people.'))
add_option('incimages', self.include_images)
self.include_images.connect('value-changed', self.images_changed)
self.image_location = EnumeratedListOption(_('Thumbnail location'), 0)
self.image_location.add_item(0, _('Above the name'))
self.image_location.add_item(1, _('Beside the name'))
self.image_location.set_help(_('Where the thumbnail image '
'should appear relative to the name'))
add_option('imageonside', self.image_location)
# ---------------------
add_option = partial(menu.add_option, _('Options'))
# ---------------------
color = EnumeratedListOption(_("Graph coloring"), "filled")
for i in range(len(_COLORS)):
color.add_item(_COLORS[i]["value"], _COLORS[i]["name"])
color.set_help(_("Males will be shown with blue, females "
"with red, unless otherwise set above for filled. "
"If the sex of an individual "
"is unknown it will be shown with gray."))
add_option("color", color)
use_roundedcorners = BooleanOption(_('Use rounded corners'), False)
use_roundedcorners.set_help(_('Use rounded corners to differentiate '
'between women and men.'))
add_option("useroundedcorners", use_roundedcorners)
self.include_dates = BooleanOption(_('Include dates'), True)
self.include_dates.set_help(_('Whether to include dates for people '
'and families.'))
add_option('incdates', self.include_dates)
self.include_dates.connect('value-changed', self.include_dates_changed)
self.justyears = BooleanOption(_("Limit dates to years only"), False)
self.justyears.set_help(_("Prints just dates' year, neither "
"month or day nor date approximation "
"or interval are shown."))
add_option("justyears", self.justyears)
include_places = BooleanOption(_('Include places'), True)
include_places.set_help(_('Whether to include placenames for people '
'and families.'))
add_option('incplaces', include_places)
include_num_children = BooleanOption(
_('Include the number of children'), True)
include_num_children.set_help(_('Whether to include the number of '
'children for families with more '
'than 1 child.'))
add_option('incchildcnt', include_num_children)
include_private = BooleanOption(_('Include private records'), False)
include_private.set_help(_('Whether to include names, dates, and '
'families that are marked as private.'))
add_option('incprivate', include_private)
self.limit_changed() self.limit_changed()
self.images_changed() self.images_changed()
@ -298,25 +290,28 @@ class FamilyLinesReport(Report):
The arguments are: The arguments are:
database - the GRAMPS database instance database - the GRAMPS database instance
options - instance of the FamilyLinesOptions class for this report options - instance of the FamilyLinesOptions class for this report
user - a gen.user.User() instance user - a gen.user.User() instance
name_format - Preferred format to display names name_format - Preferred format to display names
incl_private - Whether to include private data
""" """
Report.__init__(self, database, options, user) Report.__init__(self, database, options, user)
menu = options.menu
get_option_by_name = menu.get_option_by_name
get_value = lambda name: get_option_by_name(name).get_value()
stdoptions.run_private_data_option(self, menu)
self._db = self.database
# initialize several convenient variables # initialize several convenient variables
self._db = database
self._people = set() # handle of people we need in the report self._people = set() # handle of people we need in the report
self._families = set() # handle of families we need in the report self._families = set() # handle of families we need in the report
self._deleted_people = 0 self._deleted_people = 0
self._deleted_families = 0 self._deleted_families = 0
self._user = user self._user = user
menu = options.menu
get_option_by_name = menu.get_option_by_name
get_value = lambda name: get_option_by_name(name).get_value()
self._followpar = get_value('followpar') self._followpar = get_value('followpar')
self._followchild = get_value('followchild') self._followchild = get_value('followchild')
self._removeextra = get_value('removeextra') self._removeextra = get_value('removeextra')
@ -337,7 +332,6 @@ class FamilyLinesReport(Report):
self._just_years = get_value('justyears') self._just_years = get_value('justyears')
self._incplaces = get_value('incplaces') self._incplaces = get_value('incplaces')
self._incchildcount = get_value('incchildcnt') self._incchildcount = get_value('incchildcnt')
self._incprivate = get_value('incprivate')
# the gidlist is annoying for us to use since we always have to convert # the gidlist is annoying for us to use since we always have to convert
# the GIDs to either Person or to handles, so we may as well convert the # the GIDs to either Person or to handles, so we may as well convert the
@ -438,7 +432,7 @@ class FamilyLinesReport(Report):
handle = ancestorsNotYetProcessed.pop() handle = ancestorsNotYetProcessed.pop()
# One of 2 things can happen here: # One of 2 things can happen here:
# 1) we've already know about this person and he/she is already # 1) we already know about this person and he/she is already
# in our list # in our list
# 2) this is someone new, and we need to remember him/her # 2) this is someone new, and we need to remember him/her
# #
@ -453,12 +447,6 @@ class FamilyLinesReport(Report):
person = self._db.get_person_from_handle(handle) person = self._db.get_person_from_handle(handle)
# if this is a private record, and we're not
# including private records, then go back to the
# top of the while loop to get the next person
if person.private and not self._incprivate:
continue
# remember this person! # remember this person!
self._people.add(handle) self._people.add(handle)
@ -468,6 +456,8 @@ class FamilyLinesReport(Report):
# to link spouses together # to link spouses together
for family_handle in person.get_family_handle_list(): for family_handle in person.get_family_handle_list():
family = self._db.get_family_from_handle(family_handle) family = self._db.get_family_from_handle(family_handle)
if not family:
continue
spouse_handle = ReportUtils.find_spouse(person, family) spouse_handle = ReportUtils.find_spouse(person, family)
if spouse_handle: if spouse_handle:
if (spouse_handle in self._people or if (spouse_handle in self._people or
@ -488,21 +478,18 @@ class FamilyLinesReport(Report):
for family_handle in person.get_parent_family_handle_list(): for family_handle in person.get_parent_family_handle_list():
family = self._db.get_family_from_handle(family_handle) family = self._db.get_family_from_handle(family_handle)
if not family.private or self._incprivate: father = self._db.get_person_from_handle(
father = self._db.get_person_from_handle( family.get_father_handle())
family.get_father_handle()) mother = self._db.get_person_from_handle(
mother = self._db.get_person_from_handle( family.get_mother_handle())
family.get_mother_handle()) if father:
if father: ancestorsNotYetProcessed.add(
if not father.private or self._incprivate: family.get_father_handle())
ancestorsNotYetProcessed.add( self._families.add(family_handle)
family.get_father_handle()) if mother:
self._families.add(family_handle) ancestorsNotYetProcessed.add(
if mother: family.get_mother_handle())
if not mother.private or self._incprivate: self._families.add(family_handle)
ancestorsNotYetProcessed.add(
family.get_mother_handle())
self._families.add(family_handle)
def removeUninterestingParents(self): def removeUninterestingParents(self):
# start with all the people we've already identified # start with all the people we've already identified
@ -511,6 +498,8 @@ class FamilyLinesReport(Report):
while len(unprocessed_parents) > 0: while len(unprocessed_parents) > 0:
handle = unprocessed_parents.pop() handle = unprocessed_parents.pop()
person = self._db.get_person_from_handle(handle) person = self._db.get_person_from_handle(handle)
if not person:
continue
# There are a few things we're going to need, # There are a few things we're going to need,
# so look it all up right now; such as: # so look it all up right now; such as:
@ -669,12 +658,6 @@ class FamilyLinesReport(Report):
person = self._db.get_person_from_handle(handle) person = self._db.get_person_from_handle(handle)
# if this is a private record, and we're not
# including private records, then go back to the
# top of the while loop to get the next person
if person.private and not self._incprivate:
continue
# remember this person! # remember this person!
childrenToInclude.add(handle) childrenToInclude.add(handle)
@ -693,27 +676,23 @@ class FamilyLinesReport(Report):
# iterate through this person's families # iterate through this person's families
for family_handle in person.get_family_handle_list(): for family_handle in person.get_family_handle_list():
family = self._db.get_family_from_handle(family_handle) family = self._db.get_family_from_handle(family_handle)
if (family.private and self._incprivate) or not family.private:
# queue up any children from this person's family # queue up any children from this person's family
for childRef in family.get_child_ref_list(): for childRef in family.get_child_ref_list():
child = self._db.get_person_from_handle(childRef.ref) child = self._db.get_person_from_handle(childRef.ref)
if (child.private and self._incprivate) or not child.private: childrenNotYetProcessed.add(child.get_handle())
childrenNotYetProcessed.add(child.get_handle()) self._families.add(family_handle)
self._families.add(family_handle)
# include the spouse from this person's family # include the spouse from this person's family
spouse_handle = ReportUtils.find_spouse(person, family) spouse_handle = ReportUtils.find_spouse(person, family)
if spouse_handle: if spouse_handle:
spouse = self._db.get_person_from_handle(spouse_handle) spouse = self._db.get_person_from_handle(spouse_handle)
if (spouse.private and self._incprivate) or not spouse.private: childrenToInclude.add(spouse_handle)
childrenToInclude.add(spouse_handle) self._families.add(family_handle)
self._families.add(family_handle)
# we now merge our temp set "childrenToInclude" into our master set # we now merge our temp set "childrenToInclude" into our master set
self._people.update(childrenToInclude) self._people.update(childrenToInclude)
def writePeople(self): def writePeople(self):
self.doc.add_comment('') self.doc.add_comment('')
@ -753,50 +732,48 @@ class FamilyLinesReport(Report):
# output the birth or fallback event # output the birth or fallback event
birthStr = None birthStr = None
if bth_event and self._incdates: if bth_event and self._incdates:
if not bth_event.private or self._incprivate: date = bth_event.get_date_object()
date = bth_event.get_date_object() if self._just_years and date.get_year_valid():
if self._just_years and date.get_year_valid(): birthStr = '%i' % date.get_year()
birthStr = '%i' % date.get_year() else:
else: birthStr = self._get_date(date)
birthStr = self._get_date(date)
# get birth place (one of: city, state, or country) we can use # get birth place (one of: city, state, or country) we can use
birthplace = None birthplace = None
if bth_event and self._incplaces: if bth_event and self._incplaces:
if not bth_event.private or self._incprivate: place = self._db.get_place_from_handle(
place = self._db.get_place_from_handle(bth_event.get_place_handle()) bth_event.get_place_handle())
if place: if place:
location = get_main_location(self._db, place) location = get_main_location(self._db, place)
if location.get(PlaceType.CITY): if location.get(PlaceType.CITY):
birthplace = location.get(PlaceType.CITY) birthplace = location.get(PlaceType.CITY)
elif location.get(PlaceType.STATE): elif location.get(PlaceType.STATE):
birthplace = location.get(PlaceType.STATE) birthplace = location.get(PlaceType.STATE)
elif location.get(PlaceType.COUNTRY): elif location.get(PlaceType.COUNTRY):
birthplace = location.get(PlaceType.COUNTRY) birthplace = location.get(PlaceType.COUNTRY)
# see if we have a deceased date we can use # see if we have a deceased date we can use
deathStr = None deathStr = None
if dth_event and self._incdates: if dth_event and self._incdates:
if not dth_event.private or self._incprivate: date = dth_event.get_date_object()
date = dth_event.get_date_object() if self._just_years and date.get_year_valid():
if self._just_years and date.get_year_valid(): deathStr = '%i' % date.get_year()
deathStr = '%i' % date.get_year() else:
else: deathStr = self._get_date(date)
deathStr = self._get_date(date)
# get death place (one of: city, state, or country) we can use # get death place (one of: city, state, or country) we can use
deathplace = None deathplace = None
if dth_event and self._incplaces: if dth_event and self._incplaces:
if not dth_event.private or self._incprivate: place = self._db.get_place_from_handle(
place = self._db.get_place_from_handle(dth_event.get_place_handle()) dth_event.get_place_handle())
if place: if place:
location = get_main_location(self._db, place) location = get_main_location(self._db, place)
if location.get(PlaceType.CITY): if location.get(PlaceType.CITY):
deathplace = location.get(PlaceType.CITY) deathplace = location.get(PlaceType.CITY)
elif location.get(PlaceType.STATE): elif location.get(PlaceType.STATE):
deathplace = location.get(PlaceType.STATE) deathplace = location.get(PlaceType.STATE)
elif location.get(PlaceType.COUNTRY): elif location.get(PlaceType.COUNTRY):
deathplace = location.get(PlaceType.COUNTRY) deathplace = location.get(PlaceType.COUNTRY)
# see if we have an image to use for this person # see if we have an image to use for this person
imagePath = None imagePath = None
@ -904,24 +881,24 @@ class FamilyLinesReport(Report):
(event_ref.get_role() == EventRoleType.FAMILY or (event_ref.get_role() == EventRoleType.FAMILY or
event_ref.get_role() == EventRoleType.PRIMARY ): event_ref.get_role() == EventRoleType.PRIMARY ):
# get the wedding date # get the wedding date
if (event.private and self._incprivate) or not event.private: if self._incdates:
if self._incdates: date = event.get_date_object()
date = event.get_date_object() if self._just_years and date.get_year_valid():
if self._just_years and date.get_year_valid(): weddingDate = '%i' % date.get_year()
weddingDate = '%i' % date.get_year() else:
else: weddingDate = self._get_date(date)
weddingDate = self._get_date(date) # get the wedding location
# get the wedding location if self._incplaces:
if self._incplaces: place = self._db.get_place_from_handle(
place = self._db.get_place_from_handle(event.get_place_handle()) event.get_place_handle())
if place: if place:
location = get_main_location(self._db, place) location = get_main_location(self._db, place)
if location.get(PlaceType.CITY): if location.get(PlaceType.CITY):
weddingPlace = location.get(PlaceType.CITY) weddingPlace = location.get(PlaceType.CITY)
elif location.get(PlaceType.STATE): elif location.get(PlaceType.STATE):
weddingPlace = location.get(PlaceType.STATE) weddingPlace = location.get(PlaceType.STATE)
elif location.get(PlaceType.COUNTRY): elif location.get(PlaceType.COUNTRY):
weddingPlace = location.get(PlaceType.COUNTRY) weddingPlace = location.get(PlaceType.COUNTRY)
break break
# figure out the number of children (if any) # figure out the number of children (if any)