gramps/src/FamilyView.py

632 lines
23 KiB
Python
Raw Normal View History

2002-10-20 19:55:16 +05:30
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 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
#
#-------------------------------------------------------------------------
#
# standard python modules
#
#-------------------------------------------------------------------------
import pickle
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gobject
import gtk
import gtk.glade
from gtk.gdk import ACTION_COPY, BUTTON1_MASK
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import const
import sort
import Utils
import GrampsCfg
import AddSpouse
2002-11-03 02:49:58 +05:30
import SelectChild
2002-10-20 19:55:16 +05:30
import DisplayTrace
import Marriage
import ChooseParents
import RelLib
from intl import gettext as _
from QuestionDialog import QuestionDialog,WarningDialog
pycode_tgts = [('child', 0, 0)]
2002-10-20 19:55:16 +05:30
#-------------------------------------------------------------------------
#
# FamilyView
#
#-------------------------------------------------------------------------
class FamilyView:
def __init__(self,parent):
self.parent = parent
self.top = parent.gtop
2003-02-24 10:21:57 +05:30
self.ap_data = self.top.get_widget('ap_data')
self.ap_model = gtk.ListStore(gobject.TYPE_STRING)
self.ap_data.set_model(self.ap_model)
column = gtk.TreeViewColumn('',gtk.CellRendererText(),text=0)
self.ap_data.append_column(column)
self.ap_data.connect('button-press-event',self.edit_active_person)
2002-10-20 19:55:16 +05:30
self.swap_btn = self.top.get_widget('swap_spouse_btn')
self.add_spouse_btn = self.top.get_widget('add_spouse')
self.remove_spouse_btn = self.top.get_widget('remove_spouse')
self.ap_parents = self.top.get_widget('ap_parents')
self.ap_parents_model = gtk.ListStore(gobject.TYPE_STRING)
self.ap_parents.set_model(self.ap_parents_model)
self.ap_selection = self.ap_parents.get_selection()
column = gtk.TreeViewColumn('',gtk.CellRendererText(),text=0)
self.ap_parents.append_column(column)
self.ap_parents.connect('button-press-event',self.edit_ap_parents)
self.sp_parents = self.top.get_widget('sp_parents')
self.sp_parents_model = gtk.ListStore(gobject.TYPE_STRING)
self.sp_parents.set_model(self.sp_parents_model)
self.sp_selection = self.sp_parents.get_selection()
column = gtk.TreeViewColumn('',gtk.CellRendererText(),text=0)
self.sp_parents.append_column(column)
self.sp_parents.connect('button-press-event',self.edit_sp_parents)
self.spouse_list = self.top.get_widget('sp_list')
self.spouse_model = gtk.ListStore(gobject.TYPE_STRING)
self.spouse_list.set_model(self.spouse_model)
self.spouse_selection = self.spouse_list.get_selection()
self.spouse_selection.connect('changed',self.spouse_changed)
2002-11-28 11:22:02 +05:30
self.spouse_list.connect('button-press-event',self.edit_relationship)
2002-10-20 19:55:16 +05:30
self.top.get_widget('add_parents').connect('clicked',self.add_parents_clicked)
self.top.get_widget('del_parents').connect('clicked',self.del_parents_clicked)
self.top.get_widget('add_spparents').connect('clicked',self.add_sp_parents)
self.top.get_widget('del_spparents').connect('clicked',self.del_sp_parents)
self.top.get_widget('fam_back').connect('clicked',self.child_back)
2002-10-28 19:06:39 +05:30
self.top.get_widget('del_child_btn').connect('clicked',self.remove_child_clicked)
2002-11-03 02:49:58 +05:30
self.top.get_widget('add_child_btn').connect('clicked',self.add_child_clicked)
2002-10-20 19:55:16 +05:30
column = gtk.TreeViewColumn('',gtk.CellRendererText(),text=0)
self.spouse_list.append_column(column)
self.selected_spouse = None
self.child_list = self.top.get_widget('chlist')
self.child_list.drag_dest_set(gtk.DEST_DEFAULT_ALL,pycode_tgts,ACTION_COPY)
self.child_list.drag_source_set(BUTTON1_MASK, pycode_tgts, ACTION_COPY)
self.child_list.connect('drag_data_get', self.drag_data_get)
self.child_list.connect('drag_begin', self.drag_begin)
self.child_list.connect('drag_data_received',self.drag_data_received)
2002-10-20 19:55:16 +05:30
self.child_model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING,
gobject.TYPE_STRING,gobject.TYPE_STRING,
gobject.TYPE_STRING,gobject.TYPE_STRING,
gobject.TYPE_STRING)
2002-10-20 19:55:16 +05:30
self.child_selection = self.child_list.get_selection()
self.child_list.connect('button-press-event',self.on_child_list_button_press)
self.top.get_widget('ap_parents_btn').connect('clicked',self.ap_parents_clicked)
self.top.get_widget('sp_parents_btn').connect('clicked',self.sp_parents_clicked)
self.swap_btn.connect('clicked',self.spouse_swap)
self.remove_spouse_btn.connect('clicked',self.remove_spouse)
self.add_spouse_btn.connect('clicked',self.add_spouse)
self.child_list.set_model(self.child_model)
self.child_list.set_search_column(0)
self.child_selection = self.child_list.get_selection()
self.family = None
Utils.build_columns(self.child_list,
2003-02-04 00:54:27 +05:30
[ ('',30,-1), (_('Name'),250,-1), (_('ID'),50,-1),
(_('Gender'),100,-1), (_('Birth Date'),150,-1),
(_('Status'),150,-1), ('',0,-1) ])
2002-10-20 19:55:16 +05:30
2003-02-24 10:21:57 +05:30
def edit_active_person(self,obj,event):
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
self.parent.load_person(self.person)
2002-10-20 19:55:16 +05:30
def on_child_list_button_press(self,obj,event):
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
model, iter = self.child_selection.get_selected()
if iter:
id = self.child_model.get_value(iter,2)
self.parent.load_person(self.parent.db.getPerson(id))
def spouse_changed(self,obj):
model, iter = obj.get_selected()
if not iter:
self.display_marriage(None)
else:
row = model.get_path(iter)
self.display_marriage(self.person.getFamilyList()[row[0]])
2002-11-28 11:22:02 +05:30
def edit_relationship(self,obj,event):
2002-10-20 19:55:16 +05:30
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
if self.person:
try:
2002-11-28 11:22:02 +05:30
if self.selected_spouse:
Marriage.Marriage(self.family,self.parent.db,
self.parent.new_after_edit)
else:
AddSpouse.AddSpouse(self.parent.db,self.person,
self.load_family,
self.parent.redisplay_person_list,
self.family)
2002-10-20 19:55:16 +05:30
except:
DisplayTrace.DisplayTrace()
def add_spouse(self,obj):
if not self.person:
return
try:
AddSpouse.AddSpouse(self.parent.db, self.person,
self.load_family,
self.parent.redisplay_person_list)
except:
DisplayTrace.DisplayTrace()
2002-11-03 02:49:58 +05:30
def add_child_clicked(self,obj):
if not self.person:
return
2003-02-10 18:41:21 +05:30
try:
2002-11-03 02:49:58 +05:30
SelectChild.SelectChild(self.parent.db, self.family,
self.person, self.load_family,
self.parent.update_person_list)
2002-11-03 02:49:58 +05:30
except:
DisplayTrace.DisplayTrace()
2002-10-28 19:06:39 +05:30
def remove_child_clicked(self,obj):
if not self.family or not self.person:
return
model, iter = self.child_selection.get_selected()
if not iter:
return
id = self.child_model.get_value(iter,2)
child = self.parent.db.getPerson(id)
self.family.removeChild(child)
2003-02-09 08:44:51 +05:30
child.removeAltFamily(self.family)
2002-10-28 19:06:39 +05:30
if len(self.family.getChildList()) == 0:
if self.family.getFather() == None:
2002-11-28 11:22:02 +05:30
self.delete_family_from(self.family.getMother())
2002-10-28 19:06:39 +05:30
elif self.family.getMother() == None:
2002-11-28 11:22:02 +05:30
self.delete_family_from(self.family.getFather())
2002-10-28 19:06:39 +05:30
Utils.modified()
self.load_family()
2002-10-20 19:55:16 +05:30
def remove_spouse(self,obj):
if self.selected_spouse:
2003-02-24 10:21:57 +05:30
nap = GrampsCfg.nameof(self.person)
nsp = GrampsCfg.nameof(self.selected_spouse)
QuestionDialog(_('Remove %s as a spouse of %s?') % (nsp,nap),
_('Removing a spouse removes the relationship betwen '
'the spouse and the active person. It does not '
'remove the spouse from the database'),
_('Remove Spouse'),
self.really_remove_spouse)
elif self.family and not self.family.getChildList():
self.really_remove_spouse()
def really_remove_spouse(self):
2002-10-20 19:55:16 +05:30
"""Delete the currently selected spouse from the family"""
if self.person == None:
return
if self.selected_spouse == self.family.getFather():
self.family.setMother(None)
else:
self.family.setFather(None)
if self.selected_spouse:
self.selected_spouse.removeFamily(self.family)
if len(self.family.getChildList()) == 0:
self.person.removeFamily(self.family)
self.parent.db.deleteFamily(self.family)
if len(self.person.getFamilyList()) > 0:
self.load_family(self.person.getFamilyList()[0])
else:
self.load_family()
else:
self.load_family()
if len(self.person.getFamilyList()) <= 1:
self.spouse_selection.set_mode(gtk.SELECTION_NONE)
Utils.modified()
def spouse_swap(self,obj):
if self.selected_spouse:
self.parent.active_person = self.selected_spouse
self.load_family()
def ap_parents_clicked(self,obj):
self.change_families(self.person)
def sp_parents_clicked(self,obj):
self.change_families(self.selected_spouse)
def change_families(self,person):
if not person:
return
plist = person.getParentList()
if len(plist) == 0:
return
if len(plist) == 1:
family,m,r = plist[0]
else:
model, iter = self.ap_selection.get_selected()
path = model.get_path(iter)
family,m,r = plist[path[0]]
if family.getFather():
person = family.getFather()
else:
person = family.getMother()
self.parent.change_active_person(person)
self.load_family(family)
def clear(self):
self.spouse_model.clear()
self.child_model.clear()
self.sp_parents_model.clear()
self.ap_parents_model.clear()
2003-02-24 10:21:57 +05:30
self.ap_model.clear()
2002-10-20 19:55:16 +05:30
def load_family(self,family=None):
self.person = self.parent.active_person
if not self.person:
self.clear()
2002-10-20 19:55:16 +05:30
return
2003-01-02 10:01:52 +05:30
2003-01-19 11:55:20 +05:30
n = "%s\n\tb. %s\n\td. %s " % (GrampsCfg.nameof(self.person),
2002-10-20 19:55:16 +05:30
self.person.getBirth().getDate(),
self.person.getDeath().getDate())
2003-02-24 10:21:57 +05:30
self.ap_model.clear()
self.ap_data.get_selection().set_mode(gtk.SELECTION_NONE)
iter = self.ap_model.append()
self.ap_model.set(iter,0,n)
2002-10-20 19:55:16 +05:30
self.selected_spouse = None
self.spouse_model.clear()
self.child_model.clear()
2003-01-02 10:01:52 +05:30
self.sp_parents_model.clear()
2002-10-20 19:55:16 +05:30
splist = self.person.getFamilyList()
f = None
first_family = None
first_spouse = None
for f in splist:
if not f:
continue
if f.getFather() == self.person:
sp = f.getMother()
else:
sp = f.getFather()
iter = self.spouse_model.append()
if f == family:
first_spouse = sp
first_family = f
elif first_spouse == None:
first_spouse = sp
first_family = f
if len(splist) > 1:
self.spouse_selection.set_mode(gtk.SELECTION_SINGLE)
self.spouse_selection.select_iter(iter)
else:
self.spouse_selection.set_mode(gtk.SELECTION_NONE)
if sp:
if f.getMarriage():
mdate = " - %s" % f.getMarriage().getDate()
else:
mdate = ""
2003-01-19 11:55:20 +05:30
v = "%s\n\t%s%s" % (GrampsCfg.nameof(sp),
2002-10-20 19:55:16 +05:30
f.getRelationship(),mdate)
self.spouse_model.set(iter,0,v)
else:
self.spouse_model.set(iter,0,"unknown\n")
if first_family:
self.display_marriage(first_family)
self.update_list(self.ap_parents_model,self.ap_parents,self.person)
self.family = first_family
def update_list(self,model,tree,person):
model.clear()
sel = None
selection = tree.get_selection()
list = person.getParentList()
for (f,mrel,frel) in list:
father = self.nameof(_("Father"),f.getFather(),frel)
mother = self.nameof(_("Mother"),f.getMother(),mrel)
iter = model.append()
if not sel:
sel = iter
v = "%s\n%s" % (father,mother)
model.set(iter,0,v)
if len(list) > 1:
selection.set_mode(gtk.SELECTION_SINGLE)
selection.select_iter(sel)
else:
selection.set_mode(gtk.SELECTION_NONE)
def nameof(self,l,p,mode):
if p:
2003-01-19 11:55:20 +05:30
n = GrampsCfg.nameof(p)
return _("%s: %s\n\tRelationship: %s") % (l,n,mode)
2002-10-20 19:55:16 +05:30
else:
return _("%s: unknown") % (l)
2002-10-20 19:55:16 +05:30
2002-11-28 11:22:02 +05:30
def delete_family_from(self,person):
person.removeFamily(self.family)
self.parent.db.deleteFamily(self.family)
2002-11-28 11:22:02 +05:30
flist = self.person.getFamilyList()
if len(flist) > 0:
self.family = flist[0][0]
else:
self.family = None
2002-10-20 19:55:16 +05:30
def display_marriage(self,family):
self.child_model.clear()
if not family:
return
else:
self.family = family
if family.getFather() == self.person:
self.selected_spouse = family.getMother()
else:
self.selected_spouse = family.getFather()
if self.selected_spouse:
self.update_list(self.sp_parents_model,self.sp_parents,
self.selected_spouse)
i = 0
fiter = None
child_list = list(family.getChildList())
child_list.sort(sort.by_birthdate)
self.child_map = {}
attr = ""
for child in child_list:
status = _("Unknown")
if child.getGender() == RelLib.Person.male:
2002-10-20 19:55:16 +05:30
gender = const.male
elif child.getGender() == RelLib.Person.female:
2002-10-20 19:55:16 +05:30
gender = const.female
else:
gender = const.unknown
for fam in child.getParentList():
if fam[0] == family:
if self.person == family.getFather():
status = "%s/%s" % (_(fam[2]),_(fam[1]))
else:
status = "%s/%s" % (_(fam[1]),_(fam[2]))
iter = self.child_model.append()
self.child_map[iter] = child.getId()
if fiter == None:
fiter = self.child_model.get_path(iter)
self.child_model.set(iter,
0,(i+1),
1,GrampsCfg.nameof(child),
2,child.getId(),
3,gender,
4,Utils.birthday(child),
5,status,
6,attr)
def edit_ap_parents(self,obj,event):
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
self.parent_editor(self.person,self.ap_selection)
def edit_sp_parents(self,obj,event):
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
self.parent_editor(self.selected_spouse,self.sp_selection)
def add_parents_clicked(self,obj):
self.parent_add(self.person)
def add_sp_parents(self,obj):
if self.selected_spouse:
self.parent_add(self.selected_spouse)
2002-10-20 19:55:16 +05:30
def del_parents_clicked(self,obj):
if len(self.person.getParentList()) == 0:
return
2003-02-24 10:21:57 +05:30
n = GrampsCfg.nameof(self.person)
QuestionDialog(_('Remove Parents of %s') % n,
_('Removing the parents of a person removes the person as a '
'child of the parents. The parents are not removed from the '
'database, and the relationship between the parents '
'is not removed.'),
_('Remove Parents'),
self.really_del_parents)
def really_del_parents(self):
2002-10-20 19:55:16 +05:30
self.parent_deleter(self.person,self.ap_selection)
def del_sp_parents(self,obj):
if not self.selected_spouse or len(self.selected_spouse.getParentList()) == 0:
return
2003-02-24 10:21:57 +05:30
QuestionDialog(_('Remove Parents of %s') % n,
_('Removing the parents of a person removes the person as a '
'child of the parents. The parents are not removed from the '
'database, and the relationship between the parents '
'is not removed.'),
_('Remove Parents'),
self.really_del_sp_parents)
def really_del_sp_parents(self):
2002-10-20 19:55:16 +05:30
self.parent_deleter(self.selected_spouse,self.sp_selection)
def child_back(self,obj):
"""makes the currently select child the active person"""
model, iter = self.child_selection.get_selected()
if iter:
id = self.child_model.get_value(iter,2)
self.parent.change_active_person(self.parent.db.getPerson(id))
self.load_family()
2002-10-20 19:55:16 +05:30
def parent_editor(self,person,selection):
if not person:
return
plist = person.getParentList()
if len(plist) == 0:
return
elif len(plist) == 1:
parents,mrel,frel = plist[0]
else:
model, iter = selection.get_selected()
if not iter:
return
row = model.get_path(iter)
parents,mrel,frel = plist[row[0]]
try:
ChooseParents.ModifyParents(self.parent.db,person,parents,
self.load_family,self.parent.full_update)
except:
DisplayTrace.DisplayTrace()
def parent_add(self,person):
if not person:
return
try:
ChooseParents.ChooseParents(self.parent.db,person,None,
self.load_family,self.parent.full_update)
except:
DisplayTrace.DisplayTrace()
def parent_deleter(self,person,selection):
if not person:
return
plist = person.getParentList()
if len(plist) == 0:
return
if len(plist) == 1:
person.clearAltFamilyList()
else:
model, iter = selection.get_selected()
if not iter:
return
row = model.get_path(iter)
fam = person.getParentList()[row[0]]
person.removeAltFamily(fam[0])
Utils.modified()
2002-10-20 19:55:16 +05:30
self.load_family()
def drag_data_received(self,widget,context,x,y,sel_data,info,time):
path = self.child_list.get_path_at_pos(x,y)
if path == None:
row = len(self.family.getChildList())
else:
row = path[0][0] -1
if sel_data and sel_data.data:
exec 'data = %s' % sel_data.data
exec 'mytype = "%s"' % data[0]
exec 'person = "%s"' % data[1]
if mytype != 'child':
return
s,i = self.child_selection.get_selected()
if not i:
return
spath = s.get_path(i)
src = spath[0]
list = self.family.getChildList()
obj = list[src]
list.remove(obj)
list.insert(row,obj)
if (birth_dates_in_order(list) == 0):
msg = _("Invalid move. Children must be ordered by birth date.")
WarningDialog(msg)
return
self.family.setChildList(list)
self.load_family()
Utils.modified()
def drag_data_get(self,widget, context, sel_data, info, time):
store,iter = self.child_selection.get_selected()
if not iter:
return
id = self.child_model.get_value(iter,2)
person = self.parent.db.getPerson(id)
bits_per = 8; # we're going to pass a string
pickled = pickle.dumps(person);
data = str(('child',id,pickled));
sel_data.set(sel_data.target, bits_per, data)
def drag_begin(self, context, a):
return
#-------------------------------------------------------------------------
#
# birth_dates_in_order
#
# Check any *valid* birthdates in the list to insure that they are in
# numerically increasing order.
#
#-------------------------------------------------------------------------
def birth_dates_in_order(list):
inorder = 1
prev_date = "00000000"
for i in range(len(list)):
child = list[i]
bday = child.getBirth().getDateObj()
child_date = sort.build_sort_date(bday)
if (child_date == "99999999"):
continue
if (prev_date <= child_date): # <= allows for twins
prev_date = child_date
else:
inorder = 0
return inorder