speed improvements until object selector is functional

svn: r6175
This commit is contained in:
Don Allingham 2006-03-19 03:25:31 +00:00
parent e42618c337
commit a08d178f1b
11 changed files with 176 additions and 107 deletions

View File

@ -1,3 +1,20 @@
2006-03-18 Don Allingham <don@gramps-project.org>
* src/DataViews/_PersonView.py: use fixed width/height mode to
prevent unnecessary reads during initialization. Prevent double
loading of data from filter.
* src/GrampsDb/_GrampsDbBase.py: provide widths for person view columns
* src/RelLib/_Name.py: provide fast, shallow initialization of values
for quick access when only name functions are needed
* src/Editors/_EditFamily.py: Switch from ObjectSelector to SelectPerson
until the ObjectSelector cursor issues are resolved
* src/PeopleModel.py: Faster access to rebuilding data
* src/Utils.py: handle if locale.getpreferredencondings fails
* src/NameDisplay.py: speed up name display by using string join
* src/GenericFilter.py: provide match function as a temporary fix until
filters are redesigned
* src/SelectPerson.py: used fixed width/height mode
* src/PageView.py: suppress tooltips if requested
2006-03-17 Don Allingham <don@gramps-project.org> 2006-03-17 Don Allingham <don@gramps-project.org>
* src/Editors/_EditFamily.py: convert father to use SelectPerson instead * src/Editors/_EditFamily.py: convert father to use SelectPerson instead
of ObjectSelector of ObjectSelector

View File

@ -148,6 +148,7 @@ class PersonView(PageView.PersonNavView):
self.tree = gtk.TreeView() self.tree = gtk.TreeView()
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.set_fixed_height_mode(True)
self.tree.connect('key-press-event',self.key_press) self.tree.connect('key-press-event',self.key_press)
scrollwindow = gtk.ScrolledWindow() scrollwindow = gtk.ScrolledWindow()
@ -247,7 +248,7 @@ class PersonView(PageView.PersonNavView):
db.connect('person-update', self.person_updated) db.connect('person-update', self.person_updated)
db.connect('person-delete', self.person_removed) db.connect('person-delete', self.person_removed)
db.connect('person-rebuild', self.build_tree) db.connect('person-rebuild', self.build_tree)
self.build_tree() # self.build_tree()
self.generic_filter_widget.apply_filter() self.generic_filter_widget.apply_filter()
def goto_active_person(self,obj=None): def goto_active_person(self,obj=None):
@ -349,7 +350,8 @@ class PersonView(PageView.PersonNavView):
self.tree.set_model(self.model) self.tree.set_model(self.model)
if self.model.tooltip_column != None: if self.model.tooltip_column != None:
self.tooltips = TreeTips.TreeTips(self.tree,self.model.tooltip_column,True) self.tooltips = TreeTips.TreeTips(self.tree, self.model.tooltip_column,
True)
self.build_columns() self.build_columns()
self.dirty = False self.dirty = False
else: else:
@ -453,8 +455,8 @@ class PersonView(PageView.PersonNavView):
column.set_resizable(True) column.set_resizable(True)
#column.set_clickable(True) #column.set_clickable(True)
#column.connect('clicked',self.sort_clicked) #column.connect('clicked',self.sort_clicked)
column.set_min_width(225)
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
column.set_fixed_width(225)
self.tree.append_column(column) self.tree.append_column(column)
self.columns = [column] self.columns = [column]
@ -468,8 +470,8 @@ class PersonView(PageView.PersonNavView):
except AttributeError: except AttributeError:
column = gtk.TreeViewColumn(name, self.renderer, markup=pair[1]) column = gtk.TreeViewColumn(name, self.renderer, markup=pair[1])
column.set_resizable(True) column.set_resizable(True)
column.set_min_width(60) column.set_fixed_width(pair[2])
column.set_sizing(gtk.TREE_VIEW_COLUMN_GROW_ONLY) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
self.columns.append(column) self.columns.append(column)
self.tree.append_column(column) self.tree.append_column(column)

View File

@ -236,6 +236,24 @@ class ChildEmbedList(EmbeddedList):
except Errors.WindowActiveError: except Errors.WindowActiveError:
pass pass
class FastMaleFilter:
def __init__(self,db):
self.db = db
def match(self, handle):
value = self.db.get_raw_person_data(handle)
return value[2] == RelLib.Person.MALE
class FastFemaleFilter:
def __init__(self,db):
self.db = db
def match(self, handle):
value = self.db.get_raw_person_data(handle)
return value[2] == RelLib.Person.FEMALE
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# EditFamily # EditFamily
@ -403,33 +421,50 @@ class EditFamily(EditPrimary):
selector_window.close() selector_window.close()
def mother_clicked(self,obj): def mother_clicked(self, obj):
handle = self.obj.get_mother_handle() handle = self.obj.get_mother_handle()
if handle: if handle:
self.obj.set_mother_handle(None) self.obj.set_mother_handle(None)
self.update_mother(None) self.update_mother(None)
else: else:
filter_spec = PersonFilterSpec() from SelectPerson import SelectPerson
filter_spec.set_gender(RelLib.Person.FEMALE)
data_filter = FastFemaleFilter(self.dbstate.db)
sel = SelectPerson(self.dbstate.db, "Select Mother",
filter=data_filter,
skip=self.obj.get_child_handle_list())
person = sel.run()
if person:
self.obj.set_mother_handle(person.handle)
self.update_mother(person.handle)
# def mother_clicked(self,obj):
# handle = self.obj.get_mother_handle()
# if handle:
# self.obj.set_mother_handle(None)
# self.update_mother(None)
# else:
# filter_spec = PersonFilterSpec()
# filter_spec.set_gender(RelLib.Person.FEMALE)
child_birth_years = [] # child_birth_years = []
for person_handle in self.obj.get_child_handle_list(): # for person_handle in self.obj.get_child_handle_list():
person = self.db.get_person_from_handle(person_handle) # person = self.db.get_person_from_handle(person_handle)
event_ref = person.get_birth_ref() # event_ref = person.get_birth_ref()
if event_ref and event_ref.ref: # if event_ref and event_ref.ref:
event = self.db.get_event_from_handle(event_ref.ref) # event = self.db.get_event_from_handle(event_ref.ref)
child_birth_years.append(event.get_date_object().get_year()) # child_birth_years.append(event.get_date_object().get_year())
if len(child_birth_years) > 0: # if len(child_birth_years) > 0:
filter_spec.set_birth_year(min(child_birth_years)) # filter_spec.set_birth_year(min(child_birth_years))
filter_spec.set_birth_criteria(PersonFilterSpec.BEFORE) # filter_spec.set_birth_criteria(PersonFilterSpec.BEFORE)
selector = PersonSelector(self.dbstate,self.uistate, # selector = PersonSelector(self.dbstate,self.uistate,
self.track,filter_spec=filter_spec) # self.track,filter_spec=filter_spec)
selector.connect('add-object',self.on_change_mother) # selector.connect('add-object',self.on_change_mother)
def on_change_father(self, selector_window, obj): def on_change_father(self, selector_window, obj):
if obj.__class__ == RelLib.Person: if obj.__class__ == RelLib.Person:
try: try:
@ -457,11 +492,8 @@ class EditFamily(EditPrimary):
self.update_father(None) self.update_father(None)
else: else:
from SelectPerson import SelectPerson from SelectPerson import SelectPerson
import GenericFilter
data_filter = GenericFilter.GenericFilter() data_filter = FastMaleFilter(self.dbstate.db)
data_filter.add_rule(GenericFilter.IsMale([]))
sel = SelectPerson(self.dbstate.db, "Select Father", sel = SelectPerson(self.dbstate.db, "Select Father",
filter=data_filter, filter=data_filter,
skip=self.obj.get_child_handle_list()) skip=self.obj.get_child_handle_list())

View File

@ -1913,6 +1913,9 @@ class GenericFilter:
self.logical_op = 'and' self.logical_op = 'and'
self.invert = False self.invert = False
def match(self,handle):
return True
def is_empty(self): def is_empty(self):
return len(self.flist) == 1 and self.flist[0].is_empty() return len(self.flist) == 1 and self.flist[0].is_empty()

View File

@ -1708,7 +1708,8 @@ class GrampsDbBase(GrampsDBCallback):
Returns the Person display common information stored in the Returns the Person display common information stored in the
database's metadata. database's metadata.
""" """
default = [(1,1),(1,2),(1,3),(0,4),(1,5),(0,6),(0,7),(0,8),(0,9,)] default = [(1,1,100),(1,2,100),(1,3,150),(0,4,150),(1,5,150),
(0,6,150),(0,7,100),(0,8,100),(0,9,100)]
return self._get_column_order(PERSON_COL_KEY,default) return self._get_column_order(PERSON_COL_KEY,default)
def _get_columns(self,key,default): def _get_columns(self,key,default):

View File

@ -102,16 +102,16 @@ class NameDisplay:
else: else:
last = name.patronymic last = name.patronymic
if name.suffix == "": if name.suffix:
if name.prefix:
return "%s %s, %s" % (name.prefix, last, first)
else:
return "%s, %s" % (last, first)
else:
if name.prefix: if name.prefix:
return "%s %s %s, %s" % (name.prefix, last, name.suffix, first) return "%s %s %s, %s" % (name.prefix, last, name.suffix, first)
else: else:
return "%s %s, %s" % (last, name.suffix, first) return "%s %s, %s" % (last, name.suffix, first)
else:
if name.prefix:
return "%s %s, %s" % (name.prefix, last, first)
else:
return "%s, %s" % (last, first)
def _fnln(self,name,nickname=""): def _fnln(self,name,nickname=""):
""" """
@ -120,12 +120,8 @@ class NameDisplay:
FirstName Patronymic SurnamePrefix Surname SurnameSuffix FirstName Patronymic SurnamePrefix Surname SurnameSuffix
""" """
first = name.first_name first = name.first_name
if nickname:
first = '%s "%s"' % (first,nickname)
if name.patronymic: if name.patronymic:
first = "%s %s" % (first, name.patronymic) first = "%s %s" % (first, name.patronymic)
@ -134,16 +130,16 @@ class NameDisplay:
else: else:
last = name.surname last = name.surname
if name.suffix == "": if name.suffix:
if name.prefix:
return "%s %s %s" % (first, name.prefix, last)
else:
return "%s %s" % (first, last)
else:
if name.prefix: if name.prefix:
return "%s %s %s, %s" % (first, name.prefix, last, name.suffix) return "%s %s %s, %s" % (first, name.prefix, last, name.suffix)
else: else:
return "%s %s, %s" % (first, last, name.suffix) return "%s %s, %s" % (first, last, name.suffix)
else:
if name.prefix:
return "%s %s %s" % (first, name.prefix, last)
else:
return "%s %s" % (first, last)
def _lnfn(self,name,nickname=u""): def _lnfn(self,name,nickname=u""):
""" """
@ -152,12 +148,6 @@ class NameDisplay:
SurnamePrefix Surname, FirstName Patronymic SurnameSuffix SurnamePrefix Surname, FirstName Patronymic SurnameSuffix
""" """
first = name.first_name
if name.patronymic:
first = "%s %s" % (first, name.patronymic)
if self.force_upper: if self.force_upper:
last = name.surname.upper() last = name.surname.upper()
else: else:
@ -166,20 +156,13 @@ class NameDisplay:
if last: if last:
last += "," last += ","
if name.suffix: return " ".join([x for x in [name.prefix, last, name.first_name,
if name.prefix: name.patronymic, name.suffix]])
return "%s %s %s %s" % (name.prefix, last, first, name.suffix)
else:
return "%s %s %s" % (last, first, name.suffix)
else:
if name.prefix:
return "%s %s %s" % (name.prefix, last, first)
else:
return "%s %s" % (last, first)
fn_array = { Name.FNLN : _fnln, fn_array = { Name.FNLN : _fnln,
Name.PTFN : _ptfn, Name.PTFN : _ptfn,
Name.FN : _empty, Name.FN : _empty,
Name.LNFN : _lnfn,
} }
def sorted_name(self,name): def sorted_name(self,name):

View File

@ -42,6 +42,7 @@ import pango
#---------------------------------------------------------------- #----------------------------------------------------------------
import TreeTips import TreeTips
import GenericFilter import GenericFilter
import const
NAVIGATION_NONE = -1 NAVIGATION_NONE = -1
NAVIGATION_PERSON = 0 NAVIGATION_PERSON = 0
@ -454,7 +455,7 @@ class ListView(PageView):
self.list.set_model(self.model) self.list.set_model(self.model)
self.selection = self.list.get_selection() self.selection = self.list.get_selection()
if self.model.tooltip_column != None: if const.use_tips and self.model.tooltip_column != None:
self.tooltips = TreeTips.TreeTips(self.list, self.tooltips = TreeTips.TreeTips(self.list,
self.model.tooltip_column,True) self.model.tooltip_column,True)
self.dirty = False self.dirty = False

View File

@ -32,6 +32,8 @@ import sys
import traceback import traceback
import locale import locale
import cPickle as pickle
try: try:
set() set()
except: except:
@ -131,9 +133,9 @@ class PeopleModel(gtk.GenericTreeModel):
self.calculate_data(data_filter,skip) self.calculate_data(data_filter,skip)
self.assign_data() self.assign_data()
def calculate_data(self,data_filter=None,skip=[]): def calculate_data(self,dfilter=None,skip=[]):
if data_filter: if dfilter:
self.data_filter = data_filter self.dfilter = dfilter
self.temp_top_path2iter = [] self.temp_top_path2iter = []
self.temp_iter2path = {} self.temp_iter2path = {}
self.temp_path2iter = {} self.temp_path2iter = {}
@ -142,37 +144,42 @@ class PeopleModel(gtk.GenericTreeModel):
if not self.db.is_open(): if not self.db.is_open():
return return
if data_filter and not data_filter.is_empty():
keys = data_filter.apply(self.db)
if self.invert_result:
handle_list = self.db.get_person_handles(sort_handles=False)
#TODO: Could be optimized by using a cursor
keys = [k for k in handle_list if k not in keys]
del handle_list
else:
keys = self.db.get_person_handles(sort_handles=False)
self.sortnames = {}
cursor = self.db.get_person_cursor()
node = cursor.next()
ngn = NameDisplay.displayer.name_grouping_name ngn = NameDisplay.displayer.name_grouping_name
nsn = NameDisplay.displayer.sorted_name nsn = NameDisplay.displayer.sorted_name
flist = set([key for key in keys if key not in skip]) flist = set(skip)
self.sortnames = {}
cursor = self.db.surnames.cursor()
node = cursor.first()
while node: while node:
n,d = node n,d = node
if n in flist: d = pickle.loads(d)
primary_name = Name() handle = d[0]
primary_name.unserialize(d[_NAME_COL]) primary_name = Name(data=d[_NAME_COL])
surname = ngn(self.db,primary_name) #surname = ngn(self.db,primary_name)
self.sortnames[n] = nsn(primary_name) surname = n
try:
self.temp_sname_sub[surname].append(n) if not (handle in skip or (dfilter and not dfilter.match(handle))):
except: self.sortnames[handle] = nsn(primary_name)
self.temp_sname_sub[surname] = [n] self.temp_sname_sub[surname] = [handle]
node = cursor.next()
node = cursor.next_dup()
while node:
n,d = node
d = pickle.loads(d)
handle = d[0]
primary_name = Name(data=d[_NAME_COL])
if not (handle in skip or (dfilter and not dfilter.match(handle))):
self.sortnames[handle] = nsn(primary_name)
try:
self.temp_sname_sub[surname].append(handle)
except:
self.temp_sname_sub[surname] = [handle]
node = cursor.next_dup()
node = cursor.next_nodup()
cursor.close() cursor.close()
self.temp_top_path2iter = locale_sort(self.temp_sname_sub.keys()) self.temp_top_path2iter = locale_sort(self.temp_sname_sub.keys())
@ -184,9 +191,10 @@ class PeopleModel(gtk.GenericTreeModel):
def build_sub_entry(self,name): def build_sub_entry(self,name):
self.prev_handle = None self.prev_handle = None
slist = map(lambda x: (self.sortnames[x],x),self.temp_sname_sub[name]) slist = [ (locale.strxfrm(self.sortnames[x]),x) \
slist.sort(lambda f,s: locale.strcoll(f[0],s[0])) for x in self.temp_sname_sub[name] ]
entries = map(lambda x: x[1], slist) slist.sort()
entries = [ x[1] for x in slist ]
val = 0 val = 0
for person_handle in entries: for person_handle in entries:
@ -513,12 +521,12 @@ COLUMN_DEFS = [
# these columns are hidden, and must always be last in the list # these columns are hidden, and must always be last in the list
(PeopleModel.column_tooltip, None, object), (PeopleModel.column_tooltip, None, object),
(PeopleModel.column_sort_name, None, str), # (PeopleModel.column_sort_name, None, str),
(PeopleModel.column_int_id, None, str), (PeopleModel.column_int_id, None, str),
] ]
# dynamic calculation of column indices, for use by various Views # dynamic calculation of column indices, for use by various Views
COLUMN_INT_ID = 14 COLUMN_INT_ID = 13
# indices into main column definition table # indices into main column definition table
COLUMN_DEF_LIST = 0 COLUMN_DEF_LIST = 0

View File

@ -63,12 +63,16 @@ class Name(PrivateSourceNote,DateBase):
BIRTH = 2 BIRTH = 2
MARRIED = 3 MARRIED = 3
def __init__(self,source=None): def __init__(self,source=None,data=None):
"""creates a new Name instance, copying from the source if provided""" """creates a new Name instance, copying from the source if provided"""
PrivateSourceNote.__init__(self,source) if data:
DateBase.__init__(self,source) (psn,date,
self.first_name,self.surname,self.suffix,self.title,
if source: self.type,self.prefix,self.patronymic,self.sname,
self.group_as,self.sort_as,self.display_as) = data
elif source:
PrivateSourceNote.__init__(self,source)
DateBase.__init__(self,source)
self.first_name = source.first_name self.first_name = source.first_name
self.surname = source.surname self.surname = source.surname
self.suffix = source.suffix self.suffix = source.suffix
@ -81,6 +85,8 @@ class Name(PrivateSourceNote,DateBase):
self.sort_as = source.sort_as self.sort_as = source.sort_as
self.display_as = source.display_as self.display_as = source.display_as
else: else:
PrivateSourceNote.__init__(self,source)
DateBase.__init__(self,source)
self.first_name = "" self.first_name = ""
self.surname = "" self.surname = ""
self.suffix = "" self.suffix = ""

View File

@ -76,20 +76,27 @@ class SelectPerson:
self.top.set_transient_for(parent_window) self.top.set_transient_for(parent_window)
def add_columns(self,tree): def add_columns(self,tree):
column = gtk.TreeViewColumn(_('Name'), self.renderer,text=0) tree.set_fixed_height_mode(True)
column = gtk.TreeViewColumn(_('Name'), self.renderer, text=0)
column.set_resizable(True) column.set_resizable(True)
column.set_clickable(True) column.set_clickable(True)
column.set_sort_column_id(0) column.set_sort_column_id(0)
column.set_min_width(225) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
column.set_fixed_width(225)
tree.append_column(column) tree.append_column(column)
column = gtk.TreeViewColumn(_('ID'), self.renderer,text=1)
column = gtk.TreeViewColumn(_('ID'), self.renderer, text=1)
column.set_resizable(True) column.set_resizable(True)
column.set_clickable(True) column.set_clickable(True)
column.set_sort_column_id(1) column.set_sort_column_id(1)
column.set_min_width(75) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
column.set_fixed_width(75)
tree.append_column(column) tree.append_column(column)
column = gtk.TreeViewColumn(_('Birth date'), self.renderer,text=3)
column = gtk.TreeViewColumn(_('Birth date'), self.renderer, text=3)
column.set_clickable(True) column.set_clickable(True)
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
column.set_fixed_width(160)
tree.append_column(column) tree.append_column(column)
def select_function(self,store,path,iter,id_list): def select_function(self,store,path,iter,id_list):

View File

@ -31,6 +31,11 @@ import locale
import sets import sets
from TransUtils import sgettext as _ from TransUtils import sgettext as _
try:
set()
except:
from sets import Set as set
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# GNOME/GTK # GNOME/GTK
@ -525,7 +530,7 @@ def find_file( filename):
# Build list of elternate encodings # Build list of elternate encodings
encodings = [sys.getfilesystemencoding(), locale.getpreferredencoding(), 'UTF-8', 'ISO-8859-1'] encodings = [sys.getfilesystemencoding(), locale.getpreferredencoding(), 'UTF-8', 'ISO-8859-1']
encodings = list(sets.Set(encodings)) encodings = list(set(encodings))
for enc in encodings: for enc in encodings:
try: try:
fname = filename.encode(enc) fname = filename.encode(enc)
@ -547,8 +552,12 @@ def find_folder( filename):
pass pass
# Build list of elternate encodings # Build list of elternate encodings
encodings = [sys.getfilesystemencoding(), locale.getpreferredencoding(), 'UTF-8', 'ISO-8859-1'] try:
encodings = list(sets.Set(encodings)) encodings = [sys.getfilesystemencoding(), locale.getpreferredencoding(),
'UTF-8', 'ISO-8859-1']
except:
encodings = [sys.getfilesystemencoding(), 'UTF-8', 'ISO-8859-1']
encodings = list(set(encodings))
for enc in encodings: for enc in encodings:
try: try:
fname = filename.encode(enc) fname = filename.encode(enc)