From cd092897bcc93bba29673356918ba7579023a796 Mon Sep 17 00:00:00 2001 From: SNoiraud Date: Mon, 13 May 2019 11:15:52 +0100 Subject: [PATCH] GEPS 039: Genealogical symbols in gramps Gramps should be able to use genealogy symbols everywhere. Several kinds of use for the genealogical symbols : The graphical interface (GUI, editors, graphical views, ...) The Web reports (webcal, narrativeweb, ...) The Text reports (odf, rtf, pdf, ...) The graphical reports (odf, rtf, svg, ...) Resolves #9098 --- gramps/gen/config.py | 6 + gramps/gen/utils/libformatting.py | 39 +++- gramps/gen/utils/symbols.py | 189 ++++++++++++++++ gramps/gui/configure.py | 275 +++++++++++++++++++++++- gramps/gui/displaystate.py | 7 + gramps/gui/viewmanager.py | 37 ++++ gramps/gui/views/pageview.py | 8 +- gramps/gui/widgets/fanchart.py | 29 ++- gramps/plugins/lib/maps/datelayer.py | 10 +- gramps/plugins/lib/maps/geography.py | 11 +- gramps/plugins/lib/maps/messagelayer.py | 7 +- gramps/plugins/view/fanchart2wayview.py | 9 + gramps/plugins/view/fanchartdescview.py | 9 + gramps/plugins/view/fanchartview.py | 9 + gramps/plugins/view/geoclose.py | 1 + gramps/plugins/view/geoevents.py | 14 +- gramps/plugins/view/geofamclose.py | 1 + gramps/plugins/view/geofamily.py | 1 + gramps/plugins/view/geomoves.py | 1 + gramps/plugins/view/geoperson.py | 1 + gramps/plugins/view/pedigreeview.py | 23 +- gramps/plugins/view/relview.py | 100 +++++++-- 22 files changed, 746 insertions(+), 41 deletions(-) create mode 100644 gramps/gen/utils/symbols.py diff --git a/gramps/gen/config.py b/gramps/gen/config.py index 14e15233c..1c2a42289 100644 --- a/gramps/gen/config.py +++ b/gramps/gen/config.py @@ -6,6 +6,7 @@ # Copyright (C) 2008-2009 Gary Burton # Copyright (C) 2009-2012 Doug Blank # Copyright (C) 2011 Tim G L Lyons +# Copyright (C) 2015- Serge Noiraud # # 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 @@ -310,6 +311,11 @@ register('researcher.researcher-state', '') register('plugin.hiddenplugins', []) register('plugin.addonplugins', []) +register('utf8.in-use', False) +register('utf8.available-fonts', []) +register('utf8.selected-font', "") +register('utf8.death-symbol', 13) + if __debug__: # enable a simple CLI test to see if the datestrings exist register('test.january', _("localized lexeme inflections||January")) diff --git a/gramps/gen/utils/libformatting.py b/gramps/gen/utils/libformatting.py index 7d4f8efe6..e1b679b86 100644 --- a/gramps/gen/utils/libformatting.py +++ b/gramps/gen/utils/libformatting.py @@ -41,6 +41,7 @@ from ..display.name import displayer as name_displayer from ..display.place import displayer as place_displayer from .db import (get_birth_or_fallback, get_death_or_fallback, get_marriage_or_fallback) +from gramps.gen.utils.symbols import Symbols #------------------------------------------------------------------------- # @@ -51,10 +52,29 @@ class FormattingHelper: """Format of commonly used expressions, making use of a cache to not recompute """ - def __init__(self, dbstate): + def __init__(self, dbstate, uistate=None): self.dbstate = dbstate + self.uistate = uistate self._text_cache = {} self._markup_cache = {} + self.symbols = Symbols() + self.reload_symbols() + + def reload_symbols(self): + self.clear_cache() + if self.uistate and self.uistate.symbols: + death_idx = self.uistate.death_symbol + self.male = self.symbols.get_symbol_for_string(self.symbols.SYMBOL_MALE) + self.female = self.symbols.get_symbol_for_string(self.symbols.SYMBOL_FEMALE) + self.bth = self.symbols.get_symbol_for_string(self.symbols.SYMBOL_BIRTH) + self.marr = self.symbols.get_symbol_for_string(self.symbols.SYMBOL_MARRIAGE) + self.dth = self.symbols.get_death_symbol_for_char(death_idx) + else: + death_idx = self.symbols.DEATH_SYMBOL_LATIN_CROSS + self.male = self.symbols.get_symbol_fallback(self.symbols.SYMBOL_MALE) + self.female = self.symbols.get_symbol_fallback(self.symbols.SYMBOL_FEMALE) + self.marr = self.symbols.get_symbol_fallback(self.symbols.SYMBOL_MARRIAGE) + self.dth = self.symbols.get_death_symbol_fallback(death_idx) def format_relation(self, family, line_count, use_markup=False): """ Format a relation between parents of a family @@ -73,18 +93,15 @@ class FormattingHelper: text = "" marriage = get_marriage_or_fallback(self.dbstate.db, family) if marriage and use_markup and marriage.get_type() != EventType.MARRIAGE: - mdate = "%s %s" % (marriage.get_type().get_abbreviation(), - escape(get_date(marriage))) + mdate = "%s %s" % (self.marr, escape(get_date(marriage))) mplace = "%s" % escape(self.get_place_name(marriage.get_place_handle())) name = "%s" % str(marriage.get_type()) elif marriage and use_markup: - mdate = "%s %s" % (marriage.get_type().get_abbreviation(), - escape(get_date(marriage))) + mdate = "%s %s" % (self.marr, escape(get_date(marriage))) mplace = escape(self.get_place_name(marriage.get_place_handle())) name = str(marriage.get_type()) elif marriage: - mdate = "%s %s" % (marriage.get_type().get_abbreviation(), - get_date(marriage)) + mdate = "%s %s" % (self.marr, get_date(marriage)) mplace = self.get_place_name(marriage.get_place_handle()) name = str(marriage.get_type()) else: @@ -178,10 +195,12 @@ class FormattingHelper: dplace = "" if line_count < 5: - text = "%s\n* %s\n+ %s" % (name, bdate, ddate) + text = "%s\n%s %s\n%s %s" % (name, self.bth, bdate, + self.dth, ddate) else: - text = "%s\n* %s\n %s\n+ %s\n %s" % (name, bdate, bplace, - ddate, dplace) + text = "%s\n%s %s\n %s\n%s %s\n %s" % (name, self.bth, bdate, + bplace, self.dth, + ddate, dplace) if use_markup: if not person.handle in self._markup_cache: self._markup_cache[person.handle] = {} diff --git a/gramps/gen/utils/symbols.py b/gramps/gen/utils/symbols.py new file mode 100644 index 000000000..25e7556fb --- /dev/null +++ b/gramps/gen/utils/symbols.py @@ -0,0 +1,189 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2015- Serge Noiraud +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# https://en.wikipedia.org/wiki/Miscellaneous_Symbols +# http://www.w3schools.com/charsets/ref_utf_symbols.asp +# + +#------------------------------------------------------------------------- +# +# Standard python modules +# +#------------------------------------------------------------------------- +from gramps.gen.const import GRAMPS_LOCALE as glocale +_ = glocale.translation.sgettext + +# pylint: disable=superfluous-parens +# pylint: disable=anomalous-unicode-escape-in-string + +class Symbols(object): + # genealogical symbols + SYMBOL_FEMALE = 0 + SYMBOL_MALE = 1 + SYMBOL_ASEXUAL_SEXLESS = 2 # Unknown + SYMBOL_LESBIAN = 3 + SYMBOL_MALE_HOMOSEXUAL = 4 + SYMBOL_HETEROSEXUAL = 5 + SYMBOL_HERMAPHRODITE = 6 + SYMBOL_TRANSGENDER = 7 + SYMBOL_NEUTER = 8 + + SYMBOL_ILLEGITIM = 9 + SYMBOL_BIRTH = 10 + SYMBOL_BAPTISM = 11 # CHRISTENING + SYMBOL_ENGAGED = 12 + SYMBOL_MARRIAGE = 13 + SYMBOL_DIVORCE = 14 + SYMBOL_UNMARRIED_PARTNERSHIP = 15 + SYMBOL_BURIED = 16 + SYMBOL_CREMATED = 17 # Funeral urn + SYMBOL_KILLED_IN_ACTION = 18 + SYMBOL_EXTINCT = 19 + + all_symbols = [ + # Name UNICODE SUBSTITUTION + (_("Female"), '\u2640', ""), + (_("Male"), '\u2642', ""), + (_("Asexuality, sexless, genderless"), '\u26aa', ""), + (_("Lesbianism"), '\u26a2', "oo"), + (_("Male homosexuality"), '\u26a3', "oo"), + (_("Heterosexuality"), '\u26a4', "oo"), + (_("Transgender, hermaphrodite (in entomology)"), '\u26a5', ""), + (_("Transgender"), '\u26a6', ""), + (_("Neuter"), '\u26b2', ""), + + (_("Illegitimate"), '\u229b', ""), + (_("Birth"), '\u002a', "*"), + (_("Baptism/Christening"), '\u007e', "~"), + (_("Engaged"), '\u26ac', "o"), + (_("Marriage"), '\u26ad', "oo"), + (_("Divorce"), '\u26ae', "o|o"), + (_("Unmarried partnership"), '\u26af', "o-o"), + (_("Buried"), '\u26b0', "d"), + (_("Cremated/Funeral urn"), '\u26b1', "d"), + (_("Killed in action"), '\u2694', "d"), + (_("Extinct"), '\u2021', ""), + ] + + # genealogical death symbols + DEATH_SYMBOL_NONE = 0 + DEATH_SYMBOL_X = 1 + DEATH_SYMBOL_SKULL = 2 + DEATH_SYMBOL_ANKH = 3 + DEATH_SYMBOL_ORTHODOX_CROSS = 4 + DEATH_SYMBOL_CHI_RHO = 5 + DEATH_SYMBOL_LORRAINE_CROSS = 6 + DEATH_SYMBOL_JERUSALEM_CROSS = 7 + DEATH_SYMBOL_STAR_CRESCENT = 8 + DEATH_SYMBOL_WEST_SYRIAC_CROSS = 9 + DEATH_SYMBOL_EAST_SYRIAC_CROSS = 10 + DEATH_SYMBOL_HEAVY_GREEK_CROSS = 11 + DEATH_SYMBOL_LATIN_CROSS = 12 + DEATH_SYMBOL_SHADOWED_LATIN_CROSS = 13 + DEATH_SYMBOL_MALTESE_CROSS = 14 + DEATH_SYMBOL_STAR_OF_DAVID = 15 + DEATH_SYMBOL_DEAD = 16 + + # The following is used in the global preferences in the display tab. + # Name + # UNICODE SUBSTITUTION + death_symbols = [(_("Nothing"), "", ""), + ("x", "x", "x"), + (_("Skull and crossbones"), "\u2620", "+"), + (_("Ankh"), "\u2625", "+"), + (_("Orthodox cross"), "\u2626", "+"), + (_("Chi rho"), "\u2627", "+"), + (_("Cross of Lorraine"), "\u2628", "+"), + (_("Cross of Jerusalem"), "\u2629", "+"), + (_("Star and crescent"), "\u262a", "+"), + (_("West Syriac cross"), "\u2670", "+"), + (_("East Syriac cross"), "\u2671", "+"), + (_("Heavy Greek cross"), "\u271a", "+"), + (_("Latin cross"), "\u271d", "+"), + (_("Shadowed White Latin cross"), "\u271e", "+"), + (_("Maltese cross"), "\u2720", "+"), + (_("Star of David"), "\u2721", "+"), + (_("Dead"), _("Dead"), _("Dead")) + ] + + def __init__(self): + self.symbols = None + # + # functions for general symbols + # + def get_symbol_for_html(self, symbol): + """ return the html string like '⚪' """ + return '&#%d;' % ord(self.all_symbols[symbol][1]) + + def get_symbol_name(self, symbol): + """ + Return the name of the symbol. + """ + return self.all_symbols[symbol][0] + + def get_symbol_for_string(self, symbol): + """ return the utf-8 character like '\u2670' """ + return self.all_symbols[symbol][1] + + def get_symbol_fallback(self, symbol): + """ + Return the replacement string. + This is used if the utf-8 symbol in not present within a font. + """ + return self.all_symbols[symbol][2] + + # + # functions for death symbols + # + def get_death_symbols(self): + """ + Return the list of death symbols. + This is used in the global preference to choose which symbol we'll use. + """ + return self.death_symbols + + def get_death_symbol_name(self, symbol): + """ + Return the name of the symbol. + """ + return self.death_symbols[symbol][0] + + def get_death_symbol_for_html(self, symbol): + """ + return the html string like '⚪'. + """ + return '&#%d;' % ord(self.death_symbols[symbol][1]) + + def get_death_symbol_for_char(self, symbol): + """ + Return the utf-8 character for the symbol. + """ + return self.death_symbols[symbol][1] + + def get_death_symbol_fallback(self, symbol): + """ + Return the string replacement for the symbol. + """ + return self.death_symbols[symbol][2] + + # + # functions for all symbols + # + def get_how_many_symbols(self): + return len(self.death_symbols) + len(self.all_symbols) - 4 diff --git a/gramps/gui/configure.py b/gramps/gui/configure.py index 314303747..a65f25c93 100644 --- a/gramps/gui/configure.py +++ b/gramps/gui/configure.py @@ -6,6 +6,7 @@ # Copyright (C) 2010 Benny Malengier # Copyright (C) 2010 Nick Hall # Copyright (C) 2012 Doug Blank +# Copyright (C) 2015- Serge Noiraud # # 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 @@ -72,6 +73,8 @@ from .plug import PluginWindows from .spell import HAVE_GTKSPELL from gramps.gen.constfunc import win _ = glocale.translation.gettext +from gramps.gen.utils.symbols import Symbols +from gramps.gen.constfunc import get_env_var #------------------------------------------------------------------------- # @@ -363,6 +366,14 @@ class ConfigureDialog(ManagedWindow): grid.attach(text, start, index, stop - start, 1) return text + def add_button(self, grid, label, index, constant, extra_callback=None, config=None): + if not config: + config = self.__config + button = Gtk.Button(label=label) + button.connect('clicked', extra_callback) + grid.attach(button, 1, index, 1, 1) + return button + def add_path_box(self, grid, label, index, entry, path, callback_label, callback_sel, config=None): """ @@ -555,7 +566,8 @@ class GrampsPreferences(ConfigureDialog): self.add_date_panel, self.add_researcher_panel, self.add_advanced_panel, - self.add_color_panel + self.add_color_panel, + self.add_symbols_panel ) ConfigureDialog.__init__(self, uistate, dbstate, page_funcs, GrampsPreferences, config, @@ -1932,3 +1944,264 @@ class GrampsPreferences(ConfigureDialog): def build_menu_names(self, obj): return (_('Preferences'), _('Preferences')) + + def add_symbols_panel(self, configdialog): + self.grid = Gtk.Grid() + self.grid.set_border_width(12) + self.grid.set_column_spacing(6) + self.grid.set_row_spacing(6) + + message = _('This tab gives you the possibility to use one font' + ' which is able to show all genealogical symbols\n\n' + 'If you select the "use symbols" checkbox, ' + 'Gramps will use the selected font if it exists.' + ) + message += '\n' + message += _('This can be useful if you want to add phonetic in ' + 'a note to show how to pronounce a name or if you mix' + ' multiple languages like greek and russian.' + ) + self.add_text(self.grid, message, + 0, line_wrap=True) + self.add_checkbox(self.grid, + _('Use symbols'), + 1, + 'utf8.in-use', + extra_callback=self.activate_change_font + ) + message = _('Be careful, if you click on the "Try to find" button, it can ' + 'take a while before you can continue (10 minutes or more). ' + '\nIf you cancel the process, nothing will be changed.' + ) + self.add_text(self.grid, message, + 2, line_wrap=True) + available_fonts = config.get('utf8.available-fonts') + self.all_avail_fonts = list(enumerate(available_fonts)) + if len(available_fonts) > 0: + self.add_text(self.grid, + _('You have already run the tool to search for genealogy fonts.' + '\nRun it again only if you added fonts on your system.' + ), + 3, line_wrap=True) + self.add_button(self.grid, + _('Try to find'), + 4, + 'utf8.in-use', + extra_callback=self.can_we_use_genealogical_fonts) + sel_font = config.get('utf8.selected-font') + if len(available_fonts) > 0: + try: + active_val = available_fonts.index(sel_font) + except: + active_val = 0 + self.add_combo(self.grid, + _('Choose font'), + 5, 'utf8.selected-font', + self.all_avail_fonts, + callback=self.utf8_update_font, + valueactive=True, setactive=active_val) + symbols = Symbols() + all_sbls = symbols.get_death_symbols() + all_symbols = [] + for symbol in all_sbls: + all_symbols.append(symbol[1] + " " + symbol[0]) + self.all_death_symbols = list(enumerate(all_symbols)) + pos = config.get('utf8.death-symbol') + combo = self.add_combo(self.grid, + _('Select default death symbol'), + 6, 'utf8.death-symbol', + self.all_death_symbols, + callback=self.utf8_update_death_symbol, + valueactive=True, setactive='') + combo.set_active(pos) + if config.get('utf8.selected-font') != "": + self.utf8_show_example() + + return _('Genealogical Symbols'), self.grid + + def can_we_use_genealogical_fonts(self, obj): + try: + import fontconfig + from gramps.gui.utils import ProgressMeter + from collections import defaultdict + except: + from gramps.gui.dialog import WarningDialog + WarningDialog(_("Cannot look for genealogical fonts"), + _("I am not able to select genealogical fonts. " + "Please, install the module fontconfig for python 3."), + parent=self.uistate.window) + return False + try: + # remove the old messages with old font + self.grid.remove_row(8) + self.grid.remove_row(7) + self.grid.remove_row(6) + self.grid.remove_row(5) + except: + pass + fonts = fontconfig.query() + all_fonts = defaultdict(set) + symbols = Symbols() + nb_symbols = symbols.get_how_many_symbols() + self.in_progress = True + self.progress = ProgressMeter(_('Checking available genealogical fonts'), + can_cancel=True, + cancel_callback=self.stop_looking_for_font, + parent=self.uistate.window) + self.progress.set_pass(_('Looking for all fonts with genealogical symbols.'), nb_symbols*len(fonts)) + for path in fonts: + if not self.in_progress: + return # We clicked on Cancel + font = fontconfig.FcFont(path) + local = get_env_var('LANGUAGE', 'en') + if isinstance(font.family, list): + fontname = None + for lang,fam in font.family: + if lang == local: + fontname = fam + if not fontname: + fontname = font.family[0][1] + else: + if local in font.family: + fontname = font.family[local] + else: + for lang, name in font.family: # version 0.6.0 use dict + fontname = name + break + for rand in range(symbols.SYMBOL_MALE, symbols.SYMBOL_EXTINCT+1): + string = symbols.get_symbol_for_html(rand) + value = symbols.get_symbol_for_string(rand) + if font.has_char(value): + all_fonts[fontname].add(value) + self.progress.step() + for rand in range(symbols.DEATH_SYMBOL_SKULL, + symbols.DEATH_SYMBOL_DEAD): + value = symbols.get_death_symbol_for_char(rand) + if font.has_char(value): + all_fonts[fontname].add(value) + self.progress.step() + self.progress.close() + available_fonts = [] + for font, font_usage in all_fonts.items(): + if not font_usage: + continue + if len(font_usage) == nb_symbols: # If the font use all symbols + available_fonts.append(font) + config.set('utf8.available-fonts', available_fonts) + sel_font = config.get('utf8.selected-font') + try: + active_val = available_fonts.index(sel_font) + except: + active_val = 0 + if len(available_fonts) > 0: + self.all_avail_fonts = list(enumerate(available_fonts)) + choosefont = self.add_combo(self.grid, + _('Choose font'), + 5, 'utf8.selected-font', + self.all_avail_fonts, callback=self.utf8_update_font, + valueactive=True, setactive=active_val) + if len(available_fonts) == 1: + single_font = self.all_avail_fonts[choosefont.get_active()][1] + config.set('utf8.selected-font', + self.all_avail_fonts[single_font]) + self.utf8_show_example() + symbols = Symbols() + all_sbls = symbols.get_death_symbols() + all_symbols = [] + for symbol in all_sbls: + all_symbols.append(symbol[1] + " " + symbol[0]) + self.all_death_symbols = list(enumerate(all_symbols)) + pos = config.get('utf8.death-symbol') + combo = self.add_combo(self.grid, + _('Select default death symbol'), + 6, 'utf8.death-symbol', + self.all_death_symbols, + callback=self.utf8_update_death_symbol, + valueactive=True, setactive='') + combo.set_active(pos) + else: + self.add_text(self.grid, + _('You have no font with genealogical symbols on your ' + 'system. Gramps will not be able to use symbols.' + ), + 6, line_wrap=True) + config.set('utf8.selected-font',"") + self.grid.show_all() + self.in_progress = False + + def utf8_update_font(self, obj, constant): + entry = obj.get_active() + config.set(constant, self.all_avail_fonts[entry][1]) + self.utf8_show_example() + + def activate_change_font(self, obj=None): + if obj: + if not obj.get_active(): + # reset to the system default + self.uistate.viewmanager.reset_font() + font = config.get('utf8.selected-font') + if not self.uistate.viewmanager.change_font(font): + # We can't change the font, so reset the checkbox. + if obj: + obj.set_active(False) + self.uistate.reload_symbols() + self.uistate.emit('font-changed') + + def utf8_show_example(self): + from gi.repository import Pango + from gramps.gen.utils.grampslocale import _LOCALE_NAMES as X + from string import ascii_letters + try: + # remove the old messages with old font + self.grid.remove_row(8) + self.grid.remove_row(7) + except: + pass + font = config.get('utf8.selected-font') + symbols = Symbols() + my_characters = _("What you will see") + " :\n" + my_characters += ascii_letters + my_characters += " àäâçùéèiïîêëiÉÀÈïÏËÄœŒÅåØøìòô ...\n" + for k,v in sorted(X.items()): + lang = Pango.Language.from_string(k) + my_characters += v[2] + ":\t" + lang.get_sample_string() + "\n" + + scrollw = Gtk.ScrolledWindow() + scrollw.set_size_request(600, 100) + text = Gtk.Label() + text.set_line_wrap(True) + font_description = Pango.font_description_from_string(font) + text.modify_font(font_description) + self.activate_change_font() + text.set_halign(Gtk.Align.START) + text.set_text(my_characters) + scrollw.add(text) + scrollw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self.grid.attach(scrollw, 1, 7, 8, 1) + + my_characters = "" + for idx in range(symbols.SYMBOL_FEMALE, symbols.SYMBOL_EXTINCT+1): + my_characters += symbols.get_symbol_for_string(idx) + " " + + death_symbl = config.get('utf8.death-symbol') + my_characters += symbols.get_death_symbol_for_char(death_symbl) + text = Gtk.Label() + text.set_line_wrap(True) + font_description = Pango.font_description_from_string(font) + text.modify_font(font_description) + text.set_halign(Gtk.Align.START) + text.set_markup("" + + my_characters + + "") + self.grid.attach(text, 1, 8, 8, 1) + self.grid.show_all() + + def stop_looking_for_font(self, *args, **kwargs): + self.progress.close() + self.in_progress = False + + def utf8_update_death_symbol(self, obj, constant): + entry = obj.get_active() + config.set(constant, entry) + self.utf8_show_example() + diff --git a/gramps/gui/displaystate.py b/gramps/gui/displaystate.py index 865288c8a..68c603360 100644 --- a/gramps/gui/displaystate.py +++ b/gramps/gui/displaystate.py @@ -400,6 +400,7 @@ class DisplayState(Callback): 'grampletbar-close-changed' : None, 'update-available' : (list, ), 'autobackup' : None, + 'font-changed' : None, } #nav_type to message @@ -439,6 +440,8 @@ class DisplayState(Callback): self.set_relationship_class() self.export = False self.backup_timer = None + self.symbols = config.get('utf8.in-use') + self.death_symbol = config.get('utf8.death-symbol') formatter = logging.Formatter('%(levelname)s %(name)s: %(message)s') warnbtn = status.get_warning_button() @@ -669,3 +672,7 @@ class DisplayState(Callback): self.status.pop(self.status_id) self.status.push(self.status_id, text) process_pending_events() + + def reload_symbols(self): + self.symbols = config.get('utf8.in-use') + self.death_symbol = config.get('utf8.death-symbol') diff --git a/gramps/gui/viewmanager.py b/gramps/gui/viewmanager.py index 272cee6a5..540cd219b 100644 --- a/gramps/gui/viewmanager.py +++ b/gramps/gui/viewmanager.py @@ -114,6 +114,11 @@ WIKI_HELP_PAGE_FAQ = '%s_-_FAQ' % URL_MANUAL_PAGE WIKI_HELP_PAGE_KEY = '%s_-_Keybindings' % URL_MANUAL_PAGE WIKI_HELP_PAGE_MAN = '%s' % URL_MANUAL_PAGE +CSS_FONT = """ +#view { + font-family: %s; + } +""" #------------------------------------------------------------------------- # # ViewManager @@ -247,12 +252,17 @@ class ViewManager(CLIManager): height = config.get('interface.main-window-height') horiz_position = config.get('interface.main-window-horiz-position') vert_position = config.get('interface.main-window-vert-position') + font = config.get('utf8.selected-font') self.window = Gtk.ApplicationWindow(application=self.app) self.app.window = self.window self.window.set_icon_from_file(ICON) self.window.set_default_size(width, height) self.window.move(horiz_position, vert_position) + + self.provider = Gtk.CssProvider() + self.change_font(font) + #Set the mnemonic modifier on Macs to alt-ctrl so that it #doesn't interfere with the extended keyboard, see #https://gramps-project.org/bugs/view.php?id=6943 @@ -661,6 +671,33 @@ class ViewManager(CLIManager): except WindowActiveError: return + def reset_font(self): + """ + Reset to the default application font. + """ + Gtk.StyleContext.remove_provider_for_screen(self.window.get_screen(), + self.provider) + + def change_font(self, font): + """ + Change the default application font. + Only in the case we use symbols. + """ + if config.get('utf8.in-use') and font != "": + css_font = CSS_FONT % font + try: + self.provider.load_from_data(css_font.encode('UTF-8')) + Gtk.StyleContext.add_provider_for_screen( + self.window.get_screen(), self.provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) + return True + except: + # Force gramps to use the standard font. + print("I can't set the new font :", font) + config.set('utf8.in-use', False) + config.set('utf8.selected-font', "") + return False + def tip_of_day_activate(self, *obj): """ Display Tip of the day diff --git a/gramps/gui/views/pageview.py b/gramps/gui/views/pageview.py index 687ce546c..c264b30b0 100644 --- a/gramps/gui/views/pageview.py +++ b/gramps/gui/views/pageview.py @@ -137,6 +137,7 @@ class PageView(DbGUIElement, metaclass=ABCMeta): self.top = None self.sidebar = None self.bottombar = None + self.widget = None DbGUIElement.__init__(self, dbstate.db) @@ -159,9 +160,10 @@ class PageView(DbGUIElement, metaclass=ABCMeta): hpane.show() vpane.show() - widget = self.build_widget() - widget.show_all() - vpane.pack1(widget, resize=True, shrink=False) + self.widget = self.build_widget() + self.widget.show_all() + self.widget.set_name('view') + vpane.pack1(self.widget, resize=True, shrink=False) vpane.pack2(self.bottombar, resize=False, shrink=True) self._setup_slider_config(vpane, 'vpane.slider-position') diff --git a/gramps/gui/widgets/fanchart.py b/gramps/gui/widgets/fanchart.py index b2764e5a5..58db5ed24 100644 --- a/gramps/gui/widgets/fanchart.py +++ b/gramps/gui/widgets/fanchart.py @@ -93,6 +93,7 @@ from gramps.gen.const import ( TYPE_BOX_FAMILY) _ = glocale.translation.gettext from ..utilscairo import warpPath +from gramps.gen.utils.symbols import Symbols # following are used in name_displayer format def # (must not conflict with standard defs) @@ -166,6 +167,7 @@ class FanChartBaseWidget(Gtk.DrawingArea): [DdTargets.PERSON_LINK.target()], Gdk.DragAction.COPY) self.connect('drag_data_received', self.on_drag_data_received) + self.uistate.connect('font-changed', self.reload_symbols) self._mouse_click = False self.rotate_value = 90 # degrees, initially, 1st gen male on right half @@ -176,6 +178,17 @@ class FanChartBaseWidget(Gtk.DrawingArea): #(re)compute everything self.reset() self.set_size_request(120, 120) + self.symbols = Symbols() + self.reload_symbols() + + def reload_symbols(self): + dth_idx = self.uistate.death_symbol + if self.uistate.symbols: + self.bth = self.symbols.get_symbol_for_string(self.symbols.SYMBOL_BIRTH) + self.dth = self.symbols.get_death_symbol_for_char(dth_idx) + else: + self.bth = self.symbols.get_symbol_fallback(self.symbols.SYMBOL_BIRTH) + self.dth = self.symbols.get_death_symbol_fallback(dth_idx) def reset(self): """ @@ -582,8 +595,14 @@ class FanChartBaseWidget(Gtk.DrawingArea): radial=False, fontcolor=(0, 0, 0), bold=False, can_flip = True): if not person: return draw_radial = radial and self.radialtext + try: + alive = probably_alive(person, self.dbstate.db) + except RuntimeError: + alive = False if not self.twolinename: name=name_displayer.display(person) + if self.uistate.symbols and not alive: + name = self.dth + ' ' + name self.draw_text(cr, name, radiusin, radiusout, start, stop, draw_radial, fontcolor, bold) else: @@ -656,7 +675,7 @@ class FanChartBaseWidget(Gtk.DrawingArea): Display text at a particular radius, between start_rad and stop_rad radians. """ - font = Pango.FontDescription(self.fontdescr) + font = Pango.FontDescription("") fontsize = self.fontsize font.set_size(fontsize * Pango.SCALE) if bold: @@ -767,7 +786,7 @@ class FanChartBaseWidget(Gtk.DrawingArea): cr.translate(-self.center_xy[0], -self.center_xy[1]) - font = Pango.FontDescription(self.fontdescr) + font = Pango.FontDescription("") fontsize = self.fontsize font.set_size(fontsize * Pango.SCALE) for color, text in zip(self.gradcol, self.gradval): @@ -1505,7 +1524,11 @@ class FanChartGrampsGUI: """ self.fan = None self.on_childmenu_changed = on_childmenu_changed - self.format_helper = FormattingHelper(self.dbstate) + self.format_helper = FormattingHelper(self.dbstate, self.uistate) + self.uistate.connect('font-changed', self.reload_symbols) + + def reload_symbols(self): + self.format_helper.reload_symbols() def set_fan(self, fan): """ diff --git a/gramps/plugins/lib/maps/datelayer.py b/gramps/plugins/lib/maps/datelayer.py index 823a814ea..0f74ca007 100644 --- a/gramps/plugins/lib/maps/datelayer.py +++ b/gramps/plugins/lib/maps/datelayer.py @@ -48,6 +48,7 @@ import cairo # Gramps Modules # #------------------------------------------------------------------------- +from gramps.gen.config import config #------------------------------------------------------------------------- # @@ -77,7 +78,7 @@ class DateLayer(GObject.GObject, osmgpsmap.MapLayer): self.first = " " self.last = " " self.color = "black" - self.font = "Arial" + self.font = config.get('utf8.selected-font') self.size = 36 def clear_dates(self): @@ -87,7 +88,7 @@ class DateLayer(GObject.GObject, osmgpsmap.MapLayer): self.first = " " self.last = " " self.color = "black" - self.font = "Arial" + self.font = config.get('utf8.selected-font') self.size = 36 def set_font_attributes(self, font, size, color): @@ -95,7 +96,10 @@ class DateLayer(GObject.GObject, osmgpsmap.MapLayer): Set the font color, size and name """ self.color = color - self.font = font + if font: + self.font = font + else: + self.font = config.get('utf8.selected-font') self.size = size def add_date(self, date): diff --git a/gramps/plugins/lib/maps/geography.py b/gramps/plugins/lib/maps/geography.py index cb6a16b99..8c87a78b7 100644 --- a/gramps/plugins/lib/maps/geography.py +++ b/gramps/plugins/lib/maps/geography.py @@ -144,7 +144,10 @@ class GeoGraphyView(OsmGps, NavigationView): if config.get('geography.path') == "": config.set('geography.path', GEOGRAPHY_PATH) - self.format_helper = FormattingHelper(self.dbstate) + self.uistate = uistate + self.uistate.connect('font-changed', self.font_changed) + self.uistate.connect('nameformat-changed', self.build_tree) + self.format_helper = FormattingHelper(self.dbstate, self.uistate) self.centerlat = self.centerlon = 0.0 self.cross_map = None self.current_map = None @@ -184,6 +187,12 @@ class GeoGraphyView(OsmGps, NavigationView): self.nbmarkers = 0 self.place_without_coordinates = [] + def font_changed(self): + """ + The font or the death symbol changed. + """ + self.build_tree() + def add_bookmark(self, menu): """ Add the place to the bookmark diff --git a/gramps/plugins/lib/maps/messagelayer.py b/gramps/plugins/lib/maps/messagelayer.py index 7f8a2e70c..6093d84f9 100644 --- a/gramps/plugins/lib/maps/messagelayer.py +++ b/gramps/plugins/lib/maps/messagelayer.py @@ -48,6 +48,7 @@ from gi.repository import Pango, PangoCairo # Gramps Modules # #------------------------------------------------------------------------- +from gramps.gen.config import config from gramps.gen.constfunc import is_quartz #------------------------------------------------------------------------- @@ -78,7 +79,7 @@ class MessageLayer(GObject.GObject, osmgpsmap.MapLayer): GObject.GObject.__init__(self) self.message = "" self.color = "black" - self.font = "Sans" + self.font = config.get('utf8.selected-font') self.size = 13 def clear_messages(self): @@ -92,7 +93,7 @@ class MessageLayer(GObject.GObject, osmgpsmap.MapLayer): reset the font attributes. """ self.color = "black" - self.font = "Sans" + self.font = config.get('utf8.selected-font') self.size = 13 def set_font_attributes(self, font, size, color): @@ -103,6 +104,8 @@ class MessageLayer(GObject.GObject, osmgpsmap.MapLayer): self.color = color if font is not None: self.font = font + else: + self.font = config.get('utf8.selected-font') if size is not None: self.size = size diff --git a/gramps/plugins/view/fanchart2wayview.py b/gramps/plugins/view/fanchart2wayview.py index 662ad6cad..a3b611382 100644 --- a/gramps/plugins/view/fanchart2wayview.py +++ b/gramps/plugins/view/fanchart2wayview.py @@ -105,6 +105,15 @@ class FanChart2WayView(fanchart2way.FanChart2WayGrampsGUI, NavigationView): self.additional_uis.append(FanChartView.additional_ui) self.allfonts = [x for x in enumerate(SystemFonts().get_system_fonts())] + self.func_list.update({ + 'J' : self.jump, + }) + self.uistate.connect('font-changed', self.font_changed) + + def font_changed(self): + self.format_helper.reload_symbols() + self.update() + def navigation_type(self): return 'Person' diff --git a/gramps/plugins/view/fanchartdescview.py b/gramps/plugins/view/fanchartdescview.py index 9580f6534..00ca8f735 100644 --- a/gramps/plugins/view/fanchartdescview.py +++ b/gramps/plugins/view/fanchartdescview.py @@ -100,6 +100,15 @@ class FanChartDescView(fanchartdesc.FanChartDescGrampsGUI, NavigationView): self.additional_uis.append(FanChartView.additional_ui) self.allfonts = [x for x in enumerate(SystemFonts().get_system_fonts())] + self.func_list.update({ + 'J' : self.jump, + }) + self.uistate.connect('font-changed', self.font_changed) + + def font_changed(self): + self.format_helper.reload_symbols() + self.update() + def navigation_type(self): return 'Person' diff --git a/gramps/plugins/view/fanchartview.py b/gramps/plugins/view/fanchartview.py index 61e45e75f..ced026809 100644 --- a/gramps/plugins/view/fanchartview.py +++ b/gramps/plugins/view/fanchartview.py @@ -96,6 +96,15 @@ class FanChartView(fanchart.FanChartGrampsGUI, NavigationView): self.additional_uis.append(self.additional_ui) self.allfonts = [x for x in enumerate(SystemFonts().get_system_fonts())] + self.func_list.update({ + 'J' : self.jump, + }) + self.uistate.connect('font-changed', self.font_changed) + + def font_changed(self): + self.format_helper.reload_symbols() + self.update() + def navigation_type(self): return 'Person' diff --git a/gramps/plugins/view/geoclose.py b/gramps/plugins/view/geoclose.py index 877913b15..0ac9ec63a 100644 --- a/gramps/plugins/view/geoclose.py +++ b/gramps/plugins/view/geoclose.py @@ -296,6 +296,7 @@ class GeoClose(GeoGraphyView): self.remove_all_markers() self.lifeway_layer.clear_ways() self.message_layer.clear_messages() + self.message_layer.set_font_attributes(None, None, None) active = self.get_active() if active: indiv1 = self.dbstate.db.get_person_from_handle(active) diff --git a/gramps/plugins/view/geoevents.py b/gramps/plugins/view/geoevents.py index 1a6f28284..9424a19ff 100644 --- a/gramps/plugins/view/geoevents.py +++ b/gramps/plugins/view/geoevents.py @@ -331,6 +331,8 @@ class GeoEvents(GeoGraphyView): self.nbplaces = 0 self.without = 0 self.cal = config.get('preferences.calendar-format-report') + self.message_layer.clear_messages() + self.message_layer.clear_font_attributes() self.no_show_places_in_status_bar = False if self.show_all: self.show_all = False @@ -358,9 +360,15 @@ class GeoEvents(GeoGraphyView): self._createmap_for_one_event(event) progress.step() progress.close() - elif obj: - event = dbstate.db.get_event_from_handle(obj) - self._createmap_for_one_event(event) + else: + if obj: + event = dbstate.db.get_event_from_handle(obj) + self._createmap_for_one_event(event) + self.message_layer.add_message( + _("Right click on the map and select 'show all events'" + " to show all known events with coordinates. " + "You can use the history to navigate on the map. " + "You can use filtering.")) self.sort = sorted(self.place_list, key=operator.itemgetter(3, 4, 6) ) diff --git a/gramps/plugins/view/geofamclose.py b/gramps/plugins/view/geofamclose.py index fca0c28e4..7b019dea2 100644 --- a/gramps/plugins/view/geofamclose.py +++ b/gramps/plugins/view/geofamclose.py @@ -329,6 +329,7 @@ class GeoFamClose(GeoGraphyView): self.remove_all_markers() self.lifeway_layer.clear_ways() self.message_layer.clear_messages() + self.message_layer.set_font_attributes(None, None, None) active = self.get_active() family = None if active: diff --git a/gramps/plugins/view/geofamily.py b/gramps/plugins/view/geofamily.py index 42fcac16d..67d981ad2 100644 --- a/gramps/plugins/view/geofamily.py +++ b/gramps/plugins/view/geofamily.py @@ -445,6 +445,7 @@ class GeoFamily(GeoGraphyView): self.minyear = 9999 self.maxyear = 0 self.message_layer.clear_messages() + self.message_layer.set_font_attributes(None, None, None) if self.dbstate.db.has_family_handle(handle): family = self.dbstate.db.get_family_from_handle(handle) self._createmap_for_one_family(family) diff --git a/gramps/plugins/view/geomoves.py b/gramps/plugins/view/geomoves.py index 00234c764..9f9638f43 100644 --- a/gramps/plugins/view/geomoves.py +++ b/gramps/plugins/view/geomoves.py @@ -299,6 +299,7 @@ class GeoMoves(GeoGraphyView): self.lifeway_layer.clear_ways() self.date_layer.clear_dates() self.message_layer.clear_messages() + self.message_layer.set_font_attributes(None, None, None) def draw(self, menu, marks, color): """ diff --git a/gramps/plugins/view/geoperson.py b/gramps/plugins/view/geoperson.py index 2c5e09c3f..d20a79a22 100644 --- a/gramps/plugins/view/geoperson.py +++ b/gramps/plugins/view/geoperson.py @@ -368,6 +368,7 @@ class GeoPerson(GeoGraphyView): self.nbplaces = 0 self.nbmarkers = 0 self.message_layer.clear_messages() + self.message_layer.set_font_attributes(None, None, None) self.kml_layer.clear() person_handle = self.uistate.get_active('Person') person = None diff --git a/gramps/plugins/view/pedigreeview.py b/gramps/plugins/view/pedigreeview.py index 1cb4f5684..860c55387 100644 --- a/gramps/plugins/view/pedigreeview.py +++ b/gramps/plugins/view/pedigreeview.py @@ -68,6 +68,7 @@ from gramps.gui.utils import color_graph_box, hex_to_rgb_float, is_right_click from gramps.gen.constfunc import lin from gramps.gen.const import GRAMPS_LOCALE as glocale _ = glocale.translation.sgettext +from gramps.gen.utils.symbols import Symbols #------------------------------------------------------------------------- # @@ -530,11 +531,13 @@ class PedigreeView(NavigationView): PersonBookmarks, nav_group) self.dbstate = dbstate + self.uistate = uistate self.dbstate.connect('database-changed', self.change_db) uistate.connect('nameformat-changed', self.person_rebuild) uistate.connect('placeformat-changed', self.person_rebuild) + uistate.connect('font-changed', self.person_rebuild) - self.format_helper = FormattingHelper(self.dbstate) + self.format_helper = FormattingHelper(self.dbstate, self.uistate) # Depth of tree. self._depth = 1 @@ -568,6 +571,23 @@ class PedigreeView(NavigationView): self.show_unknown_people = self._config.get( 'interface.pedview-show-unknown-people') + self.func_list.update({ + 'J' : self.jump, + }) + + # use symbols + self.symbols = Symbols() + self.uistate.connect('font-changed', self.reload_symbols) + + def reload_symbols(self): + dth_idx = self.uistate.death_symbol + if self.uistate.symbols: + self.bth = self.symbols.get_symbol_for_string(self.symbols.SYMBOL_BIRTH) + self.dth = self.symbols.get_death_symbol_for_char(dth_idx) + else: + self.bth = self.symbols.get_symbol_fallback(self.symbols.SYMBOL_BIRTH) + self.dth = self.symbols.get_death_symbol_fallback(dth_idx) + def get_handle_from_gramps_id(self, gid): """ returns the handle of the specified object @@ -833,6 +853,7 @@ class PedigreeView(NavigationView): def person_rebuild(self, dummy=None): """Callback function for signals of change database.""" self.format_helper.clear_cache() + self.format_helper.reload_symbols() self.dirty = True if self.active: self.rebuild_trees(self.get_active()) diff --git a/gramps/plugins/view/relview.py b/gramps/plugins/view/relview.py index 9fab72a30..b340349a6 100644 --- a/gramps/plugins/view/relview.py +++ b/gramps/plugins/view/relview.py @@ -80,12 +80,7 @@ from gramps.gen.const import CUSTOM_FILTERS from gramps.gen.utils.db import (get_birth_or_fallback, get_death_or_fallback, preset_name) from gramps.gui.ddtargets import DdTargets - -_GenderCode = { - Person.MALE : '\u2642', - Person.FEMALE : '\u2640', - Person.UNKNOWN : '\u2650', - } +from gramps.gen.utils.symbols import Symbols _NAME_START = 0 _LABEL_START = 0 @@ -141,6 +136,7 @@ class RelationshipView(NavigationView): dbstate.connect('database-changed', self.change_db) uistate.connect('nameformat-changed', self.build_tree) uistate.connect('placeformat-changed', self.build_tree) + uistate.connect('font-changed', self.font_changed) self.redrawing = False self.child = None @@ -157,7 +153,8 @@ class RelationshipView(NavigationView): self.theme = self._config.get('preferences.relation-display-theme') self.toolbar_visible = config.get('interface.toolbar-on') self.age_precision = config.get('preferences.age-display-precision') - + self.symbols = Symbols() + self.reload_symbols() def get_handle_from_gramps_id(self, gid): """ @@ -186,6 +183,36 @@ class RelationshipView(NavigationView): self.callman.add_db_signal('person-delete', self.redraw) + def reload_symbols(self): + if self.uistate and self.uistate.symbols: + gsfs = self.symbols.get_symbol_for_string + self.male = gsfs(self.symbols.SYMBOL_MALE) + self.female = gsfs(self.symbols.SYMBOL_FEMALE) + self.bth = gsfs(self.symbols.SYMBOL_BIRTH) + self.marr = gsfs(self.symbols.SYMBOL_HETEROSEXUAL) + self.homom = gsfs(self.symbols.SYMBOL_MALE_HOMOSEXUAL) + self.homof = gsfs(self.symbols.SYMBOL_LESBIAN) + self.divorce = gsfs(self.symbols.SYMBOL_DIVORCE) + self.unmarr = gsfs(self.symbols.SYMBOL_UNMARRIED_PARTNERSHIP) + death_idx = self.uistate.death_symbol + self.dth = self.symbols.get_death_symbol_for_char(death_idx) + else: + gsf = self.symbols.get_symbol_fallback + self.male = gsf(self.symbols.SYMBOL_MALE) + self.female = gsf(self.symbols.SYMBOL_FEMALE) + self.bth = gsf(self.symbols.SYMBOL_BIRTH) + self.marr = gsf(self.symbols.SYMBOL_HETEROSEXUAL) + self.homom = gsf(self.symbols.SYMBOL_MALE_HOMOSEXUAL) + self.homof = gsf(self.symbols.SYMBOL_LESBIAN) + self.divorce = gsf(self.symbols.SYMBOL_DIVORCE) + self.unmarr = gsf(self.symbols.SYMBOL_UNMARRIED_PARTNERSHIP) + death_idx = self.symbols.DEATH_SYMBOL_LATIN_CROSS + self.dth = self.symbols.get_death_symbol_fallback(death_idx) + + def font_changed(self): + self.reload_symbols() + self.build_tree() + def navigation_type(self): return 'Person' @@ -554,7 +581,7 @@ class RelationshipView(NavigationView): person = self.dbstate.db.get_person_from_handle(handle) name = name_displayer.display(person) if use_gender: - gender = _GenderCode[person.gender] + gender = self.symbols.get_symbol_for_string(person.gender) else: gender = "" return (name, gender) @@ -667,7 +694,8 @@ class RelationshipView(NavigationView): name = name_displayer.display(person) fmt = '%s' text = fmt % escape(name) - label = widgets.DualMarkupLabel(text, _GenderCode[person.gender], + gender_code = self.symbols.get_symbol_for_string(person.gender) + label = widgets.DualMarkupLabel(text, gender_code, halign=Gtk.Align.END) if self._config.get('preferences.releditbtn'): button = widgets.IconButton(self.edit_button_press, @@ -847,6 +875,29 @@ class RelationshipView(NavigationView): _ADATA_STOP-_ADATA_START, 1) self.row += 1 + def marriage_symbol(self, family, markup=True): + if family: + father = mother = None + hdl1 = family.get_father_handle() + if hdl1: + father = self.dbstate.db.get_person_from_handle(hdl1).gender + hdl2 = family.get_mother_handle() + if hdl2: + mother = self.dbstate.db.get_person_from_handle(hdl2).gender + if father != mother: + symbol = self.marr + elif father == Person.MALE: + symbol = self.homom + else: + symbol = self.homof + if markup: + msg = '%s' % symbol + else: + msg = symbol + else: + msg = "" + return msg + def write_label(self, title, family, is_parent, person = None): """ Write a Family header row @@ -897,6 +948,10 @@ class RelationshipView(NavigationView): hbox = Gtk.Box() hbox.set_spacing(12) hbox.set_hexpand(True) + if self.uistate and self.uistate.symbols: + msg = self.marriage_symbol(family) + marriage = widgets.MarkupLabel(msg) + hbox.pack_start(marriage, False, True, 0) if is_parent: call_fcn = self.add_parent_family del_fcn = self.delete_parent_family @@ -984,6 +1039,7 @@ class RelationshipView(NavigationView): childmsg = _(" (1 sibling)") else : childmsg = _(" (only child)") + self.family = family box = self.get_people_box(family.get_father_handle(), family.get_mother_handle(), post_msg=childmsg) @@ -1038,6 +1094,7 @@ class RelationshipView(NavigationView): childmsg = _(" (1 sibling)") else : childmsg = _(" (only child)") + self.family = None box = self.get_people_box(post_msg=childmsg) eventbox = widgets.ShadeBox(self.use_shade) eventbox.add(box) @@ -1077,6 +1134,10 @@ class RelationshipView(NavigationView): def get_people_box(self, *handles, **kwargs): hbox = Gtk.Box() initial_name = True + if self.uistate and self.uistate.symbols: + msg = self.marriage_symbol(self.family) + " " + marriage = widgets.MarkupLabel(msg) + hbox.pack_start(marriage, False, True, 0) for handle in handles: if not initial_name: link_label = Gtk.Label(label=" %s " % _('and')) @@ -1317,15 +1378,15 @@ class RelationshipView(NavigationView): if bdate and ddate: value = _("%(birthabbrev)s %(birthdate)s, %(deathabbrev)s %(deathdate)s") % { - 'birthabbrev': birth.type.get_abbreviation(), - 'deathabbrev': death.type.get_abbreviation(), + 'birthabbrev': self.bth, + 'deathabbrev': self.dth, 'birthdate' : bdate, 'deathdate' : ddate } elif bdate: - value = _("%(event)s %(date)s") % {'event': birth.type.get_abbreviation(), 'date': bdate} + value = _("%(event)s %(date)s") % {'event': self.bth, 'date': bdate} elif ddate: - value = _("%(event)s %(date)s") % {'event': death.type.get_abbreviation(), 'date': ddate} + value = _("%(event)s %(date)s") % {'event': self.dth, 'date': ddate} else: value = "" return value @@ -1395,7 +1456,16 @@ class RelationshipView(NavigationView): if (event and event.get_type().is_relationship_event() and (event_ref.get_role() == EventRoleType.FAMILY or event_ref.get_role() == EventRoleType.PRIMARY)): - self.write_event_ref(vbox, event.get_type().string, event) + if event.get_type() == EventType.MARRIAGE: + msg = self.marriage_symbol(family, markup=False) + etype = msg + elif event.get_type() == EventType.DIVORCE: + etype = self.divorce + elif event.get_type() == EventType.DIVORCE: + etype = self.divorce + else: + etype = event.get_type().string + self.write_event_ref(vbox, etype, event) value = True return value @@ -1470,6 +1540,7 @@ class RelationshipView(NavigationView): ).format(number_of=count) else : childmsg = _(" (no children)") + self.family = family box = self.get_people_box(handle, post_msg=childmsg) eventbox = widgets.ShadeBox(self.use_shade) eventbox.add(box) @@ -1515,6 +1586,7 @@ class RelationshipView(NavigationView): ).format(number_of=count) else : childmsg = _(" (no children)") + self.family = None box = self.get_people_box(post_msg=childmsg) eventbox = widgets.ShadeBox(self.use_shade) eventbox.add(box)