diff --git a/data/css/ancestortree.css b/data/css/ancestortree.css index 5e6ff1d0e..9b53b54d8 100644 --- a/data/css/ancestortree.css +++ b/data/css/ancestortree.css @@ -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; diff --git a/data/tests/imp_sample.gramps b/data/tests/imp_sample.gramps index 9f4b108e0..7f2c7a260 100644 --- a/data/tests/imp_sample.gramps +++ b/data/tests/imp_sample.gramps @@ -919,7 +919,7 @@ - U + X Magnes Smith diff --git a/gramps/gen/config.py b/gramps/gen/config.py index 49924111c..882d1d1a2 100644 --- a/gramps/gen/config.py +++ b/gramps/gen/config.py @@ -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']) diff --git a/gramps/gen/filters/rules/person/__init__.py b/gramps/gen/filters/rules/person/__init__.py index 14da55bd7..7812cec52 100644 --- a/gramps/gen/filters/rules/person/__init__.py +++ b/gramps/gen/filters/rules/person/__init__.py @@ -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, diff --git a/gramps/gen/filters/rules/person/_hasothergender.py b/gramps/gen/filters/rules/person/_hasothergender.py new file mode 100644 index 000000000..eba966bf0 --- /dev/null +++ b/gramps/gen/filters/rules/person/_hasothergender.py @@ -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 diff --git a/gramps/gen/lib/genderstats.py b/gramps/gen/lib/genderstats.py index 0b4bc3ed7..271c922e8 100644 --- a/gramps/gen/lib/genderstats.py +++ b/gramps/gen/lib/genderstats.py @@ -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 diff --git a/gramps/gen/lib/person.py b/gramps/gen/lib/person.py index 00ec9462d..4c9c2d5d2 100644 --- a/gramps/gen/lib/person.py +++ b/gramps/gen/lib/person.py @@ -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 """ diff --git a/gramps/gen/plug/docgen/treedoc.py b/gramps/gen/plug/docgen/treedoc.py index 354a73eb3..2fe8d4a53 100644 --- a/gramps/gen/plug/docgen/treedoc.py +++ b/gramps/gen/plug/docgen/treedoc.py @@ -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() diff --git a/gramps/gen/utils/string.py b/gramps/gen/utils/string.py index b75155975..16b9e72fc 100644 --- a/gramps/gen/utils/string.py +++ b/gramps/gen/utils/string.py @@ -46,6 +46,7 @@ gender = { Person.MALE : _("male"), Person.FEMALE : _("female"), Person.UNKNOWN : _("unknown", "gender"), + Person.OTHER : _("other", "gender"), } def format_gender(type): diff --git a/gramps/gen/utils/symbols.py b/gramps/gen/utils/symbols.py index 8631cafc8..4fc0907ef 100644 --- a/gramps/gen/utils/symbols.py +++ b/gramps/gen/utils/symbols.py @@ -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', ""), diff --git a/gramps/gen/utils/unknown.py b/gramps/gen/utils/unknown.py index bf326475f..0753338d2 100644 --- a/gramps/gen/utils/unknown.py +++ b/gramps/gen/utils/unknown.py @@ -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: diff --git a/gramps/gui/configure.py b/gramps/gui/configure.py index 4d7c13c18..8f660df4b 100644 --- a/gramps/gui/configure.py +++ b/gramps/gui/configure.py @@ -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 diff --git a/gramps/gui/editors/editperson.py b/gramps/gui/editors/editperson.py index 81daa1254..8a2a06258 100644 --- a/gramps/gui/editors/editperson.py +++ b/gramps/gui/editors/editperson.py @@ -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) diff --git a/gramps/gui/filters/sidebar/_personsidebarfilter.py b/gramps/gui/filters/sidebar/_personsidebarfilter.py index 7d11fdc85..8b97b991a 100644 --- a/gramps/gui/filters/sidebar/_personsidebarfilter.py +++ b/gramps/gui/filters/sidebar/_personsidebarfilter.py @@ -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([])) diff --git a/gramps/gui/merge/mergeperson.py b/gramps/gui/merge/mergeperson.py index 8927f6065..42850ea33 100644 --- a/gramps/gui/merge/mergeperson.py +++ b/gramps/gui/merge/mergeperson.py @@ -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.""" diff --git a/gramps/gui/utils.py b/gramps/gui/utils.py index cf661ecb8..3d2231d2c 100644 --- a/gramps/gui/utils.py +++ b/gramps/gui/utils.py @@ -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], diff --git a/gramps/gui/views/treemodels/peoplemodel.py b/gramps/gui/views/treemodels/peoplemodel.py index e2c70c2ff..6fb3bed15 100644 --- a/gramps/gui/views/treemodels/peoplemodel.py +++ b/gramps/gui/views/treemodels/peoplemodel.py @@ -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): """ diff --git a/gramps/gui/widgets/fanchart.py b/gramps/gui/widgets/fanchart.py index 83fedab4b..30dc9e490 100644 --- a/gramps/gui/widgets/fanchart.py +++ b/gramps/gui/widgets/fanchart.py @@ -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): diff --git a/gramps/plugins/db/dbapi/test/db_test.py b/gramps/plugins/db/dbapi/test/db_test.py index 7204a046c..01db47304 100644 --- a/gramps/plugins/db/dbapi/test/db_test.py +++ b/gramps/plugins/db/dbapi/test/db_test.py @@ -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__": diff --git a/gramps/plugins/drawreport/statisticschart.py b/gramps/plugins/drawreport/statisticschart.py index 794314d6a..c5831cdee 100644 --- a/gramps/plugins/drawreport/statisticschart.py +++ b/gramps/plugins/drawreport/statisticschart.py @@ -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 diff --git a/gramps/plugins/export/exportcsv.py b/gramps/plugins/export/exportcsv.py index b8f5cb26e..50aa746a9 100644 --- a/gramps/plugins/export/exportcsv.py +++ b/gramps/plugins/export/exportcsv.py @@ -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: diff --git a/gramps/plugins/export/exportgedcom.py b/gramps/plugins/export/exportgedcom.py index 21b92c4ea..933c4d592 100644 --- a/gramps/plugins/export/exportgedcom.py +++ b/gramps/plugins/export/exportgedcom.py @@ -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): """ diff --git a/gramps/plugins/export/exportvcard.py b/gramps/plugins/export/exportvcard.py index ee62ea30b..cda6236a5 100644 --- a/gramps/plugins/export/exportvcard.py +++ b/gramps/plugins/export/exportvcard.py @@ -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)) diff --git a/gramps/plugins/export/exportxml.py b/gramps/plugins/export/exportxml.py index fac655b08..08830e5ea 100644 --- a/gramps/plugins/export/exportxml.py +++ b/gramps/plugins/export/exportxml.py @@ -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) diff --git a/gramps/plugins/gramplet/statsgramplet.py b/gramps/plugins/gramplet/statsgramplet.py index baa4e6ab9..251c01cf3 100644 --- a/gramps/plugins/gramplet/statsgramplet.py +++ b/gramps/plugins/gramplet/statsgramplet.py @@ -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) diff --git a/gramps/plugins/graph/gvfamilylines.py b/gramps/plugins/graph/gvfamilylines.py index 9215135a4..b64a80ffd 100644 --- a/gramps/plugins/graph/gvfamilylines.py +++ b/gramps/plugins/graph/gvfamilylines.py @@ -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() diff --git a/gramps/plugins/graph/gvhourglass.py b/gramps/plugins/graph/gvhourglass.py index 370246666..3656f62ff 100644 --- a/gramps/plugins/graph/gvhourglass.py +++ b/gramps/plugins/graph/gvhourglass.py @@ -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.')) diff --git a/gramps/plugins/graph/gvrelgraph.py b/gramps/plugins/graph/gvrelgraph.py index 71457a33a..9c1f40171 100644 --- a/gramps/plugins/graph/gvrelgraph.py +++ b/gramps/plugins/graph/gvrelgraph.py @@ -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.') diff --git a/gramps/plugins/importer/importcsv.py b/gramps/plugins/importer/importcsv.py index 957287385..61101a7be 100644 --- a/gramps/plugins/importer/importcsv.py +++ b/gramps/plugins/importer/importcsv.py @@ -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) diff --git a/gramps/plugins/importer/importvcard.py b/gramps/plugins/importer/importvcard.py index 375bb30f2..8e3d3c2fd 100644 --- a/gramps/plugins/importer/importvcard.py +++ b/gramps/plugins/importer/importvcard.py @@ -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) diff --git a/gramps/plugins/importer/importxml.py b/gramps/plugins/importer/importxml.py index f135c357b..0f5e5fe2d 100644 --- a/gramps/plugins/importer/importxml.py +++ b/gramps/plugins/importer/importxml.py @@ -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) diff --git a/gramps/plugins/lib/libgedcom.py b/gramps/plugins/lib/libgedcom.py index d180dce1a..eda0e6ac5 100644 --- a/gramps/plugins/lib/libgedcom.py +++ b/gramps/plugins/lib/libgedcom.py @@ -597,6 +597,7 @@ QUALITY_MAP = { SEX_MAP = { 'F' : Person.FEMALE, 'M' : Person.MALE, + 'X' : Person.OTHER, } FAMILYCONSTANTEVENTS = { diff --git a/gramps/plugins/lib/libnarrate.py b/gramps/plugins/lib/libnarrate.py index 33a593ed0..04ea28468 100644 --- a/gramps/plugins/lib/libnarrate.py +++ b/gramps/plugins/lib/libnarrate.py @@ -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. diff --git a/gramps/plugins/quickview/filterbyname.py b/gramps/plugins/quickview/filterbyname.py index 34ddb04c9..53ea9c3da 100644 --- a/gramps/plugins/quickview/filterbyname.py +++ b/gramps/plugins/quickview/filterbyname.py @@ -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 diff --git a/gramps/plugins/test/tools_test.py b/gramps/plugins/test/tools_test.py index 9d915eaf7..80e6cf346 100644 --- a/gramps/plugins/test/tools_test.py +++ b/gramps/plugins/test/tools_test.py @@ -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", diff --git a/gramps/plugins/textreport/familygroup.py b/gramps/plugins/textreport/familygroup.py index a42cc8d38..26b8ff242 100644 --- a/gramps/plugins/textreport/familygroup.py +++ b/gramps/plugins/textreport/familygroup.py @@ -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() diff --git a/gramps/plugins/textreport/indivcomplete.py b/gramps/plugins/textreport/indivcomplete.py index 6fe889139..abe256fa6 100644 --- a/gramps/plugins/textreport/indivcomplete.py +++ b/gramps/plugins/textreport/indivcomplete.py @@ -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) diff --git a/gramps/plugins/textreport/summary.py b/gramps/plugins/textreport/summary.py index 0f0f56834..74b5175c9 100644 --- a/gramps/plugins/textreport/summary.py +++ b/gramps/plugins/textreport/summary.py @@ -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) diff --git a/gramps/plugins/tool/testcasegenerator.py b/gramps/plugins/tool/testcasegenerator.py index 103c2db7a..123b8e203 100644 --- a/gramps/plugins/tool/testcasegenerator.py +++ b/gramps/plugins/tool/testcasegenerator.py @@ -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) diff --git a/gramps/plugins/tool/verify.py b/gramps/plugins/tool/verify.py index adcea2bf2..848c6a81f 100644 --- a/gramps/plugins/tool/verify.py +++ b/gramps/plugins/tool/verify.py @@ -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 """ diff --git a/gramps/plugins/webreport/person.py b/gramps/plugins/webreport/person.py index ed82d80bc..44dce57bc 100644 --- a/gramps/plugins/webreport/person.py +++ b/gramps/plugins/webreport/person.py @@ -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" diff --git a/gramps/plugins/webreport/statistics.py b/gramps/plugins/webreport/statistics.py index 250361db6..a3e4eaf35 100644 --- a/gramps/plugins/webreport/statistics.py +++ b/gramps/plugins/webreport/statistics.py @@ -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 = " :
" + 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) diff --git a/images/webstuff/Web_Gender_Other.png b/images/webstuff/Web_Gender_Other.png new file mode 100644 index 000000000..0f48038b5 Binary files /dev/null and b/images/webstuff/Web_Gender_Other.png differ diff --git a/po/POTFILES.in b/po/POTFILES.in index dc945c5a1..c7d642da5 100755 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -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