2002-10-20 19:55:16 +05:30
|
|
|
#
|
|
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
|
|
#
|
2004-02-23 10:11:37 +05:30
|
|
|
# Copyright (C) 2000-2004 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 string
|
|
|
|
import os
|
2003-06-15 05:35:43 +05:30
|
|
|
import locale
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# GNOME/GTK
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
import gtk
|
2004-05-14 04:15:51 +05:30
|
|
|
import gnome
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Gramps modules
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
import const
|
|
|
|
import RelImage
|
2004-04-04 10:09:52 +05:30
|
|
|
import GrampsMime
|
2004-10-11 04:52:12 +05:30
|
|
|
import Date
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# internationalization
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
2003-08-17 07:44:33 +05:30
|
|
|
from gettext import gettext as _
|
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
|
|
|
|
|
2003-04-04 11:18:25 +05:30
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# force_unicode
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
_t = type(u'')
|
|
|
|
|
|
|
|
def force_unicode(n):
|
|
|
|
if type(n) != _t:
|
|
|
|
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
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
def phonebook_name(person):
|
|
|
|
if person:
|
2004-02-14 11:10:30 +05:30
|
|
|
return person.get_primary_name().get_name()
|
2002-10-20 19:55:16 +05:30
|
|
|
else:
|
2003-04-04 11:18:25 +05:30
|
|
|
return u''
|
2002-10-20 19:55:16 +05:30
|
|
|
|
2003-10-12 09:56:00 +05:30
|
|
|
def phonebook_upper_name(person):
|
|
|
|
if person:
|
2004-02-14 11:10:30 +05:30
|
|
|
return person.get_primary_name().get_upper_name()
|
2003-10-12 09:56:00 +05:30
|
|
|
else:
|
|
|
|
return u''
|
|
|
|
|
|
|
|
def normal_name(person):
|
|
|
|
if person:
|
2004-02-14 11:10:30 +05:30
|
|
|
return person.get_primary_name().get_regular_name()
|
2003-10-12 09:56:00 +05:30
|
|
|
else:
|
|
|
|
return u''
|
|
|
|
|
|
|
|
def upper_name(person):
|
|
|
|
if person:
|
2004-02-14 11:10:30 +05:30
|
|
|
return person.get_primary_name().get_regular_upper_name()
|
2003-10-12 09:56:00 +05:30
|
|
|
else:
|
|
|
|
return u''
|
|
|
|
|
2004-02-23 10:11:37 +05:30
|
|
|
def family_name(family,db):
|
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:
|
2004-02-14 11:10:30 +05:30
|
|
|
fname = father.get_primary_name().get_name()
|
|
|
|
mname = mother.get_primary_name().get_name()
|
2002-10-20 19:55:16 +05:30
|
|
|
name = _("%s and %s") % (fname,mname)
|
|
|
|
elif father:
|
2004-02-14 11:10:30 +05:30
|
|
|
name = father.get_primary_name().get_name()
|
2002-10-20 19:55:16 +05:30
|
|
|
else:
|
2004-02-14 11:10:30 +05:30
|
|
|
name = mother.get_primary_name().get_name()
|
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 build_confidence_menu(menu):
|
|
|
|
myMenu = gtk.Menu()
|
|
|
|
index = 0
|
|
|
|
for name in const.confidence:
|
|
|
|
item = gtk.MenuItem(name)
|
|
|
|
item.set_data("a",index)
|
|
|
|
item.show()
|
|
|
|
myMenu.append(item)
|
|
|
|
index = index + 1
|
|
|
|
menu.set_menu(myMenu)
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
#
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
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:
|
2004-08-23 04:46:57 +05:30
|
|
|
data = GrampsMime.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
|
2002-10-20 19:55:16 +05:30
|
|
|
|
2002-11-03 02:49:58 +05:30
|
|
|
args = string.split(prog)
|
2004-02-14 11:10:30 +05:30
|
|
|
args.append(photo.get_path())
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
if os.fork() == 0:
|
|
|
|
os.execvp(args[0],args)
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
#
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
def strip_id(text):
|
|
|
|
index = string.rfind(text,'[')
|
|
|
|
if (index > 0):
|
|
|
|
text = text[:index]
|
|
|
|
text = string.rstrip(text)
|
|
|
|
return text
|
|
|
|
|
2004-08-23 04:46:57 +05:30
|
|
|
def nautilus_icon(icon,mime_type):
|
2004-09-25 10:42:15 +05:30
|
|
|
import GrampsGconfKeys
|
2002-11-12 09:42:18 +05:30
|
|
|
|
2004-09-25 10:42:15 +05:30
|
|
|
theme = GrampsGconfKeys.client.get_string("/desktop/gnome/file_views/icon_theme")
|
2002-11-12 09:42:18 +05:30
|
|
|
|
|
|
|
if icon :
|
|
|
|
newicon = "%s/%s/%s.png" % (const.nautdir,theme,icon)
|
|
|
|
if os.path.isfile(newicon):
|
|
|
|
return newicon
|
|
|
|
else:
|
|
|
|
newicon = "%s/document-icons/%s.png" % (const.pixdir,icon)
|
|
|
|
if os.path.isfile(newicon):
|
|
|
|
return newicon
|
|
|
|
return None
|
2004-08-23 04:46:57 +05:30
|
|
|
elif mime_type == "x-directory/":
|
2002-11-12 09:42:18 +05:30
|
|
|
if theme:
|
|
|
|
newicon = "%s/%s/i-directory.png" % (const.nautdir,theme)
|
|
|
|
else:
|
|
|
|
newicon = "%s/gnome-folder.png" % const.pixdir
|
|
|
|
if os.path.isfile(newicon):
|
|
|
|
return newicon
|
|
|
|
return None
|
|
|
|
else:
|
2004-08-23 04:46:57 +05:30
|
|
|
icontmp = mime_type.replace('/','-')
|
2002-11-12 09:42:18 +05:30
|
|
|
if theme:
|
|
|
|
newicon = "%s/%s/gnome-%s.png" % (const.nautdir,theme,icontmp)
|
|
|
|
if os.path.isfile(newicon):
|
|
|
|
return newicon
|
|
|
|
else:
|
|
|
|
newicon = "%s/document-icons/gnome-%s.png" % (const.nautdir,icontmp)
|
|
|
|
if os.path.isfile(newicon):
|
|
|
|
return newicon
|
|
|
|
return None
|
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
def find_icon(mtype):
|
2002-11-12 09:42:18 +05:30
|
|
|
n = nautilus_icon(None,mtype)
|
|
|
|
if n:
|
2002-10-25 10:22:51 +05:30
|
|
|
return n
|
|
|
|
else:
|
|
|
|
return const.icon
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
def get_mime_type(file):
|
2004-04-04 10:09:52 +05:30
|
|
|
try:
|
|
|
|
return gnome.vfs.get_mime_type(file)
|
|
|
|
except:
|
|
|
|
return "unknown"
|
2002-10-20 19:55:16 +05:30
|
|
|
|
2004-08-23 04:46:57 +05:30
|
|
|
def get_mime_description(mime_type):
|
2004-04-04 10:09:52 +05:30
|
|
|
try:
|
2004-08-23 04:46:57 +05:30
|
|
|
value = gnome.vfs.mime_get_description(mime_type)
|
2004-04-04 10:09:52 +05:30
|
|
|
if value:
|
|
|
|
return value
|
|
|
|
else:
|
|
|
|
return ''
|
|
|
|
except:
|
|
|
|
return ''
|
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
2004-05-12 09:28:14 +05:30
|
|
|
#
|
2002-10-20 19:55:16 +05:30
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
def thumb_path(dir,mobj):
|
2004-08-23 04:46:57 +05:30
|
|
|
mime_type = mobj.get_mime_type()
|
2003-02-09 00:46:12 +05:30
|
|
|
|
2004-08-23 04:46:57 +05:30
|
|
|
if mime_type[0:5] == "image":
|
2004-08-26 09:33:11 +05:30
|
|
|
thumb = "%s/.thumb/%s.jpg" % (os.path.dirname(dir),mobj.get_gramps_id())
|
2002-10-20 19:55:16 +05:30
|
|
|
try:
|
2004-02-14 11:10:30 +05:30
|
|
|
if RelImage.check_thumb(mobj.get_path(),thumb,const.thumbScale):
|
2002-10-20 19:55:16 +05:30
|
|
|
return thumb
|
|
|
|
else:
|
2004-08-23 04:46:57 +05:30
|
|
|
return find_icon(mime_type)
|
2002-10-20 19:55:16 +05:30
|
|
|
except:
|
2004-08-23 04:46:57 +05:30
|
|
|
return find_icon(mime_type)
|
2002-10-20 19:55:16 +05:30
|
|
|
else:
|
2004-08-23 04:46:57 +05:30
|
|
|
return find_icon(mime_type)
|
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] == '':
|
|
|
|
column.set_clickable(gtk.TRUE)
|
|
|
|
column.set_visible(gtk.FALSE)
|
|
|
|
cnum = cnum + 1
|
|
|
|
tree.append_column(column)
|
2003-01-10 10:51:32 +05:30
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Iterate over ancestors.
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
def for_each_ancestor(start, func, data):
|
|
|
|
"""
|
|
|
|
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):
|
|
|
|
p = todo.pop()
|
2004-07-28 07:59:07 +05:30
|
|
|
pid = p.get_handle()
|
2003-01-10 10:51:32 +05:30
|
|
|
# Don't process the same Id twice. This can happen
|
|
|
|
# if there is a cycle in the database, or if the
|
|
|
|
# initial list contains X and some of X's ancestors.
|
|
|
|
if doneIds.has_key(pid):
|
|
|
|
continue
|
|
|
|
doneIds[pid] = 1
|
|
|
|
if func(data,pid):
|
|
|
|
return 1
|
2004-07-28 07:59:07 +05:30
|
|
|
for fam, mrel, frel in p.get_parent_family_handle_list():
|
|
|
|
f = fam.get_father_handle()
|
|
|
|
m = fam.get_mother_handle()
|
2003-01-10 10:51:32 +05:30
|
|
|
if f: todo.append(f)
|
|
|
|
if m: todo.append(m)
|
|
|
|
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)
|
|
|
|
title_label.set_use_markup(gtk.TRUE)
|
2003-03-06 11:42:51 +05:30
|
|
|
|
|
|
|
def set_titles(window,title,t,msg=None):
|
|
|
|
title.set_text('<span weight="bold" size="larger">%s</span>' % t)
|
|
|
|
title.set_use_markup(gtk.TRUE)
|
|
|
|
if msg:
|
|
|
|
window.set_title('%s - GRAMPS' % msg)
|
|
|
|
else:
|
|
|
|
window.set_title('%s - GRAMPS' % t)
|
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):
|
|
|
|
"""Performs ("%.3f" % val) formatting with the resulting string always
|
|
|
|
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):
|
|
|
|
for i in os.environ['PATH'].split(':'):
|
|
|
|
fname = os.path.join(i,name)
|
2003-11-26 03:04:39 +05:30
|
|
|
if os.access(fname,os.X_OK) and not os.path.isdir(fname):
|
2003-11-25 23:15:34 +05:30
|
|
|
return 1
|
|
|
|
return 0
|
2003-06-14 22:41:11 +05:30
|
|
|
|
2003-05-10 11:47:07 +05:30
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Roman numbers
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
def roman(num):
|
|
|
|
"Simple-and-dirty way to get roman numerals for small numbers."
|
|
|
|
|
|
|
|
romans = {
|
|
|
|
1 : 'I', 2 : 'II', 3 : 'III', 4 : 'IV', 5 : 'V',
|
|
|
|
6 : 'VI', 7 : 'VII', 8 : 'VIII', 9 : 'IX', 10 : 'X',
|
|
|
|
11 : 'XI', 12 : 'XII', 13 : 'XIII', 14 : 'XIV', 15 : 'XV',
|
|
|
|
16 : 'XVI', 17 : 'XVII', 18 : 'XVIII', 19 : 'XIX', 20 : 'XX',
|
|
|
|
21 : 'XXI', 22 : 'XXII', 23 : 'XXIII', 24 : 'XXIV', 25 : 'XXV',
|
|
|
|
26 : 'XXVI', 27 : 'XXVII', 28 : 'XXVIII', 29 : 'XXIX', 30 : 'XXX',
|
|
|
|
31 : 'XXXI', 32 : 'XXXII', 33 : 'XXXIII', 34 : 'XXXIV', 35 : 'XXXV',
|
|
|
|
36 : 'XXXVI', 37 : 'XXXVII', 38 : 'XXXVIII', 39 : 'XXXIX', 40 : 'XV'
|
|
|
|
}
|
|
|
|
|
|
|
|
if isinstance(num,type(1)) and num<=41:
|
|
|
|
rnum = romans[num]
|
|
|
|
return rnum
|
|
|
|
else:
|
2004-10-06 09:12:54 +05:30
|
|
|
return '?'
|
2003-11-13 00:15:07 +05:30
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Change label apperance
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
def bold_label(label):
|
2003-12-17 10:53:16 +05:30
|
|
|
text = unicode(label.get_text())
|
2003-11-13 00:15:07 +05:30
|
|
|
label.set_text("<b>%s</b>" % text )
|
|
|
|
label.set_use_markup(1)
|
|
|
|
|
|
|
|
def unbold_label(label):
|
2003-12-17 10:53:16 +05:30
|
|
|
text = unicode(label.get_text())
|
2003-11-13 00:15:07 +05:30
|
|
|
text = string.replace(text,'<b>','')
|
|
|
|
text = string.replace(text,'</b>','')
|
|
|
|
label.set_text(text)
|
|
|
|
label.set_use_markup(0)
|
2004-04-25 10:18:02 +05:30
|
|
|
|
2004-06-30 09:36:10 +05:30
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# create_id
|
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
import random
|
|
|
|
import time
|
|
|
|
rand = random.Random(time.time())
|
|
|
|
|
2004-06-27 08:40:06 +05:30
|
|
|
def create_id():
|
2004-06-30 09:36:10 +05:30
|
|
|
s = ""
|
|
|
|
for val in [ int(time.time()*10000) & 0x7fffffff,
|
|
|
|
rand.randint(0,0x7fffffff),
|
|
|
|
rand.randint(0,0x7fffffff)]:
|
|
|
|
while val != 0:
|
2004-08-24 09:18:15 +05:30
|
|
|
rem = val % 36
|
|
|
|
if rem <= 9:
|
|
|
|
s += chr(48+rem)
|
|
|
|
else:
|
|
|
|
s += chr(rem+55)
|
|
|
|
val = int(val/36)
|
2004-06-30 09:36:10 +05:30
|
|
|
return s
|
2004-07-09 23:49:47 +05:30
|
|
|
|
2004-10-08 09:29:55 +05:30
|
|
|
|
|
|
|
def probably_alive(person,db):
|
|
|
|
"""Returns true if the person may be alive."""
|
|
|
|
if person.death_handle:
|
|
|
|
return False
|
|
|
|
|
|
|
|
# Look for Cause Of Death, Burial or Cremation events.
|
|
|
|
# These are fairly good indications that someone's not alive.
|
|
|
|
for ev_handle in person.event_list:
|
|
|
|
ev = db.get_event_from_handle(ev_handle)
|
|
|
|
if ev.name in ["Cause Of Death", "Burial", "Cremation"]:
|
|
|
|
return False
|
|
|
|
|
|
|
|
if person.birth_handle:
|
|
|
|
birth = db.get_event_from_handle(person.birth_handle)
|
|
|
|
if birth.get_date_object().get_start_date() != Date.EMPTY:
|
|
|
|
return not_too_old(birth.get_date_object())
|
|
|
|
|
|
|
|
# Neither birth nor death events are available. Try looking
|
|
|
|
# for descendants that were born more than a lifespan ago.
|
|
|
|
|
|
|
|
min_generation = 13
|
|
|
|
max_generation = 60
|
|
|
|
max_age_difference = 60
|
|
|
|
|
|
|
|
def descendants_too_old (person, years):
|
|
|
|
for family_handle in person.get_family_handle_list():
|
|
|
|
family = db.get_family_from_handle(family_handle)
|
|
|
|
for child_handle in family.get_child_handle_list():
|
|
|
|
child = db.get_person_from_handle(child_handle)
|
|
|
|
if child.birth_handle:
|
|
|
|
child_birth = db.get_event_from_handle(child.birth_handle)
|
|
|
|
dobj = child_birth.get_date_object()
|
|
|
|
if dobj.get_start_date() != Date.EMPTY:
|
|
|
|
d = Date(dobj)
|
|
|
|
d.set_year(d.get_year() - years)
|
|
|
|
if not not_too_old (d):
|
|
|
|
return True
|
|
|
|
|
|
|
|
if child.death_handle:
|
|
|
|
child_death = db.get_event_from_handle(child.death_handle)
|
|
|
|
dobj = child_death.get_date_object()
|
|
|
|
if dobj.get_start_date != Date.EMPTY:
|
|
|
|
if not not_too_old (dobj):
|
|
|
|
return True
|
|
|
|
|
|
|
|
if descendants_too_old (child, years + min_generation):
|
|
|
|
return True
|
|
|
|
|
|
|
|
if descendants_too_old (person, min_generation):
|
|
|
|
return False
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
# What about their parents?
|
|
|
|
|
|
|
|
def parents_too_old (person, age_difference):
|
|
|
|
family_handle = person.get_main_parents_family_handle()
|
|
|
|
if family_handle:
|
|
|
|
family = db.get_family_from_handle(family_handle)
|
|
|
|
for parent_id in [family.get_father_handle(), family.get_mother_handle()]:
|
|
|
|
if not parent_id:
|
|
|
|
continue
|
|
|
|
|
|
|
|
parent = db.get_person_from_handle(parent_id)
|
|
|
|
if parent.birth_handle:
|
|
|
|
parent_birth = db.get_event_from_handle(parent.birth_handle)
|
|
|
|
if parent_birth.get_date():
|
|
|
|
d = SingleDate (parent_birth.get_date_object().get_start_date())
|
|
|
|
d.set_year (d.get_year() + max_generation + age_difference)
|
|
|
|
if not not_too_old (d):
|
|
|
|
return True
|
|
|
|
|
|
|
|
if parent.death_handle:
|
|
|
|
parent_death = db.get_event_from_handle(parent.death_handle)
|
|
|
|
if parent_death.get_date() != "":
|
|
|
|
d = SingleDate (parent_death.get_date_object().get_start_date())
|
|
|
|
d.set_year (d.get_year() + age_difference)
|
|
|
|
if not not_too_old (d):
|
|
|
|
return True
|
|
|
|
|
|
|
|
if parents_too_old (person, 0):
|
|
|
|
return False
|
|
|
|
|
|
|
|
# As a last resort, trying seeing if their spouse's age gives
|
|
|
|
# any clue.
|
|
|
|
for family_handle in person.get_family_handle_list():
|
|
|
|
family = db.get_family_from_handle(family_handle)
|
|
|
|
for spouse_id in [family.get_father_handle(), family.get_mother_handle()]:
|
|
|
|
if not spouse_id or spouse_id == person.handle:
|
|
|
|
continue
|
|
|
|
spouse = db.get_person_from_handle(spouse_id)
|
|
|
|
sp_birth_handle = spouse.get_birth_handle()
|
|
|
|
sp_death_handle = spouse.get_death_handle()
|
|
|
|
if sp_birth_handle:
|
|
|
|
spouse_birth = db.get_event_from_handle(sp_birth_handle)
|
|
|
|
if spouse_birth.get_date() != "":
|
|
|
|
d = SingleDate (spouse_birth.get_date_object().get_start_date())
|
|
|
|
d.set_year (d.get_year() + max_age_difference)
|
|
|
|
if not not_too_old (d):
|
|
|
|
return False
|
|
|
|
|
|
|
|
if sp_death_handle:
|
|
|
|
spouse_death = db.get_event_from_handle(sp_death_handle)
|
|
|
|
if spouse_death.get_date() != "":
|
|
|
|
d = SingleDate (spouse_death.get_date_object().get_start_date())
|
|
|
|
d.set_year (d.get_year() - min_generation)
|
|
|
|
if not not_too_old (d):
|
|
|
|
return False
|
|
|
|
|
|
|
|
if parents_too_old (spouse, max_age_difference):
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
2004-10-11 04:52:12 +05:30
|
|
|
def not_too_old(date):
|
|
|
|
time_struct = time.localtime(time.time())
|
|
|
|
current_year = time_struct[0]
|
|
|
|
year = date.get_year()
|
|
|
|
return not( year != 0 and current_year - year > 110)
|
|
|
|
|
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
|
|
|
_NEW_NAME_PATTERN = '%sUntitled_%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
|
* 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
|
|
|
while os.path.isfile(os.path.expanduser(_NEW_NAME_PATTERN % (folder,ix,ext) )):
|
2004-07-09 23:49:47 +05:30
|
|
|
ix = ix + 1
|
* 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
|
|
|
return os.path.expanduser(_NEW_NAME_PATTERN % (folder,ix,ext))
|