Add new gender option of "Other"

This commit is contained in:
Nick Hall 2022-10-23 20:53:51 +01:00
parent b33c94a0d2
commit 06446a4ba9
44 changed files with 227 additions and 39 deletions

View File

@ -180,6 +180,10 @@ Females Web_Gender_Female.png
#treeContainer div.female span.unlinked {
background:url(../images/Web_Gender_Female.png) #FFC0CB no-repeat top right;
}
#treeContainer div.other a,
#treeContainer div.other span.unlinked {
background:url(../images/Web_Gender_Other.png) #94EF9E no-repeat top right;
}
#treeContainer div.unknown a,
#treeContainer div.unknown span.unlinked {
background-color: #000;

View File

@ -919,7 +919,7 @@
<childof hlink="_0000001d0000001d"/>
</person>
<person handle="_0000007f0000007f" change="1198222526" id="I0003">
<gender>U</gender>
<gender>X</gender>
<name type="Birth Name">
<first>Magnes</first>
<surname>Smith</surname>

View File

@ -289,6 +289,8 @@ register('colors.male-alive', ['#b8cee6', '#1f344a'])
register('colors.male-dead', ['#b8cee6', '#2d3039'])
register('colors.female-alive', ['#feccf0', '#62242D'])
register('colors.female-dead', ['#feccf0', '#3a292b'])
register('colors.other-alive', ['#94ef9e', '#285b27'])
register('colors.other-dead', ['#94ef9e', '#062304'])
register('colors.unknown-alive', ['#f3dbb6', '#75507B'])
register('colors.unknown-dead', ['#f3dbb6', '#35103b'])
register('colors.family', ['#eeeeee', '#454545'])
@ -302,6 +304,8 @@ register('colors.border-male-alive', ['#1f4986', '#171d26'])
register('colors.border-male-dead', ['#000000', '#000000'])
register('colors.border-female-alive', ['#861f69', '#261111'])
register('colors.border-female-dead', ['#000000', '#000000'])
register('colors.border-other-alive', ['#2a5f16', '#26a269'])
register('colors.border-other-dead', ['#000000', '#000000'])
register('colors.border-unknown-alive', ['#8e5801', '#8e5801'])
register('colors.border-unknown-dead', ['#000000', '#000000'])
register('colors.border-family', ['#cccccc', '#252525'])

View File

@ -51,6 +51,7 @@ from ._hasnickname import HasNickname
from ._hasnote import HasNote
from ._hasnotematchingsubstringof import HasNoteMatchingSubstringOf
from ._hasnoteregexp import HasNoteRegexp
from ._hasothergender import HasOtherGender
from ._hasrelationship import HasRelationship
from ._hassourcecount import HasSourceCount
from ._hassourceof import HasSourceOf
@ -120,8 +121,9 @@ from ._hassoundexname import HasSoundexName
editor_rule_list = [
Everyone,
IsFemale,
HasUnknownGender,
IsMale,
HasOtherGender,
HasUnknownGender,
IsDefaultPerson,
IsBookmarked,
HasAlternateName,

View File

@ -0,0 +1,50 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2002-2006 Donald N. Allingham
#
# 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.
#
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
from ....const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from .. import Rule
from ....lib.person import Person
#-------------------------------------------------------------------------
#
# HasOtherGender
#
#-------------------------------------------------------------------------
class HasOtherGender(Rule):
"""Rule that checks for a person that has other gender"""
name = _('People who are neither male nor female')
category = _('General filters')
description = _('Matches all people with other gender')
def apply(self, db, person):
return person.gender == Person.OTHER

View File

@ -98,7 +98,7 @@ class GenderStats:
female += increment
if female < 0:
female = 0
elif gender == Person.UNKNOWN:
elif gender in (Person.UNKNOWN, Person.OTHER):
unknown += increment
if unknown < 0:
unknown = 0

View File

@ -73,6 +73,7 @@ class Person(CitationBase, NoteBase, AttributeBase, MediaBase,
"""
OTHER = 3
UNKNOWN = 2
MALE = 1
FEMALE = 0
@ -644,10 +645,12 @@ class Person(CitationBase, NoteBase, AttributeBase, MediaBase,
- Person.MALE
- Person.FEMALE
- Person.OTHER
- Person.UNKNOWN
:type gender: int
"""
if gender not in (Person.MALE, Person.FEMALE, Person.UNKNOWN):
if gender not in (Person.MALE, Person.FEMALE, Person.OTHER,
Person.UNKNOWN):
raise ValueError('Attempt to assign invalid gender')
self.__gender = gender
@ -659,6 +662,7 @@ class Person(CitationBase, NoteBase, AttributeBase, MediaBase,
- Person.MALE
- Person.FEMALE
- Person.OTHER
- Person.UNKNOWN
:rtype: int
"""

View File

@ -434,7 +434,7 @@ class TreeDocBase(BaseDoc, TreeDoc):
self.write(level+1, 'male,\n')
elif person.gender == Person.FEMALE:
self.write(level+1, 'female,\n')
elif person.gender == Person.UNKNOWN:
elif person.gender in (Person.UNKNOWN, Person.OTHER):
self.write(level+1, 'neuter,\n')
name = person.get_primary_name()
nick = name.get_nick_name()

View File

@ -46,6 +46,7 @@ gender = {
Person.MALE : _("male"),
Person.FEMALE : _("female"),
Person.UNKNOWN : _("unknown", "gender"),
Person.OTHER : _("other", "gender"),
}
def format_gender(type):

View File

@ -83,10 +83,10 @@ class Symbols(object):
(_("Female"), '\u2640', ""),
(_("Male"), '\u2642', ""),
(_("Asexuality, sexless, genderless"), '\u26aa', ""),
(_("Transgender, hermaphrodite (in entomology)"), '\u26a5', ""),
(_("Lesbianism"), '\u26a2', ""),
(_("Male homosexuality"), '\u26a3', ""),
(_("Heterosexuality"), '\u26a4', ""),
(_("Transgender, hermaphrodite (in entomology)"), '\u26a5', ""),
(_("Transgender"), '\u26a6', ""),
(_("Neuter"), '\u26b2', ""),
(_("Illegitimate"), '\u229b', ""),

View File

@ -181,7 +181,7 @@ def add_personref_to_family(family, person):
(family.get_mother_handle() is None)):
family.set_mother_handle(person_handle)
else:
# This includes cases of Person.UNKNOWN
# This includes cases of Person.UNKNOWN and Person.OTHER
if family.get_father_handle() is None:
family.set_father_handle(person_handle)
else:

View File

@ -720,9 +720,10 @@ class GrampsPreferences(ConfigureDialog):
color_type = {'Male': _('Colors for Male persons'),
'Female': _('Colors for Female persons'),
'Other': _('Colors for people who are neither male nor female'),
'Unknown': _('Colors for Unknown persons'),
'Family': _('Colors for Family nodes'),
'Other': _('Other colors')}
'Misc': _('Other colors')}
bg_alive_text = _('Background for Alive')
bg_dead_text = _('Background for Dead')
@ -741,6 +742,11 @@ class GrampsPreferences(ConfigureDialog):
(bg_dead_text, 'female-dead', 2, 1, 'Female'),
(brd_alive_text, 'border-female-alive', 1, 4, 'Female'),
(brd_dead_text, 'border-female-dead', 2, 4, 'Female'),
# for other
(bg_alive_text, 'other-alive', 1, 1, 'Other'),
(bg_dead_text, 'other-dead', 2, 1, 'Other'),
(brd_alive_text, 'border-other-alive', 1, 4, 'Other'),
(brd_dead_text, 'border-other-dead', 2, 4, 'Other'),
# for unknown
(bg_alive_text, 'unknown-alive', 1, 1, 'Unknown'),
(bg_dead_text, 'unknown-dead', 2, 1, 'Unknown'),
@ -759,7 +765,7 @@ class GrampsPreferences(ConfigureDialog):
(_('Border for Divorced'),
'border-family-divorced', 7, 4, 'Family'),
# for other
(_('Background for Home Person'), 'home-person', 1, 1, 'Other'),
(_('Background for Home Person'), 'home-person', 1, 1, 'Misc'),
]
# prepare scrolled window for colors settings

View File

@ -339,7 +339,8 @@ class EditPerson(EditPrimary):
(
(_('female'), Person.FEMALE),
(_('male'), Person.MALE),
(_('unknown'), Person.UNKNOWN)
(_('unknown', 'gender'), Person.UNKNOWN),
(_('other', 'gender'), Person.OTHER)
),
self.db.readonly)
@ -1110,4 +1111,5 @@ class GenderDialog(Gtk.MessageDialog):
self.add_button(_('_Male'), Person.MALE)
self.add_button(_('_Female'), Person.FEMALE)
self.add_button(_('_Other'), Person.OTHER)
self.add_button(_('_Unknown'), Person.UNKNOWN)

View File

@ -49,7 +49,7 @@ from gramps.gen.filters.rules.person import (RegExpName, RegExpIdOf, IsMale,
IsFemale, HasUnknownGender,
HasEvent, HasTag, HasBirth,
HasDeath, HasNoteRegexp,
MatchesFilter)
MatchesFilter, HasOtherGender)
def extract_text(entry_widget):
"""
@ -91,7 +91,8 @@ class PersonSidebarFilter(SidebarFilter):
self.filter_note = widgets.BasicEntry()
self.filter_gender = Gtk.ComboBoxText()
list(map(self.filter_gender.append_text,
[ _('any'), _('male'), _('female'), _('unknown') ]))
[ _('any'), _('male'), _('female'), _('other', 'gender'),
_('unknown', 'gender') ]))
self.filter_gender.set_active(0)
self.filter_regex = Gtk.CheckButton(label=_('Use regular expressions'))
@ -208,6 +209,8 @@ class PersonSidebarFilter(SidebarFilter):
generic_filter.add_rule(IsMale([]))
elif gender == 2:
generic_filter.add_rule(IsFemale([]))
elif gender == 3:
generic_filter.add_rule(HasOtherGender([]))
else:
generic_filter.add_rule(HasUnknownGender([]))

View File

@ -61,7 +61,7 @@ _GLADE_FILE = "mergeperson.glade"
# Translators: needed for French, ignore otherwise
KEYVAL = _("%(key)s:\t%(value)s")
sex = ( _("female"), _("male"), _("unknown") )
sex = ( _("female"), _("male"), _("other"), _("unknown") )
def name_of(person):
"""Return string with name and ID of a person."""

View File

@ -494,6 +494,13 @@ def color_graph_box(alive=False, gender=Person.MALE):
else:
return (config.get('colors.female-dead')[scheme],
config.get('colors.border-female-dead')[scheme])
elif gender == Person.OTHER:
if alive:
return (config.get('colors.other-alive')[scheme],
config.get('colors.border-other-alive')[scheme])
else:
return (config.get('colors.other-dead')[scheme],
config.get('colors.border-other-dead')[scheme])
elif gender == Person.UNKNOWN:
if alive:
return (config.get('colors.unknown-alive')[scheme],

View File

@ -95,7 +95,7 @@ class PeopleBaseModel(BaseModel):
"""
Basic Model interface to handle the PersonViews
"""
_GENDER = [ _('female'), _('male'), _('unknown') ]
_GENDER = [ _('female'), _('male'), _('unknown'), _('other') ]
def __init__(self, db):
"""

View File

@ -483,6 +483,8 @@ class FanChartBaseWidget(Gtk.DrawingArea):
color = self.colors[generation % len(self.colors)]
if person.gender == Person.MALE:
color = [x*.9 for x in color]
elif person.gender == Person.OTHER:
color = [x*.8 for x in color]
# now we set transparency data
if self.filter and not self.filter.match(person.handle,
self.dbstate.db):

View File

@ -832,7 +832,7 @@ class DbPersonTest(unittest.TestCase):
self.__add_person(Person.FEMALE, 'Mary', 'Baker', trans)
self.__add_person(Person.FEMALE, 'Mary', 'Clark', trans)
self.__add_person(Person.MALE, 'Mary', 'Davis', trans)
self.__add_person(Person.FEMALE, 'Mary', 'Evans', trans)
self.__add_person(Person.OTHER, 'Mary', 'Evans', trans)
def tearDown(self):
with DbTxn('Remove test objects', self.db) as trans:
@ -859,11 +859,11 @@ class DbPersonTest(unittest.TestCase):
def test_gender_stats(self):
stats = self.db.genderStats
self.assertEqual(stats.name_stats('John'), (3, 1, 1))
self.assertEqual(stats.name_stats('Mary'), (1, 4, 0))
self.assertEqual(stats.name_stats('Mary'), (1, 3, 1))
self.db.save_gender_stats(stats)
saved = self.db.get_gender_stats()
self.assertEqual(saved['John'], (3, 1, 1))
self.assertEqual(saved['Mary'], (1, 4, 0))
self.assertEqual(saved['Mary'], (1, 3, 1))
if __name__ == "__main__":

View File

@ -312,9 +312,10 @@ class _options:
(SORT_KEY, "Item name", _("Item name"))
]
opt_genders = [
(Person.UNKNOWN, "Both", _("Both")),
(Person.UNKNOWN, "All", _("All")),
(Person.MALE, "Men", _("Men")),
(Person.FEMALE, "Women", _("Women"))
(Person.FEMALE, "Women", _("Women")),
(Person.OTHER, "Other", _("Other"))
]
@ -419,6 +420,8 @@ class Extract:
return [_T_("Men")]
if person.gender == Person.FEMALE:
return [_T_("Women")]
if person.gender == Person.OTHER:
return [_T_("Other")]
return [_T_("Gender unknown")]
def get_year(self, event):
@ -794,6 +797,8 @@ class StatisticsChart(Report):
genders = self._("Men")
elif gender == Person.FEMALE:
genders = self._("Women")
elif gender == Person.OTHER:
genders = self._("Other")
else:
genders = None

View File

@ -396,6 +396,8 @@ class CSVWriter:
gender = gender_map[Person.MALE]
elif gender == Person.FEMALE:
gender = gender_map[Person.FEMALE]
elif gender == Person.OTHER:
gender = gender_map[Person.OTHER]
else:
gender = gender_map[Person.UNKNOWN]
# Birth:

View File

@ -512,14 +512,16 @@ class GedcomWriter(UpdateCallback):
Write out the gender of the person to the file.
If the gender is not male or female, simply do not output anything.
The only valid values are M (male) or F (female). So if the geneder is
unknown, we output nothing.
The only valid values are M (male), F (female) and X (other). So if
the gender is unknown, we output nothing.
"""
if person.get_gender() == Person.MALE:
self._writeln(1, "SEX", "M")
elif person.get_gender() == Person.FEMALE:
self._writeln(1, "SEX", "F")
elif person.get_gender() == Person.OTHER:
self._writeln(1, "SEX", "X")
def _lds_ords(self, obj, level):
"""

View File

@ -260,6 +260,8 @@ class VCardWriter:
gender_value = 'Male'
elif gender == Person.FEMALE:
gender_value = 'Female'
elif gender == Person.OTHER:
gender_value = 'Other'
log.info("gender: %s -> %s" % (gender, gender_value))
if gender_value:
self.writeln("X-GENDER:%s" % (gender_value))

View File

@ -521,6 +521,8 @@ class GrampsXmlWriter(UpdateCallback):
self.write_line("gender","M",index+1)
elif person.get_gender() == Person.FEMALE:
self.write_line("gender","F",index+1)
elif person.get_gender() == Person.OTHER:
self.write_line("gender","X",index+1)
else:
self.write_line("gender","U",index+1)
self.dump_name(person.get_primary_name(),False,index+1)

View File

@ -79,6 +79,7 @@ class StatsGramplet(Gramplet):
missing_bday = 0
males = 0
females = 0
others = 0
unknowns = 0
bytes_cnt = 0
notfound = []
@ -132,6 +133,8 @@ class StatsGramplet(Gramplet):
females += 1
elif person.get_gender() == Person.MALE:
males += 1
elif person.get_gender() == Person.OTHER:
others += 1
else:
unknowns += 1
if not cnt % _YIELD_INTERVAL:
@ -149,6 +152,10 @@ class StatsGramplet(Gramplet):
self.link(_("%s:") % _("Females"), 'Filter', 'females')
self.append_text(" %s" % females)
self.append_text("\n")
self.link(_("%s:") % _("Individuals with other gender"),
'Filter', 'people with other gender')
self.append_text(" %s" % others)
self.append_text("\n")
self.link(_("%s:") % _("Individuals with unknown gender"),
'Filter', 'people with unknown gender')
self.append_text(" %s" % unknowns)

View File

@ -292,6 +292,11 @@ class FamilyLinesOptions(MenuReportOptions):
color_females.set_help(_('The color to use to display women.'))
add_option('colorfemales', color_females)
color_other = ColorOption(_('Other'), '#94ef9e')
color_other.set_help(_('The color to use to display people who are '
'neither men nor women.'))
add_option('colorother', color_other)
color_unknown = ColorOption(_('Unknown'), '#e0e0e0')
color_unknown.set_help(_('The color to use '
'when the gender is unknown.'))
@ -378,6 +383,7 @@ class FamilyLinesReport(Report):
self._gidlist = get_value('gidlist')
self._colormales = get_value('colormales')
self._colorfemales = get_value('colorfemales')
self._colorother = get_value('colorother')
self._colorunknown = get_value('colorunknown')
self._colorfamilies = get_value('colorfamilies')
self._limitparents = get_value('limitparents')
@ -806,6 +812,8 @@ class FamilyLinesReport(Report):
colour = self._colormales
elif gender == Person.FEMALE:
colour = self._colorfemales
elif gender == Person.OTHER:
colour = self._colorother
# see if we have surname colours that match this person
surname = person.get_primary_name().get_surname()

View File

@ -112,6 +112,7 @@ class HourGlassReport(Report):
self.colorize = menu.get_option_by_name('color').get_value()
self.colors = {'male': menu.get_option_by_name('colormales').get_value(),
'female': menu.get_option_by_name('colorfemales').get_value(),
'other': menu.get_option_by_name('colorother').get_value(),
'unknown': menu.get_option_by_name('colorunknown').get_value(),
'family': menu.get_option_by_name('colorfamilies').get_value()
}
@ -332,6 +333,8 @@ class HourGlassReport(Report):
color = self.colors['male']
elif gender == person.FEMALE:
color = self.colors['female']
elif gender == person.OTHER:
color = self.colors['other']
else:
color = self.colors['unknown']
elif self.colorize == 'filled':
@ -340,6 +343,8 @@ class HourGlassReport(Report):
fill = self.colors['male']
elif gender == person.FEMALE:
fill = self.colors['female']
elif gender == person.OTHER:
fill = self.colors['other']
else:
fill = self.colors['unknown']
return(shape, style, color, fill)
@ -426,6 +431,11 @@ class HourGlassOptions(MenuReportOptions):
color_females.set_help(_('The color to use to display women.'))
menu.add_option(category_name, 'colorfemales', color_females)
color_other = ColorOption(_('Other'), '#94ef9e')
color_other.set_help(_('The color to use to display people who are '
'neither men nor women.'))
menu.add_option(category_name, 'colorother', color_other)
color_unknown = ColorOption(_('Unknown'), '#e0e0e0')
color_unknown.set_help(_('The color to use '
'when the gender is unknown.'))

View File

@ -156,11 +156,13 @@ class RelGraphReport(Report):
self.colorize = get_value('color')
color_males = get_value('colormales')
color_females = get_value('colorfemales')
color_other = get_value('colorother')
color_unknown = get_value('colorunknown')
color_families = get_value('colorfamilies')
self.colors = {
'male': color_males,
'female': color_females,
'other': color_other,
'unknown': color_unknown,
'family': color_families
}
@ -558,6 +560,8 @@ class RelGraphReport(Report):
color = self.colors['male']
elif gender == person.FEMALE:
color = self.colors['female']
elif gender == person.OTHER:
color = self.colors['other']
else:
color = self.colors['unknown']
elif self.colorize == 'filled':
@ -566,6 +570,8 @@ class RelGraphReport(Report):
fill = self.colors['male']
elif gender == person.FEMALE:
fill = self.colors['female']
elif gender == person.OTHER:
fill = self.colors['other']
else:
fill = self.colors['unknown']
return(shape, style, color, fill)
@ -949,6 +955,11 @@ class RelGraphOptions(MenuReportOptions):
color_females.set_help(_('The color to use to display women.'))
add_option('colorfemales', color_females)
color_other = ColorOption(_('Other'), '#94ef9e')
color_other.set_help(_('The color to use to display people who are '
'neither men nor women.'))
add_option('colorother', color_other)
color_unknown = ColorOption(_('Unknown'), '#e0e0e0')
color_unknown.set_help(
_('The color to use when the gender is unknown.')

View File

@ -571,6 +571,8 @@ class CSVParser:
gender = Person.MALE
elif gender == gender_map[Person.FEMALE].lower():
gender = Person.FEMALE
elif gender == gender_map[Person.OTHER].lower():
gender = Person.OTHER
else:
gender = Person.UNKNOWN
child.set_gender(gender)
@ -720,6 +722,8 @@ class CSVParser:
gender = Person.MALE
elif gender == gender_map[Person.FEMALE].lower():
gender = Person.FEMALE
elif gender == gender_map[Person.OTHER].lower():
gender = Person.OTHER
else:
gender = Person.UNKNOWN
person.set_gender(gender)

View File

@ -577,6 +577,8 @@ class VCardParser:
gender = Person.MALE
elif gender_value == 'F':
gender = Person.FEMALE
elif gender_value == 'O':
gender = Person.OTHER
else:
return
self.person.set_gender(gender)

View File

@ -2848,6 +2848,8 @@ class GrampsParser(UpdateCallback):
self.person.set_gender (Person.MALE)
elif t == "F":
self.person.set_gender (Person.FEMALE)
elif t == "X":
self.person.set_gender (Person.OTHER)
else:
self.person.set_gender (Person.UNKNOWN)

View File

@ -597,6 +597,7 @@ QUALITY_MAP = {
SEX_MAP = {
'F' : Person.FEMALE,
'M' : Person.MALE,
'X' : Person.OTHER,
}
FAMILYCONSTANTEVENTS = {

View File

@ -1474,7 +1474,7 @@ class Narrator:
'modified_date' : bdate,
}
gender = self.__person.get_gender()
gender = self.__get_gender()
if bdate:
if bdate_mod:
@ -1591,7 +1591,7 @@ class Narrator:
'month_year' : ddate,
}
gender = self.__person.get_gender()
gender = self.__get_gender()
if ddate and ddate_mod:
if dplace and self.__verbose:
@ -1661,7 +1661,7 @@ class Narrator:
else:
name_index = _NAME_INDEX_EXCLUDE_NAME
gender = self.__person.get_gender()
gender = self.__get_gender()
text = ""
@ -1772,7 +1772,7 @@ class Narrator:
else:
name_index = _NAME_INDEX_EXCLUDE_NAME
gender = self.__person.get_gender()
gender = self.__get_gender()
text = ""
@ -1883,7 +1883,7 @@ class Narrator:
else:
name_index = _NAME_INDEX_EXCLUDE_NAME
gender = self.__person.get_gender()
gender = self.__get_gender()
text = ""
@ -2045,7 +2045,7 @@ class Narrator:
elif dobj and dobj.get_day_valid():
date_full = 1
gender = self.__person.get_gender()
gender = self.__get_gender()
# This would be much simpler, excepting for translation considerations
# Currently support FamilyRelType's:
@ -2214,7 +2214,7 @@ class Narrator:
else:
index = _NAME_INDEX_EXCLUDE_NAME
gender = self.__person.get_gender()
gender = self.__get_gender()
text = ""
if mother_name and father_name and self.__verbose:
@ -2236,6 +2236,15 @@ class Narrator:
return text
def __get_gender(self):
"""
Return a gender to be used for translations.
"""
gender = self.__person.get_gender()
if gender == Person.OTHER:
gender = Person.UNKNOWN
return gender
def __get_age_at_death(self):
"""
Calculate the age the person died.

View File

@ -57,6 +57,8 @@ fname_map = {'all': _('all', 'Filtering_on'),
'all notes': _('all notes', 'Filtering_on'),
'males': _('males', 'Filtering_on'),
'females': _('females', 'Filtering_on'),
'people with other gender':
_('people with other gender', 'Filtering_on'),
'people with unknown gender':
_('people with unknown gender', 'Filtering_on'),
'incomplete names':
@ -294,10 +296,18 @@ def run(database, document, filter_name, *args, **kwargs):
str(person.get_primary_name().get_type()))
matches += 1
elif (filter_name == 'people with other gender'):
stab.columns(_("Person"), _("Birth Date"), _("Name type"))
for person in database.iter_people():
if person.gender == Person.OTHER:
stab.row(person, sdb.birth_or_fallback(person),
str(person.get_primary_name().get_type()))
matches += 1
elif (filter_name == 'people with unknown gender'):
stab.columns(_("Person"), _("Birth Date"), _("Name type"))
for person in database.iter_people():
if person.gender not in [Person.FEMALE, Person.MALE]:
if person.gender == Person.UNKNOWN:
stab.row(person, sdb.birth_or_fallback(person),
str(person.get_primary_name().get_type()))
matches += 1

View File

@ -145,8 +145,8 @@ class ToolControl(unittest.TestCase):
"1 invalid birth event name was fixed",
"1 invalid death event name was fixed",
"2 places were referenced, but not found",
"10 citations were referenced, but not found",
"13 sources were referenced, but not found",
"14 citations were referenced, but not found",
"17 sources were referenced, but not found",
"9 Duplicated Gramps IDs fixed",
"7 empty objects removed",
"1 person objects",

View File

@ -503,6 +503,8 @@ class FamilyGroup(Report):
self.doc.write_text(index_str + self._("M", "acronym for male"))
elif person.get_gender() == Person.FEMALE:
self.doc.write_text(index_str + self._("F", "acronym for female"))
elif person.get_gender() == Person.OTHER:
self.doc.write_text(index_str + self._("X", "acronym for other"))
else:
self.doc.write_text(self._("%dU", "acronym for unknown") % index)
self.doc.end_paragraph()

View File

@ -942,6 +942,8 @@ class IndivCompleteReport(Report):
self.write_paragraph(self._("Male"))
elif self.person.get_gender() == Person.FEMALE:
self.write_paragraph(self._("Female"))
elif self.person.get_gender() == Person.OTHER:
self.write_paragraph(self._("Other"))
else:
self.write_paragraph(self._("Unknown"))
self.write_paragraph(father, mark=fmark)

View File

@ -112,6 +112,7 @@ class SummaryReport(Report):
missing_bday = 0
males = 0
females = 0
others = 0
unknowns = 0
namelist = []
@ -160,6 +161,8 @@ class SummaryReport(Report):
females += 1
elif person.get_gender() == Person.MALE:
males += 1
elif person.get_gender() == Person.OTHER:
others += 1
else:
unknowns += 1
@ -181,6 +184,11 @@ class SummaryReport(Report):
self.doc.write_text(self._("Females: %d") % females)
self.doc.end_paragraph()
self.doc.start_paragraph("SR-Normal")
self.doc.write_text(self._("Individuals with other gender: %d"
) % others)
self.doc.end_paragraph()
self.doc.start_paragraph("SR-Normal")
self.doc.write_text(self._("Individuals with unknown gender: %d"
) % unknowns)

View File

@ -1364,8 +1364,11 @@ class TestcaseGenerator(tool.BatchTool):
# Gender
if gender is None:
gender = _randint(0, 1)
if _randint(0, 10) == 1: # Set some persons to unknown gender
pers.set_gender(Person.UNKNOWN)
if _randint(0, 10) == 1: # Set some persons to unknown and other gender
if _randint(0, 1) == 0:
pers.set_gender(Person.OTHER)
else:
pers.set_gender(Person.UNKNOWN)
else:
pers.set_gender(gender)

View File

@ -1057,9 +1057,7 @@ class UnknownGender(PersonRule):
SEVERITY = Rule.WARNING
def broken(self):
""" return boolean indicating whether this rule is violated """
female = self.obj.get_gender() == Person.FEMALE
male = self.obj.get_gender() == Person.MALE
return not (male or female)
return self.obj.get_gender() == Person.UNKNOWN
def get_message(self):
""" return the rule's error message """

View File

@ -481,6 +481,7 @@ class PersonPages(BasePage):
self.gender_map = {
Person.MALE : self._('male'),
Person.FEMALE : self._('female'),
Person.OTHER : self._('other'),
Person.UNKNOWN : self._('unknown'),
}
@ -1151,6 +1152,8 @@ class PersonPages(BasePage):
divclass = "male"
elif sex == Person.FEMALE:
divclass = "female"
elif sex == Person.OTHER:
divclass = "other"
else:
divclass = "unknown"

View File

@ -87,6 +87,7 @@ class StatisticsPage(BasePage):
addressbookpage, dummy_head, dummy_body, outerwrapper = result
(males,
females,
others,
unknown) = self.get_gender(report.database.iter_person_handles())
step()
@ -125,6 +126,8 @@ class StatisticsPage(BasePage):
"%d" % males, inline=True)
sec1 += Html("br", self._("Females") + self.colon +
"%d" % females, inline=True)
sec1 += Html("br", self._("Individuals with other gender") +
self.colon + "%d" % others, inline=True)
sec1 += Html("br", self._("Individuals with unknown gender") +
self.colon + "%d" % unknown, inline=True)
outerwrapper += sec1
@ -173,6 +176,7 @@ class StatisticsPage(BasePage):
(males,
females,
others,
unknown) = self.get_gender(self.report.bkref_dict[Person].keys())
origin = " :<br/>" + report.filter.get_name(self.rlocale)
@ -190,6 +194,8 @@ class StatisticsPage(BasePage):
"%d" % males, inline=True)
sec5 += Html("br", self._("Females") + self.colon +
"%d" % females, inline=True)
sec5 += Html("br", self._("Individuals with other gender") +
self.colon + "%d" % others, inline=True)
sec5 += Html("br", self._("Individuals with unknown gender") +
self.colon + "%d" % unknown, inline=True)
outerwrapper += sec5
@ -229,13 +235,14 @@ class StatisticsPage(BasePage):
def get_gender(self, person_list):
"""
This function return the number of males, females and unknown gender
from a person list.
This function return the number of males, females, others and unknown
gender from a person list.
@param: person_list -- The list to process
"""
males = 0
females = 0
others = 0
unknown = 0
for person_handle in person_list:
person = self.report.database.get_person_from_handle(person_handle)
@ -244,6 +251,8 @@ class StatisticsPage(BasePage):
males += 1
elif gender == Person.FEMALE:
females += 1
elif gender == Person.OTHER:
others += 1
else:
unknown += 1
return (males, females, unknown)
return (males, females, others, unknown)

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

View File

@ -181,6 +181,7 @@ gramps/gen/filters/rules/person/_hasnickname.py
gramps/gen/filters/rules/person/_hasnote.py
gramps/gen/filters/rules/person/_hasnotematchingsubstringof.py
gramps/gen/filters/rules/person/_hasnoteregexp.py
gramps/gen/filters/rules/person/_hasothergender.py
gramps/gen/filters/rules/person/_hasrelationship.py
gramps/gen/filters/rules/person/_hassoundexname.py
gramps/gen/filters/rules/person/_hassourcecount.py