2007-01-29 Benny Malengier <benny.malengier@ugent.be>

* src/DataViews/_PersonView.py: numlock handling
	* src/PageView.py: numlock handling
	* src/Filters/_SearchBar.py: numblock handling
	* src/Filters/SideBar/_SidebarFilter.py: numblock handling

	* src/DataViews/_PersonView.py: refactoring
	* src/DisplayModels/_PeopleModel.py: refactoring


svn: r8013
This commit is contained in:
Don Allingham 2007-01-30 04:35:13 +00:00
parent f6c7d5b2a1
commit 00bafcca5b
6 changed files with 213 additions and 149 deletions

View File

@ -1,4 +1,12 @@
2007-01-29 Benny Malengier <benny.malengier@ugent.be>
* src/DataViews/_PersonView.py: numlock handling
* src/PageView.py: numlock handling
* src/Filters/_SearchBar.py: numblock handling
* src/Filters/SideBar/_SidebarFilter.py: numblock handling
2007-01-29 Don Allingham <don@gramps-project.org> 2007-01-29 Don Allingham <don@gramps-project.org>
* src/DataViews/_PersonView.py: refactoring
* src/DisplayModels/_PeopleModel.py: refactoring
* src/DisplayModels/_BaseModel.py: Refactor out node/path maps * src/DisplayModels/_BaseModel.py: Refactor out node/path maps
* various: remove sets import * various: remove sets import
* NEWS: update * NEWS: update

View File

@ -742,8 +742,8 @@ class PersonView(PageView.PersonNavView):
if not self.model.is_visable(node): if not self.model.is_visable(node):
continue continue
if (not self.model.sname_sub.has_key(top) or if (not self.model.mapper.has_top_node(top) or
len(self.model.sname_sub[top]) == 1): self.model.mapper.number_of_children(top) == 1):
path = self.model.on_get_path(top) path = self.model.on_get_path(top)
pnode = self.model.get_iter(path) pnode = self.model.get_iter(path)
self.model.row_inserted(path, pnode) self.model.row_inserted(path, pnode)
@ -754,7 +754,7 @@ class PersonView(PageView.PersonNavView):
self.dirty = True self.dirty = True
def func(self, tree, path, ex_list): def func(self, tree, path, ex_list):
ex_list.append(self.model.top_path2iter[path[0]]) ex_list.append(self.model.mapper.top_path2iter[path[0]])
def person_removed(self, handle_list): def person_removed(self, handle_list):
if not self.model: if not self.model:
@ -765,7 +765,7 @@ class PersonView(PageView.PersonNavView):
self.build_tree(handle_list) self.build_tree(handle_list)
for i in expand: for i in expand:
path = self.model.top_iter2path.get(i) path = self.model.mapper.top_iter2path.get(i)
if path: if path:
self.tree.expand_row(path, False) self.tree.expand_row(path, False)
@ -777,7 +777,7 @@ class PersonView(PageView.PersonNavView):
for node in handle_list: for node in handle_list:
person = self.dbstate.db.get_person_from_handle(node) person = self.dbstate.db.get_person_from_handle(node)
try: try:
oldpath = self.model.iter2path[node] oldpath = self.model.mapper.iter2path[node]
except: except:
return return
pathval = self.model.on_get_path(node) pathval = self.model.on_get_path(node)
@ -800,7 +800,7 @@ class PersonView(PageView.PersonNavView):
self.model.calculate_data() self.model.calculate_data()
# find the path of the person in the new data build # find the path of the person in the new data build
newpath = self.model.temp_iter2path[node] newpath = self.model.mapper.temp_iter2path[node]
# if paths same, just issue row changed signal # if paths same, just issue row changed signal
@ -850,7 +850,7 @@ class PersonView(PageView.PersonNavView):
return False return False
def key_press(self,obj,event): def key_press(self,obj,event):
if not event.state: if not event.state or event.state in (gtk.gdk.MOD2_MASK,):
if event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter): if event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter):
if self.dbstate.active: if self.dbstate.active:
self.edit(obj) self.edit(obj)

View File

@ -70,30 +70,145 @@ from Lru import LRU
_CACHE_SIZE = 250 _CACHE_SIZE = 250
#------------------------------------------------------------------------- def locale_sort(mylist):
# """
# python 2.3 has a bug in the unicode sorting using locale.strcoll. Seems Normal sort routine
# to have a buffer overrun. We can convince it to do the right thing by """
# forcing the string to be nul terminated, sorting, then stripping off the l = [ (locale.strxfrm(x),x) for x in mylist ]
# nul. l.sort()
# return [ x[1] for x in l ]
#-------------------------------------------------------------------------
if sys.version_info[0:2] == (2, 3): class NodeTreeMap:
def locale_sort(mylist):
""" def __init__(self):
Sort version to get around a python2.3 bug with unicode strings
""" self.sortnames = {}
mylist = [ value + "\x00" for value in mylist ] self.temp_top_path2iter = []
mylist.sort(locale.strcoll)
return [ value[:-1] for value in mylist ] self.iter2path = {}
else: self.path2iter = {}
def locale_sort(mylist): self.sname_sub = {}
"""
Normal sort routine self.temp_iter2path = {}
""" self.temp_path2iter = {}
mylist.sort(locale.strcoll) self.temp_sname_sub = {}
return mylist
def clear_sort_names(self):
self.sortnames = {}
def clear_temp_data(self):
self.temp_iter2path = {}
self.temp_path2iter = {}
self.temp_sname_sub = {}
def build_toplevel(self):
self.temp_top_path2iter = locale_sort(self.temp_sname_sub.keys())
for name in self.temp_top_path2iter:
self.build_sub_entry(name)
def get_group_names(self):
return self.temp_top_path2iter
def assign_sort_name(self, handle, sorted_name, group_name):
self.sortnames[handle] = sorted_name
try:
self.temp_sname_sub[group_name].append(handle)
except:
self.temp_sname_sub[group_name] = [handle]
def assign_data(self):
self.top_path2iter = self.temp_top_path2iter
self.iter2path = self.temp_iter2path
self.path2iter = self.temp_path2iter
self.sname_sub = self.temp_sname_sub
self.top_iter2path = {}
i = 0
for item in self.top_path2iter:
self.top_iter2path[item] = i
i+=1
def get_path(self, node):
try:
return (self.top_iter2path[node], )
except:
(surname, index) = self.iter2path[node]
return (self.top_iter2path[surname], index)
def has_entry(self, handle):
return self.iter2path.has_key(handle)
def get_iter(self, path):
try:
if len(path)==1: # Top Level
return self.top_path2iter[path[0]]
else: # Sublevel
surname = self.top_path2iter[path[0]]
return self.path2iter[(surname, path[1])]
except:
return None
def has_top_node(self, node):
return self.sname_sub.has_key(node)
def find_next_node(self, node):
try:
path = self.top_iter2path[node]
if path+1 == len(self.top_path2iter):
return None
return self.top_path2iter[path+1]
except:
(surname, val) = self.iter2path[node]
return self.path2iter.get((surname, val+1))
def first_child(self, node):
if node == None:
return self.top_path2iter[0]
else:
return self.path2iter.get((node, 0))
def has_child(self, node):
if node == None:
return len(self.sname_sub)
if self.sname_sub.has_key(node) and len(self.sname_sub[node]) > 0:
return True
return False
def number_of_children(self, node):
if node == None:
return len(self.sname_sub)
try:
return len(self.sname_sub[node])
except:
return 0
def get_nth_child(self, node, n):
try:
if node == None:
return self.top_path2iter[n]
try:
return self.path2iter[(node, n)]
except:
return None
except IndexError:
return None
def get_parent_of(self, node):
path = self.iter2path.get(node)
if path:
return path[0]
return None
def build_sub_entry(self, name):
slist = [ (locale.strxfrm(self.sortnames[x]), x) \
for x in self.temp_sname_sub[name] ]
slist.sort()
val = 0
for (junk, person_handle) in slist:
tpl = (name, val)
self.temp_iter2path[person_handle] = tpl
self.temp_path2iter[tpl] = person_handle
val += 1
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -122,7 +237,6 @@ class PeopleModel(gtk.GenericTreeModel):
_CHANGE_COL = 17 _CHANGE_COL = 17
_MARKER_COL = 18 _MARKER_COL = 18
_GENDER = [ _(u'female'), _(u'male'), _(u'unknown') ] _GENDER = [ _(u'female'), _(u'male'), _(u'unknown') ]
# dynamic calculation of column indices, for use by various Views # dynamic calculation of column indices, for use by various Views
@ -153,13 +267,10 @@ class PeopleModel(gtk.GenericTreeModel):
self.todo_color = Config.get(Config.TODO_COLOR) self.todo_color = Config.get(Config.TODO_COLOR)
self.custom_color = Config.get(Config.CUSTOM_MARKER_COLOR) self.custom_color = Config.get(Config.CUSTOM_MARKER_COLOR)
self.sortnames = {}
self.marker_color_column = 10 self.marker_color_column = 10
self.tooltip_column = 11 self.tooltip_column = 11
self.temp_top_path2iter = []
self.iter2path = {} self.mapper = NodeTreeMap()
self.path2iter = {}
self.sname_sub = {}
if filter_info and filter_info != (1, (0, u'', False)): if filter_info and filter_info != (1, (0, u'', False)):
if filter_info[0] == PeopleModel.GENERIC: if filter_info[0] == PeopleModel.GENERIC:
@ -204,11 +315,12 @@ class PeopleModel(gtk.GenericTreeModel):
self.current_filter = data_filter self.current_filter = data_filter
def _build_search_sub(self,dfilter, skip): def _build_search_sub(self,dfilter, skip):
self.sortnames = {}
ngn = NameDisplay.displayer.name_grouping_data ngn = NameDisplay.displayer.name_grouping_data
nsn = NameDisplay.displayer.raw_sorted_name nsn = NameDisplay.displayer.raw_sorted_name
self.mapper.clear_sort_names()
cursor = self.db.get_person_cursor() cursor = self.db.get_person_cursor()
node = cursor.first() node = cursor.first()
@ -216,17 +328,15 @@ class PeopleModel(gtk.GenericTreeModel):
handle, d = node handle, d = node
if not (handle in skip or (dfilter and not dfilter.match(handle))): if not (handle in skip or (dfilter and not dfilter.match(handle))):
name_data = d[PeopleModel._NAME_COL] name_data = d[PeopleModel._NAME_COL]
sn = ngn(self.db, name_data)
self.sortnames[handle] = nsn(name_data) group_name = ngn(self.db, name_data)
try: sorted_name = nsn(name_data)
self.temp_sname_sub[sn].append(handle)
except: self.mapper.assign_sort_name(handle, sorted_name, group_name)
self.temp_sname_sub[sn] = [handle]
node = cursor.next() node = cursor.next()
cursor.close() cursor.close()
def _build_filter_sub(self,dfilter, skip): def _build_filter_sub(self,dfilter, skip):
self.sortnames = {}
ngn = NameDisplay.displayer.name_grouping_data ngn = NameDisplay.displayer.name_grouping_data
nsn = NameDisplay.displayer.raw_sorted_name nsn = NameDisplay.displayer.raw_sorted_name
@ -236,16 +346,17 @@ class PeopleModel(gtk.GenericTreeModel):
else: else:
handle_list = self.db.get_person_handles() handle_list = self.db.get_person_handles()
self.mapper.clear_sort_names()
for handle in handle_list: for handle in handle_list:
d = self.db.get_raw_person_data(handle) d = self.db.get_raw_person_data(handle)
if not (handle in skip or (dfilter and not dfilter.match(handle))): if not (handle in skip or (dfilter and not dfilter.match(handle))):
name_data = d[PeopleModel._NAME_COL] name_data = d[PeopleModel._NAME_COL]
sn = ngn(self.db, name_data)
self.sortnames[handle] = nsn(name_data) group_name = ngn(self.db, name_data)
try: sorted_name = nsn(name_data)
self.temp_sname_sub[sn].append(handle)
except: self.mapper.assign_sort_name(handle, sorted_name, group_name)
self.temp_sname_sub[sn] = [handle]
def calculate_data(self, dfilter=None, skip=[]): def calculate_data(self, dfilter=None, skip=[]):
""" """
@ -259,18 +370,16 @@ class PeopleModel(gtk.GenericTreeModel):
if dfilter: if dfilter:
self.dfilter = dfilter self.dfilter = dfilter
self.temp_iter2path = {}
self.temp_path2iter = {} self.mapper.clear_temp_data()
self.temp_sname_sub = {}
if not self.db.is_open(): if not self.db.is_open():
return return
self._build_data(dfilter, skip) self._build_data(dfilter, skip)
self.temp_top_path2iter = locale_sort(self.temp_sname_sub.keys()) self.mapper.build_toplevel()
for name in self.temp_top_path2iter:
self.build_sub_entry(name)
self.in_build = False self.in_build = False
def clear_cache(self): def clear_cache(self):
@ -280,27 +389,10 @@ class PeopleModel(gtk.GenericTreeModel):
self.lru_ddate = LRU(_CACHE_SIZE) self.lru_ddate = LRU(_CACHE_SIZE)
def build_sub_entry(self, name): def build_sub_entry(self, name):
slist = [ (locale.strxfrm(self.sortnames[x]), x) \ self.mapper.build_sub_entry(name)
for x in self.temp_sname_sub[name] ]
slist.sort()
val = 0
for (junk, person_handle) in slist:
tpl = (name, val)
self.temp_iter2path[person_handle] = tpl
self.temp_path2iter[tpl] = person_handle
val += 1
def assign_data(self): def assign_data(self):
self.top_path2iter = self.temp_top_path2iter self.mapper.assign_data()
self.iter2path = self.temp_iter2path
self.path2iter = self.temp_path2iter
self.sname_sub = self.temp_sname_sub
self.top_iter2path = {}
i = 0
for item in self.top_path2iter:
self.top_iter2path[item] = i
i+=1
def on_get_flags(self): def on_get_flags(self):
'''returns the GtkTreeModelFlags for this particular type of model''' '''returns the GtkTreeModelFlags for this particular type of model'''
@ -312,31 +404,20 @@ class PeopleModel(gtk.GenericTreeModel):
def on_get_path(self, node): def on_get_path(self, node):
'''returns the tree path (a tuple of indices at the various '''returns the tree path (a tuple of indices at the various
levels) for a particular node.''' levels) for a particular node.'''
try: return self.mapper.get_path(node)
return (self.top_iter2path[node], )
except:
(surname, index) = self.iter2path[node]
return (self.top_iter2path[surname], index)
def is_visable(self, handle): def is_visable(self, handle):
return self.iter2path.has_key(handle) return self.mapper.has_entry(handle)
def on_get_column_type(self, index): def on_get_column_type(self, index):
return PeopleModel.COLUMN_DEFS[index][PeopleModel.COLUMN_DEF_TYPE] return PeopleModel.COLUMN_DEFS[index][PeopleModel.COLUMN_DEF_TYPE]
def on_get_iter(self, path): def on_get_iter(self, path):
try: return self.mapper.get_iter(path)
if len(path)==1: # Top Level
return self.top_path2iter[path[0]]
else: # Sublevel
surname = self.top_path2iter[path[0]]
return self.path2iter[(surname, path[1])]
except:
return None
def on_get_value(self, node, col): def on_get_value(self, node, col):
# test for header or data row-type # test for header or data row-type
if self.sname_sub.has_key(node): if self.mapper.has_top_node(node):
# Header rows dont get the foreground color set # Header rows dont get the foreground color set
if col == self.marker_color_column: if col == self.marker_color_column:
return None return None
@ -364,55 +445,25 @@ class PeopleModel(gtk.GenericTreeModel):
def on_iter_next(self, node): def on_iter_next(self, node):
'''returns the next node at this level of the tree''' '''returns the next node at this level of the tree'''
try: return self.mapper.find_next_node(node)
path = self.top_iter2path[node]
if path+1 == len(self.top_path2iter):
return None
return self.top_path2iter[path+1]
except:
(surname, val) = self.iter2path[node]
return self.path2iter.get((surname, val+1))
def on_iter_children(self, node): def on_iter_children(self, node):
"""Return the first child of the node""" """Return the first child of the node"""
if node == None: return self.mapper.first_child(node)
return self.top_path2iter[0]
else:
return self.path2iter.get((node, 0))
def on_iter_has_child(self, node): def on_iter_has_child(self, node):
'''returns true if this node has children''' '''returns true if this node has children'''
if node == None: return self.mapper.has_child(node)
return len(self.sname_sub)
if self.sname_sub.has_key(node) and len(self.sname_sub[node]) > 0:
return True
return False
def on_iter_n_children(self, node): def on_iter_n_children(self, node):
if node == None: return self.mapper.number_of_children(node)
return len(self.sname_sub)
try:
return len(self.sname_sub[node])
except:
return 0
def on_iter_nth_child(self, node, n): def on_iter_nth_child(self, node, n):
try: return self.mapper.get_nth_child(node, n)
if node == None:
return self.top_path2iter[n]
try:
return self.path2iter[(node, n)]
except:
return None
except IndexError:
return None
def on_iter_parent(self, node): def on_iter_parent(self, node):
'''returns the parent of this node''' '''returns the parent of this node'''
path = self.iter2path.get(node) return self.mapper.get_parent_of(node)
if path:
return path[0]
return None
def column_sort_name(self, data, node): def column_sort_name(self, data, node):
n = Name() n = Name()
@ -489,7 +540,7 @@ class PeopleModel(gtk.GenericTreeModel):
if (etype in [EventType.BAPTISM, EventType.CHRISTEN] if (etype in [EventType.BAPTISM, EventType.CHRISTEN]
and er.get_role() == EventRoleType.PRIMARY and er.get_role() == EventRoleType.PRIMARY
and date_str != ""): and date_str != ""):
return "<i>" + cgi.escape(date_str) + "</i>" return "<i>%s</i>" % cgi.escape(date_str)
return u"" return u""
@ -524,8 +575,8 @@ class PeopleModel(gtk.GenericTreeModel):
date_str = DateHandler.get_date(event) date_str = DateHandler.get_date(event)
if (etype in [EventType.BURIAL, EventType.CREMATION] if (etype in [EventType.BURIAL, EventType.CREMATION]
and er.get_role() == EventRoleType.PRIMARY and er.get_role() == EventRoleType.PRIMARY
and date_str != ""): and date_str):
return "<i>" + cgi.escape(date_str) + "</i>" return "<i>%s</i>" % cgi.escape(date_str)
return u"" return u""
@ -542,7 +593,7 @@ class PeopleModel(gtk.GenericTreeModel):
if place_handle: if place_handle:
place = self.db.get_place_from_handle(place_handle) place = self.db.get_place_from_handle(place_handle)
place_title = place.get_title() place_title = place.get_title()
if place_title != "": if place_title:
return cgi.escape(place_title) return cgi.escape(place_title)
except: except:
return u'' return u''
@ -558,8 +609,8 @@ class PeopleModel(gtk.GenericTreeModel):
if place_handle: if place_handle:
place = self.db.get_place_from_handle(place_handle) place = self.db.get_place_from_handle(place_handle)
place_title = place.get_title() place_title = place.get_title()
if place_title != "": if place_title:
return "<i>" + cgi.escape(place_title) + "</i>" return "<i>%s</i>" % cgi.escape(place_title)
return u"" return u""
@ -576,7 +627,7 @@ class PeopleModel(gtk.GenericTreeModel):
if place_handle: if place_handle:
place = self.db.get_place_from_handle(place_handle) place = self.db.get_place_from_handle(place_handle)
place_title = place.get_title() place_title = place.get_title()
if place_title != "": if place_title:
return cgi.escape(place_title) return cgi.escape(place_title)
except: except:
return u'' return u''

View File

@ -25,6 +25,7 @@ import gtk
import GrampsWidgets import GrampsWidgets
_RETURN = gtk.gdk.keyval_from_name("Return") _RETURN = gtk.gdk.keyval_from_name("Return")
_KP_ENTER = gtk.gdk.keyval_from_name("KP_Enter")
class SidebarFilter: class SidebarFilter:
@ -99,8 +100,9 @@ class SidebarFilter:
self.tooltips.set_tip(widget, tooltip) self.tooltips.set_tip(widget, tooltip)
def key_press(self, obj, event): def key_press(self, obj, event):
if event.keyval == _RETURN and not event.state: if not event.state or event.state in (gtk.gdk.MOD2_MASK,):
self.clicked(obj) if event.keyval in (_RETURN, _KP_ENTER):
self.clicked(obj)
return False return False
def add_entry(self, name, widget): def add_entry(self, name, widget):

View File

@ -33,6 +33,7 @@ import gtk
from gettext import gettext as _ from gettext import gettext as _
_RETURN = gtk.gdk.keyval_from_name("Return") _RETURN = gtk.gdk.keyval_from_name("Return")
_KP_ENTER = gtk.gdk.keyval_from_name("KP_Enter")
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -114,10 +115,11 @@ class SearchBar:
self.clear_button.set_sensitive(True) self.clear_button.set_sensitive(True)
def key_press(self, obj, event): def key_press(self, obj, event):
if event.keyval == _RETURN and not event.state: if not event.state or event.state in (gtk.gdk.MOD2_MASK,):
self.filter_button.set_sensitive(False) if event.keyval in (_RETURN, _KP_ENTER):
self.clear_button.set_sensitive(True) self.filter_button.set_sensitive(False)
self.apply_filter() self.clear_button.set_sensitive(True)
self.apply_filter()
return False return False
def apply_filter_clicked(self, obj): def apply_filter_clicked(self, obj):

View File

@ -174,10 +174,11 @@ class PageView:
pass pass
def key_press(self,obj,event): def key_press(self,obj,event):
ret_key = gtk.gdk.keyval_from_name("Return") #act if no modifier, and allow Num Lock as MOD2_MASK
if event.keyval == ret_key and not event.state: if not event.state or event.state in (gtk.gdk.MOD2_MASK,):
self.edit(obj) if event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter):
return True self.edit(obj)
return True
return False return False
def blist(self,store,path,iter,sel_list): def blist(self,store,path,iter,sel_list):
@ -771,8 +772,8 @@ class ListView(BookMarkView):
def row_add(self,handle_list): def row_add(self,handle_list):
if self.active: if self.active:
for handle in handle_list: for handle in handle_list:
self.model.add_row_by_handle(handle) self.model.add_row_by_handle(handle)
else: else:
self.dirty = True self.dirty = True
@ -837,10 +838,10 @@ class ListView(BookMarkView):
return False return False
def key_press(self,obj,event): def key_press(self,obj,event):
ret_key = gtk.gdk.keyval_from_name("Return") if not event.state or event.state in (gtk.gdk.MOD2_MASK,):
if event.keyval == ret_key and not event.state: if event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter):
self.edit(obj) self.edit(obj)
return True return True
return False return False
def double_click(self,obj,event): def double_click(self,obj,event):