From 967f99bf7baba9202ab99cdc25133b5dc20376e3 Mon Sep 17 00:00:00 2001
From: Benny Malengier <benny.malengier@gramps-project.org>
Date: Wed, 3 Feb 2010 13:01:04 +0000
Subject: [PATCH] Use the new view plugin structure to offer a flat list person
 view

svn: r14195
---
 po/POTFILES.in                                |   4 +-
 src/gui/selectors/selectperson.py             |   6 +-
 src/gui/views/treemodels/__init__.py          |   2 +-
 src/gui/views/treemodels/flatbasemodel.py     |  18 ++
 src/gui/views/treemodels/peoplemodel.py       | 205 ++++++++++++------
 src/gui/views/treemodels/treebasemodel.py     |  12 +-
 src/plugins/lib/Makefile.am                   |   1 +
 .../personview.py => lib/libpersonview.py}    |  66 ++----
 src/plugins/lib/libplugins.gpr.py             |  16 ++
 src/plugins/tool/RelCalc.py                   |  47 ++--
 src/plugins/view/Makefile.am                  |   3 +-
 src/plugins/view/view.gpr.py                  |  18 +-
 12 files changed, 244 insertions(+), 154 deletions(-)
 rename src/plugins/{view/personview.py => lib/libpersonview.py} (88%)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index aebab53d5..b4dc226ae 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -446,6 +446,7 @@ src/plugins/lib/libhtmlconst.py
 src/plugins/lib/libmapservice.py
 src/plugins/lib/libnarrate.py
 src/plugins/lib/libodfbackend.py
+src/plugins/lib/libpersonview.py
 src/plugins/lib/libplugins.gpr.py
 src/plugins/lib/libtranslate.py
 
@@ -546,7 +547,8 @@ src/plugins/view/noteview.py
 src/plugins/view/pedigreeview.py
 src/plugins/view/pedigreeviewext.py
 src/plugins/view/pedigreeviewext.gpr.py
-src/plugins/view/personview.py
+src/plugins/view/personlistview.py
+src/plugins/view/persontreeview.py
 src/plugins/view/placeview.py
 src/plugins/view/placetreeview.gpr.py
 src/plugins/view/placetreeview.py
diff --git a/src/gui/selectors/selectperson.py b/src/gui/selectors/selectperson.py
index c4303550d..29c6164d5 100644
--- a/src/gui/selectors/selectperson.py
+++ b/src/gui/selectors/selectperson.py
@@ -34,7 +34,7 @@ import gtk
 # gramps modules
 #
 #-------------------------------------------------------------------------
-from gui.views.treemodels import PeopleModel
+from gui.views.treemodels import PeopleBaseModel, PersonTreeModel
 from baseselector import BaseSelector
 
 #-------------------------------------------------------------------------
@@ -67,7 +67,7 @@ class SelectPerson(BaseSelector):
         return _("Select Person")
         
     def get_model_class(self):
-        return PeopleModel
+        return PersonTreeModel
 
     def get_column_titles(self):
         return [
@@ -86,7 +86,7 @@ class SelectPerson(BaseSelector):
         return self.db.get_person_from_handle
         
     def get_handle_column(self):
-        return PeopleModel.COLUMN_INT_ID
+        return PeopleBaseModel.COLUMN_INT_ID
 
     def exact_search(self):
         """
diff --git a/src/gui/views/treemodels/__init__.py b/src/gui/views/treemodels/__init__.py
index f59fcd5f0..115012777 100644
--- a/src/gui/views/treemodels/__init__.py
+++ b/src/gui/views/treemodels/__init__.py
@@ -23,7 +23,7 @@
 Package init for the treemodels package.
 """
 
-from peoplemodel import PeopleModel
+from peoplemodel import PeopleBaseModel, PersonListModel, PersonTreeModel
 from familymodel import FamilyModel
 from eventmodel import EventModel
 from sourcemodel import SourceModel
diff --git a/src/gui/views/treemodels/flatbasemodel.py b/src/gui/views/treemodels/flatbasemodel.py
index 17cdd7183..1b9cd3afd 100644
--- a/src/gui/views/treemodels/flatbasemodel.py
+++ b/src/gui/views/treemodels/flatbasemodel.py
@@ -392,6 +392,7 @@ class FlatBaseModel(gtk.GenericTreeModel):
             self.sort_func = self.smap[scol]
         self.sort_col = scol
         self.skip = skip
+        self._in_build = False
 
         self.node_map = FlatNodeMap()
         self.set_search(search)
@@ -494,6 +495,15 @@ class FlatBaseModel(gtk.GenericTreeModel):
         """
         return None
 
+    def clear_cache(self, handle=None):
+        """
+        If you use a cache, overwrite here so it is cleared when this 
+        method is called (on rebuild)
+        :param handle: if None, clear entire cache, otherwise clear the handle
+                       entry if present
+        """
+        pass
+
     def sort_keys(self):
         """
         Return the (sort_key, handle) list of all data that can maximally 
@@ -513,6 +523,8 @@ class FlatBaseModel(gtk.GenericTreeModel):
         """ function called when view must be build, given a search text
             in the top search bar
         """
+        self.clear_cache()
+        self._in_build = True
         if self.db.is_open():
             allkeys = self.node_map.full_srtkey_hndl_map()
             if not allkeys:
@@ -534,11 +546,14 @@ class FlatBaseModel(gtk.GenericTreeModel):
                                        reverse=self._reverse)
         else:
             self.node_map.clear_map()
+        self._in_build = False
 
     def _rebuild_filter(self, ignore=None):
         """ function called when view must be build, given filter options
             in the filter sidebar
         """
+        self.clear_cache()
+        self._in_build = True
         if self.db.is_open():
             allkeys = self.node_map.full_srtkey_hndl_map()
             if not allkeys:
@@ -561,6 +576,7 @@ class FlatBaseModel(gtk.GenericTreeModel):
                                        reverse=self._reverse)
         else:
             self.node_map.clear_map()
+        self._in_build = False
         
     def add_row_by_handle(self, handle):
         """
@@ -584,6 +600,7 @@ class FlatBaseModel(gtk.GenericTreeModel):
         """
         Delete a row, called after the object with handle is deleted
         """
+        self.clear_cache(handle)
         data = self.map(handle)
         delete_val = (conv_unicode_tosrtkey_ongtk(self.sort_func(data)), handle)
         delete_path = self.node_map.delete(delete_val)
@@ -595,6 +612,7 @@ class FlatBaseModel(gtk.GenericTreeModel):
         """
         Update a row, called after the object with handle is changed
         """
+        self.clear_cache(handle)
         oldsortkey = self.node_map.get_sortkey(handle)
         newsortkey = conv_unicode_tosrtkey_ongtk(self.sort_func(self.map(
                             handle)))
diff --git a/src/gui/views/treemodels/peoplemodel.py b/src/gui/views/treemodels/peoplemodel.py
index 71fe48e99..459c5a42e 100644
--- a/src/gui/views/treemodels/peoplemodel.py
+++ b/src/gui/views/treemodels/peoplemodel.py
@@ -32,7 +32,6 @@ TreeModel for the GRAMPS Person tree.
 # Standard python modules
 #
 #-------------------------------------------------------------------------
-from __future__ import with_statement
 from gen.ggettext import gettext as _
 import time
 import cgi
@@ -64,6 +63,7 @@ import DateHandler
 import ToolTips
 import GrampsLocale
 from Lru import LRU
+from gui.views.treemodels.flatbasemodel import FlatBaseModel
 from gui.views.treemodels.treebasemodel import TreeBaseModel
 import config
 
@@ -86,34 +86,26 @@ invalid_date_format = config.get('preferences.invalid-date-format')
 
 #-------------------------------------------------------------------------
 #
-# PeopleModel
+# PeopleBaseModel
 #
 #-------------------------------------------------------------------------
-class PeopleModel(TreeBaseModel):
+class PeopleBaseModel(object):
     """
-    Basic GenericTreeModel interface to handle the Tree interface for
-    the PersonView
+    Basic Model interface to handle the PersonViews
     """
     _GENDER = [ _(u'female'), _(u'male'), _(u'unknown') ]
 
     # The following is accessed from PersonView - CHECK
     COLUMN_INT_ID = 12  # dynamic calculation of column indices
+    # LRU cache size
+    _CACHE_SIZE = 250
 
-    def __init__(self, db, scol=0, order=gtk.SORT_ASCENDING, search=None,
-                 skip=set(), sort_map=None):
+    def __init__(self, db):
         """
         Initialize the model building the initial data
         """
-        TreeBaseModel.__init__(self, db, search=search, skip=skip,
-                                tooltip_column=11, marker_column=10,
-                                scol=scol, order=order, sort_map=sort_map)
-
-    def _set_base_data(self):
-        """See TreeBaseModel, we also set some extra lru caches
-        """
-        self.gen_cursor = self.db.get_person_cursor
-        self.number_items = self.db.get_number_of_people
-        self.map = self.db.get_raw_person_data
+        self.gen_cursor = db.get_person_cursor
+        self.map = db.get_raw_person_data
 
         self.fmap = [
             self.column_name,
@@ -145,59 +137,71 @@ class PeopleModel(TreeBaseModel):
             self.column_tooltip,
             self.column_int_id,
             ]
-        self.hmap = [self.column_header] + [None]*len(self.smap)
 
-        self.lru_name  = LRU(TreeBaseModel._CACHE_SIZE)
-        self.lru_bdate = LRU(TreeBaseModel._CACHE_SIZE)
-        self.lru_ddate = LRU(TreeBaseModel._CACHE_SIZE)
+        #columns are accessed on every mouse over, so it is worthwhile to
+        #cache columns visible in one screen to avoid expensive database 
+        #lookup of derived values
+        self.lru_name  = LRU(PeopleBaseModel._CACHE_SIZE)
+        self.lru_spouse = LRU(PeopleBaseModel._CACHE_SIZE)
+        self.lru_bdate = LRU(PeopleBaseModel._CACHE_SIZE)
+        self.lru_ddate = LRU(PeopleBaseModel._CACHE_SIZE)
 
-    def clear_cache(self):
+    def clear_local_cache(self, handle=None):
         """ Clear the LRU cache """
-        TreeBaseModel.clear_cache(self)
-        self.lru_name.clear()
-        self.lru_bdate.clear()
-        self.lru_ddate.clear()
-        
+        if handle:
+            try:
+                del self.lru_name[handle]
+            except KeyError:
+                pass
+            try:
+                del self.lru_spouse[handle]
+            except KeyError:
+                pass
+            try:
+                del self.lru_bdate[handle]
+            except KeyError:
+                pass
+            try:
+                del self.lru_ddate[handle]
+            except KeyError:
+                pass
+        else:
+            self.lru_name.clear()
+            self.lru_spouse.clear()
+            self.lru_bdate.clear()
+            self.lru_ddate.clear()
+
     def on_get_n_columns(self):
         """ Return the number of columns in the model """
         return len(self.fmap)+1
 
-    def get_tree_levels(self):
-        """
-        Return the headings of the levels in the hierarchy.
-        """
-        return ['Group As', 'Name']
-
-    def add_row(self, handle, data):
-        """
-        Add nodes to the node map for a single person.
-
-        handle      The handle of the gramps object.
-        data        The object data.
-        """
-        ngn = name_displayer.name_grouping_data
-        nsn = name_displayer.raw_sorted_name
-        
-        name_data = data[COLUMN_NAME]
-        group_name = ngn(self.db, name_data)
-        sort_key = self.sort_func(data)
-
-        #if group_name not in self.group_list:
-            #self.group_list.append(group_name)
-            #self.add_node(None, group_name, group_name, None)
-            
-        # add as node: parent, child, sortkey, handle; parent and child are 
-        # nodes in the treebasemodel, and will be used as iters
-        self.add_node(group_name, handle, sort_key, handle)
-        
     def sort_name(self, data):
         n = Name()
         n.unserialize(data[COLUMN_NAME])
         return name_displayer.sort_string(n)
 
-    def column_spouse(self, data):
-        spouses_names = u""
+    def column_name(self, data):
         handle = data[0]
+        if handle in self.lru_name:
+            name = self.lru_name[handle]
+        else:
+            name = name_displayer.raw_sorted_name(data[COLUMN_NAME])
+            if not self._in_build:
+                self.lru_name[handle] = name
+        return name
+
+    def column_spouse(self, data):
+        handle = data[0]
+        if handle in self.lru_spouse:
+            value = self.lru_spouse[handle]
+        else:
+            value = self._get_spouse_data(data)
+            if not self._in_build:
+                self.lru_spouse[handle] = value
+        return value
+    
+    def _get_spouse_data(self, data):
+        spouses_names = u""
         for family_handle in data[COLUMN_FAMILY]:
             family = self.db.get_family_from_handle(family_handle)
             for spouse_id in [family.get_father_handle(),
@@ -212,16 +216,6 @@ class PeopleModel(TreeBaseModel):
                 spouses_names += name_displayer.display(spouse)
         return spouses_names
 
-    def column_name(self, data):
-        handle = data[0]
-        if handle in self.lru_name:
-            name = self.lru_name[handle]
-        else:
-            name = name_displayer.raw_sorted_name(data[COLUMN_NAME])
-            if not self._in_build:
-                self.lru_name[handle] = name
-        return name
-
     def column_id(self, data):
         return data[COLUMN_ID]
         
@@ -232,7 +226,7 @@ class PeopleModel(TreeBaseModel):
             GrampsLocale.codeset)
 
     def column_gender(self, data):
-        return PeopleModel._GENDER[data[COLUMN_GENDER]]
+        return PeopleBaseModel._GENDER[data[COLUMN_GENDER]]
 
     def column_birth_day(self, data):
         handle = data[0]
@@ -445,9 +439,80 @@ class PeopleModel(TreeBaseModel):
     def column_int_id(self, data):
         return data[0]
 
+class PersonListModel(PeopleBaseModel, FlatBaseModel):
+    """
+    Listed people model.
+    """
+    def __init__(self, db, scol=0, order=gtk.SORT_ASCENDING, search=None,
+                 skip=set(), sort_map=None):
+
+        PeopleBaseModel.__init__(self, db)
+        FlatBaseModel.__init__(self, db, search=search, skip=skip,
+                                tooltip_column=11,
+                                scol=scol, order=order, sort_map=sort_map)
+
+    def clear_cache(self, handle=None):
+        """ Clear the LRU cache """
+        PeopleBaseModel.clear_local_cache(self, handle)
+
+    def marker_column(self):
+        """
+        Return the column for marker colour.
+        """
+        return 10
+
+class PersonTreeModel(PeopleBaseModel, TreeBaseModel):
+    """
+    Hierarchical people model.
+    """
+    def __init__(self, db, scol=0, order=gtk.SORT_ASCENDING, search=None,
+                 skip=set(), sort_map=None):
+
+        PeopleBaseModel.__init__(self, db)
+        TreeBaseModel.__init__(self, db, 11, search=search, skip=skip,
+                                marker_column=10,
+                                scol=scol, order=order, sort_map=sort_map)
+
+    def _set_base_data(self):
+        """See TreeBaseModel, we also set some extra lru caches
+        """
+        self.number_items = self.db.get_number_of_people
+        self.hmap = [self.column_header] + [None]*len(self.smap)
+
+    def clear_cache(self, handle=None):
+        """ Clear the LRU cache 
+        overwrite of base methods
+        """
+        TreeBaseModel.clear_cache(self, handle)
+        PeopleBaseModel.clear_local_cache(self, handle)
+
+    def get_tree_levels(self):
+        """
+        Return the headings of the levels in the hierarchy.
+        """
+        return ['Group As', 'Name']
+
     def column_header(self, node):
         return node.name
+    
+    def add_row(self, handle, data):
+        """
+        Add nodes to the node map for a single person.
 
-    def column_header_view(self, node):
-        return True
+        handle      The handle of the gramps object.
+        data        The object data.
+        """
+        ngn = name_displayer.name_grouping_data
+        nsn = name_displayer.raw_sorted_name
+        
+        name_data = data[COLUMN_NAME]
+        group_name = ngn(self.db, name_data)
+        sort_key = self.sort_func(data)
 
+        #if group_name not in self.group_list:
+            #self.group_list.append(group_name)
+            #self.add_node(None, group_name, group_name, None)
+            
+        # add as node: parent, child, sortkey, handle; parent and child are 
+        # nodes in the treebasemodel, and will be used as iters
+        self.add_node(group_name, handle, sort_key, handle)
diff --git a/src/gui/views/treemodels/treebasemodel.py b/src/gui/views/treemodels/treebasemodel.py
index 2ebe33375..18cbe04bd 100644
--- a/src/gui/views/treemodels/treebasemodel.py
+++ b/src/gui/views/treemodels/treebasemodel.py
@@ -386,11 +386,17 @@ class TreeBaseModel(gtk.GenericTreeModel):
         """
         return self._marker_column
 
-    def clear_cache(self):
+    def clear_cache(self, handle=None):
         """
         Clear the LRU cache.
         """
-        self.lru_data.clear()
+        if handle:
+            try:
+                del self.lru_data[handle]
+            except KeyError:
+                pass
+        else:
+            self.lru_data.clear()
 
     def clear(self):
         """
@@ -671,7 +677,7 @@ class TreeBaseModel(gtk.GenericTreeModel):
         Delete a row from the model.
         """
         cput = time.clock()
-        self.clear_cache()
+        self.clear_cache(handle)
 
         node = self.get_node(handle)
         parent = self.nodemap.node(node.parent)
diff --git a/src/plugins/lib/Makefile.am b/src/plugins/lib/Makefile.am
index 27e53262e..0b688e1ef 100644
--- a/src/plugins/lib/Makefile.am
+++ b/src/plugins/lib/Makefile.am
@@ -18,6 +18,7 @@ pkgdata_PYTHON = \
 	libmapservice.py\
 	libmixin.py\
 	libodfbackend.py\
+	libpersonview.py\
 	libplugins.gpr.py\
 	libtranslate.py
 
diff --git a/src/plugins/view/personview.py b/src/plugins/lib/libpersonview.py
similarity index 88%
rename from src/plugins/view/personview.py
rename to src/plugins/lib/libpersonview.py
index 6bfd11f49..5253cbf95 100644
--- a/src/plugins/view/personview.py
+++ b/src/plugins/lib/libpersonview.py
@@ -3,6 +3,7 @@
 # Copyright (C) 2000-2007  Donald N. Allingham
 # Copyright (C) 2008       Gary Burton
 # Copyright (C) 2009       Nick Hall
+# Copyright (C) 2010       Benny Malengier
 #
 # 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
@@ -16,13 +17,13 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  021111307  USA
 #
 
 # $Id$
 
 """
-Provide the person view.
+Provide the base for a list person view.
 """
 
 #-------------------------------------------------------------------------
@@ -46,8 +47,7 @@ _LOG = logging.getLogger(".gui.personview")
 #
 #-------------------------------------------------------------------------
 import gen.lib
-from gui.views.listview import ListView, LISTTREE
-from gui.views.treemodels import PeopleModel
+from gui.views.listview import ListView
 import Utils
 from gen.display.name import displayer as name_displayer
 from QuestionDialog import ErrorDialog, QuestionDialog
@@ -71,9 +71,9 @@ from gen.ggettext import sgettext as _
 # PersonView
 #
 #-------------------------------------------------------------------------
-class PersonView(ListView):
+class BasePersonView(ListView):
     """
-    PersonView class, derived from the ListView, a treeview
+    Base view for PersonView listviews ListView, a treeview
     """
     COL_NAME = 0
     COL_ID = 1
@@ -109,7 +109,7 @@ class PersonView(ListView):
     FILTER_TYPE = "Person"
     QR_CATEGORY = CATEGORY_QR_PERSON
 
-    def __init__(self, dbstate, uistate, nav_group=0):
+    def __init__(self, dbstate, uistate, title, model, nav_group=0):
         """
         Create the Person View
         """
@@ -119,12 +119,11 @@ class PersonView(ListView):
             'person-delete'  : self.row_delete,
             'person-rebuild' : self.object_build,
             }
-
+ 
         ListView.__init__(
-            self, _('People'), dbstate, uistate,
-            PersonView.COLUMN_NAMES, len(PersonView.COLUMN_NAMES), 
-            PeopleModel,
-            signal_map, dbstate.db.get_bookmarks(),
+            self, title, dbstate, uistate,
+            BasePersonView.COLUMN_NAMES, len(BasePersonView.COLUMN_NAMES), 
+            model, signal_map, dbstate.db.get_bookmarks(),
             Bookmarks.PersonBookmarks, nav_group,
             multiple=True,
             filter_class=PersonSidebarFilter,
@@ -137,12 +136,6 @@ class PersonView(ListView):
 
         config.connect("interface.filter", self.filter_toggle)
 
-    def type_list(self):
-        """
-        set the listtype, this governs eg keybinding
-        """
-        return LISTTREE
-
     def navigation_type(self):
         return 'Person'
 
@@ -168,18 +161,13 @@ class PersonView(ListView):
         """
         Returns a tuple indicating columns requiring an exact search
         """
-        return (PersonView.COL_GEN,) # Gender ('female' contains the string 'male')
+        return (BasePersonView.COL_GEN,) # Gender ('female' contains the string 'male')
 
     def get_stock(self):
         """
-        Use the gramps-person stock icon
+        Use the grampsperson stock icon
         """
         return 'gramps-person'
-    
-    def get_viewtype_stock(self):
-        """Type of view in category
-        """
-        return 'gramps-tree-group'
 
     def ui_definition(self):
         """
@@ -223,7 +211,7 @@ class PersonView(ListView):
           </menubar>
           <toolbar name="ToolBar">
             <placeholder name="CommonNavigation">
-              <toolitem action="Back"/>  
+              <toolitem action="Back"/>
               <toolitem action="Forward"/>  
               <toolitem action="HomePerson"/>
             </placeholder>
@@ -238,9 +226,6 @@ class PersonView(ListView):
             <menuitem action="Forward"/>
             <menuitem action="HomePerson"/>
             <separator/>
-            <menuitem action="OpenAllNodes"/>
-            <menuitem action="CloseAllNodes"/>
-            <separator/>
             <menuitem action="Add"/>
             <menuitem action="Edit"/>
             <menuitem action="Remove"/>
@@ -261,23 +246,11 @@ class PersonView(ListView):
     def add(self, obj):
         person = gen.lib.Person()
         
-        # attempt to get the current surname
-        (model, pathlist) = self.selection.get_selected_rows()
-        name = u""
-        if len(pathlist) == 1:
-            path = pathlist[0]
-            if len(path) == 1:
-                name = model.on_get_iter(path).name
-            else:
-                node = model.on_get_iter(path)
-                name = model.on_iter_parent(node).name
-
         try:
-            person.get_primary_name().set_surname(name)
-            EditPerson(self.dbstate, self.uistate, [], person)
+            EditPerson(self.dbstate, self.uistate, [], gen.lib.Person())
         except Errors.WindowActiveError:
             pass
-
+ 
     def edit(self, obj):
         for handle in self.selected_handles():
             person = self.dbstate.db.get_person_from_handle(handle)
@@ -336,7 +309,7 @@ class PersonView(ListView):
         path = self.model.on_get_path(node)
         (col, row) = path
         if row > 0:
-            self.selection.select_path((col, row-1))
+            self.selection.select_path((col, row1))
         elif row == 0 and self.model.on_get_iter(path):
             self.selection.select_path(path)
 
@@ -369,16 +342,13 @@ class PersonView(ListView):
         self.all_action.add_actions([
                 ('FilterEdit', None, _('Person Filter Editor'), None, None,
                 self.filter_editor),
-                ('OpenAllNodes', None, _("Expand all Nodes"), None, None, 
-                 self.open_all_nodes), 
                 ('Edit', gtk.STOCK_EDIT, _("action|_Edit..."), "<control>Return", 
                  _("Edit the selected person"), self.edit), 
-                ('CloseAllNodes', None, _("Collapse all Nodes"), None, None, 
-                 self.close_all_nodes), 
                 ('QuickReport', None, _("Quick View"), None, None, None), 
                 ('Dummy', None, '  ', None, None, self.dummy_report), 
                 ])
 
+
         self.edit_action.add_actions(
             [
                 ('Add', gtk.STOCK_ADD, _("_Add..."), "<control>Insert", 
diff --git a/src/plugins/lib/libplugins.gpr.py b/src/plugins/lib/libplugins.gpr.py
index 70e588e3f..d77cd80d1 100644
--- a/src/plugins/lib/libplugins.gpr.py
+++ b/src/plugins/lib/libplugins.gpr.py
@@ -238,3 +238,19 @@ fname = 'libtranslate.py',
 authors = ["Brian Matherly"],
 authors_email = ["brian@gramps-project.org"],
 )
+
+#------------------------------------------------------------------------
+#
+# libpersonview
+#
+#------------------------------------------------------------------------
+register(GENERAL, 
+id    = 'libpersonview',
+name  = "lib for the person list views",
+description =  _("Provides the Base needed for the List People views.") ,
+version = '1.0',
+status = STABLE,
+fname = 'libpersonview.py',
+authors = ["The Gramps project"],
+authors_email = ["http://gramps-project.org"],
+)
diff --git a/src/plugins/tool/RelCalc.py b/src/plugins/tool/RelCalc.py
index 290c73b60..31cdad624 100644
--- a/src/plugins/tool/RelCalc.py
+++ b/src/plugins/tool/RelCalc.py
@@ -45,7 +45,8 @@ import gtk
 #-------------------------------------------------------------------------
 from gen.display.name import displayer as name_displayer
 import ManagedWindow
-from gui.views.treemodels import PeopleModel
+from gui.views.treemodels import PeopleBaseModel, PersonTreeModel
+from libpersonview import BasePersonView
 import Relationship
 
 from QuestionDialog import ErrorDialog
@@ -58,18 +59,7 @@ from glade import Glade
 #
 #-------------------------------------------------------------------------
 
-column_names = [
-    _('Name'),
-    _('ID') ,
-    _('Gender'),
-    _('Birth Date'),
-    _('Birth Place'),
-    _('Death Date'),
-    _('Death Place'),
-    _('Spouse'),
-    _('Last Change'),
-    _('Cause of Death'),
-    ]
+column_names = BasePersonView.COLUMN_NAMES
 
 #-------------------------------------------------------------------------
 #
@@ -86,6 +76,21 @@ class RelCalc(Tool.Tool, ManagedWindow.ManagedWindow):
         Tool.Tool.__init__(self, dbstate, options_class, name)
         ManagedWindow.ManagedWindow.__init__(self,uistate,[],self.__class__)
 
+        #set the columns to see
+        for data in BasePersonView.CONFIGSETTINGS:
+            if data[0] == 'columns.order':
+                colord = data[1]
+            elif data[0] == 'columns.visible':
+                colvis = data[1]
+            elif data[0] == 'columns.sizecol':
+                colsize = data[1]
+        self.colord = []
+        for col, size in zip(colord, colsize):
+            if col in colvis:
+                self.colord.append((1, col, size))
+            else:
+                self.colord.append((0, col, size))
+
         self.dbstate = dbstate
         self.relationship = Relationship.get_relationship_calculator()
         self.relationship.connect_db_signals(dbstate)
@@ -110,23 +115,16 @@ class RelCalc(Tool.Tool, ManagedWindow.ManagedWindow):
         self.textbuffer = gtk.TextBuffer()
         self.text.set_buffer(self.textbuffer)
         
-        self.model = PeopleModel(self.db)
+        self.model = PersonTreeModel(self.db)
         self.tree.set_model(self.model)
 
         self.tree.connect('key-press-event', self._key_press)
         self.selection = self.tree.get_selection()
         self.selection.set_mode(gtk.SELECTION_SINGLE)
 
-        column = gtk.TreeViewColumn(_('Name'), gtk.CellRendererText(),text=0)
-        column.set_resizable(True)
-        column.set_min_width(225)
-        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
-        self.tree.append_column(column)
         #keep reference of column so garbage collection works
-        self.columns = [column]
-
-        index = 1
-        for pair in self.db.get_person_column_order():
+        self.columns = []
+        for pair in self.colord:
             if not pair[0]:
                 continue
             name = column_names[pair[1]]
@@ -138,7 +136,6 @@ class RelCalc(Tool.Tool, ManagedWindow.ManagedWindow):
             self.tree.append_column(column)
             #keep reference of column so garbage collection works
             self.columns.append(column)
-            index += 1
 
         self.sel = self.tree.get_selection()
         self.changedkey = self.sel.connect('changed',self.on_apply_clicked)
@@ -171,7 +168,7 @@ class RelCalc(Tool.Tool, ManagedWindow.ManagedWindow):
         if not node:
             return
         
-        handle = model.get_value(node, PeopleModel.COLUMN_INT_ID)
+        handle = model.get_value(node, PeopleBaseModel.COLUMN_INT_ID)
         other_person = self.db.get_person_from_handle(handle)        
         if other_person is None :
             self.textbuffer.set_text("")
diff --git a/src/plugins/view/Makefile.am b/src/plugins/view/Makefile.am
index 1855acc70..a1c38287b 100644
--- a/src/plugins/view/Makefile.am
+++ b/src/plugins/view/Makefile.am
@@ -17,7 +17,8 @@ pkgdata_PYTHON = \
 	pedigreeview.py \
 	pedigreeviewext.py \
 	pedigreeviewext.gpr.py \
-	personview.py \
+	personlistview.py \
+	persontreeview.py \
 	placetreeview.gpr.py \
 	placetreeview.py \
 	placeview.py \
diff --git a/src/plugins/view/view.gpr.py b/src/plugins/view/view.gpr.py
index b953e5901..b25da85ae 100644
--- a/src/plugins/view/view.gpr.py
+++ b/src/plugins/view/view.gpr.py
@@ -131,15 +131,29 @@ name  = _("Person View"),
 description =  _("The view showing all people in the family tree"),
 version = '1.0',
 status = STABLE,
-fname = 'personview.py',
+fname = 'persontreeview.py',
 authors = [u"The Gramps project"],
 authors_email = ["http://gramps-project.org"],
 category = ("People", _("People")),
-viewclass = 'PersonView',
+viewclass = 'PersonTreeView',
 order = START,
   )
 
 register(VIEW, 
+id    = 'personlistview',
+name  = _("Person List View"),
+description =  _("The view showing all people in the family tree"
+                 " in a flat list"),
+version = '1.0',
+status = STABLE,
+fname = 'personlistview.py',
+authors = [u"The Gramps project"],
+authors_email = ["http://gramps-project.org"],
+category = ("People", _("People")),
+viewclass = 'PersonListView',
+order = END,
+  )
+register(VIEW, 
 id    = 'placeview',
 name  = _("Place View"),
 description =  _("The view showing all the places of the family tree"),