integrated treeview/model into objectselector.

svn: r5897
This commit is contained in:
Richard Taylor
2006-02-08 15:03:06 +00:00
parent bc81ae7f5f
commit 80a0ab047d
12 changed files with 202 additions and 217 deletions

View File

@@ -1,3 +1,12 @@
2006-02-08 Richard Taylor <rjt-gramps@thegrindstone.me.uk>
* src/EditFamily.py, src/Models/_FastFilterModel.py,
src/Models/_FastModel.py, src/ObjectSelector/_FilterFrameBase.py,
src/ObjectSelector/_ObjectFrameBase.py, src/ObjectSelector/_ObjectSelectorWindow.py,
src/ObjectSelector/_PersonFilterFrame.py, src/ObjectSelector/_PersonFrame.py,
src/ObjectSelector/_PersonPreviewFrame.py, src/ObjectSelector/_PersonTreeFrame.py,
src/TreeViews/_PersonTreeView.py: Integrated new treeview/model code into ObjectSelector
2006-02-07 Don Allingham <don@gramps-project.org> 2006-02-07 Don Allingham <don@gramps-project.org>
* src/DisplayModels.py: gobject.TYPE_STRING -> str * src/DisplayModels.py: gobject.TYPE_STRING -> str
* src/EditFamily.py: privacy widget * src/EditFamily.py: privacy widget

View File

@@ -355,27 +355,23 @@ class EditFamily(DisplayState.ManagedWindow):
self.load_parent(handle, self.mbox, self.mbirth, self.load_parent(handle, self.mbox, self.mbirth,
self.mdeath, self.mbutton) self.mdeath, self.mbutton)
def on_change_mother(self, selector_window, select_result): def on_change_mother(self, selector_window, obj):
print select_result if obj.__class__ == RelLib.Person:
if select_result.is_person():
try: try:
gid = select_result.get_gramps_id() person = obj
person = self.dbstate.db.get_person_from_gramps_id(gid)
self.family.set_mother_handle(person.get_handle()) self.family.set_mother_handle(person.get_handle())
self.update_mother(person.get_handle()) self.update_mother(person.get_handle())
except: except:
log.warn( log.warn(
"Failed to update mother: \n" "Failed to update mother: \n"
"gramps_id returned from selector was: %s\n" "obj returned from selector was: %s\n"
"person returned from get_person_from_gramps_id: %s" % (repr(obj),))
% (select_result.get_gramps_id(),
repr(self.dbstate.db.get_person_from_gramps_id(
select_result.get_gramps_id()))))
raise raise
else: else:
log.warn( log.warn(
"Object selector returned a result of type = %s, it should " "Object selector returned obj.__class__ = %s, it should "
"have been of type PERSON." % (str(select_result.get_object_type()))) "have been of type %s." % (obj.__class__.__name__,
RelLib.Person.__name__))
selector_window.close() selector_window.close()
@@ -408,24 +404,23 @@ class EditFamily(DisplayState.ManagedWindow):
selector.connect('add-object',self.on_change_mother) selector.connect('add-object',self.on_change_mother)
def on_change_father(self, selector_window, select_result): def on_change_father(self, selector_window, obj):
if select_result.is_person(): if obj.__class__ == RelLib.Person:
try: try:
gid = select_result.get_gramps_id() person = obj
person = self.dbstate.db.get_person_from_gramps_id(gid)
self.family.set_father_handle(person.get_handle()) self.family.set_father_handle(person.get_handle())
self.update_father(person.get_handle()) self.update_father(person.get_handle())
except: except:
log.warn("Failed to update father: \n" log.warn("Failed to update father: \n"
"gramps_id returned from selector was: %s\n" "obj returned from selector was: %s\n"
"person returned from get_person_from_gramps_id: %s" % (repr(obj),))
% (select_result.get_gramps_id(),
repr(self.dbstate.db.get_person_from_gramps_id(
select_result.get_gramps_id()))))
raise raise
else: else:
log.warn("Object selector returned a result of type = %s, it should " log.warn(
"have been of type PERSON." % (str(select_result.get_object_type()))) "Object selector returned obj.__class__ = %s, it should "
"have been of type %s." % (obj.__class__.__name__,
RelLib.Person.__name__))
selector_window.close() selector_window.close()

View File

@@ -45,17 +45,29 @@ class FastFilterModel(gtk.GenericTreeModel):
self._db = db self._db = db
self._data_filter = data_filter self._data_filter = data_filter
self._fetch_func = self._get_fetch_func(db) self._fetch_func = self._get_fetch_func(db)
self._keys = []
self._length = 0
self._build_data() self._build_data()
def _build_data(self): def _build_data(self):
if not self._data_filter.is_empty(): if not self._data_filter.is_empty():
self._keys = self._data_filter.apply(self._db) self._keys = self._data_filter.apply(self._db)
else: else:
return return
self._length = len(self._keys) self._length = len(self._keys)
# Helper methods to enable treeviews to tell if the model is
# a tree or a list.
def is_tree(self):
return not self.is_list()
def is_list(self):
return self.on_get_flags()&gtk.TREE_MODEL_LIST_ONLY
# Methods that must be implemented by subclasses. # Methods that must be implemented by subclasses.
def _get_fetch_func(self,db): def _get_fetch_func(self,db):
@@ -84,16 +96,29 @@ class FastFilterModel(gtk.GenericTreeModel):
Fetch the real object from the database. Fetch the real object from the database.
""" """
record = None
# We only have one column # We only have one column
if column is 0: if column is 0 and self._length > 0:
record = self._fetch_func(self._keys[rowref[0]]) log.debug("on_get_value: rowref = %s", (repr(rowref)))
# This should never return none, but there is a subtle bug try:
# somewhere that I can't find and sometimes it does. record = self._fetch_func(self._keys[rowref[0]])
if record is None:
log.warn("Failed to fetch a record from the cursor rowref = %s" % (str(rowref))) # This should never return none, but there is a subtle bug
# somewhere that I can't find and sometimes it does.
if record is None:
log.warn("Failed to fetch a record from the "\
"cursor rowref = %s" % (str(rowref)))
except:
log.warn("Failed to fetch record, rowref = %s"\
" len(self._keys) = %d "\
" self._length = %d " % (repr(rowref),
len(self._keys),
self._length),
exc_info=True)
return (record,rowref) return (record,rowref)
def on_iter_next(self, rowref): def on_iter_next(self, rowref):
""" """

View File

@@ -50,6 +50,14 @@ class FastModel(gtk.GenericTreeModel):
self._num_children_cache = {} self._num_children_cache = {}
# Helper methods to enable treeviews to tell if the model is
# a tree or a list.
def is_tree(self):
return not self.is_list()
def is_list(self):
return self.on_get_flags()&gtk.TREE_MODEL_LIST_ONLY
# Methods that must be implemented by subclasses. # Methods that must be implemented by subclasses.

View File

@@ -33,7 +33,10 @@ class FilterFrameBase(gtk.Frame):
__gsignals__ = { __gsignals__ = {
'apply-filter': (gobject.SIGNAL_RUN_LAST, 'apply-filter': (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE, gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,)) (gobject.TYPE_PYOBJECT,)),
'clear-filter': (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
())
} }
__default_border_width = 5 __default_border_width = 5
@@ -56,16 +59,23 @@ class FilterFrameBase(gtk.Frame):
self._control_col = 2 self._control_col = 2
# Apply # Apply / Clear
apply_button = gtk.Button(stock=gtk.STOCK_APPLY) apply_button = gtk.Button(stock=gtk.STOCK_APPLY)
apply_button.connect('clicked',self.on_apply) apply_button.connect('clicked',self.on_apply)
clear_button = gtk.Button(stock=gtk.STOCK_CLEAR)
clear_button.connect('clicked',self.on_clear)
button_box = gtk.HBox()
button_box.pack_start(apply_button,False,False)
button_box.pack_start(clear_button,False,False)
# Outer box # Outer box
outer_box = gtk.VBox() outer_box = gtk.VBox()
outer_box.pack_start(self._table,True,True) outer_box.pack_start(self._table,True,True)
outer_box.pack_start(apply_button,False,False) outer_box.pack_start(button_box,False,False)
outer_box.set_border_width(self.__class__.__default_border_width/2) outer_box.set_border_width(self.__class__.__default_border_width/2)
outer_box.set_spacing(self.__class__.__default_border_width/2) outer_box.set_spacing(self.__class__.__default_border_width/2)
@@ -83,7 +93,12 @@ class FilterFrameBase(gtk.Frame):
"""Build a GenericFilter object from the settings in the filter controls and """Build a GenericFilter object from the settings in the filter controls and
emit a 'apply-filter' signal with the GenericFilter object as the parameter.""" emit a 'apply-filter' signal with the GenericFilter object as the parameter."""
pass raise NotImplementedError("subclass of FilterFrameBase must implement on_apply")
def on_clear(self,button):
"""Clear all the filter widgets and emit a 'clear-filter' signal."""
raise NotImplementedError("subclass of FilterFrameBase must implement on_apply")
if gtk.pygtk_version < (2,8,0): if gtk.pygtk_version < (2,8,0):
gobject.type_register(FilterFrameBase) gobject.type_register(FilterFrameBase)

View File

@@ -82,11 +82,20 @@ class ObjectFrameBase(gtk.Frame):
self.add(pane_align) self.add(pane_align)
def set_preview(self,treeselection,id_field): def set_preview(self,treeselection):
(model, iter) = treeselection.get_selected() (model, iter) = treeselection.get_selected()
if iter and model.get_value(iter,id_field): if iter:
self._preview_frame.set_sensitive(True) (obj,rowref) = model.get_value(iter,0)
self._preview_frame.set_object_from_id(model.get_value(iter,id_field)) if len(rowref) > 1 or model.is_list():
if obj:
self._preview_frame.set_sensitive(True)
self._preview_frame.set_object(obj)
else:
self._preview_frame.set_sensitive(False)
self._preview_frame.clear_object()
else:
self._preview_frame.set_sensitive(False)
self._preview_frame.clear_object()
else: else:
self._preview_frame.set_sensitive(False) self._preview_frame.set_sensitive(False)
self._preview_frame.clear_object() self._preview_frame.clear_object()

View File

@@ -33,7 +33,6 @@ from gettext import gettext as _
import _Factories import _Factories
from _Constants import ObjectTypes from _Constants import ObjectTypes
from _ObjectSelectorResult import ObjectSelectorResult
from DisplayState import ManagedWindow from DisplayState import ManagedWindow
import const import const
@@ -317,14 +316,8 @@ class ObjectSelectorWindow(gtk.Window,ManagedWindow):
self._add_button.set_sensitive(False) self._add_button.set_sensitive(False)
def get_result(self): def on_add(self,widget=None,object=None):
result = ObjectSelectorResult() self.emit('add-object',object)
result.set_object_type(self._current_object_type)
result.set_gramps_id(self._object_frames[self._current_object_type].selected_id)
return result
def on_add(self,button=None):
self.emit('add-object',self.get_result())
def on_selection_changed(self,widget,text,handle): def on_selection_changed(self,widget,text,handle):
if handle: if handle:

View File

@@ -44,28 +44,33 @@ class PersonFilterFrame(FilterFrameBase):
def __init__(self,filter_spec=None,label="Filter"): def __init__(self,filter_spec=None,label="Filter"):
FilterFrameBase.__init__(self,filter_spec,label) FilterFrameBase.__init__(self,filter_spec,label)
self._checkboxes = []
# Gramps ID # Gramps ID
self._id_check = gtk.CheckButton() self._id_check = gtk.CheckButton()
self._checkboxes.append(self._id_check)
id_label = gtk.Label("Gramps ID") id_label = gtk.Label("Gramps ID")
id_label.set_alignment(xalign=0,yalign=0.5) id_label.set_alignment(xalign=0,yalign=0.5)
self._id_edit = gtk.Entry() self._id_edit = gtk.Entry()
self._id_edit.set_sensitive(False)
self._id_check.connect('toggled',lambda b: self._id_edit.set_sensitive(self._id_check.get_active())) self._id_check.connect('toggled',lambda b: self._id_edit.set_sensitive(self._id_check.get_active()))
# Name # Name
self._name_check = gtk.CheckButton() self._name_check = gtk.CheckButton()
self._checkboxes.append(self._name_check)
name_label = gtk.Label("Name") name_label = gtk.Label("Name")
name_label.set_alignment(xalign=0,yalign=0.5) name_label.set_alignment(xalign=0,yalign=0.5)
self._name_edit = gtk.Entry() self._name_edit = gtk.Entry()
self._name_edit.set_sensitive(False)
self._name_check.connect('toggled',lambda b: self._name_edit.set_sensitive(self._name_check.get_active())) self._name_check.connect('toggled',lambda b: self._name_edit.set_sensitive(self._name_check.get_active()))
# Gender # Gender
self._gender_check = gtk.CheckButton() self._gender_check = gtk.CheckButton()
self._checkboxes.append(self._gender_check)
gender_label = gtk.Label("Gender") gender_label = gtk.Label("Gender")
gender_label.set_alignment(xalign=0,yalign=0.5) gender_label.set_alignment(xalign=0,yalign=0.5)
@@ -85,29 +90,26 @@ class PersonFilterFrame(FilterFrameBase):
self._gender_combo.pack_start(label_cell, True) self._gender_combo.pack_start(label_cell, True)
self._gender_combo.add_attribute(label_cell, 'text', 0) self._gender_combo.add_attribute(label_cell, 'text', 0)
self._gender_combo.set_active(2) self._gender_combo.set_active(2)
self._gender_combo.set_sensitive(False)
self._gender_check.connect('toggled',lambda b: self._gender_combo.set_sensitive(self._gender_check.get_active())) self._gender_check.connect('toggled',lambda b: self._gender_combo.set_sensitive(self._gender_check.get_active()))
# Birth # Birth
self._birth_check = gtk.CheckButton() self._birth_check = gtk.CheckButton()
self._birth_check.set_alignment(xalign=0,yalign=0) self._birth_check.set_alignment(xalign=0,yalign=0)
self._checkboxes.append(self._birth_check)
b_label = gtk.Label("Birth Year") b_label = gtk.Label("Birth Year")
b_label.set_alignment(xalign=0,yalign=0) b_label.set_alignment(xalign=0,yalign=0)
self._b_edit = IntEdit() self._b_edit = IntEdit()
self._b_edit.set_sensitive(False)
self._b_before = gtk.RadioButton(group=None,label="Before") self._b_before = gtk.RadioButton(group=None,label="Before")
self._b_before.set_sensitive(False)
self._b_after = gtk.RadioButton(self._b_before,"After") self._b_after = gtk.RadioButton(self._b_before,"After")
self._b_after.set_sensitive(False)
self._b_before.set_active(True) self._b_before.set_active(True)
self._b_unknown = gtk.CheckButton("Include Unknown") self._b_unknown = gtk.CheckButton("Include Unknown")
self._b_unknown.set_sensitive(False)
self._b_unknown.set_active(False) self._b_unknown.set_active(False)
self._birth_check.connect('toggled',lambda b: self._b_edit.set_sensitive(self._birth_check.get_active())) self._birth_check.connect('toggled',lambda b: self._b_edit.set_sensitive(self._birth_check.get_active()))
@@ -122,24 +124,20 @@ class PersonFilterFrame(FilterFrameBase):
# Death # Death
self._death_check = gtk.CheckButton() self._death_check = gtk.CheckButton()
self._checkboxes.append(self._death_check)
d_label = gtk.Label("Death Year") d_label = gtk.Label("Death Year")
d_label.set_alignment(xalign=0,yalign=0) d_label.set_alignment(xalign=0,yalign=0)
self._d_edit = IntEdit() self._d_edit = IntEdit()
self._d_edit.set_sensitive(False)
self._d_before = gtk.RadioButton(group=None,label="Before") self._d_before = gtk.RadioButton(group=None,label="Before")
self._d_before.set_sensitive(False)
self._d_after = gtk.RadioButton(self._d_before,"After") self._d_after = gtk.RadioButton(self._d_before,"After")
self._d_after.set_sensitive(False)
self._d_before.set_active(True) self._d_before.set_active(True)
self._d_before.set_sensitive(False)
self._d_unknown = gtk.CheckButton("Include Unknown") self._d_unknown = gtk.CheckButton("Include Unknown")
self._d_unknown.set_sensitive(False)
self._d_unknown.set_active(False) self._d_unknown.set_active(False)
self._death_check.connect('toggled',lambda b: self._d_edit.set_sensitive(self._death_check.get_active())) self._death_check.connect('toggled',lambda b: self._d_edit.set_sensitive(self._death_check.get_active()))
@@ -153,6 +151,8 @@ class PersonFilterFrame(FilterFrameBase):
# Filter # Filter
self._filter_check = gtk.CheckButton() self._filter_check = gtk.CheckButton()
self._checkboxes.append(self._filter_check)
filter_label = gtk.Label("Filter") filter_label = gtk.Label("Filter")
filter_label.set_alignment(xalign=0,yalign=0.5) filter_label.set_alignment(xalign=0,yalign=0.5)
@@ -196,15 +196,12 @@ class PersonFilterFrame(FilterFrameBase):
self._filter_combo.pack_start(label_cell, True) self._filter_combo.pack_start(label_cell, True)
self._filter_combo.add_attribute(label_cell, 'text', 1) self._filter_combo.add_attribute(label_cell, 'text', 1)
self._filter_combo.set_active(0) self._filter_combo.set_active(0)
self._filter_combo.set_sensitive(False)
self._filter_check.connect('toggled',lambda b: self._filter_combo.set_sensitive(self._filter_check.get_active())) self._filter_check.connect('toggled',lambda b: self._filter_combo.set_sensitive(self._filter_check.get_active()))
self._filter_entry_label = gtk.Label() self._filter_entry_label = gtk.Label()
self._filter_entry_label.set_sensitive(False)
self._filter_entry_edit = gtk.Entry() self._filter_entry_edit = gtk.Entry()
self._filter_entry_edit.set_sensitive(False)
# table layout # table layout
@@ -279,9 +276,30 @@ class PersonFilterFrame(FilterFrameBase):
self._table.attach(self._filter_combo,self._control_col,self._control_col+1, self._table.attach(self._filter_combo,self._control_col,self._control_col+1,
current_row,current_row+1,xoptions=gtk.EXPAND|gtk.FILL,yoptions=False) current_row,current_row+1,xoptions=gtk.EXPAND|gtk.FILL,yoptions=False)
self._reset_widgets()
if filter_spec is not None: if filter_spec is not None:
self._set_filter(filter_spec) self._set_filter(filter_spec)
def _reset_widgets(self):
self._id_edit.set_sensitive(False)
self._name_edit.set_sensitive(False)
self._gender_combo.set_sensitive(False)
self._b_edit.set_sensitive(False)
self._b_before.set_sensitive(False)
self._b_after.set_sensitive(False)
self._b_unknown.set_sensitive(False)
self._d_edit.set_sensitive(False)
self._d_after.set_sensitive(False)
self._d_before.set_sensitive(False)
self._d_unknown.set_sensitive(False)
self._filter_combo.set_sensitive(False)
self._filter_entry_label.set_sensitive(False)
self._filter_entry_edit.set_sensitive(False)
for check in self._checkboxes:
check.set_active(False)
def _set_filter(self,filter_spec): def _set_filter(self,filter_spec):
if filter_spec.include_gramps_id(): if filter_spec.include_gramps_id():
@@ -339,6 +357,9 @@ class PersonFilterFrame(FilterFrameBase):
self._death_check.set_active(False) self._death_check.set_active(False)
self._d_edit.set_text("") self._d_edit.set_text("")
def on_clear(self,button=None):
self._reset_widgets()
self.emit('clear-filter')
def on_apply(self,button=None): def on_apply(self,button=None):
filter = GenericFilter.GenericFilter() filter = GenericFilter.GenericFilter()

View File

@@ -29,12 +29,15 @@ import gobject
from RelLib import Person from RelLib import Person
from EditPerson import EditPerson from EditPerson import EditPerson
from NameDisplay import displayer
display_name = displayer.display
from _ObjectFrameBase import ObjectFrameBase from _ObjectFrameBase import ObjectFrameBase
from _PersonFilterFrame import PersonFilterFrame from _PersonFilterFrame import PersonFilterFrame
from _PersonPreviewFrame import PersonPreviewFrame from _PersonPreviewFrame import PersonPreviewFrame
from _PersonTreeFrame import PersonTreeFrame from _PersonTreeFrame import PersonTreeFrame
class PersonFrame(ObjectFrameBase): class PersonFrame(ObjectFrameBase):
__gproperties__ = {} __gproperties__ = {}
@@ -47,7 +50,7 @@ class PersonFrame(ObjectFrameBase):
'add-object': (gobject.SIGNAL_RUN_LAST, 'add-object': (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE, gobject.TYPE_NONE,
()) (gobject.TYPE_PYOBJECT,))
} }
@@ -67,30 +70,40 @@ class PersonFrame(ObjectFrameBase):
def handle_selection(treeselection): def handle_selection(treeselection):
(model, iter) = treeselection.get_selected() (model, iter) = treeselection.get_selected()
if iter and model.get_value(iter,1): if iter:
self.emit('selection-changed', "%s [%s]" % ( (person,rowref) = model.get_value(iter,0)
str(model.get_value(iter,0)), if len(rowref) > 1 or model.is_list():
str(model.get_value(iter,1))), if person:
model.get_value(iter,1)) self.emit('selection-changed', "%s [%s]" % (
display_name(person),
person.get_gramps_id()),
person.get_handle())
else:
self.emit('selection-changed',"No Selection","")
else:
self.emit('selection-changed',"No Selection","")
else: else:
self.emit('selection-changed',"No Selection","") self.emit('selection-changed',"No Selection","")
self._tree_frame.get_selection().connect('changed',handle_selection) self._tree_frame.get_selection().connect('changed',handle_selection)
self._tree_frame.get_selection().connect('changed',self.set_preview,self.__class__.__person_id_field) self._tree_frame.get_selection().connect('changed',self.set_preview)
self._tree_frame.get_tree().connect('row-activated',self._on_row_activated) self._tree_frame.get_tree().connect('row-activated',self._on_row_activated)
self._filter_frame.connect('apply-filter',lambda w,m: self._tree_frame.set_model(m)) self._filter_frame.connect('apply-filter',lambda w,m: self._tree_frame.set_model(m))
self._filter_frame.connect('clear-filter',lambda w: self._tree_frame.set_model(None))
# Now that the filter is connected we need to tell it to apply any # Now that the filter is connected we need to tell it to apply any
# filter_spec that may have been passed to it. We can't apply the filter # filter_spec that may have been passed to it. We can't apply the filter
# until the connections have been made. # until the connections have been made.
self._filter_frame.on_apply() gobject.idle_add(self._filter_frame.on_apply)
def _on_row_activated(self,widget,path,col): def _on_row_activated(self,widget,path,col):
(model, iter) = widget.get_selection().get_selected() (model, iter) = widget.get_selection().get_selected()
if iter and model.get_value(iter,self.__class__.__person_id_field): if iter:
self.emit('add-object') (o,rowref) = model.get_value(iter,0)
if o:
self.emit('add-object',o)
def new_object(self,button): def new_object(self,button):
person = Person() person = Person()

View File

@@ -130,13 +130,9 @@ class PersonPreviewFrame(gtk.Frame):
escape(short(psrc.get_title()))) escape(short(psrc.get_title())))
return s return s
def set_object_from_id(self,id):
try:
person = self._dbstate.db.get_person_from_gramps_id(id)
if not person:
return
def set_object(self,person):
try:
image_list = person.get_media_list() image_list = person.get_media_list()
if image_list: if image_list:
mobj = self._dbstate.db.get_object_from_handle(image_list[0].ref) mobj = self._dbstate.db.get_object_from_handle(image_list[0].ref)
@@ -152,6 +148,12 @@ class PersonPreviewFrame(gtk.Frame):
log.warn("Failed to generate preview for person", exc_info=True) log.warn("Failed to generate preview for person", exc_info=True)
self.clear_object() self.clear_object()
def set_object_from_id(self,id):
person = self._dbstate.db.get_person_from_gramps_id(id)
if person:
self.set_object(person)
def clear_object(self): def clear_object(self):
self._image.set_from_file(os.path.join(const.rootDir,"person.svg")) self._image.set_from_file(os.path.join(const.rootDir,"person.svg"))
self._label.set_markup("") self._label.set_markup("")

View File

@@ -25,7 +25,9 @@ from gettext import gettext as _
import gtk import gtk
import gobject import gobject
from PeopleModel import PeopleModel #from PeopleModel import PeopleModel
from TreeViews import PersonTreeView
import NameDisplay import NameDisplay
column_names = [ column_names = [
@@ -60,32 +62,12 @@ class PersonTreeFrame(gtk.Frame):
self._model = None self._model = None
self._data_filter = None self._data_filter = None
self._tree = gtk.TreeView() self._tree = PersonTreeView(dbstate.db)
self._tree.set_rules_hint(True) self._tree.set_rules_hint(True)
self._tree.set_headers_visible(True) self._tree.set_headers_visible(True)
#self._tree.connect('key-press-event',self.key_press)
self._tree.connect('row-activated',self._on_row_activated) self._tree.connect('row-activated',self._on_row_activated)
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn(_('Name'), renderer,text=0)
column.set_resizable(True)
column.set_min_width(225)
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
self._tree.append_column(column)
for pair in self._dbstate.db.get_person_column_order():
if not pair[0]:
continue
name = column_names[pair[1]]
column = gtk.TreeViewColumn(name, renderer, markup=pair[1])
column.set_resizable(True)
column.set_min_width(60)
column.set_sizing(gtk.TREE_VIEW_COLUMN_GROW_ONLY)
self._tree.append_column(column)
scrollwindow = gtk.ScrolledWindow() scrollwindow = gtk.ScrolledWindow()
scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrollwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN) scrollwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN)
@@ -106,113 +88,20 @@ class PersonTreeFrame(gtk.Frame):
def change_db(self,db): def change_db(self,db):
self.set_model() self.set_model()
db.connect('person-add', self.person_added)
db.connect('person-update', self.person_updated)
db.connect('person-delete', self.person_removed)
def set_model(self,data_filter=None): def set_model(self,data_filter=None):
self._model = PeopleModel(self._dbstate.db,data_filter=data_filter) if data_filter is None:
self._tree.get_selection().unselect_all()
self._tree.set_model(self._model) self._tree.clear_filter()
else:
self._tree.set_filter(data_filter)
self._selection = self._tree.get_selection() self._selection = self._tree.get_selection()
# expand the first row so that the tree is a sensible size. # expand the first row so that the tree is a sensible size.
self._tree.expand_row((0,),False) self._tree.expand_row((0,),False)
def person_added(self,handle_list):
for node in handle_list:
person = self._dbstate.db.get_person_from_handle(node)
top = NameDisplay.displayer.name_grouping(self._dbstate.db,person)
self._model.rebuild_data(self._data_filter)
if not self._model.is_visable(node):
continue
if (not self._model.sname_sub.has_key(top) or
len(self._model.sname_sub[top]) == 1):
path = self._model.on_get_path(top)
pnode = self._model.get_iter(path)
self._model.row_inserted(path,pnode)
path = self._model.on_get_path(node)
pnode = self._model.get_iter(path)
self._model.row_inserted(path,pnode)
self._tree.expand_to_path(path)
self._tree.set_cursor(path)
def person_removed(self,handle_list):
for node in handle_list:
person = self._dbstate.db.get_person_from_handle(node)
if not self._model.is_visable(node):
continue
top = NameDisplay.displayer.name_grouping(self._dbstate.db,person)
mylist = self._model.sname_sub.get(top,[])
if mylist:
try:
path = self._model.on_get_path(node)
self._model.row_deleted(path)
if len(mylist) == 1:
path = self._model.on_get_path(top)
self._model.row_deleted(path)
except KeyError:
pass
self._model.rebuild_data(self.DataFilter,skip=node)
def person_updated(self,handle_list):
for node in handle_list:
person = self._dbstate.db.get_person_from_handle(node)
try:
oldpath = self._model.iter2path[node]
except:
return
pathval = self._model.on_get_path(node)
pnode = self._model.get_iter(pathval)
# calculate the new data
surname = NameDisplay.displayer.name_grouping(self._dbstate.db,person)
if oldpath[0] == surname:
self._model.build_sub_entry(surname)
else:
self._model.calculate_data(self.DataFilter)
# find the path of the person in the new data build
newpath = self._model.temp_iter2path[node]
# if paths same, just issue row changed signal
if oldpath == newpath:
self._model.row_changed(pathval,pnode)
else:
# paths different, get the new surname list
mylist = self._model.temp_sname_sub.get(oldpath[0],[])
path = self._model.on_get_path(node)
# delete original
self._model.row_deleted(pathval)
# delete top node of original if necessar
if len(mylist)==0:
self._model.row_deleted(pathval[0])
# determine if we need to insert a new top node',
insert = not self._model.sname_sub.has_key(newpath[0])
# assign new data
self._model.assign_data()
# insert new row if needed
if insert:
path = self._model.on_get_path(newpath[0])
pnode = self._model.get_iter(path)
self._model.row_inserted(path,pnode)
# insert new person
path = self._model.on_get_path(node)
pnode = self._model.get_iter(path)
self._model.row_inserted(path,pnode)
def get_selection(self): def get_selection(self):
return self._selection return self._selection

View File

@@ -1,5 +1,6 @@
from gettext import gettext as _ from gettext import gettext as _
import cgi
import gtk import gtk
@@ -7,6 +8,8 @@ from Models import \
PersonTreeModel, PersonListModel, PersonFilterModel PersonTreeModel, PersonListModel, PersonFilterModel
from NameDisplay import displayer from NameDisplay import displayer
from RelLib import Event
import DateHandler
import Utils import Utils
display_given = displayer.display_given display_given = displayer.display_given
@@ -66,21 +69,24 @@ class PersonTreeView(gtk.TreeView):
def _object_id(self, column, cell, model, iter, user_data=None): def _object_id(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
if len(rowref) > 1: if ( len(rowref) > 1 or model.is_list() )and o is not None:
cell.set_property('text', o.get_gramps_id()) cell.set_property('text', o.get_gramps_id())
else: else:
cell.set_property('text', "") cell.set_property('text', "")
def _family_name(self, column, cell, model, iter, user_data=None): def _family_name(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
if len(rowref) > 1: if (len(rowref) > 1 or model.is_list()) and o is not None:
cell.set_property('text', displayer(o)) cell.set_property('text', "%s, %s"% (o.get_primary_name().surname,
display_given(o)))
elif o is not None:
cell.set_property('text',o.get_primary_name().surname)
else: else:
cell.set_property('text',o.primary_name.surname) cell.set_property('text','')
def _gender(self, column, cell, model, iter, user_data=None): def _gender(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
if len(rowref) > 1: if (len(rowref) > 1 or model.is_list()) and o is not None:
cell.set_property('text', Utils.gender[o.gender]) cell.set_property('text', Utils.gender[o.gender])
else: else:
cell.set_property('text', "") cell.set_property('text', "")
@@ -88,62 +94,62 @@ class PersonTreeView(gtk.TreeView):
def _birth_date(self, column, cell, model, iter, user_data=None): def _birth_date(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
cell_value = '' cell_value = ''
if len(rowref) > 1: if (len(rowref) > 1 or model.is_list()) and o is not None:
b = o.get_birth_ref() b = o.get_birth_ref()
if b: if b:
birth = self.db.get_event_from_handle(b.ref) birth = self._db.get_event_from_handle(b.ref)
date_str = DateHandler.get_date(birth) date_str = DateHandler.get_date(birth)
if date_str != "": if date_str != "":
cell_value = cgi.escape(date_str) cell_value = cgi.escape(date_str)
else: else:
for er in o.get_event_ref_list(): for er in o.get_event_ref_list():
event = self.db.get_event_from_handle(er.ref) event = self._db.get_event_from_handle(er.ref)
etype = event.get_type()[0] etype = event.get_type()[0]
date_str = DateHandler.get_date(event) date_str = DateHandler.get_date(event)
if (etype in [Event.BAPTISM, Event.CHRISTEN] if (etype in [Event.BAPTISM, Event.CHRISTEN]
and date_str != ""): and date_str != ""):
return return
cell_value = "<i>" + cgi.escape(date_str) + "</i>" cell_value = "<i>" + cgi.escape(date_str) + "</i>"
cell.set_property('text', cell_value) cell.set_property('markup', cell_value)
def _birth_place(self, column, cell, model, iter, user_data=None): def _birth_place(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
if len(rowref) > 1: if (len(rowref) > 1 or model.is_list()) and o is not None:
cell.set_property('text', "") cell.set_property('text', "")
else: else:
cell.set_property('text', "") cell.set_property('text', "")
def _death_date(self, column, cell, model, iter, user_data=None): def _death_date(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
if len(rowref) > 1: if (len(rowref) > 1 or model.is_list()) and o is not None:
cell.set_property('text', "") cell.set_property('text', "")
else: else:
cell.set_property('text', "") cell.set_property('text', "")
def _death_place(self, column, cell, model, iter, user_data=None): def _death_place(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
if len(rowref) > 1: if (len(rowref) > 1 or model.is_list()) and o is not None:
cell.set_property('text', "") cell.set_property('text', "")
else: else:
cell.set_property('text', "") cell.set_property('text', "")
def _last_change(self, column, cell, model, iter, user_data=None): def _last_change(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
if len(rowref) > 1: if (len(rowref) > 1 or model.is_list()) and o is not None:
cell.set_property('text', "") cell.set_property('text', "")
else: else:
cell.set_property('text', "") cell.set_property('text', "")
def _death_cause(self, column, cell, model, iter, user_data=None): def _death_cause(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
if len(rowref) > 1: if (len(rowref) > 1 or model.is_list()) and o is not None:
cell.set_property('text', "") cell.set_property('text', "")
else: else:
cell.set_property('text', "") cell.set_property('text', "")
def _spouce(self, column, cell, model, iter, user_data=None): def _spouce(self, column, cell, model, iter, user_data=None):
(o,rowref) = model.get_value(iter, 0) (o,rowref) = model.get_value(iter, 0)
if len(rowref) > 1: if (len(rowref) > 1 or model.is_list()) and o is not None:
cell.set_property('text', "") cell.set_property('text', "")
else: else:
cell.set_property('text', "") cell.set_property('text', "")