Working person treeview, insert/add/delete still todo
read/write db, make sure unicode or utf8, nothing else! svn: r19966
This commit is contained in:
parent
0b8d0a1a95
commit
9da71185a6
@ -58,7 +58,7 @@ from gen.lib import (MediaObject, Person, Family, Source, Citation, Event,
|
||||
NameOriginType)
|
||||
from gen.db.dbconst import *
|
||||
from gen.utils.callback import Callback
|
||||
from gen.utils.cast import conv_dbstr_to_unicode, conv_unicode_tosrtkey
|
||||
from gen.utils.cast import conv_dbstr_to_unicode
|
||||
from gen.db import (BsddbBaseCursor, DbReadBase)
|
||||
from gen.utils.id import create_id
|
||||
from gen.errors import DbError
|
||||
@ -826,10 +826,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
Return type is a unicode object
|
||||
"""
|
||||
if isinstance(surname, unicode):
|
||||
ssurname = conv_unicode_tosrtkey(surname)
|
||||
return unicode(self.name_group.get(ssurname, ssurname), 'utf-8')
|
||||
ssurname = surname.encode('utf-8')
|
||||
return conv_dbstr_to_unicode(self.name_group.get(ssurname, ssurname))
|
||||
else:
|
||||
return unicode(self.name_group.get(surname, surname), 'utf-8')
|
||||
return conv_dbstr_to_unicode(self.name_group.get(surname, surname))
|
||||
|
||||
def get_name_group_keys(self):
|
||||
"""
|
||||
@ -844,7 +844,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
# The use of has_key seems allright because there is no write lock
|
||||
# on the name_group table when this is called.
|
||||
if isinstance(name, unicode):
|
||||
return self.name_group.has_key(conv_unicode_tosrtkey(name))
|
||||
return self.name_group.has_key(name.encode('utf-8'))
|
||||
else:
|
||||
return self.name_group.has_key(name)
|
||||
|
||||
|
@ -62,8 +62,7 @@ from gen.db import (DbBsddbRead, DbWriteBase, BSDDBTxn,
|
||||
find_surname_name, DbUndoBSDDB as DbUndo)
|
||||
from gen.db.dbconst import *
|
||||
from gen.utils.callback import Callback
|
||||
from gen.utils.cast import (conv_unicode_tosrtkey_ongtk, conv_dbstr_to_unicode,
|
||||
conv_unicode_tosrtkey)
|
||||
from gen.utils.cast import (conv_unicode_tosrtkey_ongtk, conv_dbstr_to_unicode)
|
||||
from gen.updatecallback import UpdateCallback
|
||||
from gen.errors import DbError
|
||||
from gen.constfunc import win
|
||||
@ -1416,7 +1415,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
if not self.readonly:
|
||||
# Start transaction
|
||||
with BSDDBTxn(self.env, self.name_group) as txn:
|
||||
sname = conv_unicode_tosrtkey(name)
|
||||
sname = name.encode('utf-8')
|
||||
data = txn.get(sname)
|
||||
if data is not None:
|
||||
txn.delete(sname)
|
||||
|
@ -107,9 +107,9 @@ class Name(SecondaryObject, PrivacyBase, SurnameBase, CitationBase, NoteBase,
|
||||
self.group_as = ""
|
||||
self.sort_as = self.DEF
|
||||
self.display_as = self.DEF
|
||||
self.call = u''
|
||||
self.nick = u''
|
||||
self.famnick = u''
|
||||
self.call = ""
|
||||
self.nick = ""
|
||||
self.famnick = ""
|
||||
|
||||
def serialize(self):
|
||||
"""
|
||||
@ -130,9 +130,9 @@ class Name(SecondaryObject, PrivacyBase, SurnameBase, CitationBase, NoteBase,
|
||||
"""
|
||||
Indicate if the name is empty.
|
||||
"""
|
||||
namefieldsempty = (self.first_name == u"" and
|
||||
self.suffix == u"" and self.title == u"" and self.nick ==u""
|
||||
and self.famnick == u"")
|
||||
namefieldsempty = (self.first_name == "" and
|
||||
self.suffix == "" and self.title == "" and self.nick == ""
|
||||
and self.famnick == "")
|
||||
surnamefieldsempty = not (False in
|
||||
[surn.is_empty() for surn in self.surname_list])
|
||||
return namefieldsempty and surnamefieldsempty
|
||||
|
@ -48,6 +48,9 @@ conv_unicode_tosrtkey = lambda x: locale.strxfrm(x.encode('utf-8', 'replace'))
|
||||
conv_unicode_tosrtkey_ongtk = lambda x: locale.strxfrm(x.encode(
|
||||
codeset, 'replace'))
|
||||
|
||||
conv_str_tosrtkey_ongtk = lambda x: locale.strxfrm(unicode(x,'utf-8').encode(
|
||||
codeset, 'replace'))
|
||||
|
||||
conv_dbstr_to_unicode = lambda x: unicode(x, 'utf-8')
|
||||
|
||||
def cast_to_bool(val):
|
||||
|
@ -378,8 +378,9 @@ class ListView(NavigationView):
|
||||
|
||||
if self.type_list() == LISTFLAT:
|
||||
# Flat
|
||||
iter = self.model.nodemap.new_iter(handle)
|
||||
try:
|
||||
path = self.model.on_get_path(handle)
|
||||
path = self.model.do_get_path(iter)
|
||||
except:
|
||||
path = None
|
||||
else:
|
||||
@ -387,15 +388,17 @@ class ListView(NavigationView):
|
||||
path = None
|
||||
node = self.model.get_node(handle)
|
||||
if node:
|
||||
parent_node = self.model.on_iter_parent(node)
|
||||
if parent_node:
|
||||
parent_path = self.model.on_get_path(parent_node)
|
||||
iter = self.model.get_iter(node)
|
||||
has_parent, parent_iter = self.model.do_iter_parent(iter)
|
||||
if has_parent:
|
||||
parent_path = self.model.do_get_path(parent_iter)
|
||||
if parent_path:
|
||||
for i in range(len(parent_path)):
|
||||
parent_path_list = parent_path.get_indices()
|
||||
for i in range(len(parent_path_list)):
|
||||
expand_path = Gtk.TreePath(
|
||||
tuple([x for x in parent_path[:i+1]]))
|
||||
tuple([x for x in parent_path_list[:i+1]]))
|
||||
self.list.expand_row(expand_path, False)
|
||||
path = self.model.on_get_path(node)
|
||||
path = self.model.do_get_path(iter)
|
||||
|
||||
if path is not None:
|
||||
self.selection.unselect_all()
|
||||
@ -535,11 +538,14 @@ class ListView(NavigationView):
|
||||
if not prompt:
|
||||
self.uistate.set_busy_cursor(0)
|
||||
|
||||
def blist(self, store, path, node, sel_list):
|
||||
if store.get_flags() & Gtk.TreeModelFlags.LIST_ONLY:
|
||||
handle = store.get_value(node, self.handle_col)
|
||||
def blist(self, store, path, iter, sel_list):
|
||||
'''GtkTreeSelectionForeachFunc
|
||||
construct a list sel_list with all selected handles
|
||||
'''
|
||||
if store.do_get_flags() & Gtk.TreeModelFlags.LIST_ONLY:
|
||||
handle = store.node_map.get_handle(path)
|
||||
else:
|
||||
handle = store.get_handle(store.on_get_iter(path))
|
||||
handle = store.get_handle(store.get_node_from_iter(iter))
|
||||
|
||||
if handle is not None:
|
||||
sel_list.append(handle)
|
||||
@ -756,7 +762,8 @@ class ListView(NavigationView):
|
||||
store, paths = self.selection.get_selected_rows()
|
||||
if paths:
|
||||
firstsel = paths[0]
|
||||
firstnode = self.model.on_get_iter(firstsel)
|
||||
firstnode = self.model.get_node_from_iter(
|
||||
self.model.do_get_iter(firstsel)[1])
|
||||
if len(paths)==1 and firstnode.handle is None:
|
||||
return self.expand_collapse_tree_branch()
|
||||
else:
|
||||
@ -832,7 +839,8 @@ class ListView(NavigationView):
|
||||
store, paths = self.selection.get_selected_rows()
|
||||
if paths:
|
||||
firstsel = paths[0]
|
||||
firstnode = self.model.on_get_iter(firstsel)
|
||||
firstnode = self.model.get_node_from_iter(
|
||||
self.model.do_get_iter(firstsel)[1])
|
||||
if len(paths) == 1 and firstnode.handle is None:
|
||||
return self.expand_collapse_tree_branch()
|
||||
else:
|
||||
@ -840,7 +848,8 @@ class ListView(NavigationView):
|
||||
store, paths = self.selection.get_selected_rows()
|
||||
if paths:
|
||||
firstsel = paths[0]
|
||||
firstnode = self.model.on_get_iter(firstsel)
|
||||
firstnode = self.model.get_node_from_iter(
|
||||
self.model.do_get_iter(firstsel)[1])
|
||||
if len(paths) == 1 and firstnode.handle is None:
|
||||
return self.expand_collapse_tree()
|
||||
else:
|
||||
@ -857,7 +866,8 @@ class ListView(NavigationView):
|
||||
store, paths = self.selection.get_selected_rows()
|
||||
if paths:
|
||||
firstsel = paths[0]
|
||||
firstnode = self.model.on_get_iter(firstsel)
|
||||
firstnode = self.model.get_node_from_iter(
|
||||
self.model.do_get_iter(firstsel)[1])
|
||||
if firstnode.handle:
|
||||
return False
|
||||
if self.list.row_expanded(firstsel):
|
||||
@ -875,7 +885,8 @@ class ListView(NavigationView):
|
||||
store, paths = self.selection.get_selected_rows()
|
||||
if paths:
|
||||
firstsel = paths[0]
|
||||
firstnode = self.model.on_get_iter(firstsel)
|
||||
firstnode = self.model.get_node_from_iter(
|
||||
self.model.do_get_iter(firstsel)[1])
|
||||
if firstnode.handle:
|
||||
return False
|
||||
if self.list.row_expanded(firstsel):
|
||||
@ -996,7 +1007,7 @@ class ListView(NavigationView):
|
||||
ofile.end_row()
|
||||
else:
|
||||
# Tree model
|
||||
node = self.model.on_get_iter((0,))
|
||||
node = self.model.get_node_from_iter(self.model.do_get_iter((0,))[1])
|
||||
self.write_node(node, len(levels), [], ofile, data_cols)
|
||||
|
||||
ofile.end_page()
|
||||
@ -1006,18 +1017,20 @@ class ListView(NavigationView):
|
||||
if node is None:
|
||||
return
|
||||
while node is not None:
|
||||
new_level = level + [self.model.on_get_value(node, 0)]
|
||||
new_level = level + [self.model.do_get_value(node, 0)]
|
||||
if self.model.get_handle(node):
|
||||
ofile.start_row()
|
||||
padded_level = new_level + [''] * (depth - len(new_level))
|
||||
map(ofile.write_cell, padded_level)
|
||||
for index in data_cols:
|
||||
ofile.write_cell(self.model.on_get_value(node, index))
|
||||
ofile.write_cell(self.model.do_get_value(node, index))
|
||||
ofile.end_row()
|
||||
|
||||
first_child = self.model.on_iter_children(node)
|
||||
has_child, first_child = self.model.do_iter_children(node)
|
||||
self.write_node(first_child, depth, new_level, ofile, data_cols)
|
||||
node = self.model.on_iter_next(node)
|
||||
has_next = self.model.do_iter_next(node)
|
||||
if not has_next:
|
||||
node = None
|
||||
|
||||
####################################################################
|
||||
# Template functions
|
||||
|
@ -151,15 +151,14 @@ class FlatNodeMap(object):
|
||||
Reverse sets up how the path is determined from the index. If True the
|
||||
first index is the last path
|
||||
|
||||
:param index2hndllist: the ascending sorted (sortkey, handle, iter) values
|
||||
:param index2hndllist: the ascending sorted (sortkey, handle) values
|
||||
as they will appear in the flat treeview. This often is
|
||||
a subset of all possible data.
|
||||
Set iter=None, it will be set internally
|
||||
:type index2hndllist: a list of (sortkey, handle) tuples
|
||||
:param fullhndllist: the list of all possilbe ascending sorted
|
||||
[sortkey, handle, iter] values as they will appear in the flat
|
||||
(sortkey, handle) values as they will appear in the flat
|
||||
treeview if all data is shown.
|
||||
:type fullhndllist: a list of (sortkey, handle, iter) tuples
|
||||
:type fullhndllist: a list of (sortkey, handl) tuples
|
||||
:param identical: identify if index2hndllist and fullhndllist are the
|
||||
same list, so only one is kept in memory.
|
||||
:type identical: bool
|
||||
@ -446,7 +445,10 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
#inheriting classes must set self.map to obtain the data
|
||||
self.prev_handle = None
|
||||
self.prev_data = None
|
||||
|
||||
#GTK3 We leak ref, yes??
|
||||
#self.set_property("leak_references", False)
|
||||
|
||||
self.db = db
|
||||
#normally sort on first column, so scol=0
|
||||
if sort_map:
|
||||
@ -752,7 +754,7 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
data = self.map(str(handle))
|
||||
if data is None:
|
||||
#object is no longer present
|
||||
return u''
|
||||
return ''
|
||||
self.prev_data = data
|
||||
self.prev_handle = handle
|
||||
val = self.fmap[col](self.prev_data)
|
||||
@ -784,13 +786,14 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
else:
|
||||
return False
|
||||
|
||||
def do_iter_children(self, iter):
|
||||
def do_iter_children(self, iterparent):
|
||||
"""
|
||||
Return the first child of the node
|
||||
See Gtk.TreeModel
|
||||
"""
|
||||
#print 'do_iter_children'
|
||||
print 'ERROR: iter children, should not be called in flat base!!'
|
||||
raise NotImplementedError
|
||||
if handle is None and len(self.node_map):
|
||||
return self.node_map.get_first_handle()
|
||||
return None
|
||||
|
@ -90,7 +90,7 @@ class PeopleBaseModel(object):
|
||||
"""
|
||||
Basic Model interface to handle the PersonViews
|
||||
"""
|
||||
_GENDER = [ _(u'female'), _(u'male'), _(u'unknown') ]
|
||||
_GENDER = [ _('female'), _('male'), _('unknown') ]
|
||||
|
||||
# The following is accessed from the Person Selector
|
||||
COLUMN_INT_ID = 10 # dynamic calculation of column indices
|
||||
@ -191,7 +191,11 @@ class PeopleBaseModel(object):
|
||||
return len(self.fmap)+1
|
||||
|
||||
def sort_name(self, data):
|
||||
return name_displayer.raw_sorted_name(data[COLUMN_NAME])
|
||||
name = name_displayer.raw_sorted_name(data[COLUMN_NAME])
|
||||
# internally we work with utf-8
|
||||
if isinstance(name, unicode):
|
||||
name = name.encode('utf-8')
|
||||
return name
|
||||
|
||||
def column_name(self, data):
|
||||
handle = data[0]
|
||||
@ -199,6 +203,9 @@ class PeopleBaseModel(object):
|
||||
name = self.lru_name[handle]
|
||||
else:
|
||||
name = name_displayer.raw_display_name(data[COLUMN_NAME])
|
||||
# internally we work with utf-8
|
||||
if isinstance(name, unicode):
|
||||
name = name.encode('utf-8')
|
||||
if not self._in_build:
|
||||
self.lru_name[handle] = name
|
||||
return name
|
||||
@ -214,7 +221,7 @@ class PeopleBaseModel(object):
|
||||
return value
|
||||
|
||||
def _get_spouse_data(self, data):
|
||||
spouses_names = u""
|
||||
spouses_names = ""
|
||||
for family_handle in data[COLUMN_FAMILY]:
|
||||
family = self.db.get_family_from_handle(family_handle)
|
||||
for spouse_id in [family.get_father_handle(),
|
||||
@ -274,7 +281,7 @@ class PeopleBaseModel(object):
|
||||
else:
|
||||
return retval
|
||||
except:
|
||||
return u''
|
||||
return ''
|
||||
|
||||
for event_ref in data[COLUMN_EVENT]:
|
||||
er = EventRef()
|
||||
@ -288,13 +295,13 @@ class PeopleBaseModel(object):
|
||||
if sort_mode:
|
||||
retval = "%09d" % event.get_date_object().get_sort_value()
|
||||
else:
|
||||
retval = u"<i>%s</i>" % cgi.escape(date_str)
|
||||
retval = "<i>%s</i>" % cgi.escape(date_str)
|
||||
if not gen.datehandler.get_date_valid(event):
|
||||
return invalid_date_format % retval
|
||||
else:
|
||||
return retval
|
||||
|
||||
return u""
|
||||
return ""
|
||||
|
||||
def column_death_day(self, data):
|
||||
handle = data[0]
|
||||
@ -329,7 +336,7 @@ class PeopleBaseModel(object):
|
||||
else:
|
||||
return retval
|
||||
except:
|
||||
return u''
|
||||
return ''
|
||||
|
||||
for event_ref in data[COLUMN_EVENT]:
|
||||
er = EventRef()
|
||||
@ -350,7 +357,7 @@ class PeopleBaseModel(object):
|
||||
return invalid_date_format % retval
|
||||
else:
|
||||
return retval
|
||||
return u""
|
||||
return ""
|
||||
|
||||
def column_birth_place(self, data):
|
||||
index = data[COLUMN_BIRTH]
|
||||
@ -368,7 +375,7 @@ class PeopleBaseModel(object):
|
||||
if place_title:
|
||||
return cgi.escape(place_title)
|
||||
except:
|
||||
return u''
|
||||
return ''
|
||||
|
||||
for event_ref in data[COLUMN_EVENT]:
|
||||
er = EventRef()
|
||||
@ -385,7 +392,7 @@ class PeopleBaseModel(object):
|
||||
if place_title:
|
||||
return "<i>%s</i>" % cgi.escape(place_title)
|
||||
|
||||
return u""
|
||||
return ""
|
||||
|
||||
def column_death_place(self, data):
|
||||
index = data[COLUMN_DEATH]
|
||||
@ -403,7 +410,7 @@ class PeopleBaseModel(object):
|
||||
if place_title:
|
||||
return cgi.escape(place_title)
|
||||
except:
|
||||
return u''
|
||||
return ''
|
||||
|
||||
for event_ref in data[COLUMN_EVENT]:
|
||||
er = EventRef()
|
||||
@ -420,10 +427,10 @@ class PeopleBaseModel(object):
|
||||
place_title = place.get_title()
|
||||
if place_title != "":
|
||||
return "<i>" + cgi.escape(place_title) + "</i>"
|
||||
return u""
|
||||
return ""
|
||||
|
||||
def column_tooltip(self, data):
|
||||
return u'Person tooltip'
|
||||
return 'Person tooltip'
|
||||
|
||||
def column_int_id(self, data):
|
||||
return data[0]
|
||||
@ -528,6 +535,8 @@ class PersonTreeModel(PeopleBaseModel, TreeBaseModel):
|
||||
|
||||
name_data = data[COLUMN_NAME]
|
||||
group_name = ngn(self.db, name_data)
|
||||
if isinstance(group_name, unicode):
|
||||
group_name = group_name.encode('utf-8')
|
||||
sort_key = self.sort_func(data)
|
||||
|
||||
#if group_name not in self.group_list:
|
||||
|
@ -4,7 +4,7 @@
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2009 Gary Burton
|
||||
# Copyright (C) 2009-2011 Nick Hall
|
||||
# Copyright (C) 2009 Benny Malengier
|
||||
# Copyright (C) 2009-2012 Benny Malengier
|
||||
# Copyright (C) 2011 Tim G L lyons
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
@ -34,7 +34,7 @@ This module provides the model that is used for all hierarchical treeviews.
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from __future__ import with_statement
|
||||
from __future__ import with_statement, print_function
|
||||
import time
|
||||
import locale
|
||||
from gen.ggettext import gettext as _
|
||||
@ -55,7 +55,7 @@ from gi.repository import Gtk
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gen.utils.cast import conv_unicode_tosrtkey_ongtk
|
||||
from gen.utils.cast import conv_str_tosrtkey_ongtk, conv_unicode_tosrtkey_ongtk
|
||||
import gui.widgets.progressdialog as progressdlg
|
||||
from lru import LRU
|
||||
from bisect import bisect_right
|
||||
@ -87,10 +87,17 @@ class Node(object):
|
||||
'prev', 'next', 'children')#, '__weakref__')
|
||||
|
||||
def __init__(self, ref, parent, sortkey, handle, secondary):
|
||||
self.name = sortkey
|
||||
if sortkey:
|
||||
self.sortkey = map(conv_unicode_tosrtkey_ongtk, sortkey)
|
||||
if isinstance(sortkey, unicode):
|
||||
self.name = sortkey.encode('utf-8')
|
||||
#sortkey must be localized sort, so
|
||||
self.sortkey = conv_unicode_tosrtkey_ongtk(sortkey)
|
||||
else:
|
||||
self.name = sortkey
|
||||
#sortkey must be localized sort, so
|
||||
self.sortkey = conv_str_tosrtkey_ongtk(sortkey)
|
||||
else:
|
||||
self.name = ''
|
||||
self.sortkey = None
|
||||
self.ref = ref
|
||||
self.handle = handle
|
||||
@ -284,10 +291,15 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
nrgroups = 1,
|
||||
group_can_have_handle = False,
|
||||
has_secondary=False):
|
||||
#TODO GTK3, first get flatbasemodel working !
|
||||
raise NotImplementedError
|
||||
cput = time.clock()
|
||||
GObject.GObject.__init__(self)
|
||||
#We create a stamp to recognize invalid iterators. From the docs:
|
||||
#Set the stamp to be equal to your model's stamp, to mark the
|
||||
#iterator as valid. When your model's structure changes, you should
|
||||
#increment your model's stamp to mark all older iterators as invalid.
|
||||
#They will be recognised as invalid because they will then have an
|
||||
#incorrect stamp.
|
||||
self.stamp = 0
|
||||
#two unused attributes pesent to correspond to flatbasemodel
|
||||
self.prev_handle = None
|
||||
self.prev_data = None
|
||||
@ -306,7 +318,9 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
self.nodemap = NodeMap()
|
||||
self.handle2node = {}
|
||||
|
||||
self.set_property("leak_references", False)
|
||||
#GTK3 We leak ref, yes??
|
||||
#self.set_property("leak_references", False)
|
||||
|
||||
#normally sort on first column, so scol=0
|
||||
if sort_map:
|
||||
#sort_map is the stored order of the columns and if they are
|
||||
@ -349,6 +363,7 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
self.sort_func2 = None
|
||||
if self.nodemap:
|
||||
self.nodemap.destroy()
|
||||
|
||||
self.nodemap = None
|
||||
self.rebuild_data = None
|
||||
self._build_data = None
|
||||
@ -422,10 +437,9 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
"""
|
||||
Clear the data map.
|
||||
"""
|
||||
#invalidate the iters within gtk
|
||||
self.invalidate_iters()
|
||||
self.tree.clear()
|
||||
self.handle2node.clear()
|
||||
self.stamp += 1
|
||||
self.nodemap.clear()
|
||||
#start with creating the new iters
|
||||
topnode = Node(None, None, None, None, False)
|
||||
@ -450,7 +464,7 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
if search[1]:
|
||||
# we have search[1] = (index, text_unicode, inversion)
|
||||
col, text, inv = search[1]
|
||||
func = lambda x: self._get_value(x, col) or u""
|
||||
func = lambda x: self._get_value(x, col) or ""
|
||||
if search[2]:
|
||||
self.search = ExactSearchFilter(func, text, inv)
|
||||
else:
|
||||
@ -784,6 +798,31 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
# If the node hasn't moved, all we need is to call row_changed.
|
||||
#self.row_changed(path, node)
|
||||
|
||||
def new_iter(self, nodeid):
|
||||
"""
|
||||
Return a new iter containing the nodeid in the nodemap
|
||||
"""
|
||||
iter = Gtk.TreeIter()
|
||||
iter.stamp = self.stamp
|
||||
#user data should be an object, so we store the long as str
|
||||
|
||||
iter.user_data = str(nodeid)
|
||||
return iter
|
||||
|
||||
def get_iter(self, node):
|
||||
"""
|
||||
Return an iter from the node.
|
||||
iters are always created afresh
|
||||
|
||||
Will raise IndexError if the maps are not filled yet, or if it is empty.
|
||||
Caller should take care of this if it allows calling with invalid path
|
||||
|
||||
:param path: node as it appears in the treeview
|
||||
:type path: Node
|
||||
"""
|
||||
iter = self.new_iter(id(node))
|
||||
return iter
|
||||
|
||||
def get_handle(self, node):
|
||||
"""
|
||||
Get the gramps handle for a node. Return None if the node does
|
||||
@ -804,49 +843,56 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
"""
|
||||
return self.on_get_path(self.get_node(handle))
|
||||
|
||||
# The following implement the public interface of Gtk.GenericTreeModel
|
||||
# The following implement the public interface of Gtk.TreeModel
|
||||
|
||||
def on_get_flags(self):
|
||||
def do_get_flags(self):
|
||||
"""
|
||||
See Gtk.GenericTreeModel
|
||||
See Gtk.TreeModel
|
||||
"""
|
||||
return Gtk.TreeModelFlags.ITERS_PERSIST
|
||||
return 0 #Gtk.TreeModelFlags.ITERS_PERSIST
|
||||
|
||||
def on_get_n_columns(self):
|
||||
def do_get_n_columns(self):
|
||||
"""
|
||||
Return the number of columns. Must be implemented in the child objects
|
||||
See Gtk.GenericTreeModel
|
||||
See Gtk.TreeModel
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_get_column_type(self, index):
|
||||
def do_get_column_type(self, index):
|
||||
"""
|
||||
See Gtk.GenericTreeModel
|
||||
See Gtk.TreeModel
|
||||
"""
|
||||
if index == self._tooltip_column:
|
||||
return object
|
||||
return str
|
||||
|
||||
def on_get_value(self, nodeid, col):
|
||||
def do_get_value(self, iter, col):
|
||||
"""
|
||||
See Gtk.GenericTreeModel
|
||||
See Gtk.TreeModel
|
||||
"""
|
||||
#print 'get_value', nodeid, col
|
||||
nodeid = id(nodeid)
|
||||
nodeid = long(iter.user_data)
|
||||
node = self.nodemap.node(nodeid)
|
||||
if node.handle is None:
|
||||
# Header rows dont get the foreground color set
|
||||
if col == self.color_column():
|
||||
return None
|
||||
return "#000000000000"
|
||||
|
||||
# Return the node name for the first column
|
||||
if col == 0:
|
||||
return self.column_header(node)
|
||||
|
||||
else:
|
||||
#no value to show in other header column
|
||||
return ''
|
||||
else:
|
||||
# return values for 'data' row, calling a function
|
||||
# according to column_defs table
|
||||
return self._get_value(node.handle, col, node.secondary)
|
||||
val = self._get_value(node.handle, col, node.secondary)
|
||||
#GTK 3 should convert unicode objects automatically, but this
|
||||
# gives wrong column values, so we convert
|
||||
if isinstance(val, unicode):
|
||||
return val.encode('utf-8')
|
||||
else:
|
||||
return val
|
||||
|
||||
def _get_value(self, handle, col, secondary=False):
|
||||
"""
|
||||
@ -864,29 +910,38 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
|
||||
try:
|
||||
if not secondary:
|
||||
return (self.fmap[col](data))
|
||||
return self.fmap[col](data)
|
||||
else:
|
||||
return (self.fmap2[col](data))
|
||||
return self.fmap2[col](data)
|
||||
except:
|
||||
return None
|
||||
return ''
|
||||
|
||||
def on_get_iter(self, path):
|
||||
def do_get_iter(self, path):
|
||||
"""
|
||||
Returns a node from a given path.
|
||||
"""
|
||||
if not self.tree or not self.tree[None].children:
|
||||
return None
|
||||
return False, Gtk.TreeIter()
|
||||
node = self.tree[None]
|
||||
pathlist = list(path)
|
||||
pathlist = path.get_indices()
|
||||
for index in pathlist:
|
||||
_index = (-index - 1) if self.__reverse else index
|
||||
node = self.nodemap.node(node.children[_index][1])
|
||||
return node
|
||||
return True, self.get_iter(node)
|
||||
|
||||
def on_get_path(self, node):
|
||||
def get_node_from_iter(self, iter):
|
||||
if iter and iter.user_data:
|
||||
return self.nodemap.node(long(iter.user_data))
|
||||
else:
|
||||
print ('Problem', iter, iter.user_data)
|
||||
raise NotImplementedError
|
||||
return None
|
||||
|
||||
def do_get_path(self, iter):
|
||||
"""
|
||||
Returns a path from a given node.
|
||||
"""
|
||||
node = self.get_node_from_iter(iter)
|
||||
pathlist = []
|
||||
while node.parent is not None:
|
||||
parent = self.nodemap.node(node.parent)
|
||||
@ -901,62 +956,79 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
|
||||
if pathlist is not None:
|
||||
pathlist.reverse()
|
||||
return tuple(pathlist)
|
||||
return Gtk.TreePath(tuple(pathlist))
|
||||
else:
|
||||
return None
|
||||
|
||||
def on_iter_next(self, node):
|
||||
def do_iter_next(self, iter):
|
||||
"""
|
||||
Sets iter to the next node at this level of the tree
|
||||
See Gtk.TreeModel
|
||||
Get the next node with the same parent as the given node.
|
||||
"""
|
||||
node = self.get_node_from_iter(iter)
|
||||
val = node.prev if self.__reverse else node.next
|
||||
return val and self.nodemap.node(val)
|
||||
if val:
|
||||
#user_data contains the nodeid
|
||||
iter.user_data = str(val)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def on_iter_children(self, node):
|
||||
def do_iter_children(self, iterparent):
|
||||
"""
|
||||
Get the first child of the given node.
|
||||
"""
|
||||
if node is None:
|
||||
node = self.tree[None]
|
||||
if node.children:
|
||||
return self.nodemap.node(
|
||||
node.children[-1 if self.__reverse else 0][1])
|
||||
if iterparent is None:
|
||||
nodeid = id(self.tree[None])
|
||||
else:
|
||||
return None
|
||||
nodeparent = self.get_node_from_iter(iterparent)
|
||||
if nodeparent.children:
|
||||
nodeid = nodeparent.children[-1 if self.__reverse else 0][1]
|
||||
else:
|
||||
return False, None
|
||||
return True, self.new_iter(nodeid)
|
||||
|
||||
def on_iter_has_child(self, node):
|
||||
def do_iter_has_child(self, iter):
|
||||
"""
|
||||
Find if the given node has any children.
|
||||
"""
|
||||
if node is None:
|
||||
node = self.tree[None]
|
||||
node = self.get_node_from_iter(iter)
|
||||
return True if node.children else False
|
||||
|
||||
def on_iter_n_children(self, node):
|
||||
def do_iter_n_children(self, iter):
|
||||
"""
|
||||
Get the number of children of the given node.
|
||||
"""
|
||||
if node is None:
|
||||
if iter is None:
|
||||
node = self.tree[None]
|
||||
else:
|
||||
node = self.get_node_from_iter(iter)
|
||||
return len(node.children)
|
||||
|
||||
def on_iter_nth_child(self, node, index):
|
||||
def do_iter_nth_child(self, iterparent, index):
|
||||
"""
|
||||
Get the nth child of the given node.
|
||||
"""
|
||||
if node is None:
|
||||
if iterparent is None:
|
||||
node = self.tree[None]
|
||||
else:
|
||||
node = self.get_node_from_iter(iterparent)
|
||||
if node.children:
|
||||
if len(node.children) > index:
|
||||
_index = (-index - 1) if self.__reverse else index
|
||||
return self.nodemap.node(node.children[_index][1])
|
||||
return True, self.new_iter(node.children[_index][1])
|
||||
else:
|
||||
return None
|
||||
return False, None
|
||||
else:
|
||||
return None
|
||||
return False, None
|
||||
|
||||
def on_iter_parent(self, node):
|
||||
def do_iter_parent(self, iterchild):
|
||||
"""
|
||||
Get the parent of the given node.
|
||||
"""
|
||||
return node.parent and self.nodemap.node(node.parent)
|
||||
node = self.get_node_from_iter(iterchild)
|
||||
if node.parent:
|
||||
return True, self.new_iter(node.parent)
|
||||
else:
|
||||
return False, None
|
||||
|
@ -53,7 +53,7 @@ from gen.ggettext import gettext as _
|
||||
#-------------------------------------------------------------------------
|
||||
class PersonTreeView(BasePersonView):
|
||||
"""
|
||||
A hierarchical view of the top three levels of places.
|
||||
A hierarchical view of the people based on family name.
|
||||
"""
|
||||
def __init__(self, pdata, dbstate, uistate, nav_group=0):
|
||||
BasePersonView.__init__(self, pdata, dbstate, uistate,
|
||||
|
Loading…
Reference in New Issue
Block a user