From 9da71185a63fd916057186b4782e661883894aab Mon Sep 17 00:00:00 2001 From: Benny Malengier Date: Tue, 10 Jul 2012 03:32:08 +0000 Subject: [PATCH] Working person treeview, insert/add/delete still todo read/write db, make sure unicode or utf8, nothing else! svn: r19966 --- src/gen/db/read.py | 10 +- src/gen/db/write.py | 5 +- src/gen/lib/name.py | 12 +- src/gen/utils/cast.py | 3 + src/gui/views/listview.py | 55 ++++--- src/gui/views/treemodels/flatbasemodel.py | 15 +- src/gui/views/treemodels/peoplemodel.py | 37 +++-- src/gui/views/treemodels/treebasemodel.py | 192 +++++++++++++++------- src/plugins/view/persontreeview.py | 2 +- 9 files changed, 215 insertions(+), 116 deletions(-) diff --git a/src/gen/db/read.py b/src/gen/db/read.py index 2e4360a2e..53c3ee11d 100644 --- a/src/gen/db/read.py +++ b/src/gen/db/read.py @@ -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) diff --git a/src/gen/db/write.py b/src/gen/db/write.py index 853ded8d8..0b8b00e6b 100644 --- a/src/gen/db/write.py +++ b/src/gen/db/write.py @@ -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) diff --git a/src/gen/lib/name.py b/src/gen/lib/name.py index c810536db..352b4e739 100644 --- a/src/gen/lib/name.py +++ b/src/gen/lib/name.py @@ -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 diff --git a/src/gen/utils/cast.py b/src/gen/utils/cast.py index a9ba2d711..be81f0a50 100644 --- a/src/gen/utils/cast.py +++ b/src/gen/utils/cast.py @@ -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): diff --git a/src/gui/views/listview.py b/src/gui/views/listview.py index 559101a55..a23702fe5 100644 --- a/src/gui/views/listview.py +++ b/src/gui/views/listview.py @@ -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 diff --git a/src/gui/views/treemodels/flatbasemodel.py b/src/gui/views/treemodels/flatbasemodel.py index ca59f8e1f..bd0435a91 100644 --- a/src/gui/views/treemodels/flatbasemodel.py +++ b/src/gui/views/treemodels/flatbasemodel.py @@ -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 diff --git a/src/gui/views/treemodels/peoplemodel.py b/src/gui/views/treemodels/peoplemodel.py index 39dbd7050..d50a3fdba 100644 --- a/src/gui/views/treemodels/peoplemodel.py +++ b/src/gui/views/treemodels/peoplemodel.py @@ -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(), @@ -231,7 +238,7 @@ class PeopleBaseModel(object): def column_id(self, data): return data[COLUMN_ID] - + def sort_change(self,data): return "%012x" % data[COLUMN_CHANGE] @@ -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"%s" % cgi.escape(date_str) + retval = "%s" % 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 "%s" % 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 "" + cgi.escape(place_title) + "" - 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: diff --git a/src/gui/views/treemodels/treebasemodel.py b/src/gui/views/treemodels/treebasemodel.py index 4379493b8..cfd6d9e21 100644 --- a/src/gui/views/treemodels/treebasemodel.py +++ b/src/gui/views/treemodels/treebasemodel.py @@ -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: @@ -783,14 +797,39 @@ 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 not correspond to a gramps object. """ return node.handle - + def get_node(self, handle): """ Get the node for a handle. @@ -804,50 +843,57 @@ 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): """ Returns the contents of a given column of a gramps object @@ -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 - - def on_get_path(self, node): + return True, self.get_iter(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 diff --git a/src/plugins/view/persontreeview.py b/src/plugins/view/persontreeview.py index cf8299909..e9eb39dd3 100644 --- a/src/plugins/view/persontreeview.py +++ b/src/plugins/view/persontreeview.py @@ -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,