2003-06-24 Tim Waugh <twaugh@redhat.com>

* src/GrampsParser.py: Use access methods rather than poking directly.
        * src/RelLib.py: Keep statistics on gender distribution among first
        names so that it can be used for guessing.
        * src/edit_person.glade: More event handlers.
        * src/EditPerson.py: Guess gender when appropriate.


svn: r1769
This commit is contained in:
Tim Waugh 2003-06-24 14:16:47 +00:00
parent 261fcfaece
commit c876640eaa
5 changed files with 125 additions and 4 deletions

View File

@ -1,3 +1,10 @@
2003-06-24 Tim Waugh <twaugh@redhat.com>
* src/GrampsParser.py: Use access methods rather than poking directly.
* src/RelLib.py: Keep statistics on gender distribution among first
names so that it can be used for guessing.
* src/edit_person.glade: More event handlers.
* src/EditPerson.py: Guess gender when appropriate.
2003-06-23 Tim Waugh <twaugh@redhat.com> 2003-06-23 Tim Waugh <twaugh@redhat.com>
* src/NoteEdit.py: Use automatic scrolling policy, to fix scrolling. * src/NoteEdit.py: Use automatic scrolling policy, to fix scrolling.

View File

@ -86,6 +86,7 @@ class EditPerson:
self.update_death = 0 self.update_death = 0
self.pdmap = {} self.pdmap = {}
self.add_places = [] self.add_places = []
self.should_guess_gender = (self.original_id == '')
for key in db.getPlaceKeys(): for key in db.getPlaceKeys():
p = db.getPlaceDisplay(key) p = db.getPlaceDisplay(key)
@ -318,6 +319,8 @@ class EditPerson:
"on_update_attr_clicked" : self.on_update_attr_clicked, "on_update_attr_clicked" : self.on_update_attr_clicked,
"on_update_url_clicked" : self.on_update_url_clicked, "on_update_url_clicked" : self.on_update_url_clicked,
"on_web_go_clicked" : self.on_web_go_clicked, "on_web_go_clicked" : self.on_web_go_clicked,
"on_gender_activate" : self.on_gender_activate,
"on_givenName_focus_out_event": self.on_givenName_focus_out_event,
}) })
self.update_birth_death() self.update_birth_death()
@ -438,6 +441,21 @@ class EditPerson:
self.build_seal_menu() self.build_seal_menu()
self.build_endow_menu() self.build_endow_menu()
def on_gender_activate (self, button):
self.should_guess_gender = 0
def on_givenName_focus_out_event (self, entry, event):
if not self.should_guess_gender:
return
gender = self.db.genderStats.guess_gender (entry.get_text ())
if gender == RelLib.Person.unknown:
self.is_unknown.set_active (1)
elif gender == RelLib.Person.male:
self.is_male.set_active (1)
else:
self.is_female.set_active (1)
def build_menu(self,list,task,opt_menu): def build_menu(self,list,task,opt_menu):
menu = gtk.Menu() menu = gtk.Menu()
index = 0 index = 0

View File

@ -617,9 +617,9 @@ class GrampsParser:
self.event = None self.event = None
def stop_name(self,tag): def stop_name(self,tag):
self.person.PrimaryName = self.name
if self.name.getType() == "": if self.name.getType() == "":
self.name.setType("Birth Name") self.name.setType("Birth Name")
self.person.setPrimaryName (self.name)
self.name = None self.name = None
def stop_place(self,tag): def stop_place(self,tag):
@ -667,11 +667,11 @@ class GrampsParser:
def stop_gender(self,tag): def stop_gender(self,tag):
t = tag t = tag
if t == "M": if t == "M":
self.person.gender = RelLib.Person.male self.person.setGender (RelLib.Person.male)
elif t == "F": elif t == "F":
self.person.gender = RelLib.Person.female self.person.setGender (RelLib.Person.female)
else: else:
self.person.gender = RelLib.Person.unknown self.person.setGender (RelLib.Person.unknown)
def stop_stitle(self,tag): def stop_stitle(self,tag):
self.source.setTitle(tag) self.source.setTitle(tag)

View File

@ -1016,6 +1016,11 @@ class Person(Persistent):
self.lds_endow = None self.lds_endow = None
self.lds_seal = None self.lds_seal = None
# We hold a reference to the GrampsDB so that we can maintain
# its genderStats. It doesn't get set here, but from
# GenderStats.count_person.
self.db = None
def getDisplayInfo(self): def getDisplayInfo(self):
if self.gender == Person.male: if self.gender == Person.male:
gender = const.male gender = const.male
@ -1033,8 +1038,15 @@ class Person(Persistent):
def setPrimaryName(self,name): def setPrimaryName(self,name):
"""sets the primary name of the Person to the specified """sets the primary name of the Person to the specified
Name instance""" Name instance"""
db = self.db
if db:
db.genderStats.uncount_person (self)
self.PrimaryName = name self.PrimaryName = name
if db:
db.genderStats.count_person (self, db)
def getPrimaryName(self): def getPrimaryName(self):
"""returns the Name instance marked as the Person's primary name""" """returns the Name instance marked as the Person's primary name"""
if not self.PrimaryName: if not self.PrimaryName:
@ -1093,8 +1105,15 @@ class Person(Persistent):
def setGender(self,val) : def setGender(self,val) :
"""sets the gender of the Person""" """sets the gender of the Person"""
db = self.db
if db:
db.genderStats.uncount_person (self)
self.gender = val self.gender = val
if db:
db.genderStats.count_person (self, db)
def getGender(self) : def getGender(self) :
"""returns the gender of the Person""" """returns the gender of the Person"""
return self.gender return self.gender
@ -1937,6 +1956,70 @@ class SourceRef(Persistent):
"""Creates a unique instance of the current note""" """Creates a unique instance of the current note"""
self.comments = Note(self.comments.get()) self.comments = Note(self.comments.get())
class GenderStats:
def __init__ (self):
self.stats = {}
def _get_key (self, person):
name = person.getPrimaryName ().getFirstName ()
return self._get_key_from_name (name)
def _get_key_from_name (self, name):
return name.split (' ')[0].replace ('?', '')
def name_stats (self, name):
if self.stats.has_key (name):
return self.stats[name]
return (0, 0, 0)
def count_person (self, person, db, undo = 0):
# Let the Person do their own counting later
person.db = db
name = self._get_key (person)
if not name:
return
gender = person.getGender ()
(male, female, unknown) = self.name_stats (name)
if not undo:
increment = 1
else:
increment = -1
if gender == Person.male:
male += increment
elif gender == Person.female:
female += increment
elif gender == Person.unknown:
unknown += increment
self.stats[name] = (male, female, unknown)
return
def uncount_person (self, person):
return self.count_person (person, None, undo = 1)
def guess_gender (self, name):
name = self._get_key_from_name (name)
if not name or not self.stats.has_key (name):
return Person.unknown
(male, female, unknown) = self.stats[name]
if unknown == 0:
if male and not female:
return Person.male
if female and not male:
return Person.female
if male > (2 * female):
return Person.male
if female > (2 * male):
return Person.female
return Person.unknown
class GrampsDB(Persistent): class GrampsDB(Persistent):
"""GRAMPS database object. This object is a base class for other """GRAMPS database object. This object is a base class for other
objects.""" objects."""
@ -1958,6 +2041,7 @@ class GrampsDB(Persistent):
self.placeMap = {} self.placeMap = {}
self.new() self.new()
self.added_files = [] self.added_files = []
self.genderStats = GenderStats ()
def get_added_media_objects(self): def get_added_media_objects(self):
return self.added_files return self.added_files
@ -2075,6 +2159,7 @@ class GrampsDB(Persistent):
self.bookmarks = [] self.bookmarks = []
self.path = "" self.path = ""
self.place2title = {} self.place2title = {}
self.genderStats = GenderStats ()
def getSurnames(self): def getSurnames(self):
return self.surnames return self.surnames
@ -2130,6 +2215,7 @@ class GrampsDB(Persistent):
def setPersonMap(self,map): def setPersonMap(self,map):
"""sets the map of gramps's IDs to Person instances""" """sets the map of gramps's IDs to Person instances"""
# Should recalculate self.genderStats here.
self.personMap = map self.personMap = map
def getPlaceMap(self): def getPlaceMap(self):
@ -2219,6 +2305,7 @@ class GrampsDB(Persistent):
return map.keys() return map.keys()
def removePerson(self,id): def removePerson(self,id):
self.genderStats.uncount_person (self.personMap[id])
del self.personMap[id] del self.personMap[id]
del self.personTable[id] del self.personTable[id]
@ -2229,6 +2316,7 @@ class GrampsDB(Persistent):
def addPersonAs(self,person): def addPersonAs(self,person):
self.personMap[person.getId()] = person self.personMap[person.getId()] = person
self.personTable[person.getId()] = person.getDisplayInfo() self.personTable[person.getId()] = person.getDisplayInfo()
self.genderStats.count_person (person, self)
return person.getId() return person.getId()
def addPerson(self,person): def addPerson(self,person):
@ -2241,6 +2329,7 @@ class GrampsDB(Persistent):
self.personMap[index] = person self.personMap[index] = person
self.personTable[index] = person.getDisplayInfo() self.personTable[index] = person.getDisplayInfo()
self.pmapIndex = self.pmapIndex + 1 self.pmapIndex = self.pmapIndex + 1
self.genderStats.count_person (person, self)
return index return index
def findPerson(self,idVal,map): def findPerson(self,idVal,map):
@ -2259,6 +2348,7 @@ class GrampsDB(Persistent):
person = Person() person = Person()
map[idVal] = self.addPerson(person) map[idVal] = self.addPerson(person)
self.personTable[map[idVal]] = person.getDisplayInfo() self.personTable[map[idVal]] = person.getDisplayInfo()
self.genderStats.count_person (person, self)
return person return person
def findPersonNoMap(self,val): def findPersonNoMap(self,val):
@ -2272,6 +2362,7 @@ class GrampsDB(Persistent):
self.personMap[val] = person self.personMap[val] = person
self.pmapIndex = self.pmapIndex+1 self.pmapIndex = self.pmapIndex+1
self.personTable[val] = person.getDisplayInfo() self.personTable[val] = person.getDisplayInfo()
self.genderStats.count_person (person, self)
return person return person
def addPersonNoMap(self,person,id): def addPersonNoMap(self,person,id):
@ -2282,6 +2373,7 @@ class GrampsDB(Persistent):
self.personMap[id] = person self.personMap[id] = person
self.pmapIndex = self.pmapIndex+1 self.pmapIndex = self.pmapIndex+1
self.personTable[id] = person.getDisplayInfo() self.personTable[id] = person.getDisplayInfo()
self.genderStats.count_person (person, self)
return id return id
def addSource(self,source): def addSource(self,source):

View File

@ -438,6 +438,7 @@
<property name="has_frame">True</property> <property name="has_frame">True</property>
<property name="invisible_char" translatable="yes">*</property> <property name="invisible_char" translatable="yes">*</property>
<property name="activates_default">False</property> <property name="activates_default">False</property>
<signal name="focus_out_event" handler="on_givenName_focus_out_event" last_modification_time="Tue, 24 Jun 2003 13:35:15 GMT"/>
</widget> </widget>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">2</property>
@ -723,6 +724,7 @@
<property name="active">False</property> <property name="active">False</property>
<property name="inconsistent">False</property> <property name="inconsistent">False</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<signal name="toggled" handler="on_gender_activate" last_modification_time="Tue, 24 Jun 2003 13:34:54 GMT"/>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property> <property name="padding">0</property>
@ -742,6 +744,7 @@
<property name="inconsistent">False</property> <property name="inconsistent">False</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">genderMale</property> <property name="group">genderMale</property>
<signal name="toggled" handler="on_gender_activate" last_modification_time="Tue, 24 Jun 2003 13:34:29 GMT"/>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property> <property name="padding">0</property>
@ -761,6 +764,7 @@
<property name="inconsistent">False</property> <property name="inconsistent">False</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">genderMale</property> <property name="group">genderMale</property>
<signal name="toggled" handler="on_gender_activate" last_modification_time="Tue, 24 Jun 2003 13:34:11 GMT"/>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property> <property name="padding">0</property>