# # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id$ "View/Verify" #------------------------------------------------------------------------ # # standard python modules # #------------------------------------------------------------------------ import os import cStringIO from gettext import gettext as _ #------------------------------------------------------------------------ # # GNOME/GTK modules # #------------------------------------------------------------------------ import gtk import gtk.glade import GrampsDisplay #------------------------------------------------------------------------ # # GRAMPS modules # #------------------------------------------------------------------------ import RelLib import Utils import Date import Tool #------------------------------------------------------------------------- # # Actual tool # #------------------------------------------------------------------------- class Verify(Tool.Tool): def __init__(self,db,person,options_class,name,callback=None,parent=None): Tool.Tool.__init__(self,db,person,options_class,name) if parent: self.init_gui(parent) else: err_text,warn_text = self.run_tool(cli=True) self.print_results(err_text,warn_text) def init_gui(self,parent): # Draw dialog and make it handle everything self.parent = parent if self.parent.child_windows.has_key(self.__class__): self.parent.child_windows[self.__class__].present(None) return self.win_key = self.__class__ base = os.path.dirname(__file__) self.glade_file = base + os.sep + "verify.glade" self.top = gtk.glade.XML(self.glade_file,"verify_settings","gramps") self.top.signal_autoconnect({ "destroy_passed_object" : self.close, "on_verify_delete_event": self.on_delete_event, "on_help_clicked" : self.on_help_clicked, "on_verify_ok_clicked" : self.on_apply_clicked }) self.window = self.top.get_widget('verify_settings') self.window.set_icon(self.parent.topWindow.get_icon()) Utils.set_titles(self.window, self.top.get_widget('title'), _('Database Verify')) self.top.get_widget("oldage").set_value( self.options.handler.options_dict['oldage']) self.top.get_widget("hwdif").set_value( self.options.handler.options_dict['hwdif']) self.top.get_widget("cspace").set_value( self.options.handler.options_dict['cspace']) self.top.get_widget("cbspan").set_value( self.options.handler.options_dict['cbspan']) self.top.get_widget("yngmar").set_value( self.options.handler.options_dict['yngmar']) self.top.get_widget("oldmar").set_value( self.options.handler.options_dict['oldmar']) self.top.get_widget("oldmom").set_value( self.options.handler.options_dict['oldmom']) self.top.get_widget("yngmom").set_value( self.options.handler.options_dict['yngmom']) self.top.get_widget("olddad").set_value( self.options.handler.options_dict['olddad']) self.top.get_widget("yngdad").set_value( self.options.handler.options_dict['yngdad']) self.top.get_widget("wedder").set_value( self.options.handler.options_dict['wedder']) self.top.get_widget("mxchildmom").set_value( self.options.handler.options_dict['mxchildmom']) self.top.get_widget("mxchilddad").set_value( self.options.handler.options_dict['mxchilddad']) self.top.get_widget("lngwdw").set_value( self.options.handler.options_dict['lngwdw']) self.top.get_widget("estimate").set_active( self.options.handler.options_dict['estimate_age']) self.add_itself_to_menu() self.window.show() def on_delete_event(self,obj,b): self.remove_itself_from_menu() def close(self,obj): self.remove_itself_from_menu() self.window.destroy() def add_itself_to_menu(self): self.parent.child_windows[self.win_key] = self self.parent_menu_item = gtk.MenuItem(_('Database Verify')) self.parent_menu_item.connect("activate",self.present) self.parent_menu_item.show() self.parent.winsmenu.append(self.parent_menu_item) def remove_itself_from_menu(self): del self.parent.child_windows[self.win_key] self.parent_menu_item.destroy() def present(self,obj): self.window.present() def on_help_clicked(self,obj): """Display the relevant portion of GRAMPS manual""" GrampsDisplay.help('tools-util-other') def get_year(self,event_handle): """ Returns the year of an event (by its id) or 0 if no event_handle or no year specified in the event """ year = 0 if event_handle: event = self.db.get_event_from_handle(event_handle) dateObj = event.get_date_object() if dateObj: if dateObj.get_calendar() != Date.CAL_GREGORIAN: dateObj.set_calendar(Date.CAL_GREGORIAN) year = dateObj.get_year() return year def on_apply_clicked(self,obj): self.options.handler.options_dict['oldage'] = self.top.get_widget( "oldage").get_value_as_int() self.options.handler.options_dict['hwdif'] = self.top.get_widget( "hwdif").get_value_as_int() self.options.handler.options_dict['cspace'] = self.top.get_widget( "cspace").get_value_as_int() self.options.handler.options_dict['cbspan'] = self.top.get_widget( "cbspan").get_value_as_int() self.options.handler.options_dict['yngmar'] = self.top.get_widget( "yngmar").get_value_as_int() self.options.handler.options_dict['oldmar'] = self.top.get_widget( "oldmar").get_value_as_int() self.options.handler.options_dict['oldmom'] = self.top.get_widget( "oldmom").get_value_as_int() self.options.handler.options_dict['yngmom'] = self.top.get_widget( "yngmom").get_value_as_int() self.options.handler.options_dict['olddad'] = self.top.get_widget( "olddad").get_value_as_int() self.options.handler.options_dict['yngdad'] = self.top.get_widget( "yngdad").get_value_as_int() self.options.handler.options_dict['wedder'] = self.top.get_widget( "wedder").get_value_as_int() self.options.handler.options_dict['mxchildmom'] = self.top.get_widget( "mxchildmom").get_value_as_int() self.options.handler.options_dict['mxchilddad'] = self.top.get_widget( "mxchilddad").get_value_as_int() self.options.handler.options_dict['lngwdw'] = self.top.get_widget( "lngwdw").get_value_as_int() self.options.handler.options_dict['estimate_age'] = \ self.top.get_widget( "estimate").get_active() err_text,warn_text = self.run_tool(cli=False) # Save options self.options.handler.save_options() VerifyResults(err_text,warn_text,self.parent) def run_tool(self,cli=False): personList = self.db.get_person_handles(sort_handles=False) oldage = self.options.handler.options_dict['oldage'] hwdif = self.options.handler.options_dict['hwdif'] cspace = self.options.handler.options_dict['cspace'] cbspan = self.options.handler.options_dict['cbspan'] yngmar = self.options.handler.options_dict['yngmar'] oldmar = self.options.handler.options_dict['oldmar'] oldmom = self.options.handler.options_dict['oldmom'] yngmom = self.options.handler.options_dict['yngmom'] olddad = self.options.handler.options_dict['olddad'] yngdad = self.options.handler.options_dict['yngdad'] wedder = self.options.handler.options_dict['wedder'] mxchildmom = self.options.handler.options_dict['mxchildmom'] mxchilddad = self.options.handler.options_dict['mxchilddad'] lngwdw = self.options.handler.options_dict['lngwdw'] estimate_age = self.options.handler.options_dict['estimate_age'] # FIXME: This has to become an option as well! # OR should be removed. What's the reason behind it? oldunm = 99 # maximum age at death for unmarried person error = cStringIO.StringIO() warn = cStringIO.StringIO() if not cli: progress = Utils.ProgressMeter(_('Verify the database'),'') progress.set_pass(_('Checking data'), self.db.get_number_of_people()) for person_handle in personList: person = self.db.get_person_from_handle(person_handle) idstr = "%s (%s)" % (person.get_primary_name().get_name(),person.get_gramps_id()) # individual checks total_children = 0 ageatdeath = 0 byear = self.get_year( person.get_birth_handle() ) bapyear = 0 dyear = self.get_year( person.get_death_handle() ) buryear = 0 for event_handle in person.get_event_list(): if event_handle: event = self.db.get_event_from_handle(event_handle) event_name = event.get_name().lower() if event.get_name() == "burial": buryear = self.get_year( event.get_handle() ) elif event_name == "baptism": bapyear = self.get_year( event.get_handle() ) if byear>0 and bapyear>0: if byear > bapyear: if person.get_gender() == RelLib.Person.MALE: error.write( _("Baptized before birth: %(male_name)s born %(byear)d, baptized %(bapyear)d.\n") % { 'male_name' : idstr, 'byear' : byear, 'bapyear' : bapyear } ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Baptized before birth: %(female_name)s born %(byear)d, baptized %(bapyear)d.\n") % { 'female_name' : idstr, 'byear' : byear, 'bapyear' : bapyear } ) if byear < bapyear: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Baptized late: %(male_name)s born %(byear)d, baptized %(bapyear)d.\n") % { 'male_name' : idstr, 'byear' : byear, 'bapyear' : bapyear } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Baptized late: %(female_name)s born %(byear)d, baptized %(bapyear)d.\n") % { 'female_name' : idstr, 'byear' : byear, 'bapyear' : bapyear } ) if dyear>0 and buryear>0: if dyear > buryear: if person.get_gender() == RelLib.Person.MALE: error.write( _("Buried before death: %(male_name)s died %(dyear)d, buried %(buryear)d.\n") % { 'male_name' : idstr, 'dyear' : dyear, 'buryear' : buryear } ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Buried before death: %(female_name)s died %(dyear)d, buried %(buryear)d.\n") % { 'female_name' : idstr, 'dyear' : dyear, 'buryear' : buryear } ) if dyear < buryear: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Buried late: %(male_name)s died %(dyear)d, buried %(buryear)d.\n") % { 'male_name' : idstr, 'dyear' : dyear, 'buryear' : buryear } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Buried late: %(female_name)s died %(dyear)d, buried %(buryear)d.\n") % { 'female_name' : idstr, 'dyear' : dyear, 'buryear' : buryear } ) if dyear>0 and (byear>dyear): if person.get_gender() == RelLib.Person.MALE: error.write( _("Died before birth: %(male_name)s born %(byear)d, died %(dyear)d.\n") % { 'male_name' : idstr, 'byear' : byear, 'dyear' : dyear } ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Died before birth: %(female_name)s born %(byear)d, died %(dyear)d.\n") % { 'female_name' : idstr, 'byear' : byear, 'dyear' : dyear } ) if dyear>0 and (bapyear>dyear): if person.get_gender() == RelLib.Person.MALE: error.write( _("Died before baptism: %(male_name)s baptized %(bapyear)d, died %(dyear)d.\n") % { 'male_name' : idstr, 'bapyear' : bapyear, 'dyear' : dyear } ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Died before baptism: %(female_name)s baptized %(bapyear)d, died %(dyear)d.\n") % { 'female_name' : idstr, 'bapyear' : bapyear, 'dyear' : dyear } ) if buryear>0 and (byear>buryear): if person.get_gender() == RelLib.Person.MALE: error.write( _("Buried before birth: %(male_name)s born %(byear)d, buried %(buryear)d.\n") % { 'male_name' : idstr, 'byear' : byear, 'buryear' : buryear } ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Buried before birth: %(female_name)s born %(byear)d, buried %(buryear)d.\n") % { 'female_name' : idstr, 'byear' : byear, 'buryear' : buryear } ) if buryear>0 and (bapyear>buryear): if person.get_gender() == RelLib.Person.MALE: error.write( _("Buried before baptism: %(male_name)s baptized %(bapyear)d, buried %(buryear)d.\n") % { 'male_name' : idstr, 'bapyear' : bapyear, 'buryear' : buryear } ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Buried before baptism: %(female_name)s baptized %(bapyear)d, buried %(buryear)d.\n") % { 'female_name' : idstr, 'bapyear' : bapyear, 'buryear' : buryear } ) if byear == 0 and estimate_age: byear = bapyear # guess baptism = birth if dyear == 0 and estimate_age: dyear = buryear # guess burial = death if byear>0 and dyear>0: ageatdeath = dyear - byear else: ageatdeath = 0 if ageatdeath > oldage: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Old age: %(male_name)s born %(byear)d, died %(dyear)d, at the age of %(ageatdeath)d.\n") % { 'male_name' : idstr, 'byear' : byear, 'dyear' : dyear, 'ageatdeath' : ageatdeath } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Old age: %(female_name)s born %(byear)d, died %(dyear)d, at the age of %(ageatdeath)d.\n") % { 'female_name' : idstr, 'byear' : byear, 'dyear' : dyear, 'ageatdeath' : ageatdeath } ) # gender checks if person.get_gender() == RelLib.Person.FEMALE: oldpar = oldmom yngpar = yngmom if person.get_gender() == RelLib.Person.MALE: oldpar = olddad yngpar = yngdad if (person.get_gender() != RelLib.Person.FEMALE) and (person.get_gender() != RelLib.Person.MALE): warn.write( _("Unknown gender for %s.\n") % idstr ) oldpar = olddad yngpar = yngdad if (person.get_gender() == RelLib.Person.FEMALE) and (person.get_gender() == RelLib.Person.MALE): error.write( _("Ambiguous gender for %s.\n") % idstr ) oldpar = olddad yngpar = yngdad # multiple parentage check if( len( person.get_parent_family_handle_list() ) > 1 ): warn.write( _("Multiple parentage for %s.\n") % idstr ) # marriage checks nkids = 0 nfam = len( person.get_family_handle_list() ) if nfam > wedder: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Married often: %(male_name)s married %(nfam)d times.\n") % { 'male_name' : idstr, 'nfam' : nfam } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Married often: %(female_name)s married %(nfam)d times.\n") % { 'female_name' : idstr, 'nfam' : nfam } ) if ageatdeath>oldunm and nfam == 0: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Old and unmarried: %(male_name)s died unmarried, at the age of %(ageatdeath)d years.\n") % { 'male_name' : idstr, 'ageatdeath' : ageatdeath } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Old and unmarried: %(female_name)s died unmarried, at the age of %(ageatdeath)d years.\n") % { 'female_name' : idstr, 'ageatdeath' : ageatdeath } ) prev_cbyear=0 prev_maryear=0 prev_sdyear=0 fnum = 0 for family_handle in person.get_family_handle_list(): family = self.db.get_family_from_handle(family_handle) fnum = fnum + 1 mother_handle = family.get_mother_handle() father_handle = family.get_father_handle() if mother_handle: mother = self.db.get_person_from_handle(mother_handle) if father_handle: father = self.db.get_person_from_handle(father_handle) if mother_handle and father_handle: if ( mother.get_gender() == father.get_gender() ) and mother.get_gender() != RelLib.Person.UNKNOWN: warn.write( _("Homosexual marriage: %s in family %s.\n") % ( idstr, family.get_gramps_id() ) ) if father_handle == person.get_handle() and person.get_gender() == RelLib.Person.FEMALE: error.write( _("Female husband: %s in family %s.\n") % ( idstr, family.get_gramps_id() ) ) if mother_handle == person.get_handle() and person.get_gender() == RelLib.Person.MALE: error.write( _("Male wife: %s in family %s.\n") % ( idstr, family.get_gramps_id() ) ) if father_handle == person.get_handle(): spouse_id = mother_handle else: spouse_id = father_handle if spouse_id: spouse = self.db.get_person_from_handle(spouse_id) if person.get_gender() == RelLib.Person.MALE and \ person.get_primary_name().get_surname() == spouse.get_primary_name().get_surname(): warn.write( _("Husband and wife with the same surname: %s in family %s, and %s.\n") % ( idstr,family.get_gramps_id(), spouse.get_primary_name().get_name() ) ) sdyear = self.get_year( spouse.get_death_handle() ) sbyear = self.get_year( spouse.get_birth_handle() ) if sbyear != 0 and byear != 0 and abs(sbyear-byear) > hwdif: warn.write( _("Large age difference between husband and wife: %s in family %s, and %s.\n") % ( idstr,family.get_gramps_id(), spouse.get_primary_name().get_name() ) ) if sdyear == 0: sdyear = 0 # burial year for event_handle in family.get_event_list(): if event_handle: event = self.db.get_event_from_handle(event_handle) if event.get_name() == "Marriage": marriage_id = event_handle break else: marriage_id = None maryear = self.get_year( marriage_id ) if maryear == 0 and estimate_age: # estimate marriage year cnum=0 for child_handle in family.get_child_handle_list(): cnum = cnum + 1 if maryear == 0: child = self.db.get_person_from_handle(child_handle) birthyear = self.get_year( child.get_birth_handle() ) if birthyear > 0: maryear = birthyear-cnum if maryear > 0: if byear > 0: marage = maryear - byear if marage < 0: if person.get_gender() == RelLib.Person.MALE: error.write( _("Married before birth: %(male_name)s born %(byear)d, married %(maryear)d to %(spouse)s.\n") % { 'male_name' : idstr, 'byear' : byear, 'maryear' : maryear, 'spouse' : spouse.get_primary_name().get_name() } ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Married before birth: %(female_name)s born %(byear)d, married %(maryear)d to %(spouse)s.\n") % { 'female_name' : idstr, 'byear' : byear, 'maryear' : maryear, 'spouse' : spouse.get_primary_name().get_name() } ) else: if marage < yngmar: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Young marriage: %(male_name)s married at age %(marage)d to %(spouse)s.\n") % { 'male_name' : idstr, 'marage' : marage, 'spouse' : spouse.get_primary_name().get_name() } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Young marriage: %(female_name)s married at age %(marage)d to %(spouse)s.\n") % { 'female_name' : idstr, 'marage' : marage, 'spouse' : spouse.get_primary_name().get_name() } ) if marage > oldmar: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Old marriage: %(male_name)s married at age %(marage)d to %(spouse)s.\n") % { 'male_name' : idstr, 'marage' : marage, 'spouse' : spouse.get_primary_name().get_name() } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Old marriage: %(female_name)s married at age %(marage)d to %(spouse)s.\n") % { 'female_name' : idstr, 'marage' : marage, 'spouse' : spouse.get_primary_name().get_name() } ) if dyear>0 and maryear > dyear: if person.get_gender() == RelLib.Person.MALE: error.write( _("Married after death: %(male_name)s died %(dyear)d, married %(maryear)d to %(spouse)s.\n") % { 'male_name' : idstr, 'dyear' : dyear, 'maryear' : maryear, 'spouse' : spouse.get_primary_name().get_name() } ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Married after death: %(female_name)s died %(dyear)d, married %(maryear)d to %(spouse)s.\n") % { 'female_name' : idstr, 'dyear' : dyear, 'maryear' : maryear, 'spouse' : spouse.get_primary_name().get_name() } ) if prev_cbyear > maryear: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Marriage before birth from previous family: %(male_name)s married %(maryear)d to %(spouse)s, previous birth %(prev_cbyear)d.\n") % { 'male_name' : idstr, 'maryear' : maryear, 'spouse' : spouse.get_primary_name().get_name(), 'prev_cbyear' : prev_cbyear } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Marriage before birth from previous family: %(female_name)s married %(maryear)d to %(spouse)s, previous birth %(prev_cbyear)d.\n") % { 'female_name' : idstr, 'maryear' : maryear, 'spouse' : spouse.get_primary_name().get_name(), 'prev_cbyear' : prev_cbyear } ) prev_maryear = maryear else: maryear = prev_maryear if maryear>0 and prev_sdyear > 0: wdwyear = maryear-prev_sdyear if wdwyear > lngwdw: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Long widowhood: %s was a widower %d years before, family %s.\n") % (idstr, wdwyear, family.get_gramps_id() ) ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Long widowhood: %s was a widow %d years before, family %s.\n") % (idstr, wdwyear, family.get_gramps_id() ) ) if fnum==nfam and dyear>0 and sdyear>0: wdwyear = dyear - sdyear if wdwyear > lngwdw: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Long widowhood: %s was a widower %d years.\n") % (idstr, wdwyear) ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Long widowhood: %s was a widow %d years.\n") % (idstr, wdwyear) ) nkids = 0 cbyears = [] total_children = total_children + len(family.get_child_handle_list()) for child_handle in family.get_child_handle_list(): nkids = nkids+1 child = self.db.get_person_from_handle(child_handle) cbyear = self.get_year( child.get_birth_handle() ) if cbyear: cbyears.append(cbyear) # parentage checks if byear>0 and cbyear>0: bage = cbyear - byear if bage > oldpar: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Old father: %(male_name)s at age of %(bage)d in family %(fam)s had a child %(child)s.\n") % { 'male_name' : idstr, 'bage' : bage, 'fam' : family.get_handle(), 'child' : child.get_primary_name().get_name() } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Old mother: %(female_name)s at age of %(bage)d in family %(fam)s had a child %(child)s.\n") % { 'female_name' : idstr, 'bage' : bage, 'fam' : family.get_gramps_id(), 'child' : child.get_primary_name().get_name() } ) if bage < 0: if person.get_gender() == RelLib.Person.MALE: error.write( _("Unborn father: %(male_name)s born %(byear)d, in family %(fam)s had a child %(child)s born %(cbyear)d.\n") % { 'male_name' : idstr, 'byear' : byear, 'fam' : family.get_gramps_id(), 'child' : child.get_primary_name().get_name(), 'cbyear' : cbyear } ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Unborn mother: %(female_name)s born %(byear)d, in family %(fam)s had a child %(child)s born %(cbyear)d.\n") % { 'female_name' : idstr, 'byear' : byear, 'fam' : family.get_gramps_id(), 'child' : child.get_primary_name().get_name(), 'cbyear' : cbyear } ) else: if bage < yngpar: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Young father: %(male_name)s at the age of %(bage)d in family %(fam)s had a child %(child)s.\n") % { 'male_name' : idstr, 'bage' : bage, 'fam' : family.get_gramps_id(), 'child' : child.get_primary_name().get_name() } ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Young mother: %(female_name)s at the age of %(bage)d in family %(fam)s had a child %(child)s.\n") % { 'female_name' : idstr, 'bage' : bage, 'fam' : family.get_gramps_id(), 'child' : child.get_primary_name().get_name() } ) if dyear>0 and cbyear>dyear: if cbyear-1>dyear: if person.get_gender() == RelLib.Person.MALE: error.write( _("Dead father: %(male_name)s died %(dyear)d, but in family %(fam)s had a child %(child)s born %(cbyear)d.\n") % { 'male_name' : idstr, 'dyear' : dyear, 'fam' : family.get_gramps_id(), 'child' : child.get_primary_name().get_name(), 'cbyear' : cbyear} ) if person.get_gender() == RelLib.Person.FEMALE: error.write( _("Dead mother: %(female_name)s died %(dyear)d, but in family %(fam)s had a child %(child)s born %(cbyear)d.\n") % { 'female_name' : idstr, 'dyear' : dyear, 'fam' : family.get_gramps_id(), 'child' : child.get_primary_name().get_name(), 'cbyear' : cbyear} ) else: if person.get_gender() == RelLib.Person.MALE: warn.write( _("Dead father: %(male_name)s died %(dyear)d, but in family %(fam)s had a child %(child)s born %(cbyear)d.\n") % { 'male_name' : idstr, 'dyear' : dyear, 'fam' : family.get_gramps_id(), 'child' : child.get_primary_name().get_name(), 'cbyear' : cbyear} ) if person.get_gender() == RelLib.Person.FEMALE: warn.write( _("Dead mother: %(female_name)s died %(dyear)d, but in family %(fam)s had a child %(child)s born %(cbyear)d.\n") % { 'female_name' : idstr, 'dyear' : dyear, 'fam' : family.get_gramps_id(), 'child' : child.get_primary_name().get_name(), 'cbyear' : cbyear} ) if cbyears: cbyears.sort() if (cbyears[-1] - cbyears[0]) > cbspan: warn.write(_("Large year span for all children: family %s.\n") % family.get_gramps_id() ) if len(cbyears) > 1: cby_diff = [ cbyears[i+1]-cbyears[i] for i in range(len(cbyears)-1) ] if max(cby_diff) > cspace: warn.write(_("Large age differences between children: family %s.\n") % family.get_gramps_id() ) if (person.get_gender() == RelLib.Person.MALE and total_children > mxchilddad) \ or (person.get_gender() == RelLib.Person.FEMALE and total_children > mxchildmom): warn.write(_("Too many children (%(num_children)d) for %(person_name)s.\n") % { 'num_children' : total_children, 'person_name' : idstr }) if not cli: progress.step() if not cli: progress.close() err_text = error.getvalue() warn_text = warn.getvalue() error.close() warn.close() return err_text.strip(),warn_text.strip() def print_results(self,err_text,warn_text): if warn_text: print "\nWARNINGS:" print warn_text if err_text: print "\nERRORS:" print err_text if not (warn_text or err_text): print "No warnings or errors during verification!" #------------------------------------------------------------------------- # # Display the results # #------------------------------------------------------------------------- class VerifyResults: def __init__(self,err_text,warn_text,parent): self.parent = parent self.err_text = err_text self.warn_text = warn_text self.win_key = self base = os.path.dirname(__file__) self.glade_file = base + os.sep + "verify.glade" self.top = gtk.glade.XML(self.glade_file,"verify_result","gramps") self.title = _('Database Verification Results') Utils.set_titles(self.top.get_widget('verify_result'), self.top.get_widget('title'), self.title) self.top.signal_autoconnect({ "destroy_passed_object" : self.close_result, "on_result_delete_event" : self.on_result_delete_event, }) self.window = self.top.get_widget("verify_result") self.window.set_icon(self.parent.topWindow.get_icon()) err_window = self.top.get_widget("err_window") warn_window = self.top.get_widget("warn_window") err_window.get_buffer().set_text(self.err_text) warn_window.get_buffer().set_text(self.warn_text) self.add_result_to_menu() self.window.show() def on_result_delete_event(self,obj,b): self.remove_result_from_menu() def close_result(self,obj): self.remove_result_from_menu() self.window.destroy() def add_result_to_menu(self): self.parent.child_windows[self.win_key] = self.window self.result_parent_menu_item = gtk.MenuItem(self.title) self.result_parent_menu_item.connect("activate",self.present_result) self.result_parent_menu_item.show() self.parent.winsmenu.append(self.result_parent_menu_item) def remove_result_from_menu(self): del self.parent.child_windows[self.win_key] self.result_parent_menu_item.destroy() def present_result(self,obj): self.window.present() #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class VerifyOptions(Tool.ToolOptions): """ Defines options and provides handling interface. """ def __init__(self,name,person_id=None): Tool.ToolOptions.__init__(self,name,person_id) def set_new_options(self): # Options specific for this report self.options_dict = { 'oldage' : 90, 'hwdif' : 30, 'cspace' : 8, 'cbspan' : 25, 'yngmar' : 17, 'oldmar' : 50, 'oldmom' : 48, 'yngmom' : 17, 'yngdad' : 18, 'olddad' : 65, 'wedder' : 3, 'mxchildmom' : 12, 'mxchilddad' : 15, 'lngwdw' : 30, 'estimate_age' : 0, } self.options_help = { 'oldage' : ("=num","Maximum age","Age in years"), 'hwdif' : ("=num","Maximum husband-wife age difference", "Age difference in years"), 'cspace' : ("=num", "Maximum number of years between children", "Number of years"), 'cbspan' : ("=num", "Maximum span of years for all children", "Span in years"), 'yngmar' : ("=num","Minimum age to marry","Age in years"), 'oldmar' : ("=num","Maximum age to marry","Age in years"), 'oldmom' : ("=num","Maximum age to bear a child", "Age in years"), 'yngmom' : ("=num","Minimum age to bear a child", "Age in years"), 'yngdad' : ("=num","Minimum age to father a child", "Age in years"), 'olddad' : ("=num","Maximum age to father a child", "Age in years"), 'wedder' : ("=num","Maximum number of spouses for a person", "Number of spouses"), 'mxchildmom' : ("=num","Maximum number of children for a woman", "Number of children"), 'mxchilddad' : ("=num","Maximum number of children for a man", "Number of chidlren"), 'lngwdw' : ("=num","Maximum number of consecutive years " "of widowhood","Number of years"), 'estimate_age' : ("=0/1","Whether to estimate missing dates", ["Do not estimate","Estimate dates"], True), } #------------------------------------------------------------------------- # # # #------------------------------------------------------------------------- from PluginMgr import register_tool register_tool( name = 'verify', category = Tool.TOOL_UTILS, tool_class = Verify, options_class = VerifyOptions, modes = Tool.MODE_GUI | Tool.MODE_CLI, translated_name = _("Verify the database"), description = _("Lists exceptions to assertions or checks " "about the database") )