Improve treebasemodel to allow filtering of secondary object nodes. Fix sorting of secondary object nodes.
svn: r18706
This commit is contained in:
parent
6ddb6dbcd1
commit
809c3bb833
@ -68,6 +68,7 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
|
|||||||
def __init__(self, db, scol=0, order=gtk.SORT_ASCENDING, search=None,
|
def __init__(self, db, scol=0, order=gtk.SORT_ASCENDING, search=None,
|
||||||
skip=set(), sort_map=None):
|
skip=set(), sort_map=None):
|
||||||
self.db = db
|
self.db = db
|
||||||
|
self.number_items = self.db.get_number_of_sources
|
||||||
self.map = self.db.get_raw_source_data
|
self.map = self.db.get_raw_source_data
|
||||||
self.gen_cursor = self.db.get_source_cursor
|
self.gen_cursor = self.db.get_source_cursor
|
||||||
# The items here must correspond, in order, with data in
|
# The items here must correspond, in order, with data in
|
||||||
@ -101,7 +102,8 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
|
|||||||
tooltip_column=9,
|
tooltip_column=9,
|
||||||
search=search, skip=skip, sort_map=sort_map,
|
search=search, skip=skip, sort_map=sort_map,
|
||||||
nrgroups = 1,
|
nrgroups = 1,
|
||||||
group_can_have_handle = True)
|
group_can_have_handle = True,
|
||||||
|
has_secondary=True)
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
"""
|
"""
|
||||||
@ -111,18 +113,22 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
|
|||||||
self.gen_cursor = None
|
self.gen_cursor = None
|
||||||
self.map = None
|
self.map = None
|
||||||
self.fmap = None
|
self.fmap = None
|
||||||
self.map2 = None
|
|
||||||
self.fmap2 = None
|
|
||||||
self.smap = None
|
self.smap = None
|
||||||
self.number_items = 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)
|
TreeBaseModel.destroy(self)
|
||||||
|
|
||||||
def _set_base_data(self):
|
def _set_base_data(self):
|
||||||
"""See TreeBaseModel, for citations, most have been set in init of
|
"""See TreeBaseModel, for citations, most have been set in init of
|
||||||
CitationBaseModel
|
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.map2 = self.db.get_raw_citation_data
|
||||||
|
self.gen_cursor2 = self.db.get_citation_cursor
|
||||||
self.fmap2 = [
|
self.fmap2 = [
|
||||||
self.citation_page,
|
self.citation_page,
|
||||||
self.citation_id,
|
self.citation_id,
|
||||||
@ -135,6 +141,18 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
|
|||||||
self.citation_handle,
|
self.citation_handle,
|
||||||
self.citation_tooltip
|
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):
|
def get_tree_levels(self):
|
||||||
"""
|
"""
|
||||||
@ -144,49 +162,24 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel):
|
|||||||
|
|
||||||
def add_row(self, handle, data):
|
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.
|
handle The handle of the gramps object.
|
||||||
data The object data.
|
data The object data.
|
||||||
"""
|
"""
|
||||||
# first add the source
|
|
||||||
# source_name = self.source_src_title(data)
|
|
||||||
sort_key = self.sort_func(data)
|
sort_key = self.sort_func(data)
|
||||||
# add as node: parent, child, sortkey, handle; parent and child are
|
self.add_node(None, handle, sort_key, handle)
|
||||||
# nodes in the treebasemodel, and will be used as iters
|
|
||||||
if self.get_node(handle) is None:
|
def add_row2(self, handle, data):
|
||||||
self.add_node(None, handle, sort_key, handle)
|
"""
|
||||||
# now add all the related citations
|
Add citation nodes to the node map.
|
||||||
source_handle_list = []
|
|
||||||
for i in get_source_referents(handle, self.db):
|
handle The handle of the gramps object.
|
||||||
for j in i:
|
data The object data.
|
||||||
source_handle_list.append(j)
|
"""
|
||||||
for citation_handle in source_handle_list:
|
sort_key = self.sort_func2(data)
|
||||||
if self.get_node(citation_handle) is None:
|
if self.get_node(data[5]):
|
||||||
# # add as node: parent, child, sortkey, handle; parent and child are
|
self.add_node(data[5], handle, sort_key, handle, secondary=True)
|
||||||
# # 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)
|
|
||||||
|
|
||||||
def add_secondary_row(self, handle, data):
|
def add_secondary_row(self, handle, data):
|
||||||
"""
|
"""
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||||
# Copyright (C) 2009 Gary Burton
|
# Copyright (C) 2009 Gary Burton
|
||||||
# Copyright (C) 2009-2010 Nick Hall
|
# Copyright (C) 2009-2011 Nick Hall
|
||||||
# Copyright (C) 2009 Benny Malengier
|
# 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
|
# 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
|
# 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
|
can groups have a handle. If False, this means groups
|
||||||
are only used to group subnodes, not for holding data and
|
are only used to group subnodes, not for holding data and
|
||||||
showing subnodes
|
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
|
# LRU cache size
|
||||||
@ -278,7 +281,8 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
|||||||
search=None, skip=set(),
|
search=None, skip=set(),
|
||||||
scol=0, order=gtk.SORT_ASCENDING, sort_map=None,
|
scol=0, order=gtk.SORT_ASCENDING, sort_map=None,
|
||||||
nrgroups = 1,
|
nrgroups = 1,
|
||||||
group_can_have_handle = False):
|
group_can_have_handle = False,
|
||||||
|
has_secondary=False):
|
||||||
cput = time.clock()
|
cput = time.clock()
|
||||||
gtk.GenericTreeModel.__init__(self)
|
gtk.GenericTreeModel.__init__(self)
|
||||||
#two unused attributes pesent to correspond to flatbasemodel
|
#two unused attributes pesent to correspond to flatbasemodel
|
||||||
@ -289,6 +293,7 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
|||||||
self.scol = scol
|
self.scol = scol
|
||||||
self.nrgroups = nrgroups
|
self.nrgroups = nrgroups
|
||||||
self.group_can_have_handle = group_can_have_handle
|
self.group_can_have_handle = group_can_have_handle
|
||||||
|
self.has_secondary = has_secondary
|
||||||
self.db = db
|
self.db = db
|
||||||
|
|
||||||
self._set_base_data()
|
self._set_base_data()
|
||||||
@ -307,9 +312,13 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
|||||||
#we need the model col, that corresponds with scol
|
#we need the model col, that corresponds with scol
|
||||||
col = self.sort_map[scol][1]
|
col = self.sort_map[scol][1]
|
||||||
self.sort_func = self.smap[col]
|
self.sort_func = self.smap[col]
|
||||||
|
if self.has_secondary:
|
||||||
|
self.sort_func2 = self.smap2[col]
|
||||||
self.sort_col = col
|
self.sort_col = col
|
||||||
else:
|
else:
|
||||||
self.sort_func = self.smap[scol]
|
self.sort_func = self.smap[scol]
|
||||||
|
if self.has_secondary:
|
||||||
|
self.sort_func2 = self.smap2[scol]
|
||||||
self.sort_col = scol
|
self.sort_col = scol
|
||||||
|
|
||||||
self._in_build = False
|
self._in_build = False
|
||||||
@ -333,6 +342,8 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
|||||||
"""
|
"""
|
||||||
self.db = None
|
self.db = None
|
||||||
self.sort_func = None
|
self.sort_func = None
|
||||||
|
if self.has_secondary:
|
||||||
|
self.sort_func2 = None
|
||||||
if self.nodemap:
|
if self.nodemap:
|
||||||
self.nodemap.destroy()
|
self.nodemap.destroy()
|
||||||
self.nodemap = None
|
self.nodemap = None
|
||||||
@ -354,17 +365,19 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
|||||||
map : function to obtain the raw bsddb object datamap
|
map : function to obtain the raw bsddb object datamap
|
||||||
smap : the map with functions to obtain sort value based on sort col
|
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
|
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.gen_cursor = None
|
||||||
self.number_items = None # function
|
self.number_items = None # function
|
||||||
self.map = None
|
self.map = None
|
||||||
self.map2 = None
|
|
||||||
|
|
||||||
self.smap = None
|
self.smap = None
|
||||||
self.fmap = 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):
|
def displayed(self):
|
||||||
"""
|
"""
|
||||||
@ -478,15 +491,28 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
|||||||
"""
|
"""
|
||||||
self.__total = 0
|
self.__total = 0
|
||||||
self.__displayed = 0
|
self.__displayed = 0
|
||||||
|
|
||||||
items = self.number_items()
|
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,
|
pmon = progressdlg.ProgressMonitor(progressdlg.GtkProgressDialog,
|
||||||
popup_time=2)
|
popup_time=2)
|
||||||
status = progressdlg.LongOpStatus(msg=_("Building View"),
|
status = progressdlg.LongOpStatus(msg=_("Building View"),
|
||||||
total_steps=items, interval=items//20,
|
total_steps=items, interval=items//20,
|
||||||
can_cancel=True)
|
can_cancel=True)
|
||||||
pmon.add_op(status)
|
pmon.add_op(status)
|
||||||
with self.gen_cursor() as cursor:
|
with gen_cursor() as cursor:
|
||||||
for handle, data in cursor:
|
for handle, data in cursor:
|
||||||
status.heartbeat()
|
status.heartbeat()
|
||||||
if status.should_cancel():
|
if status.should_cancel():
|
||||||
@ -495,7 +521,7 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
|||||||
if not (handle in skip or (dfilter and not
|
if not (handle in skip or (dfilter and not
|
||||||
dfilter.match(handle, self.db))):
|
dfilter.match(handle, self.db))):
|
||||||
self.__displayed += 1
|
self.__displayed += 1
|
||||||
self.add_row(handle, data)
|
add_func(handle, data)
|
||||||
if not status.was_cancelled():
|
if not status.was_cancelled():
|
||||||
status.end()
|
status.end()
|
||||||
|
|
||||||
@ -503,29 +529,46 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
|||||||
"""
|
"""
|
||||||
Rebuild the data map where a filter is applied.
|
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,
|
pmon = progressdlg.ProgressMonitor(progressdlg.GtkProgressDialog,
|
||||||
popup_time=2)
|
popup_time=2)
|
||||||
status = progressdlg.LongOpStatus(msg=_("Building People View"),
|
status = progressdlg.LongOpStatus(msg=_("Building View"),
|
||||||
total_steps=3, interval=1)
|
total_steps=3, interval=1)
|
||||||
pmon.add_op(status)
|
pmon.add_op(status)
|
||||||
self.__total = self.number_items()
|
status_ppl = progressdlg.LongOpStatus(msg=_("Obtaining all rows"),
|
||||||
status_ppl = progressdlg.LongOpStatus(msg=_("Obtaining all people"),
|
total_steps=items, interval=items//10)
|
||||||
total_steps=self.__total, interval=self.__total//10)
|
|
||||||
pmon.add_op(status_ppl)
|
pmon.add_op(status_ppl)
|
||||||
|
|
||||||
|
self.__total += items
|
||||||
|
|
||||||
def beat(key):
|
def beat(key):
|
||||||
status_ppl.heartbeat()
|
status_ppl.heartbeat()
|
||||||
return key
|
return key
|
||||||
|
|
||||||
with self.gen_cursor() as cursor:
|
with gen_cursor() as cursor:
|
||||||
handle_list = [beat(key) for key, data in cursor]
|
handle_list = [beat(key) for key, data in cursor]
|
||||||
status_ppl.end()
|
status_ppl.end()
|
||||||
self.__displayed = 0
|
|
||||||
status.heartbeat()
|
status.heartbeat()
|
||||||
|
|
||||||
if dfilter:
|
if dfilter:
|
||||||
status_filter = progressdlg.LongOpStatus(msg=_("Applying filter"),
|
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)
|
pmon.add_op(status_filter)
|
||||||
handle_list = dfilter.apply(self.db, handle_list,
|
handle_list = dfilter.apply(self.db, handle_list,
|
||||||
cb_progress=status_filter.heartbeat)
|
cb_progress=status_filter.heartbeat)
|
||||||
@ -538,9 +581,9 @@ class TreeBaseModel(gtk.GenericTreeModel):
|
|||||||
pmon.add_op(status_col)
|
pmon.add_op(status_col)
|
||||||
for handle in handle_list:
|
for handle in handle_list:
|
||||||
status_col.heartbeat()
|
status_col.heartbeat()
|
||||||
data = self.map(handle)
|
data = data_map(handle)
|
||||||
if not handle in skip:
|
if not handle in skip:
|
||||||
self.add_row(handle, data)
|
add_func(handle, data)
|
||||||
self.__displayed += 1
|
self.__displayed += 1
|
||||||
status_col.end()
|
status_col.end()
|
||||||
status.end()
|
status.end()
|
||||||
|
Loading…
Reference in New Issue
Block a user