Improve treebasemodel to allow filtering of secondary object nodes. Fix sorting of secondary object nodes.

svn: r18706
This commit is contained in:
Nick Hall 2012-01-05 19:16:34 +00:00
parent 6ddb6dbcd1
commit 809c3bb833
2 changed files with 98 additions and 62 deletions

View File

@ -68,6 +68,7 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
def __init__(self, db, scol=0, order=gtk.SORT_ASCENDING, search=None,
skip=set(), sort_map=None):
self.db = db
self.number_items = self.db.get_number_of_sources
self.map = self.db.get_raw_source_data
self.gen_cursor = self.db.get_source_cursor
# The items here must correspond, in order, with data in
@ -101,7 +102,8 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
tooltip_column=9,
search=search, skip=skip, sort_map=sort_map,
nrgroups = 1,
group_can_have_handle = True)
group_can_have_handle = True,
has_secondary=True)
def destroy(self):
"""
@ -111,18 +113,22 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
self.gen_cursor = None
self.map = None
self.fmap = None
self.map2 = None
self.fmap2 = None
self.smap = None
self.number_items = None
self.gen_cursor2 = None
self.map2 = None
self.fmap2 = None
self.smap2 = None
self.number_items2 = None
TreeBaseModel.destroy(self)
def _set_base_data(self):
"""See TreeBaseModel, for citations, most have been set in init of
CitationBaseModel
"""
self.number_items = self.db.get_number_of_citations
self.number_items2 = self.db.get_number_of_citations
self.map2 = self.db.get_raw_citation_data
self.gen_cursor2 = self.db.get_citation_cursor
self.fmap2 = [
self.citation_page,
self.citation_id,
@ -135,6 +141,18 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
self.citation_handle,
self.citation_tooltip
]
self.smap2 = [
self.citation_page,
self.citation_id,
self.citation_sort_date,
self.citation_confidence,
self.citation_sort_change,
self.dummy_sort_key,
self.dummy_sort_key,
self.dummy_sort_key,
self.citation_handle,
self.citation_tooltip
]
def get_tree_levels(self):
"""
@ -144,49 +162,24 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
def add_row(self, handle, data):
"""
Add nodes to the node map for a single citation.
Add source nodes to the node map.
handle The handle of the gramps object.
data The object data.
"""
# first add the source
# source_name = self.source_src_title(data)
sort_key = self.sort_func(data)
# add as node: parent, child, sortkey, handle; parent and child are
# nodes in the treebasemodel, and will be used as iters
if self.get_node(handle) is None:
self.add_node(None, handle, sort_key, handle)
# now add all the related citations
source_handle_list = []
for i in get_source_referents(handle, self.db):
for j in i:
source_handle_list.append(j)
for citation_handle in source_handle_list:
if self.get_node(citation_handle) is None:
# # add as node: parent, child, sortkey, handle; parent and child are
# # nodes in the treebasemodel, and will be used as iters
citation = self.db.get_citation_from_handle(citation_handle)
citation_page = citation.get_page()
self.add_node(handle, citation_handle, citation_page,
citation_handle, secondary=True)
# try:
# source_handle = data[COLUMN_SOURCE]
# except:
# LOG.debug("add_row: data %s is empty, handle %s citation %s data %s" %
# (data, handle, self.db.get_citation_from_handle(handle),
# self.db.get_citation_from_handle(handle).serialize()))
# source = self.db.get_source_from_handle(source_handle)
# if source is not None:
# source_name = source.get_title()
# sort_key = self.sort_func(data)
# if self.get_node(source_handle) is None:
# self.add_node(None, source_handle, source_name, source_handle,
# secondary=True)
# self.add_node(source_handle, handle, sort_key, handle)
# else:
# log.warn("Citation %s does not have a source" %
# unicode(data[COLUMN_PAGE]),
# exc_info=True)
self.add_node(None, handle, sort_key, handle)
def add_row2(self, handle, data):
"""
Add citation nodes to the node map.
handle The handle of the gramps object.
data The object data.
"""
sort_key = self.sort_func2(data)
if self.get_node(data[5]):
self.add_node(data[5], handle, sort_key, handle, secondary=True)
def add_secondary_row(self, handle, data):
"""

View File

@ -3,9 +3,9 @@
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2009 Gary Burton
# Copyright (C) 2009-2010 Nick Hall
# Copyright (C) 2009-2011 Nick Hall
# Copyright (C) 2009 Benny Malengier
# Copyright (C) 2011 Nick Hall, Tim G L lyons
# Copyright (C) 2011 Tim G L lyons
#
# 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
@ -269,6 +269,9 @@ class TreeBaseModel(gtk.GenericTreeModel):
can groups have a handle. If False, this means groups
are only used to group subnodes, not for holding data and
showing subnodes
has_secondary : If True, the model contains two Gramps object types.
The suffix '2' is appended to variables relating to the
secondary object type.
"""
# LRU cache size
@ -278,7 +281,8 @@ class TreeBaseModel(gtk.GenericTreeModel):
search=None, skip=set(),
scol=0, order=gtk.SORT_ASCENDING, sort_map=None,
nrgroups = 1,
group_can_have_handle = False):
group_can_have_handle = False,
has_secondary=False):
cput = time.clock()
gtk.GenericTreeModel.__init__(self)
#two unused attributes pesent to correspond to flatbasemodel
@ -289,6 +293,7 @@ class TreeBaseModel(gtk.GenericTreeModel):
self.scol = scol
self.nrgroups = nrgroups
self.group_can_have_handle = group_can_have_handle
self.has_secondary = has_secondary
self.db = db
self._set_base_data()
@ -307,9 +312,13 @@ class TreeBaseModel(gtk.GenericTreeModel):
#we need the model col, that corresponds with scol
col = self.sort_map[scol][1]
self.sort_func = self.smap[col]
if self.has_secondary:
self.sort_func2 = self.smap2[col]
self.sort_col = col
else:
self.sort_func = self.smap[scol]
if self.has_secondary:
self.sort_func2 = self.smap2[scol]
self.sort_col = scol
self._in_build = False
@ -333,6 +342,8 @@ class TreeBaseModel(gtk.GenericTreeModel):
"""
self.db = None
self.sort_func = None
if self.has_secondary:
self.sort_func2 = None
if self.nodemap:
self.nodemap.destroy()
self.nodemap = None
@ -354,17 +365,19 @@ class TreeBaseModel(gtk.GenericTreeModel):
map : function to obtain the raw bsddb object datamap
smap : the map with functions to obtain sort value based on sort col
fmap : the map with functions to obtain value of a row with handle
hmap : the map with functions to obtain value of a row without handle
"""
self.gen_cursor = None
self.number_items = None # function
self.map = None
self.map2 = None
self.smap = None
self.fmap = None
self.smap2 = None
self.fmap2 = None
if self.has_secondary:
self.gen_cursor2 = None
self.number_items2 = None # function
self.map2 = None
self.smap2 = None
self.fmap2 = None
def displayed(self):
"""
@ -478,15 +491,28 @@ class TreeBaseModel(gtk.GenericTreeModel):
"""
self.__total = 0
self.__displayed = 0
items = self.number_items()
self.__rebuild_search(dfilter, skip, items,
self.gen_cursor, self.add_row)
if self.has_secondary:
items = self.number_items2()
self.__rebuild_search(dfilter, skip, items,
self.gen_cursor2, self.add_row2)
def __rebuild_search(self, dfilter, skip, items, gen_cursor, add_func):
"""
Rebuild the data map for a single Gramps object type, where a search
condition is applied.
"""
pmon = progressdlg.ProgressMonitor(progressdlg.GtkProgressDialog,
popup_time=2)
status = progressdlg.LongOpStatus(msg=_("Building View"),
total_steps=items, interval=items//20,
can_cancel=True)
pmon.add_op(status)
with self.gen_cursor() as cursor:
with gen_cursor() as cursor:
for handle, data in cursor:
status.heartbeat()
if status.should_cancel():
@ -495,7 +521,7 @@ class TreeBaseModel(gtk.GenericTreeModel):
if not (handle in skip or (dfilter and not
dfilter.match(handle, self.db))):
self.__displayed += 1
self.add_row(handle, data)
add_func(handle, data)
if not status.was_cancelled():
status.end()
@ -503,29 +529,46 @@ class TreeBaseModel(gtk.GenericTreeModel):
"""
Rebuild the data map where a filter is applied.
"""
self.__total = 0
self.__displayed = 0
items = self.number_items()
self.__rebuild_filter(dfilter, skip, items,
self.gen_cursor, self.map, self.add_row)
if self.has_secondary:
items = self.number_items2()
self.__rebuild_filter(dfilter, skip, items,
self.gen_cursor2, self.map2, self.add_row2)
def __rebuild_filter(self, dfilter, skip, items, gen_cursor, data_map,
add_func):
"""
Rebuild the data map for a single Gramps object type, where a filter
is applied.
"""
pmon = progressdlg.ProgressMonitor(progressdlg.GtkProgressDialog,
popup_time=2)
status = progressdlg.LongOpStatus(msg=_("Building People View"),
status = progressdlg.LongOpStatus(msg=_("Building View"),
total_steps=3, interval=1)
pmon.add_op(status)
self.__total = self.number_items()
status_ppl = progressdlg.LongOpStatus(msg=_("Obtaining all people"),
total_steps=self.__total, interval=self.__total//10)
status_ppl = progressdlg.LongOpStatus(msg=_("Obtaining all rows"),
total_steps=items, interval=items//10)
pmon.add_op(status_ppl)
self.__total += items
def beat(key):
status_ppl.heartbeat()
return key
with self.gen_cursor() as cursor:
with gen_cursor() as cursor:
handle_list = [beat(key) for key, data in cursor]
status_ppl.end()
self.__displayed = 0
status.heartbeat()
if dfilter:
status_filter = progressdlg.LongOpStatus(msg=_("Applying filter"),
total_steps=self.__total, interval=self.__total//10)
total_steps=items, interval=items//10)
pmon.add_op(status_filter)
handle_list = dfilter.apply(self.db, handle_list,
cb_progress=status_filter.heartbeat)
@ -538,9 +581,9 @@ class TreeBaseModel(gtk.GenericTreeModel):
pmon.add_op(status_col)
for handle in handle_list:
status_col.heartbeat()
data = self.map(handle)
data = data_map(handle)
if not handle in skip:
self.add_row(handle, data)
add_func(handle, data)
self.__displayed += 1
status_col.end()
status.end()