2002-10-20 19:55:16 +05:30
#
# Gramps - a GTK+/GNOME based genealogy program
#
2006-02-04 03:33:53 +05:30
# Copyright (C) 2000-2006 Donald N. Allingham
2002-10-20 19:55:16 +05:30
#
# 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
#
2003-11-07 21:59:27 +05:30
# $Id$
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
# Standard python modules
#
#-------------------------------------------------------------------------
import os
2005-12-06 12:08:09 +05:30
import sys
2003-06-15 05:35:43 +05:30
import locale
2006-03-23 04:33:57 +05:30
import random
import time
2006-04-07 03:32:46 +05:30
from gettext import gettext as _
2002-10-20 19:55:16 +05:30
2006-03-19 08:55:31 +05:30
try :
set ( )
except :
from sets import Set as set
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
# GNOME/GTK
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
2006-03-03 05:53:04 +05:30
import Mime
2005-01-01 09:57:15 +05:30
import NameDisplay
2005-05-31 02:11:43 +05:30
import RelLib
2005-12-06 12:08:09 +05:30
import Errors
2006-03-01 01:24:35 +05:30
from QuestionDialog import WarningDialog
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
2005-05-31 02:11:43 +05:30
# Integer to String mappings for constants
2002-10-20 19:55:16 +05:30
#
#-------------------------------------------------------------------------
2005-05-31 02:11:43 +05:30
gender = {
RelLib . Person . MALE : _ ( " male " ) ,
RelLib . Person . FEMALE : _ ( " female " ) ,
RelLib . Person . UNKNOWN : _ ( " unknown " ) ,
}
2006-03-23 02:49:32 +05:30
def format_gender ( type ) :
return gender . get ( type [ 0 ] , _ ( " Invalid " ) )
2005-05-31 02:11:43 +05:30
confidence = {
RelLib . SourceRef . CONF_VERY_HIGH : _ ( " Very High " ) ,
RelLib . SourceRef . CONF_HIGH : _ ( " High " ) ,
RelLib . SourceRef . CONF_NORMAL : _ ( " Normal " ) ,
RelLib . SourceRef . CONF_LOW : _ ( " Low " ) ,
RelLib . SourceRef . CONF_VERY_LOW : _ ( " Very Low " ) ,
}
family_rel_descriptions = {
2006-04-19 23:57:51 +05:30
RelLib . FamilyRelType . MARRIED : _ ( " A legal or common-law relationship "
" between a husband and wife " ) ,
RelLib . FamilyRelType . UNMARRIED : _ ( " No legal or common-law relationship "
" between man and woman " ) ,
RelLib . FamilyRelType . CIVIL_UNION : _ ( " An established relationship between "
" members of the same sex " ) ,
RelLib . FamilyRelType . UNKNOWN : _ ( " Unknown relationship between a man "
" and woman " ) ,
RelLib . FamilyRelType . CUSTOM : _ ( " An unspecified relationship "
" a man and woman " ) ,
2005-05-31 02:11:43 +05:30
}
2006-03-23 02:49:32 +05:30
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
# modified flag
#
#-------------------------------------------------------------------------
2003-11-07 21:59:27 +05:30
_history_brokenFlag = 0
2002-10-20 19:55:16 +05:30
2003-11-07 21:59:27 +05:30
def history_broken ( ) :
global _history_brokenFlag
_history_brokenFlag = 1
2005-03-12 06:14:11 +05:30
data_recover_msg = _ ( ' The data can only be recovered by Undo operation '
' or by quitting with abandoning changes. ' )
2005-12-06 12:08:09 +05:30
def fix_encoding ( value ) :
if type ( value ) != unicode :
try :
return unicode ( value )
except :
codeset = locale . getpreferredencoding ( )
if codeset == ' UTF-8 ' :
codeset = ' latin1 '
return unicode ( value , codeset )
else :
return value
2005-12-13 07:37:16 +05:30
def xml_lang ( ) :
( loc , enc ) = locale . getlocale ( )
if loc == None :
return " "
else :
return loc . replace ( ' _ ' , ' - ' )
2003-04-04 11:18:25 +05:30
#-------------------------------------------------------------------------
#
# force_unicode
#
#-------------------------------------------------------------------------
def force_unicode ( n ) :
2005-01-09 07:48:49 +05:30
if type ( n ) != unicode :
2003-04-04 11:18:25 +05:30
return ( unicode ( n ) . lower ( ) , unicode ( n ) )
else :
return ( n . lower ( ) , n )
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
# Clears the modified flag. Should be called after data is saved.
#
#-------------------------------------------------------------------------
2003-11-07 21:59:27 +05:30
def clearHistory_broken ( ) :
global _history_brokenFlag
_history_brokenFlag = 0
def wasHistory_broken ( ) :
return _history_brokenFlag
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
# Short hand function to return either the person's name, or an empty
# string if the person is None
#
#-------------------------------------------------------------------------
2003-10-12 09:56:00 +05:30
2006-04-20 10:29:04 +05:30
def family_name ( family , db , noname = _ ( " unknown " ) ) :
2002-10-20 19:55:16 +05:30
""" Builds a name for the family from the parents names """
2004-07-28 07:59:07 +05:30
father_handle = family . get_father_handle ( )
mother_handle = family . get_mother_handle ( )
2004-08-07 10:46:57 +05:30
father = db . get_person_from_handle ( father_handle )
mother = db . get_person_from_handle ( mother_handle )
2002-10-20 19:55:16 +05:30
if father and mother :
2005-01-01 09:57:15 +05:30
fname = NameDisplay . displayer . display ( father )
mname = NameDisplay . displayer . display ( mother )
2005-03-12 02:35:46 +05:30
name = _ ( " %(father)s and %(mother)s " ) % {
" father " : fname ,
" mother " : mname }
2002-10-20 19:55:16 +05:30
elif father :
2005-01-01 09:57:15 +05:30
name = NameDisplay . displayer . display ( father )
2005-03-14 03:40:40 +05:30
elif mother :
2005-01-01 09:57:15 +05:30
name = NameDisplay . displayer . display ( mother )
2005-03-14 03:40:40 +05:30
else :
2006-04-20 10:29:04 +05:30
name = noname
2002-10-20 19:55:16 +05:30
return name
2004-02-23 10:11:37 +05:30
def family_upper_name ( family , db ) :
2003-10-12 09:56:00 +05:30
""" Builds a name for the family from the parents names """
2004-07-28 07:59:07 +05:30
father_handle = family . get_father_handle ( )
mother_handle = family . get_mother_handle ( )
2004-08-07 10:46:57 +05:30
father = db . get_person_from_handle ( father_handle )
mother = db . get_person_from_handle ( mother_handle )
2003-10-12 09:56:00 +05:30
if father and mother :
2004-02-14 11:10:30 +05:30
fname = father . get_primary_name ( ) . get_upper_name ( )
mname = mother . get_primary_name ( ) . get_upper_name ( )
2003-10-12 09:56:00 +05:30
name = _ ( " %s and %s " ) % ( fname , mname )
elif father :
2004-02-14 11:10:30 +05:30
name = father . get_primary_name ( ) . get_upper_name ( )
2002-10-20 19:55:16 +05:30
else :
2004-02-14 11:10:30 +05:30
name = mother . get_primary_name ( ) . get_upper_name ( )
2003-10-12 09:56:00 +05:30
return name
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def destroy_passed_object ( obj ) :
obj . destroy ( )
while gtk . events_pending ( ) :
2004-04-28 09:36:25 +05:30
gtk . main_iteration ( )
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_detail_text ( obj , priv = 1 ) :
2004-02-14 11:10:30 +05:30
if obj . get_note ( ) != " " :
2002-10-20 19:55:16 +05:30
details = " %s " % _ ( " Note " )
else :
details = " "
2004-02-14 11:10:30 +05:30
if len ( obj . get_source_references ( ) ) > 0 :
2002-10-20 19:55:16 +05:30
if details == " " :
details = _ ( " Source " )
else :
details = " %s , %s " % ( details , _ ( " Source " ) )
2004-02-14 11:10:30 +05:30
if priv and obj . get_privacy ( ) == 1 :
2002-10-20 19:55:16 +05:30
if details == " " :
details = _ ( " Private " )
else :
details = " %s , %s " % ( details , _ ( " Private " ) )
return details
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def redraw_list ( dlist , clist , func ) :
clist . clear ( )
index = 0
2004-08-23 04:46:57 +05:30
for obj in dlist :
2002-10-20 19:55:16 +05:30
col = 0
2004-08-23 04:46:57 +05:30
node = clist . append ( )
for data in func ( obj ) :
clist . set_value ( node , col , data )
2002-10-20 19:55:16 +05:30
col = col + 1
index = index + 1
return index
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def delete_selected ( obj , list ) :
sel = obj . get_selection ( )
2004-08-23 04:46:57 +05:30
model , node = sel . get_selected ( )
if node :
index = model . get_path ( node ) [ 0 ]
2002-10-20 19:55:16 +05:30
del list [ index ]
return 1
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def add_menuitem ( menu , msg , obj , func ) :
item = gtk . MenuItem ( msg )
2004-05-14 04:15:51 +05:30
item . set_data ( ' o ' , obj )
2002-10-20 19:55:16 +05:30
item . connect ( " activate " , func )
item . show ( )
menu . append ( item )
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def view_photo ( photo ) :
2004-08-23 04:46:57 +05:30
mime_type = photo . get_mime_type ( )
2004-04-04 10:09:52 +05:30
try :
2006-03-03 05:53:04 +05:30
data = Mime . get_application ( mime_type )
2004-04-04 10:09:52 +05:30
prog = data [ 0 ]
except :
2002-11-03 02:49:58 +05:30
return
2006-03-30 08:54:04 +05:30
launch ( prog , photo . get_path ( ) )
2002-10-20 19:55:16 +05:30
2005-12-06 12:08:09 +05:30
def find_file ( filename ) :
# try the filename we got
try :
fname = filename
if os . path . isfile ( filename ) :
return ( filename )
except :
pass
2006-05-24 10:58:33 +05:30
# Build list of alternate encodings
encodings = [ sys . getfilesystemencoding ( ) , locale . getpreferredencoding ( ) ,
' UTF-8 ' , ' ISO-8859-1 ' ]
2006-03-19 08:55:31 +05:30
encodings = list ( set ( encodings ) )
2005-12-06 12:08:09 +05:30
for enc in encodings :
try :
fname = filename . encode ( enc )
if os . path . isfile ( fname ) :
return fname
except :
pass
# not found
return ' '
def find_folder ( filename ) :
# try the filename we got
try :
fname = filename
if os . path . isdir ( filename ) :
return ( filename )
except :
pass
# Build list of elternate encodings
2006-03-19 08:55:31 +05:30
try :
encodings = [ sys . getfilesystemencoding ( ) , locale . getpreferredencoding ( ) ,
' UTF-8 ' , ' ISO-8859-1 ' ]
except :
encodings = [ sys . getfilesystemencoding ( ) , ' UTF-8 ' , ' ISO-8859-1 ' ]
encodings = list ( set ( encodings ) )
2005-12-06 12:08:09 +05:30
for enc in encodings :
try :
fname = filename . encode ( enc )
if os . path . isdir ( fname ) :
return fname
except :
pass
# not found
return ' '
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def build_string_optmenu ( mapping , start_val ) :
index = 0
start_index = 0
keys = mapping . keys ( )
keys . sort ( )
myMenu = gtk . Menu ( )
for key in keys :
if key == " default " :
menuitem = gtk . MenuItem ( _ ( " default " ) )
else :
menuitem = gtk . MenuItem ( key )
menuitem . set_data ( " d " , mapping [ key ] )
2003-10-31 06:50:58 +05:30
menuitem . set_data ( " l " , key )
2002-10-20 19:55:16 +05:30
menuitem . show ( )
myMenu . append ( menuitem )
if key == start_val :
start_index = index
index = index + 1
if start_index :
myMenu . set_active ( start_index )
return myMenu
2002-10-25 10:22:51 +05:30
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def build_columns ( tree , list ) :
cnum = 0
for name in list :
renderer = gtk . CellRendererText ( )
2003-07-27 09:20:57 +05:30
renderer . set_fixed_height_from_font ( 1 )
2002-10-25 10:22:51 +05:30
column = gtk . TreeViewColumn ( name [ 0 ] , renderer , text = cnum )
column . set_min_width ( name [ 1 ] )
if name [ 2 ] > = 0 :
column . set_sort_column_id ( name [ 2 ] )
if name [ 0 ] == ' ' :
2005-02-24 05:55:34 +05:30
column . set_clickable ( True )
column . set_visible ( False )
2002-10-25 10:22:51 +05:30
cnum = cnum + 1
tree . append_column ( column )
2003-01-10 10:51:32 +05:30
#-------------------------------------------------------------------------
#
# Iterate over ancestors.
#
#-------------------------------------------------------------------------
2005-01-12 04:11:15 +05:30
def for_each_ancestor ( db , start , func , data ) :
2003-01-10 10:51:32 +05:30
"""
Recursively iterate ( breadth - first ) over ancestors of
people listed in start .
Call func ( data , pid ) for the Id of each person encountered .
Exit and return 1 , as soon as func returns true .
Return 0 otherwise .
"""
todo = start
doneIds = { }
while len ( todo ) :
2005-01-12 04:11:15 +05:30
p_handle = todo . pop ( )
p = db . get_person_from_handle ( p_handle )
# Don't process the same handle twice. This can happen
2003-01-10 10:51:32 +05:30
# if there is a cycle in the database, or if the
# initial list contains X and some of X's ancestors.
2005-01-12 04:11:15 +05:30
if doneIds . has_key ( p_handle ) :
2003-01-10 10:51:32 +05:30
continue
2005-01-12 04:11:15 +05:30
doneIds [ p_handle ] = 1
if func ( data , p_handle ) :
2003-01-10 10:51:32 +05:30
return 1
2006-04-14 00:59:36 +05:30
for fam_handle in p . get_parent_family_handle_list ( ) :
2005-01-12 04:11:15 +05:30
fam = db . get_family_from_handle ( fam_handle )
if fam :
f_handle = fam . get_father_handle ( )
m_handle = fam . get_mother_handle ( )
if f_handle : todo . append ( f_handle )
if m_handle : todo . append ( m_handle )
2003-01-10 10:51:32 +05:30
return 0
2003-03-05 11:31:31 +05:30
def title ( n ) :
return ' <span weight= " bold " size= " larger " > %s </span> ' % n
def set_title_label ( xmlobj , t ) :
title_label = xmlobj . get_widget ( ' title ' )
title_label . set_text ( ' <span weight= " bold " size= " larger " > %s </span> ' % t )
2005-02-24 05:55:34 +05:30
title_label . set_use_markup ( True )
2003-03-06 11:42:51 +05:30
2006-04-24 03:48:01 +05:30
from warnings import warn
2003-03-06 11:42:51 +05:30
def set_titles ( window , title , t , msg = None ) :
2006-04-24 03:48:01 +05:30
warn ( ' The Utils.set_titles is deprecated. Use ManagedWindow methods ' )
2003-05-10 11:47:07 +05:30
2003-06-14 22:41:11 +05:30
def gfloat ( val ) :
2003-06-15 05:35:43 +05:30
""" Converts to floating number, taking care of possible locale differences.
Useful for reading float values from text entry fields
while under non - English locale .
"""
2003-06-14 22:41:11 +05:30
try :
return float ( val )
except :
try :
2003-06-14 22:44:46 +05:30
return float ( val . replace ( ' . ' , ' , ' ) )
2003-06-14 22:41:11 +05:30
except :
2003-06-14 22:44:46 +05:30
return float ( val . replace ( ' , ' , ' . ' ) )
2003-06-14 22:41:11 +05:30
return 0.0
2003-06-15 05:35:43 +05:30
def gformat ( val ) :
2005-12-06 12:08:09 +05:30
""" Performs ( ' %.3f ' % val) formatting with the resulting string always
2003-06-15 05:35:43 +05:30
using dot ( ' . ' ) as a decimal point .
Useful for writing float values into XML when under non - English locale .
"""
decimal_point = locale . localeconv ( ) [ ' decimal_point ' ]
return_val = " %.3f " % val
return return_val . replace ( decimal_point , ' . ' )
2003-11-25 23:15:34 +05:30
def search_for ( name ) :
2006-06-19 02:28:25 +05:30
if name . startswith ( ' " ' ) :
name = name . split ( ' " ' ) [ 1 ]
else :
name = name . split ( ) [ 0 ]
2006-07-22 11:22:16 +05:30
if os . sys . platform == " win32 " :
for i in os . environ [ ' PATH ' ] . split ( ' ; ' ) :
fname = os . path . join ( i , name )
if os . access ( fname , os . X_OK ) and not os . path . isdir ( fname ) :
return 1
else :
for i in os . environ [ ' PATH ' ] . split ( ' : ' ) :
fname = os . path . join ( i , name )
if os . access ( fname , os . X_OK ) and not os . path . isdir ( fname ) :
return 1
2003-11-25 23:15:34 +05:30
return 0
2003-06-14 22:41:11 +05:30
2003-11-13 00:15:07 +05:30
#-------------------------------------------------------------------------
#
2005-07-09 01:54:54 +05:30
# Change label appearance
2003-11-13 00:15:07 +05:30
#
#-------------------------------------------------------------------------
2005-05-26 10:34:36 +05:30
def bold_label ( label , widget = None ) :
2005-12-22 19:05:37 +05:30
if label . __class__ == gtk . Label :
text = unicode ( label . get_text ( ) )
text = text . replace ( ' <i> ' , ' ' )
text = text . replace ( ' </i> ' , ' ' )
label . set_text ( " <b> %s </b> " % text )
label . set_use_markup ( True )
else :
clist = label . get_children ( )
text = unicode ( clist [ 1 ] . get_text ( ) )
text = text . replace ( ' <i> ' , ' ' )
text = text . replace ( ' </i> ' , ' ' )
clist [ 0 ] . show ( )
clist [ 1 ] . set_text ( " <b> %s </b> " % text )
clist [ 1 ] . set_use_markup ( True )
2005-05-26 10:34:36 +05:30
if widget :
widget . window . set_cursor ( None )
def unbold_label ( label , widget = None ) :
2005-12-22 19:05:37 +05:30
if label . __class__ == gtk . Label :
text = unicode ( label . get_text ( ) )
text = text . replace ( ' <b> ' , ' ' )
text = text . replace ( ' </b> ' , ' ' )
text = text . replace ( ' <i> ' , ' ' )
text = text . replace ( ' </i> ' , ' ' )
label . set_text ( text )
label . set_use_markup ( False )
else :
clist = label . get_children ( )
text = unicode ( clist [ 1 ] . get_text ( ) )
text = text . replace ( ' <b> ' , ' ' )
text = text . replace ( ' </b> ' , ' ' )
text = text . replace ( ' <i> ' , ' ' )
text = text . replace ( ' </i> ' , ' ' )
clist [ 0 ] . hide ( )
clist [ 1 ] . set_text ( text )
clist [ 1 ] . set_use_markup ( False )
2005-05-26 10:34:36 +05:30
if widget :
widget . window . set_cursor ( None )
def temp_label ( label , widget = None ) :
2005-12-22 19:05:37 +05:30
if label . __class__ == gtk . Label :
text = unicode ( label . get_text ( ) )
text = text . replace ( ' <b> ' , ' ' )
text = text . replace ( ' </b> ' , ' ' )
label . set_text ( " <i> %s </i> " % text )
label . set_use_markup ( True )
else :
clist = label . get_children ( )
text = unicode ( clist [ 1 ] . get_text ( ) )
text = text . replace ( ' <b> ' , ' ' )
text = text . replace ( ' </b> ' , ' ' )
clist [ 0 ] . hide ( )
clist [ 1 ] . set_text ( " <i> %s </i> " % text )
clist [ 1 ] . set_use_markup ( True )
2005-05-26 10:34:36 +05:30
if widget :
widget . window . set_cursor ( gtk . gdk . Cursor ( gtk . gdk . WATCH ) )
2004-04-25 10:18:02 +05:30
2004-06-30 09:36:10 +05:30
#-------------------------------------------------------------------------
#
# create_id
#
#-------------------------------------------------------------------------
rand = random . Random ( time . time ( ) )
2004-06-27 08:40:06 +05:30
def create_id ( ) :
2005-04-29 03:51:20 +05:30
return " %08x %08x " % ( int ( time . time ( ) * 10000 ) ,
2006-03-23 04:33:57 +05:30
rand . randint ( 0 , sys . maxint ) )
2004-10-08 09:29:55 +05:30
2005-12-06 12:08:09 +05:30
def probably_alive ( person , db , current_year = None , limit = 0 ) :
2005-04-08 13:39:18 +05:30
""" Returns true if the person may be alive.
This works by a process of emlimination . If we can ' t find a good
reason to believe that someone is dead then we assume they must
be alive .
"""
if not current_year :
time_struct = time . localtime ( time . time ( ) )
current_year = time_struct [ 0 ]
2005-04-08 15:10:15 +05:30
death_year = None
2005-04-08 13:39:18 +05:30
# If the recorded death year is before current year then
# things are simple.
2006-05-24 02:01:39 +05:30
death_ref = person . get_death_ref ( )
2006-11-20 10:20:59 +05:30
if death_ref and death_ref . get_role ( ) == RelLib . EventRoleType . PRIMARY :
2006-05-24 02:01:39 +05:30
death = db . get_event_from_handle ( death_ref . ref )
2006-02-04 03:33:53 +05:30
if death . get_date_object ( ) . get_start_date ( ) != RelLib . Date . EMPTY :
2005-04-08 15:10:15 +05:30
death_year = death . get_date_object ( ) . get_year ( )
2006-05-02 02:41:26 +05:30
if death_year + limit < current_year :
2005-04-07 02:26:24 +05:30
return False
2005-12-06 12:08:09 +05:30
2004-10-08 09:29:55 +05:30
# Look for Cause Of Death, Burial or Cremation events.
# These are fairly good indications that someone's not alive.
2006-11-21 21:50:35 +05:30
for ev_ref in person . get_primary_event_ref_list ( ) :
2005-06-21 03:48:22 +05:30
ev = db . get_event_from_handle ( ev_ref . ref )
2006-04-20 09:04:07 +05:30
if ev and int ( ev . get_type ( ) ) in [ RelLib . EventType . CAUSE_DEATH ,
RelLib . EventType . BURIAL ,
RelLib . EventType . CREMATION ] :
2005-04-08 15:10:15 +05:30
if not death_year :
death_year = ev . get_date_object ( ) . get_year ( )
2006-02-04 03:33:53 +05:30
if ev . get_date_object ( ) . get_start_date ( ) != RelLib . Date . EMPTY :
2006-05-02 02:41:26 +05:30
if ev . get_date_object ( ) . get_year ( ) + limit < current_year :
2005-04-07 02:26:24 +05:30
return False
2005-12-13 07:37:16 +05:30
# For any other event of this person, check whether it happened
# too long ago. If so then the person is likely dead now.
elif ev and too_old ( ev . get_date_object ( ) , current_year ) :
return False
2004-10-08 09:29:55 +05:30
2005-04-08 15:10:15 +05:30
birth_year = None
2005-04-08 13:39:18 +05:30
# If they were born within 100 years before current year then
# assume they are alive (we already know they are not dead).
2006-05-24 02:01:39 +05:30
birth_ref = person . get_birth_ref ( )
2006-11-20 10:20:59 +05:30
if birth_ref and birth_ref . get_role ( ) == RelLib . EventRoleType . PRIMARY :
2006-05-24 02:01:39 +05:30
birth = db . get_event_from_handle ( birth_ref . ref )
2006-02-04 03:33:53 +05:30
if birth . get_date_object ( ) . get_start_date ( ) != RelLib . Date . EMPTY :
2005-04-08 15:10:15 +05:30
if not birth_year :
birth_year = birth . get_date_object ( ) . get_year ( )
2005-12-13 07:37:16 +05:30
# Check whether the birth event is too old because the
# code above did not look at birth, only at other events
if too_old ( birth . get_date_object ( ) , current_year ) :
return False
if not_too_old ( birth . get_date_object ( ) , current_year ) :
2005-04-08 13:39:18 +05:30
return True
2005-04-08 15:10:15 +05:30
if not birth_year and death_year :
if death_year > current_year + 110 :
# person died more tha 110 after current year
return False
2007-01-08 07:19:33 +05:30
# Neither birth nor death events are available. Try looking
# at siblings. If a sibling was born more than 120 years past,
# or more than 20 future, then problem then this person is
# probably not alive. If the sibling died more than 120 years
# past, or more than 120 years future, then probably not alive.
family_list = person . get_parent_family_handle_list ( )
for family_handle in family_list :
family = db . get_family_from_handle ( family_handle )
for child_ref in family . get_child_ref_list ( ) :
child_handle = child_ref . ref
child = db . get_person_from_handle ( child_handle )
child_birth_ref = child . get_birth_ref ( )
if child_birth_ref :
child_birth = db . get_event_from_handle ( child_birth_ref . ref )
dobj = child_birth . get_date_object ( )
if dobj . get_start_date ( ) != RelLib . Date . EMPTY :
# if sibling birth date too far away, then not alive:
year = dobj . get_year ( )
if year != 0 :
if not ( current_year - 120 < year < current_year + 20 ) :
return False
child_death_ref = child . get_death_ref ( )
if child_death_ref :
child_death = db . get_event_from_handle ( child_death_ref . ref )
dobj = child_death . get_date_object ( )
if dobj . get_start_date ( ) != RelLib . Date . EMPTY :
# if sibling death date too far away, then not alive:
year = dobj . get_year ( )
if year != 0 :
if not ( current_year - 120 < year < current_year + 120 ) :
return False
# Try looking for descendants that were born more than a lifespan
# ago.
2004-10-08 09:29:55 +05:30
min_generation = 13
def descendants_too_old ( person , years ) :
for family_handle in person . get_family_handle_list ( ) :
family = db . get_family_from_handle ( family_handle )
2005-04-08 13:39:18 +05:30
2006-04-14 00:59:36 +05:30
for child_ref in family . get_child_ref_list ( ) :
child_handle = child_ref . ref
2004-10-08 09:29:55 +05:30
child = db . get_person_from_handle ( child_handle )
2006-05-24 02:01:39 +05:30
child_birth_ref = child . get_birth_ref ( )
if child_birth_ref :
child_birth = db . get_event_from_handle ( child_birth_ref . ref )
2004-10-08 09:29:55 +05:30
dobj = child_birth . get_date_object ( )
2006-02-04 03:33:53 +05:30
if dobj . get_start_date ( ) != RelLib . Date . EMPTY :
d = RelLib . Date ( dobj )
2004-10-29 06:19:40 +05:30
val = d . get_start_date ( )
2004-12-09 04:24:26 +05:30
val = d . get_year ( ) - years
2004-10-29 06:19:40 +05:30
d . set_year ( val )
2005-04-06 21:22:52 +05:30
if not not_too_old ( d , current_year ) :
2004-10-08 09:29:55 +05:30
return True
2006-05-24 02:01:39 +05:30
child_death_ref = child . get_death_ref ( )
if child_death_ref :
child_death = db . get_event_from_handle ( child_death_ref . ref )
2004-10-08 09:29:55 +05:30
dobj = child_death . get_date_object ( )
2006-02-04 03:33:53 +05:30
if dobj . get_start_date ( ) != RelLib . Date . EMPTY :
2005-04-06 21:22:52 +05:30
if not not_too_old ( dobj , current_year ) :
2004-10-08 09:29:55 +05:30
return True
if descendants_too_old ( child , years + min_generation ) :
return True
2005-04-08 13:39:18 +05:30
return False
2004-10-08 09:29:55 +05:30
2005-04-08 13:39:18 +05:30
# If there are descendants that are too old for the person to have
# been alive in the current year then they must be dead.
2005-12-06 12:08:09 +05:30
try :
if descendants_too_old ( person , min_generation ) :
return False
except RuntimeError :
raise Errors . DatabaseError (
_ ( " Database error: %s is defined as his or her own ancestor " ) %
NameDisplay . displayer . display ( person ) )
2005-04-08 13:39:18 +05:30
average_generation_gap = 20
def ancestors_too_old ( person , year ) :
family_handle = person . get_main_parents_family_handle ( )
if family_handle :
family = db . get_family_from_handle ( family_handle )
father_handle = family . get_father_handle ( )
if father_handle :
father = db . get_person_from_handle ( father_handle )
2006-05-24 02:01:39 +05:30
father_birth_ref = father . get_birth_ref ( )
2006-11-20 10:20:59 +05:30
if father_birth_ref and father_birth_ref . get_role ( ) == RelLib . EventRoleType . PRIMARY :
2006-05-24 02:01:39 +05:30
father_birth = db . get_event_from_handle (
father_birth_ref . ref )
2005-04-08 13:39:18 +05:30
dobj = father_birth . get_date_object ( )
2006-02-04 03:33:53 +05:30
if dobj . get_start_date ( ) != RelLib . Date . EMPTY :
2005-04-08 13:39:18 +05:30
if not not_too_old ( dobj , year - average_generation_gap ) :
#print father.get_primary_name().get_name(), " father of ", person.get_primary_name().get_name(), " is too old by birth. birth year ", dobj.get_year(), " test year ", year - average_generation_gap
return True
#else:
#print father.get_primary_name().get_name(), " father of ", person.get_primary_name().get_name(), " is NOT too old by birth. birth year ", dobj.get_year(), " test year ", year - average_generation_gap
2006-05-24 02:01:39 +05:30
father_death_ref = father . get_death_ref ( )
2006-11-20 10:20:59 +05:30
if father_death_ref and father_death_ref . get_role ( ) == RelLib . EventRoleType . PRIMARY :
2006-05-24 02:01:39 +05:30
father_death = db . get_event_from_handle (
father_death_ref . ref )
2005-04-08 13:39:18 +05:30
dobj = father_death . get_date_object ( )
2006-02-04 03:33:53 +05:30
if dobj . get_start_date ( ) != RelLib . Date . EMPTY :
2005-04-08 13:39:18 +05:30
if dobj . get_year ( ) < year - average_generation_gap :
#print father.get_primary_name().get_name(), " father of ", person.get_primary_name().get_name(), " is too old by death."
return True
if ancestors_too_old ( father , year - average_generation_gap ) :
return True
mother_handle = family . get_mother_handle ( )
if mother_handle :
mother = db . get_person_from_handle ( mother_handle )
2006-05-24 02:01:39 +05:30
mother_birth_ref = mother . get_birth_ref ( )
2006-11-20 10:20:59 +05:30
if mother_birth_ref and mother_birth_ref . get_role ( ) == RelLib . EventRoleType . PRIMARY :
2006-05-24 02:01:39 +05:30
mother_birth = db . get_event_from_handle ( mother_birth_ref . ref )
2005-04-08 13:39:18 +05:30
dobj = mother_birth . get_date_object ( )
2006-02-04 03:33:53 +05:30
if dobj . get_start_date ( ) != RelLib . Date . EMPTY :
2005-04-08 13:39:18 +05:30
if not not_too_old ( dobj , year - average_generation_gap ) :
#print mother.get_primary_name().get_name(), " mother of ", person.get_primary_name().get_name(), " is too old by birth. birth year ", dobj.get_year(), " test year ", year - average_generation_gap
return True
#else:
#print mother.get_primary_name().get_name(), " mother of ", person.get_primary_name().get_name(), " is NOT too old by birth. birth year ", dobj.get_year(), " test year ", year - average_generation_gap
2006-05-24 02:01:39 +05:30
mother_death_ref = mother . get_death_ref ( )
2006-11-20 10:20:59 +05:30
if mother_death_ref and mother_death_ref . get_role ( ) == RelLib . EventRoleType . PRIMARY :
2006-05-24 02:01:39 +05:30
mother_death = db . get_event_from_handle (
mother_death_ref . ref )
2005-04-08 13:39:18 +05:30
dobj = mother_death . get_date_object ( )
2006-02-04 03:33:53 +05:30
if dobj . get_start_date ( ) != RelLib . Date . EMPTY :
2005-04-08 13:39:18 +05:30
if dobj . get_year ( ) < year - average_generation_gap :
#print mother.get_primary_name().get_name(), " mother of ", person.get_primary_name().get_name(), " is too old by death."
return True
if ancestors_too_old ( mother , year - average_generation_gap ) :
return True
2004-10-08 09:29:55 +05:30
return False
2005-04-08 13:39:18 +05:30
# If there are ancestors that would be too old in the current year
# then assume our person must be dead too.
if ancestors_too_old ( person , current_year ) :
#print person.get_primary_name().get_name(), " is dead because ancestors are too old."
return False
# If we can't find any reason to believe that they are dead we
# must assume they are alive.
#print person.get_primary_name().get_name(), " is probably alive."
return True
2004-10-08 09:29:55 +05:30
2005-04-06 21:22:52 +05:30
def not_too_old ( date , current_year = None ) :
if not current_year :
time_struct = time . localtime ( time . time ( ) )
current_year = time_struct [ 0 ]
2004-10-11 04:52:12 +05:30
year = date . get_year ( )
2005-04-07 02:26:24 +05:30
if year > current_year :
return False
2005-12-13 07:37:16 +05:30
return ( year != 0 and current_year - year < 110 )
def too_old ( date , current_year = None ) :
if current_year :
the_current_year = current_year
else :
time_struct = time . localtime ( time . time ( ) )
the_current_year = time_struct [ 0 ]
year = date . get_year ( )
if year > the_current_year :
return True
return ( year != 0 and the_current_year - year > 150 )
2004-10-11 04:52:12 +05:30
2005-03-12 02:35:46 +05:30
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_source_referents ( source_handle , db ) :
"""
Find objects that refer the source .
This function finds all primary objects that refer ( directly or through
secondary child - objects ) to a given source handle in a given database .
"""
2007-01-23 09:07:13 +05:30
# Use one pass through the reference map to grab all the references
object_list = [ item for item in db . find_backlink_handles ( source_handle ) ]
# Then form the object-specific lists
2005-03-12 02:35:46 +05:30
2007-01-23 09:07:13 +05:30
# Persons
person_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Person ' ]
2005-03-12 02:35:46 +05:30
# Families
2007-01-23 09:07:13 +05:30
family_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Family ' ]
2005-03-12 02:35:46 +05:30
# Events
2007-01-23 09:07:13 +05:30
event_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Event ' ]
2005-03-12 02:35:46 +05:30
# Places
2007-01-23 09:07:13 +05:30
place_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Place ' ]
2005-03-12 02:35:46 +05:30
# Sources
2007-01-23 09:07:13 +05:30
source_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Source ' ]
2005-03-12 02:35:46 +05:30
# Media Objects
2007-01-23 09:07:13 +05:30
media_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' MediaObject ' ]
2005-03-12 02:35:46 +05:30
2007-01-23 09:07:13 +05:30
# Repositories
repo_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Repository ' ]
return ( person_list , family_list , event_list , place_list , source_list ,
media_list , repo_list )
2005-03-12 02:35:46 +05:30
2005-03-12 06:14:11 +05:30
def get_media_referents ( media_handle , db ) :
"""
Find objects that refer the media object .
This function finds all primary objects that refer
to a given media handle in a given database .
"""
2007-01-23 09:07:13 +05:30
# Use one pass through the reference map to grab all the references
object_list = [ item for item in db . find_backlink_handles ( media_handle ) ]
# Then form the object-specific lists
2005-03-12 06:14:11 +05:30
# Persons
2007-01-23 09:07:13 +05:30
person_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Person ' ]
2005-03-12 06:14:11 +05:30
# Families
2007-01-23 09:07:13 +05:30
family_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Family ' ]
2005-03-12 06:14:11 +05:30
# Events
2007-01-23 09:07:13 +05:30
event_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Event ' ]
2005-03-12 06:14:11 +05:30
# Places
2007-01-23 09:07:13 +05:30
place_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Place ' ]
2005-03-12 06:14:11 +05:30
# Sources
2007-01-23 09:07:13 +05:30
source_list = [ item [ 1 ] for item in object_list if item [ 0 ] == ' Source ' ]
2005-03-12 06:14:11 +05:30
return ( person_list , family_list , event_list , place_list , source_list )
2004-07-09 23:49:47 +05:30
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
2006-05-10 04:45:38 +05:30
_NEW_NAME_PATTERN = ' %s %s Untitled_ %d . %s '
2004-07-09 23:49:47 +05:30
* src/Plugins.py: Add native_format flag to import plugin registration.
* src/ReadXML.py, src/ReadGedcom.py: Register as native formats
to prevent loading twice on File->Open.
* src/data/gramps.schemas: Add keys for last import and export dirs.
* src/GrampsCfg.py (get_last_import_dir, save_last_import_dir,
get_last_export_dir, save_last_export_dir): Add functions.
* src/Exportder.py (suggest_filename): Try last export and last
import folders before falling back to Home; (save): Save export folder.
* src/Utils.py (get_new_filename): Add optional folder argument.
* src/DbPrompter.py (ExistingDbPrompter.chooser): Only add
importers for non-native formats, the rest is already taken care of;
Try last file, last import, last export, then home folders;
(ImportDbPrompter.chooser): Save import folder; Try last import,
last file, last export, then home folders.
(NewNativeDbPrompter): Try last file, last import, last export folders,
then fall back to home.
svn: r3493
2004-08-24 03:35:55 +05:30
def get_new_filename ( ext , folder = ' ~/ ' ) :
2004-07-09 23:49:47 +05:30
ix = 1
2006-05-10 04:45:38 +05:30
while os . path . isfile ( os . path . expanduser ( _NEW_NAME_PATTERN %
( folder , os . path . sep , ix , ext ) ) ) :
2004-07-09 23:49:47 +05:30
ix = ix + 1
2006-05-10 04:45:38 +05:30
return os . path . expanduser ( _NEW_NAME_PATTERN % ( folder , os . path . sep , ix , ext ) )
2004-12-22 07:26:37 +05:30
def get_type_converter ( val ) :
"""
Returns function that converts strings into the type of val .
"""
val_type = type ( val )
if val_type in ( str , unicode ) :
return unicode
elif val_type == int :
return int
elif val_type == float :
return float
elif val_type in ( list , tuple ) :
return list
def type_name ( val ) :
"""
Returns the name the type of val .
Only numbers and strings are supported .
The rest becomes strings ( unicode ) .
"""
val_type = type ( val )
if val_type == int :
return ' int '
elif val_type == float :
return ' float '
elif val_type in ( str , unicode ) :
return ' unicode '
return ' unicode '
def get_type_converter_by_name ( val_str ) :
"""
Returns function that converts strings into the type given by val_str .
Only numbers and strings are supported .
The rest becomes strings ( unicode ) .
"""
if val_str == ' int ' :
return int
elif val_str == ' float ' :
return float
elif val_str in ( ' str ' , ' unicode ' ) :
return unicode
return unicode
2005-07-09 01:54:54 +05:30
2006-02-05 04:59:44 +05:30
def relative_path ( original , base ) :
if not os . path . exists ( original ) or not os . path . isdir ( base ) :
return original
base_list = ( os . path . abspath ( base ) ) . split ( os . sep )
target_list = ( os . path . abspath ( original ) ) . split ( os . sep )
# Starting from the filepath root, work out how much of the filepath is
# shared by base and target.
for i in range ( min ( len ( base_list ) , len ( target_list ) ) ) :
if base_list [ i ] < > target_list [ i ] : break
else :
i + = 1
rel_list = [ os . pardir ] * ( len ( base_list ) - i ) + target_list [ i : ]
return os . path . join ( * rel_list )
2005-08-18 11:28:28 +05:30
class ProgressMeter :
"""
Progress meter class for GRAMPS .
"""
def __init__ ( self , title , header = ' ' ) :
"""
Specify the title and the current pass header .
"""
2006-04-14 10:06:25 +05:30
self . old_val = - 1
2005-08-18 11:28:28 +05:30
self . ptop = gtk . Dialog ( )
2006-03-01 01:24:35 +05:30
self . ptop . connect ( ' delete_event ' , self . warn )
2005-08-18 11:28:28 +05:30
self . ptop . set_has_separator ( False )
self . ptop . set_title ( title )
self . ptop . set_border_width ( 12 )
self . ptop . vbox . set_spacing ( 10 )
lbl = gtk . Label ( ' <span size= " larger " weight= " bold " > %s </span> ' % title )
lbl . set_use_markup ( True )
self . lbl = gtk . Label ( header )
self . lbl . set_use_markup ( True )
self . ptop . vbox . add ( lbl )
self . ptop . vbox . add ( self . lbl )
self . ptop . vbox . set_border_width ( 24 )
self . pbar = gtk . ProgressBar ( )
self . ptop . set_size_request ( 350 , 125 )
self . ptop . vbox . add ( self . pbar )
self . ptop . show_all ( )
if header == ' ' :
self . lbl . hide ( )
def set_pass ( self , header , total ) :
"""
Reset for another pass . Provide a new header and define number
of steps to be used .
"""
if header == ' ' :
self . lbl . hide ( )
else :
self . lbl . show ( )
self . pbar_max = total
self . pbar_index = 0.0
self . lbl . set_text ( header )
self . pbar . set_fraction ( 0.0 )
while gtk . events_pending ( ) :
gtk . main_iteration ( )
def step ( self ) :
""" Click the progress bar over to the next value. Be paranoid
and insure that it doesn ' t go over 100 % . " " "
self . pbar_index = self . pbar_index + 1.0
2006-10-02 07:40:12 +05:30
if self . pbar_index > self . pbar_max :
2005-08-18 11:28:28 +05:30
self . pbar_index = self . pbar_max
2006-10-02 07:40:12 +05:30
try :
val = int ( 100 * self . pbar_index / self . pbar_max )
except ZeroDivisionError :
val = 0
2006-04-14 10:06:25 +05:30
if val != self . old_val :
self . pbar . set_text ( " %d %% " % val )
self . pbar . set_fraction ( val / 100.0 )
self . old_val = val
2005-08-18 11:28:28 +05:30
while gtk . events_pending ( ) :
gtk . main_iteration ( )
2006-03-23 04:33:57 +05:30
def warn ( self , * obj ) :
2006-03-01 01:24:35 +05:30
WarningDialog (
_ ( " Attempt to force closing the dialog " ) ,
_ ( " Please do not force closing this important dialog. " ) ,
self . ptop )
return True
2005-08-18 11:28:28 +05:30
def close ( self ) :
"""
Close the progress meter
"""
self . ptop . destroy ( )
2006-03-30 08:54:04 +05:30
def launch ( prog_str , path ) :
2006-06-19 02:28:25 +05:30
if sys . platform == " win32 " :
import subprocess
if prog_str . find ( " % 1 " ) != - 1 :
prog_str = prog_str . replace ( " % 1 " , path )
else :
prog_str = ' %s " %s " ' % ( prog_str , path )
subprocess . Popen ( prog_str )
2006-03-30 08:54:04 +05:30
else :
2006-06-19 02:28:25 +05:30
subval = {
' %F ' : path ,
' %f ' : path ,
' %u ' : path ,
' % U ' : path ,
' % n ' : path ,
' % N ' : path ,
}
prog_data = prog_str . split ( )
prog = prog_data [ 0 ]
prog_list = [ ]
need_path = True
if len ( prog_data ) > 1 :
for item in prog_data :
if subval . has_key ( item ) :
need_path = False
value = subval [ item ]
else :
value = item
prog_list . append ( value )
else :
prog_list = [ prog_data [ 0 ] ]
if need_path :
prog_list . append ( path )
os . spawnvpe ( os . P_NOWAIT , prog , prog_list , os . environ )
2006-03-30 08:54:04 +05:30
2007-01-20 15:05:40 +05:30
def profile ( func , * args ) :
2007-01-19 10:46:41 +05:30
import hotshot , hotshot . stats
pr = hotshot . Profile ( ' mystats.profile ' )
print " Start "
2007-01-20 15:05:40 +05:30
pr . runcall ( func , * args )
2007-01-19 10:46:41 +05:30
print " Finished "
pr . close ( )
print " Loading profile "
stats = hotshot . stats . load ( ' mystats.profile ' )
print " done "
stats . strip_dirs ( )
stats . sort_stats ( ' time ' , ' calls ' )
stats . print_stats ( 100 )