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>
* src/DataViews/_PersonView.py: refactoring
* src/DisplayModels/_PeopleModel.py: refactoring
* src/DisplayModels/_BaseModel.py: Refactor out node/path maps
* various: remove sets import
* NEWS: update

View File

@ -742,8 +742,8 @@ class PersonView(PageView.PersonNavView):
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):
if (not self.model.mapper.has_top_node(top) or
self.model.mapper.number_of_children(top) == 1):
path = self.model.on_get_path(top)
pnode = self.model.get_iter(path)
self.model.row_inserted(path, pnode)
@ -754,7 +754,7 @@ class PersonView(PageView.PersonNavView):
self.dirty = True
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):
if not self.model:
@ -765,7 +765,7 @@ class PersonView(PageView.PersonNavView):
self.build_tree(handle_list)
for i in expand:
path = self.model.top_iter2path.get(i)
path = self.model.mapper.top_iter2path.get(i)
if path:
self.tree.expand_row(path, False)
@ -777,7 +777,7 @@ class PersonView(PageView.PersonNavView):
for node in handle_list:
person = self.dbstate.db.get_person_from_handle(node)
try:
oldpath = self.model.iter2path[node]
oldpath = self.model.mapper.iter2path[node]
except:
return
pathval = self.model.on_get_path(node)
@ -800,7 +800,7 @@ class PersonView(PageView.PersonNavView):
self.model.calculate_data()
# 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
@ -850,7 +850,7 @@ class PersonView(PageView.PersonNavView):
return False
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 self.dbstate.active:
self.edit(obj)

View File

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

View File

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

View File

@ -33,6 +33,7 @@ import gtk
from gettext import gettext as _
_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)
def key_press(self, obj, event):
if event.keyval == _RETURN and not event.state:
self.filter_button.set_sensitive(False)
self.clear_button.set_sensitive(True)
self.apply_filter()
if not event.state or event.state in (gtk.gdk.MOD2_MASK,):
if event.keyval in (_RETURN, _KP_ENTER):
self.filter_button.set_sensitive(False)
self.clear_button.set_sensitive(True)
self.apply_filter()
return False
def apply_filter_clicked(self, obj):

View File

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