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
This commit is contained in:
parent
735e17a8cb
commit
cd092897bc
@ -6,6 +6,7 @@
|
||||
# Copyright (C) 2008-2009 Gary Burton
|
||||
# Copyright (C) 2009-2012 Doug Blank <doug.blank@gmail.com>
|
||||
# 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"))
|
||||
|
||||
|
@ -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 = "<i>%s %s</i>" % (marriage.get_type().get_abbreviation(),
|
||||
escape(get_date(marriage)))
|
||||
mdate = "<i>%s %s</i>" % (self.marr, escape(get_date(marriage)))
|
||||
mplace = "<i>%s</i>" % escape(self.get_place_name(marriage.get_place_handle()))
|
||||
name = "<i>%s</i>" % 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] = {}
|
||||
|
189
gramps/gen/utils/symbols.py
Normal file
189
gramps/gen/utils/symbols.py
Normal file
@ -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
|
@ -6,6 +6,7 @@
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
# Copyright (C) 2010 Nick Hall
|
||||
# Copyright (C) 2012 Doug Blank <doug.blank@gmail.com>
|
||||
# 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("<big><big><big><big>" +
|
||||
my_characters +
|
||||
"</big></big></big></big>")
|
||||
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()
|
||||
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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({
|
||||
'<PRIMARY>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'
|
||||
|
||||
|
@ -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({
|
||||
'<PRIMARY>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'
|
||||
|
||||
|
@ -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({
|
||||
'<PRIMARY>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'
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
)
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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
|
||||
|
@ -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({
|
||||
'<PRIMARY>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())
|
||||
|
@ -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 = '<span size="larger" weight="bold">%s</span>'
|
||||
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 = '<span size="24000" >%s</span>' % 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)
|
||||
|
Loading…
Reference in New Issue
Block a user