1# 2# Gramps - a GTK+/GNOME based genealogy program 3# 4# Copyright (C) 2013 John Ralls <jralls@ceridwen.us> 5# Copyright (C) 2013-2017 Paul Franklin 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20# 21 22""" 23Commonly used report options. Call the function, don't copy the code! 24""" 25 26#------------------------------------------------------------------------- 27# 28# Gramps modules 29# 30#------------------------------------------------------------------------- 31from ...config import config 32from ...datehandler import get_date_formats, LANG_TO_DISPLAY, main_locale 33from ...display.name import displayer as global_name_display 34from ...lib.date import Today 35from ...display.place import displayer as _pd 36from ..menu import EnumeratedListOption, BooleanOption, NumberOption 37from ...proxy import PrivateProxyDb, LivingProxyDb 38from ...utils.grampslocale import GrampsLocale 39from ...const import GRAMPS_LOCALE as glocale 40_ = glocale.translation.sgettext 41 42# _T_ is a gramps-defined keyword -- see po/update_po.py and po/genpot.sh 43def _T_(value): # enable deferred translations (see Python docs 22.1.3.4) 44 return value 45 46#------------------------------------------------------------------------- 47# 48# StandardReportOptions 49# 50#------------------------------------------------------------------------- 51 52def add_localization_option(menu, category): 53 """ 54 Insert an option for localizing the report into a different locale 55 from the UI locale. 56 """ 57 58 trans = EnumeratedListOption(_("Translation"), 59 glocale.DEFAULT_TRANSLATION_STR) 60 trans.add_item(glocale.DEFAULT_TRANSLATION_STR, _("Default")) 61 languages = glocale.get_language_dict() 62 for language in sorted(languages, key=glocale.sort_key): 63 trans.add_item(languages[language], language) 64 trans.set_help(_("The translation to be used for the report.")) 65 menu.add_option(category, "trans", trans) 66 return trans 67 68def add_name_format_option(menu, category): 69 """ 70 Insert an option for changing the report's name format to a 71 report-specific format instead of the user's Edit=>Preferences choice 72 """ 73 name_format = EnumeratedListOption(_("Name format"), 0) 74 name_format.add_item(0, _("Default")) 75 format_list = global_name_display.get_name_format() 76 for number, name, format_string, whether_active in format_list: 77 name_format.add_item(number, name) 78 name_format.set_help(_("Select the format to display names")) 79 current_format = config.get('preferences.name-format') 80 # if this report hasn't ever been run, start with user's current setting 81 name_format.set_value(current_format) 82 # if the report has been run, this line will get the user's old setting 83 menu.add_option(category, "name_format", name_format) 84 return name_format 85 86def run_name_format_option(report, menu): 87 """ 88 Run the option for changing the report's name format to a 89 report-specific format instead of the user's Edit=>Preferences choice 90 """ 91 current_format = config.get('preferences.name-format') 92 name_format = menu.get_option_by_name("name_format").get_value() 93 if name_format != current_format: 94 report._name_display.set_default_format(name_format) 95 return name_format 96 97def add_private_data_option(menu, category, default=True): 98 """ 99 Insert an option for deciding whether the information in the 100 database marked "private" shall be included in the report 101 102 Since historically, before this option, the entire database was 103 used, including private information, the default for this option 104 has been set to be True, to include such private information. 105 """ 106 incl_private = BooleanOption(_("Include data marked private"), default) 107 incl_private.set_help(_("Whether to include private data")) 108 menu.add_option(category, "incl_private", incl_private) 109 110def run_private_data_option(report, menu): 111 """ 112 Run the option for deciding whether the information in the 113 database marked "private" shall be included in the report 114 """ 115 include_private_data = menu.get_option_by_name('incl_private').get_value() 116 if not include_private_data: 117 report.database = PrivateProxyDb(report.database) 118 119def add_living_people_option(menu, category, 120 mode=LivingProxyDb.MODE_INCLUDE_ALL, 121 after_death_years=0, 122 process_names=True): 123 """ 124 Insert an option for deciding how the information in the 125 database for living people shall be handled by the report 126 127 Because historically, before this option, the entire database was 128 used, including all information on all living people, the default 129 mode for this option has been set to include all such information 130 131 The value of the "living_people" option is the same as the value 132 of the "mode" argument in the call to the LivingProxyDb proxy DB 133 134 :param menu: The menu the options should be added to. 135 :type menu: :class:`.Menu` 136 :param category: A label that describes the category that the option 137 belongs to. 138 Example: "Report Options" 139 :type category: string 140 :param mode: 141 The method for handling living people. 142 LivingProxyDb.MODE_EXCLUDE_ALL will remove living people altogether. 143 LivingProxyDb.MODE_INCLUDE_LAST_NAME_ONLY will remove all 144 information and change their given name to "[Living]" or whatever 145 has been set in Preferences -> Text -> Private given name. 146 LivingProxyDb.MODE_REPLACE_COMPLETE_NAME will remove all 147 information and change their given name and surname to 148 "[Living]" or whatever has been set in Preferences -> Text 149 for Private surname and Private given name. 150 LivingProxyDb.MODE_INCLUDE_FULL_NAME_ONLY will remove all 151 information but leave the entire name intact. 152 LivingProxyDb.MODE_INCLUDE_ALL will not invoke LivingProxyDb at all. 153 :type mode: int 154 :param after_death_years: 155 The number of years after a person's death to 156 still consider them as living. 157 :type after_death_years: int 158 :return: nothing 159 :param process_names: whether to offer name-oriented option choices 160 :type process_names: Boolean 161 """ 162 163 def living_people_changed(): 164 """ 165 Handle a change in the living_people option 166 """ 167 if living_people.get_value() == LivingProxyDb.MODE_INCLUDE_ALL: 168 years_past_death.set_available(False) 169 else: 170 years_past_death.set_available(True) 171 172 living_people = EnumeratedListOption(_("Living People"), mode) 173 items = [(LivingProxyDb.MODE_INCLUDE_ALL, 174 _T_("'living people'|Included, and all data"))] 175 if process_names: 176 items += [ 177 (LivingProxyDb.MODE_INCLUDE_FULL_NAME_ONLY, 178 _T_("'living people'|Full names, but data removed")), 179 (LivingProxyDb.MODE_INCLUDE_LAST_NAME_ONLY, 180 _T_("'living people'|Given names replaced, and data removed")), 181 (LivingProxyDb.MODE_REPLACE_COMPLETE_NAME, 182 _T_("'living people'|Complete names replaced, and data removed"))] 183 items += [(LivingProxyDb.MODE_EXCLUDE_ALL, 184 _T_("'living people'|Not included"))] 185 living_people.set_items(items, xml_items=True) # for deferred translation 186 living_people.set_help(_("How to handle living people")) 187 menu.add_option(category, "living_people", living_people) 188 living_people.connect('value-changed', living_people_changed) 189 years_past_death = NumberOption(_("Years from death to consider living"), 190 after_death_years, 0, 100) 191 years_past_death.set_help( 192 _("Whether to restrict data on recently-dead people")) 193 menu.add_option(category, "years_past_death", years_past_death) 194 living_people_changed() 195 196def run_living_people_option(report, menu, llocale=glocale): 197 """ 198 Run the option for deciding how the information in the 199 database for living people shall be handled by the report 200 201 If llocale is passed in (a :class:`.GrampsLocale`), then (insofar as 202 possible) the translated values will be returned instead. 203 204 :param llocale: allow deferred translation of "[Living]" 205 :type llocale: a :class:`.GrampsLocale` instance 206 """ 207 option = menu.get_option_by_name('living_people') 208 living_value = option.get_value() 209 years_past_death = menu.get_option_by_name('years_past_death').get_value() 210 if living_value != LivingProxyDb.MODE_INCLUDE_ALL: 211 report.database = LivingProxyDb(report.database, living_value, 212 years_after_death=years_past_death, 213 llocale=llocale) 214 return option 215 216def add_date_format_option(menu, category, localization_option): 217 """ 218 Insert an option for changing the report's date format to a 219 report-specific format instead of the user's Edit=>Preferences choice 220 221 :param localization_option: allow realtime translation of date formats 222 :type localization_option: a :class:`.EnumeratedListOption` instance 223 """ 224 225 def on_trans_value_changed(): 226 """ 227 Handle a change in the localization option (inside the date-format one) 228 """ 229 lang = localization_option.get_value() 230 if lang == GrampsLocale.DEFAULT_TRANSLATION_STR: # the UI language 231 vlocale = glocale 232 elif lang in LANG_TO_DISPLAY: # a displayer exists 233 vlocale = LANG_TO_DISPLAY[lang]._locale # locale is already loaded 234 else: # no displayer 235 vlocale = GrampsLocale(lang=main_locale[lang]) 236 ldd = vlocale.date_displayer 237 target_format_list = get_date_formats(vlocale) # get localized formats 238 # trans_text is a defined keyword (see po/update_po.py, po/genpot.sh) 239 trans_text = vlocale.translation.sgettext 240 if global_date_format < len(target_format_list): 241 ldd.set_format(global_date_format) 242 example = vlocale.get_date(today) 243 target_option_list = [ 244 (0, "%s (%s) (%s)" % (trans_text("Default"), 245 target_format_list[global_date_format], 246 example))] 247 else: 248 target_option_list = [(0, trans_text("Default"))] 249 for fmt in target_format_list: 250 index = target_format_list.index(fmt) + 1 # option default = 0 251 ldd.set_format(index - 1) 252 example = vlocale.get_date(today) 253 target_option_list += [(index, fmt + ' (%s)' % example)] 254 date_option.set_items(target_option_list) 255 256 today = Today() 257 date_option = EnumeratedListOption(_("Date format"), 0) 258 global_date_format = config.get('preferences.date-format') 259 on_trans_value_changed() 260 date_option.set_help(_("The format and language for dates, with examples")) 261 # if this report hasn't ever been run, start with user's current setting 262 date_option.set_value(global_date_format + 1) 263 # if the report has been run, this line will get the user's old setting 264 menu.add_option(category, 'date_format', date_option) 265 localization_option.connect('value-changed', on_trans_value_changed) 266 267def run_date_format_option(report, menu): 268 """ 269 Run the option for changing the report's date format to a 270 report-specific format instead of the user's Edit=>Preferences choice 271 """ 272 def warning(value): 273 """ 274 Convenience function for the error message. 275 276 The 'value' (starting at '0') is the index in the option choices list 277 (as opposed to the index (starting at '0') in the target format list, 278 which is shorter by one, so corresponding offsets are made). 279 """ 280 target_format_choices = date_option.get_items() # with numbers 281 report._user.warn( 282 _("Ignoring unknown option: %s") % value, 283 _("Valid values: ") + str(target_format_choices) 284 + '\n\n' + 285 _("Using options string: %s") % str(target_format_list[0]) 286 ) # the previous line's "0" is because ISO is always the fallback 287 288 target_format_list = get_date_formats(report._locale) 289 date_option = menu.get_option_by_name('date_format') 290 date_opt_value = date_option.get_value() 291 if date_opt_value == 0: # "default" 292 format_to_be = config.get('preferences.date-format') # the UI choice 293 elif date_opt_value <= len(target_format_list): 294 format_to_be = date_opt_value - 1 295 else: 296 warning(date_opt_value) 297 format_to_be = 0 # ISO always exists 298 if format_to_be + 1 > len(target_format_list): 299 warning(format_to_be + 1) 300 format_to_be = 0 # ISO always exists 301 report._ldd.set_format(format_to_be) 302 303def add_gramps_id_option(menu, category, ownline=False): 304 """ 305 Insert an option for deciding whether to include Gramps IDs 306 in the report 307 308 Since for some reports it makes sense to possibly have the ID on its 309 own line (e.g. Graphviz reports), that possibility is included, but 310 since for most reports it won't make sense the default is False 311 312 :param menu: The menu the options should be added to. 313 :type menu: :class:`.Menu` 314 :param category: A label that describes the category that the option 315 belongs to, e.g. "Report Options" 316 :type category: string 317 :param ownline: whether the option offers to have the ID on its own line 318 :type ownline: Boolean 319 """ 320 321 include_id = EnumeratedListOption(_('Gramps ID'), 0) 322 include_id.add_item(0, _('Do not include')) 323 if ownline: 324 include_id.add_item(1, _('Share an existing line')) 325 include_id.add_item(2, _('On a line of its own')) 326 include_id.set_help(_('Whether (and where) to include Gramps IDs')) 327 else: 328 include_id.add_item(1, _('Include')) 329 include_id.set_help(_("Whether to include Gramps IDs")) 330 menu.add_option(category, 'inc_id', include_id) 331 332def add_place_format_option(menu, category): 333 """ 334 Insert an option for changing the report's place format to a 335 report-specific format instead of the user's Edit=>Preferences choice 336 """ 337 place_format = EnumeratedListOption(_("Place format"), -1) 338 place_format.add_item(-1, _("Default")) 339 for number, fmt in enumerate(_pd.get_formats()): 340 place_format.add_item(number, fmt.name) 341 place_format.set_help(_("Select the format to display places")) 342 menu.add_option(category, "place_format", place_format) 343 return place_format 344