r20620 - gnucash/trunk/src - Add Tree view widget for owner objects, not used yet

Geert Janssens gjanssens at code.gnucash.org
Wed May 11 17:51:04 EDT 2011


Author: gjanssens
Date: 2011-05-11 17:51:03 -0400 (Wed, 11 May 2011)
New Revision: 20620
Trac: http://svn.gnucash.org/trac/changeset/20620

Added:
   gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.c
   gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.h
   gnucash/trunk/src/gnome/gtkbuilder/owner.ui
Modified:
   gnucash/trunk/src/gnome-utils/Makefile.am
   gnucash/trunk/src/gnome/gtkbuilder/Makefile.am
Log:
Add Tree view widget for owner objects, not used yet

Modified: gnucash/trunk/src/gnome/gtkbuilder/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome/gtkbuilder/Makefile.am	2011-05-11 21:50:54 UTC (rev 20619)
+++ gnucash/trunk/src/gnome/gtkbuilder/Makefile.am	2011-05-11 21:51:03 UTC (rev 20620)
@@ -8,6 +8,7 @@
 	fincalc.glade \
 	lots.glade \
 	newuser.glade \
+	owner.ui \
 	price.glade \
 	print.glade \
 	progress.glade \

Added: gnucash/trunk/src/gnome/gtkbuilder/owner.ui
===================================================================
--- gnucash/trunk/src/gnome/gtkbuilder/owner.ui	                        (rev 0)
+++ gnucash/trunk/src/gnome/gtkbuilder/owner.ui	2011-05-11 21:51:03 UTC (rev 20620)
@@ -0,0 +1,96 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkDialog" id="Filter By">
+    <property name="visible">True</property>
+    <property name="border_width">6</property>
+    <property name="title" translatable="yes">Filter By...</property>
+    <property name="type_hint">dialog</property>
+    <signal name="response" handler="gppot_filter_response_cb"/>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox13">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkCheckButton" id="show_hidden">
+            <property name="label" translatable="yes">Only show _active owners</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">False</property>
+            <property name="use_underline">True</property>
+            <property name="draw_indicator">True</property>
+            <signal name="toggled" handler="gppot_filter_show_inactive_toggled_cb"/>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="show_zero">
+            <property name="label" translatable="yes">Show _zero balance owners</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">False</property>
+            <property name="use_underline">True</property>
+            <property name="draw_indicator">True</property>
+            <signal name="toggled" handler="gppot_filter_show_zero_toggled_cb"/>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area13">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancelbutton1">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="okbutton1">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">cancelbutton1</action-widget>
+      <action-widget response="-5">okbutton1</action-widget>
+    </action-widgets>
+  </object>
+</interface>

Modified: gnucash/trunk/src/gnome-utils/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome-utils/Makefile.am	2011-05-11 21:50:54 UTC (rev 20619)
+++ gnucash/trunk/src/gnome-utils/Makefile.am	2011-05-11 21:51:03 UTC (rev 20620)
@@ -93,6 +93,7 @@
   gnc-tree-model-price.c \
   gnc-tree-view-account.c \
   gnc-tree-view-commodity.c \
+  gnc-tree-view-owner.c \
   gnc-tree-view-price.c \
   gnc-tree-view-sx-list.c \
   gnc-tree-view.c \
@@ -164,6 +165,7 @@
   gnc-tree-model-price.h \
   gnc-tree-view-account.h \
   gnc-tree-view-commodity.h \
+  gnc-tree-view-owner.h \
   gnc-tree-view-price.h \
   gnc-tree-view-sx-list.h \
   gnc-tree-view.h \

Added: gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.c	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.c	2011-05-11 21:51:03 UTC (rev 20620)
@@ -0,0 +1,1654 @@
+/********************************************************************\
+ * gnc-tree-view-owner.c -- GtkTreeView implementation to display   *
+ *                            owners in a GtkTreeView.              *
+ * Copyright (C) 2011 Geert Janssens <geert at kobaltwit.be>           *
+ *                                                                  *
+ * 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 the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ *                                                                  *
+\********************************************************************/
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "gnc-tree-view.h"
+#include "gnc-tree-model-owner.h"
+#include "gnc-tree-view-owner.h"
+
+#include "gncOwner.h"
+#include "gnc-accounting-period.h"
+#include "gnc-commodity.h"
+#include "gnc-component-manager.h"
+#include "gnc-engine.h"
+#include "gnc-glib-utils.h"
+#include "gnc-gobject-utils.h"
+#include "gnc-hooks.h"
+#include "gnc-session.h"
+#include "gnc-icons.h"
+#include "gnc-ui-util.h"
+#include "dialog-utils.h"
+#include "window-main-summarybar.h"
+#include "assistant-utils.h"
+
+#define SAMPLE_OWNER_VALUE "$1,000,000.00"
+
+/** Static Globals *******************************************************/
+
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = GNC_MOD_GUI;
+
+/** Declarations *********************************************************/
+static void gnc_tree_view_owner_class_init (GncTreeViewOwnerClass *klass);
+static void gnc_tree_view_owner_init (GncTreeViewOwner *view);
+static void gnc_tree_view_owner_finalize (GObject *object);
+
+static void gtvo_update_column_names (GncTreeView *view);
+static void gtvo_currency_changed_cb (void);
+
+static gboolean gnc_tree_view_owner_filter_helper (GtkTreeModel *model,
+        GtkTreeIter *iter,
+        gpointer data);
+
+static void gtvo_setup_column_renderer_edited_cb(GncTreeViewOwner *owner_view,
+        GtkTreeViewColumn *column,
+        GtkCellRenderer *renderer,
+        GncTreeViewOwnerColumnTextEdited col_edited_cb);
+
+typedef struct GncTreeViewOwnerPrivate
+{
+    OwnerViewInfo ovi;
+
+    gnc_tree_view_owner_filter_func filter_fn;
+    gpointer                          filter_data;
+    GtkFunction                       filter_destroy;
+
+    GtkTreeViewColumn *name_column;
+    GtkTreeViewColumn *id_column;
+    GtkTreeViewColumn *balance_report_column;
+    GtkTreeViewColumn *notes_column;
+} GncTreeViewOwnerPrivate;
+
+#define GNC_TREE_VIEW_OWNER_GET_PRIVATE(o)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_VIEW_OWNER, GncTreeViewOwnerPrivate))
+
+
+/************************************************************/
+/*               g_object required functions                */
+/************************************************************/
+
+static GObjectClass *parent_class = NULL;
+
+GType
+gnc_tree_view_owner_get_type (void)
+{
+    static GType gnc_tree_view_owner_type = 0;
+
+    if (gnc_tree_view_owner_type == 0)
+    {
+        static const GTypeInfo our_info =
+        {
+            sizeof (GncTreeViewOwnerClass),
+            NULL,
+            NULL,
+            (GClassInitFunc) gnc_tree_view_owner_class_init,
+            NULL,
+            NULL,
+            sizeof (GncTreeViewOwner),
+            0,
+            (GInstanceInitFunc) gnc_tree_view_owner_init
+        };
+
+        gnc_tree_view_owner_type = g_type_register_static (
+                                         GNC_TYPE_TREE_VIEW, GNC_TREE_VIEW_OWNER_NAME,
+                                         &our_info, 0);
+    }
+
+    return gnc_tree_view_owner_type;
+}
+
+static void
+gnc_tree_view_owner_class_init (GncTreeViewOwnerClass *klass)
+{
+    GObjectClass *o_class;
+
+    parent_class = g_type_class_peek_parent (klass);
+
+    /* GObject signals */
+    o_class = G_OBJECT_CLASS (klass);
+    o_class->finalize = gnc_tree_view_owner_finalize;
+
+    g_type_class_add_private(klass, sizeof(GncTreeViewOwnerPrivate));
+
+    gnc_hook_add_dangler(HOOK_CURRENCY_CHANGED,
+                         (GFunc)gtvo_currency_changed_cb, NULL);
+}
+
+/********************************************************************\
+ * gnc_init_owner_view_info                                         *
+ *   initialize an owner view info structure with default values    *
+ *                                                                  *
+ * Args: ovi - structure to initialize                              *
+ * Returns: nothing                                                 *
+\********************************************************************/
+static void
+gnc_init_owner_view_info(OwnerViewInfo *ovi)
+{
+    ovi->show_inactive = FALSE;
+}
+
+static void
+gnc_tree_view_owner_init (GncTreeViewOwner *view)
+{
+    GncTreeViewOwnerPrivate *priv;
+
+    priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
+    gnc_init_owner_view_info(&priv->ovi);
+}
+
+static void
+gnc_tree_view_owner_finalize (GObject *object)
+{
+    GncTreeViewOwner *owner_view;
+    GncTreeViewOwnerPrivate *priv;
+
+    ENTER("view %p", object);
+    g_return_if_fail (object != NULL);
+    g_return_if_fail (GNC_IS_TREE_VIEW_OWNER (object));
+
+    owner_view = GNC_TREE_VIEW_OWNER (object);
+
+    priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(owner_view);
+    if (priv->filter_destroy)
+    {
+        priv->filter_destroy(priv->filter_data);
+        priv->filter_destroy = NULL;
+    }
+    priv->filter_fn = NULL;
+
+    if (G_OBJECT_CLASS (parent_class)->finalize)
+        (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+    LEAVE(" ");
+}
+
+
+/************************************************************
+ *                        Callbacks                         *
+ ************************************************************/
+static void
+gnc_tree_view_owner_active_toggled (GtkCellRendererToggle *cell,
+        const gchar *s_path_str,
+        gpointer user_data)
+{
+    GncTreeViewOwner *tree_view;
+    GtkTreePath *s_path;
+    GncOwner *owner;
+    gboolean active;
+
+    /* Change the requested owner */
+    tree_view = user_data;
+    s_path = gtk_tree_path_new_from_string (s_path_str);
+    owner = gnc_tree_view_owner_get_owner_from_path (tree_view, s_path);
+    if (owner)
+    {
+        active = !gtk_cell_renderer_toggle_get_active (cell); // hasn't changed yet.
+        gncOwnerSetActive (owner, active);
+    }
+
+    /* Clean up */
+    gtk_tree_path_free (s_path);
+}
+
+
+/************************************************************/
+/*                      sort functions                      */
+/************************************************************/
+
+static GtkTreeModel *
+sort_cb_setup_w_iters (GtkTreeModel *f_model,
+                       GtkTreeIter *f_iter_a,
+                       GtkTreeIter *f_iter_b,
+                       GtkTreeIter *iter_a,
+                       GtkTreeIter *iter_b,
+                       const GncOwner **owner_a,
+                       const GncOwner **owner_b)
+{
+    GtkTreeModel *model;
+
+    model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
+    gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
+            iter_a,
+            f_iter_a);
+    gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
+            iter_b,
+            f_iter_b);
+    *owner_a = gnc_tree_model_owner_get_owner (GNC_TREE_MODEL_OWNER(model), iter_a);
+    *owner_b = gnc_tree_model_owner_get_owner (GNC_TREE_MODEL_OWNER(model), iter_b);
+    return model;
+}
+
+static void
+sort_cb_setup (GtkTreeModel *f_model,
+               GtkTreeIter *f_iter_a,
+               GtkTreeIter *f_iter_b,
+               const GncOwner **owner_a,
+               const GncOwner **owner_b)
+{
+    GtkTreeIter iter_a, iter_b;
+
+    sort_cb_setup_w_iters (f_model, f_iter_a, f_iter_b,
+                           &iter_a, &iter_b, owner_a, owner_b);
+}
+
+static gint
+sort_by_string (GtkTreeModel *f_model,
+                GtkTreeIter *f_iter1,
+                GtkTreeIter *f_iter2,
+                gpointer user_data)
+{
+    GtkTreeModel *model;
+    GtkTreeIter iter1, iter2;
+    const GncOwner *owner1, *owner2;
+    gchar *str1, *str2;
+    gint column = GPOINTER_TO_INT(user_data);
+    gint result;
+
+    model = sort_cb_setup_w_iters(f_model, f_iter1, f_iter2, &iter1, &iter2, &owner1, &owner2);
+
+    /* Get the strings. */
+    gtk_tree_model_get(GTK_TREE_MODEL(model), &iter1,  column, &str1, -1);
+    gtk_tree_model_get(GTK_TREE_MODEL(model), &iter2,  column, &str2, -1);
+
+    result = safe_utf8_collate(str1, str2);
+    g_free(str1);
+    g_free(str2);
+    if (result != 0)
+        return result;
+    return gncOwnerCompare(owner1, owner2);
+}
+
+static gint
+sort_by_boolean (GtkTreeModel *f_model,
+                GtkTreeIter *f_iter1,
+                GtkTreeIter *f_iter2,
+                gpointer user_data)
+{
+    GtkTreeModel *model;
+    GtkTreeIter iter1, iter2;
+    const GncOwner *owner1, *owner2;
+    gboolean *bool1, *bool2;
+    gint column = GPOINTER_TO_INT(user_data);
+
+    model = sort_cb_setup_w_iters(f_model, f_iter1, f_iter2, &iter1, &iter2, &owner1, &owner2);
+
+    /* Get the strings. */
+    gtk_tree_model_get(GTK_TREE_MODEL(model), &iter1,  column, &bool1, -1);
+    gtk_tree_model_get(GTK_TREE_MODEL(model), &iter2,  column, &bool2, -1);
+
+    if (bool1)
+    {
+        if (!bool2)
+            return 1; /* bool1 > bool2 */
+    }
+    else
+    {
+        if (bool2)
+            return -1; /* bool2 > bool1 */
+    }
+    return gncOwnerCompare(owner1, owner2);
+}
+
+static gint
+sort_by_xxx_value (xaccGetBalanceInCurrencyFn fn,
+                   gboolean recurse,
+                   GtkTreeModel *f_model,
+                   GtkTreeIter *f_iter_a,
+                   GtkTreeIter *f_iter_b,
+                   gpointer user_data)
+{
+    const GncOwner *owner_a, *owner_b;
+    gnc_numeric balance_a, balance_b;
+    gint result;
+
+    /* Find the owners */
+    sort_cb_setup (f_model, f_iter_a, f_iter_b, &owner_a, &owner_b);
+
+    /* Get balances */
+    /* FIXME I'm not aware of any functions to get an owner's "balance" yet.
+     *       This should be implemented before this function does anything useful.
+     *       The code below is copied from the tree-view-account source to serve
+     *       as an example.
+    balance_a = gnc_ui_owner_get_balance_full(fn, owner_a, recurse, NULL, NULL);
+    balance_b = gnc_ui_owner_get_balance_full(fn, owner_b, recurse, NULL, NULL);
+    */
+    balance_a = gnc_numeric_zero();
+    balance_b = gnc_numeric_zero();
+
+    result = gnc_numeric_compare(balance_a, balance_b);
+    if (result != 0)
+        return result;
+    return gncOwnerCompare(owner_a, owner_b);
+}
+
+static gint
+sort_by_balance_value (GtkTreeModel *f_model,
+                       GtkTreeIter *f_iter_a,
+                       GtkTreeIter *f_iter_b,
+                       gpointer user_data)
+{
+    /* FIXME I'm not aware of any functions to get an owner's "balance" yet.
+     *       This should be implemented before this function does anything useful.
+     *       The code below is copied from the tree-view-account source to serve
+     *       as an example.
+    return sort_by_xxx_value (gncOwnerGetBalanceInCurrency, TRUE,
+                              f_model, f_iter_a, f_iter_b, user_data);
+     */
+     return sort_by_xxx_value (NULL, TRUE,
+             f_model, f_iter_a, f_iter_b, user_data);
+}
+static gint
+sort_by_xxx_period_value (GtkTreeModel *f_model,
+                          GtkTreeIter *f_iter_a,
+                          GtkTreeIter *f_iter_b,
+                          gboolean recurse)
+{
+    GncOwner *owner1, *owner2;
+    time_t t1, t2;
+    gnc_numeric b1, b2;
+    gint result;
+
+    sort_cb_setup (f_model, f_iter_a, f_iter_b,
+                   (const GncOwner **)&owner1, (const GncOwner **)&owner2);
+
+    t1 = gnc_accounting_period_fiscal_start();
+    t2 = gnc_accounting_period_fiscal_end();
+
+    /* FIXME I'm not aware of any functions to get an owner's "balance" yet.
+     *       This should be implemented before this function does anything useful.
+     *       The code below is copied from the tree-view-account source to serve
+     *       as an example.
+    b1 = gncOwnerGetBalanceChangeForPeriod(owner1, t1, t2, recurse);
+    b2 = gncOwnerGetBalanceChangeForPeriod(owner2, t1, t2, recurse);
+    */
+    b1 = gnc_numeric_zero();
+    b2 = gnc_numeric_zero();
+
+    result = gnc_numeric_compare(b1, b2);
+    if (result != 0)
+        return result;
+    return gncOwnerCompare(owner1, owner2);
+}
+
+static gint
+sort_by_balance_period_value (GtkTreeModel *f_model,
+                              GtkTreeIter *f_iter_a,
+                              GtkTreeIter *f_iter_b,
+                              gpointer user_data)
+{
+    return sort_by_xxx_period_value (f_model, f_iter_a, f_iter_b, FALSE);
+}
+
+/************************************************************/
+/*                    New View Creation                     */
+/************************************************************/
+
+/*
+ * Create a new owner tree view for one type of owners.
+ * This view will be based on a model that is common to all views of
+ * the same set of books, but will have its own private filter on that
+ * model.
+ */
+GtkTreeView *
+gnc_tree_view_owner_new (GncOwnerType owner_type)
+{
+    GncTreeView *view;
+    GtkTreeModel *model, *f_model, *s_model;
+    const gchar *sample_type, *sample_currency;
+    GncTreeViewOwnerPrivate *priv;
+    GtkTreeViewColumn *tax_info_column;
+    GtkCellRenderer *renderer;
+
+    ENTER(" ");
+    /* Create our view */
+    view = g_object_new (GNC_TYPE_TREE_VIEW_OWNER,
+                         "name", "owner_tree", NULL);
+
+    priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(GNC_TREE_VIEW_OWNER (view));
+
+    /* Create/get a pointer to the existing model for this set of books. */
+    model = gnc_tree_model_owner_new (owner_type);
+
+    /* Set up the view private filter layer on the common model. */
+    f_model = gtk_tree_model_filter_new (model, NULL);
+    /* A GncTreeModelOwner is based on a GncTreeModel, which is a
+     * GObject that provides a GtkTreeModel interface. */
+    g_object_unref(G_OBJECT(model));
+
+    /* Set up the view private sort layer on the common model. */
+    s_model = gtk_tree_model_sort_new_with_model(f_model);
+    g_object_unref(G_OBJECT(f_model));
+    gnc_tree_view_set_model (view, s_model);
+    g_object_unref(G_OBJECT(s_model));
+
+    /* Set default visibilities */
+    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
+
+    sample_type = gncOwnerTypeToQofIdType (GNC_OWNER_CUSTOMER);
+    sample_currency = gnc_commodity_get_fullname(gnc_default_currency());
+
+    priv->name_column
+    = gnc_tree_view_add_text_column(view, _("Owner Name"), "name",
+                                    NULL, "GnuCash Inc.",
+                                    GNC_TREE_MODEL_OWNER_COL_NAME,
+                                    GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                    sort_by_string);
+    gnc_tree_view_add_text_column(view, _("Type"), "type", NULL, sample_type,
+                                  GNC_TREE_MODEL_OWNER_COL_TYPE,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    priv->id_column
+    = gnc_tree_view_add_text_column(view, _("Owner ID"), "owner-id", NULL,
+                                    "1-123-1234",
+                                    GNC_TREE_MODEL_OWNER_COL_ID,
+                                    GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                    sort_by_string);
+    gnc_tree_view_add_text_column(view, _("Currency"), "currency", NULL,
+                                  sample_currency,
+                                  GNC_TREE_MODEL_OWNER_COL_CURRENCY,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    gnc_tree_view_add_text_column(view, _("Address Name"), "address-name", NULL,
+                                  "GnuCash Inc.",
+                                  GNC_TREE_MODEL_OWNER_COL_ADDRESS_NAME,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    gnc_tree_view_add_text_column(view, _("Address 1"), "address-1", NULL,
+                                  "Free Software Foundation",
+                                  GNC_TREE_MODEL_OWNER_COL_ADDRESS_1,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    gnc_tree_view_add_text_column(view, _("Address 2"), "address-2", NULL,
+                                  "51 Franklin Street, Fifth Floor",
+                                  GNC_TREE_MODEL_OWNER_COL_ADDRESS_2,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    gnc_tree_view_add_text_column(view, _("Address 3"), "address-3", NULL,
+                                  "Boston, MA  02110-1301",
+                                  GNC_TREE_MODEL_OWNER_COL_ADDRESS_3,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    gnc_tree_view_add_text_column(view, _("Address 4"), "address-4", NULL,
+                                  "USA",
+                                  GNC_TREE_MODEL_OWNER_COL_ADDRESS_4,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    gnc_tree_view_add_text_column(view, _("Phone"), "phone", NULL,
+                                  "+1-617-542-5942",
+                                  GNC_TREE_MODEL_OWNER_COL_PHONE,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    gnc_tree_view_add_text_column(view, _("Fax"), "fax", NULL,
+                                  "+1-617-542-2652",
+                                  GNC_TREE_MODEL_OWNER_COL_FAX,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    gnc_tree_view_add_text_column(view, _("E-mail"), "email", NULL,
+                                  "gnu at gnu.org",
+                                  GNC_TREE_MODEL_OWNER_COL_EMAIL,
+                                  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                  sort_by_string);
+    gnc_tree_view_add_numeric_column(view, _("Balance"), "balance",
+                                     SAMPLE_OWNER_VALUE,
+                                     GNC_TREE_MODEL_OWNER_COL_BALANCE,
+                                     GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE,
+                                     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                     sort_by_balance_value);
+    priv->balance_report_column
+    = gnc_tree_view_add_numeric_column(view, _("Balance (Report)"), "balance_report",
+                                       SAMPLE_OWNER_VALUE,
+                                       GNC_TREE_MODEL_OWNER_COL_BALANCE_REPORT,
+                                       GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE,
+                                       GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                       sort_by_balance_value);
+
+    gnc_tree_view_add_numeric_column(view, _("Balance (Period)"), "balance-period",
+                                     SAMPLE_OWNER_VALUE,
+                                     GNC_TREE_MODEL_OWNER_COL_BALANCE_PERIOD,
+                                     GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE_PERIOD,
+                                     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                     sort_by_balance_period_value);
+    priv->notes_column
+    = gnc_tree_view_add_text_column(view, _("Notes"), "notes", NULL,
+                                    "Sample owner notes.",
+                                    GNC_TREE_MODEL_OWNER_COL_NOTES,
+                                    GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                    sort_by_string);
+    gnc_tree_view_add_toggle_column (view, _("Active"),
+                                     /* Translators: This string has a context prefix; the translation
+                                        must only contain the part after the | character. */
+                                     Q_("Column letter for 'Active'|A"), "active",
+                                     GNC_TREE_MODEL_OWNER_COL_ACTIVE,
+                                     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+                                     sort_by_boolean,
+                                     gnc_tree_view_owner_active_toggled);
+
+    /* Update column titles to use the currency name. */
+    gtvo_update_column_names(view);
+
+    /* By default only the first column is visible. */
+    gnc_tree_view_configure_columns(view);
+    gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (f_model),
+                                            gnc_tree_view_owner_filter_helper,
+                                            view,
+                                            NULL);
+
+    /* Default the sorting to owner name */
+    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
+                                         GNC_TREE_MODEL_OWNER_COL_NAME,
+                                         GTK_SORT_ASCENDING);
+
+    gtk_widget_show(GTK_WIDGET(view));
+    LEAVE("%p", view);
+    return GTK_TREE_VIEW(view);
+}
+
+/************************************************************/
+/*                   Auxiliary Functions                    */
+/************************************************************/
+
+#define debug_path(fn, path) {                          \
+    gchar *path_string = gtk_tree_path_to_string(path); \
+    fn("tree path %s", path_string);                    \
+    g_free(path_string);                                \
+  }
+
+static GtkTreePath *
+gnc_tree_view_owner_get_path_from_owner (GncTreeViewOwner *view,
+                                         GncOwner *owner)
+{
+    GtkTreeModel *model, *f_model, *s_model;
+    GtkTreePath *path, *f_path, *s_path;
+
+    ENTER("view %p, owner %p (%s)", view, owner, gncOwnerGetName(owner));
+
+    if (owner == NULL)
+    {
+        LEAVE("no owner");
+        return NULL;
+    }
+
+    /* Reach down to the real model and get a path for this owner */
+    s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+    f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+    model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
+    path = gnc_tree_model_owner_get_path_from_owner (GNC_TREE_MODEL_OWNER(model), owner);
+    if (path == NULL)
+    {
+        LEAVE("no path");
+        return NULL;
+    }
+
+    /* convert back to a filtered path */
+    f_path = gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (f_model), path);
+    gtk_tree_path_free(path);
+    if (!f_path)
+    {
+        LEAVE("no filter path");
+        return NULL;
+    }
+
+    /* convert back to a sorted path */
+    s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model), f_path);
+    gtk_tree_path_free(f_path);
+    debug_path(LEAVE, s_path);
+    return s_path;
+}
+
+static gboolean
+gnc_tree_view_owner_get_iter_from_owner (GncTreeViewOwner *view,
+                                         GncOwner *owner,
+                                         GtkTreeIter *s_iter)
+{
+    GtkTreeModel *model, *f_model, *s_model;
+    GtkTreeIter iter, f_iter;
+
+    g_return_val_if_fail(GNC_IS_TREE_VIEW_OWNER(view), FALSE);
+    g_return_val_if_fail(owner != NULL, FALSE);
+    g_return_val_if_fail(s_iter != NULL, FALSE);
+
+    ENTER("view %p, owner %p (%s)", view, owner, gncOwnerGetName(owner));
+
+    /* Reach down to the real model and get an iter for this owner */
+    s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+    f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+    model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
+    if (!gnc_tree_model_owner_get_iter_from_owner (
+                GNC_TREE_MODEL_OWNER(model), owner, &iter))
+    {
+        LEAVE("model_get_iter_from_owner failed");
+        return FALSE;
+    }
+
+    /* convert back to a sort iter */
+    gtk_tree_model_filter_convert_child_iter_to_iter (
+        GTK_TREE_MODEL_FILTER(f_model), &f_iter, &iter);
+    gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(s_model),
+            s_iter, &f_iter);
+    LEAVE(" ");
+    return TRUE;
+}
+
+/************************************************************/
+/*            Owner Tree View Filter Functions            */
+/************************************************************/
+
+/*
+ * Get a copy of the owner view info structure in use by the
+ * specified tree.
+ */
+void
+gnc_tree_view_owner_get_view_info (GncTreeViewOwner *owner_view,
+                                   OwnerViewInfo *ovi)
+{
+    GncTreeViewOwnerPrivate *priv;
+
+    g_return_if_fail(GNC_IS_TREE_VIEW_OWNER(owner_view));
+    g_return_if_fail(ovi != NULL);
+
+    priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(owner_view);
+
+    *ovi = priv->ovi;
+}
+
+/*
+ * Set the owner view info data in use by the specified tree to
+ * match the callers request.
+ *
+ * DRH - COMPATIBILITY WARNING
+ *
+ * This function does not do anything with the 'include_type' field.
+ * Should there be a automatic filter for backward compatibility
+ * that uses these flags, or should all uses of this be converted to
+ * a GtkTreeModelFilter?
+ *
+ * CAS - For now, I'll try the automatic filter approach by making
+ * this function use GtkTreeModelFilter.
+ */
+void
+gnc_tree_view_owner_set_view_info (GncTreeViewOwner *owner_view,
+                                   OwnerViewInfo *ovi)
+{
+    GncTreeViewOwnerPrivate *priv;
+    gint i;
+    guint sel_bits = 0;
+
+    ENTER("%p", owner_view);
+    g_return_if_fail(GNC_IS_TREE_VIEW_OWNER(owner_view));
+    g_return_if_fail(ovi != NULL);
+
+    priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(owner_view);
+    priv->ovi = *ovi;
+
+    LEAVE(" ");
+}
+
+static gboolean
+gnc_tree_view_owner_filter_helper (GtkTreeModel *model,
+                                   GtkTreeIter *iter,
+                                   gpointer data)
+{
+    GncOwner *owner;
+    GncTreeViewOwner *view = data;
+    GncTreeViewOwnerPrivate *priv;
+
+    g_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (model), FALSE);
+    g_return_val_if_fail (iter != NULL, FALSE);
+
+    owner = gnc_tree_model_owner_get_owner (
+                  GNC_TREE_MODEL_OWNER(model), iter);
+
+    priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
+    if (priv->filter_fn)
+        return priv->filter_fn(owner, priv->filter_data);
+    else return TRUE;
+}
+
+/*
+ * Set an GtkTreeModel visible filter on this owner.  This filter will be
+ * called for each owner that the tree is about to show, and the
+ * owner will be passed to the callback function.
+ *
+ * Use NULL as func to remove filter.
+ */
+void
+gnc_tree_view_owner_set_filter (GncTreeViewOwner *view,
+                                gnc_tree_view_owner_filter_func func,
+                                gpointer data,
+                                GtkFunction destroy)
+{
+    GncTreeViewOwnerPrivate *priv;
+
+    ENTER("view %p, filter func %p, data %p, destroy %p",
+          view, func, data, destroy);
+
+    g_return_if_fail(GNC_IS_TREE_VIEW_OWNER(view));
+
+    priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
+    if (priv->filter_destroy)
+    {
+        priv->filter_destroy(priv->filter_data);
+    }
+    priv->filter_destroy = destroy;
+    priv->filter_data = data;
+    priv->filter_fn = func;
+
+    gnc_tree_view_owner_refilter(view);
+    LEAVE(" ");
+}
+
+/*
+ * Forces the entire owner tree to be re-evaluated for visibility.
+ */
+void
+gnc_tree_view_owner_refilter (GncTreeViewOwner *view)
+{
+    GtkTreeModel *f_model, *s_model;
+
+    g_return_if_fail(GNC_IS_TREE_VIEW_OWNER(view));
+
+    s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+    f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+    gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
+}
+
+/************************************************************/
+/*           Owner Tree View Get/Set Functions            */
+/************************************************************/
+
+/*
+ * Retrieve the selected owner from an owner tree view.  The
+ * owner tree must be in single selection mode.
+ */
+GncOwner *
+gnc_tree_view_owner_get_owner_from_path (GncTreeViewOwner *view,
+        GtkTreePath *s_path)
+{
+    GtkTreeModel *model, *f_model, *s_model;
+    GtkTreePath *path, *f_path;
+    GtkTreeIter iter;
+    GncOwner *owner;
+
+    ENTER("view %p", view);
+    g_return_val_if_fail (GNC_IS_TREE_VIEW_OWNER (view), NULL);
+    g_return_val_if_fail (s_path != NULL, NULL);
+
+    s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+    f_path = gtk_tree_model_sort_convert_path_to_child_path (
+                 GTK_TREE_MODEL_SORT (s_model), s_path);
+    if (!f_path)
+    {
+        LEAVE("no filter path");
+        return NULL;
+    }
+
+    f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+    path = gtk_tree_model_filter_convert_path_to_child_path (
+               GTK_TREE_MODEL_FILTER (f_model), f_path);
+    gtk_tree_path_free(f_path);
+    if (!path)
+    {
+        LEAVE("no path");
+        return NULL;
+    }
+
+    model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
+    if (!gtk_tree_model_get_iter (model, &iter, path))
+    {
+        LEAVE("no iter");
+        return NULL;
+    }
+
+    owner = iter.user_data;
+    gtk_tree_path_free(path);
+    LEAVE("owner %p (%s)", owner, gncOwnerGetName (owner));
+    return owner;
+}
+
+
+GncOwner *
+gnc_tree_view_owner_get_owner_from_iter (GtkTreeModel *s_model,
+        GtkTreeIter  *s_iter)
+{
+    GtkTreeModel *model, *f_model;
+    GtkTreeIter iter, f_iter;
+    GncOwner *owner;
+
+    g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT(s_model), NULL);
+    g_return_val_if_fail (s_iter != NULL, NULL);
+
+    ENTER("model %p, iter %p", s_model, s_iter);
+
+    gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT(s_model),
+            &f_iter,
+            s_iter);
+    f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+    gtk_tree_model_filter_convert_iter_to_child_iter (
+        GTK_TREE_MODEL_FILTER(f_model), &iter, &f_iter);
+    model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
+    owner = gnc_tree_model_owner_get_owner (
+                  GNC_TREE_MODEL_OWNER(model), &iter);
+    LEAVE("owner %p (%s)", owner, gncOwnerGetName (owner));
+    return owner;
+}
+
+
+/*
+ * Retrieve the selected owner from an owner tree view.  The
+ * owner tree must be in single selection mode.
+ */
+GncOwner *
+gnc_tree_view_owner_get_selected_owner (GncTreeViewOwner *view)
+{
+    GtkTreeSelection *selection;
+    GtkTreeModel *f_model, *s_model;
+    GtkTreeIter iter, f_iter, s_iter;
+    GncOwner *owner;
+    GtkSelectionMode mode;
+
+    ENTER("view %p", view);
+    g_return_val_if_fail (GNC_IS_TREE_VIEW_OWNER (view), NULL);
+
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
+    mode = gtk_tree_selection_get_mode(selection);
+    if ((mode != GTK_SELECTION_SINGLE) && (mode != GTK_SELECTION_BROWSE))
+    {
+        return NULL;
+    }
+    if (!gtk_tree_selection_get_selected (selection, &s_model, &s_iter))
+    {
+        LEAVE("no owner, get_selected failed");
+        return FALSE;
+    }
+
+    gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
+            &f_iter, &s_iter);
+
+    f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+    gtk_tree_model_filter_convert_iter_to_child_iter (
+        GTK_TREE_MODEL_FILTER (f_model), &iter, &f_iter);
+
+    owner = iter.user_data;
+    LEAVE("owner %p (%s)", owner, gncOwnerGetName (owner));
+    return owner;
+}
+
+/*
+ * Selects a single owner in the owner tree view.  The owner
+ * tree must be in single selection mode.
+ */
+void
+gnc_tree_view_owner_set_selected_owner (GncTreeViewOwner *view,
+        GncOwner *owner)
+{
+    GtkTreeModel *model, *f_model, *s_model;
+    GtkTreePath *path, *f_path, *s_path, *parent_path;
+    GtkTreeSelection *selection;
+
+    ENTER("view %p, owner %p (%s)", view,
+          owner, gncOwnerGetName (owner));
+    g_return_if_fail (GNC_IS_TREE_VIEW_OWNER (view));
+
+    /* Clear any existing selection. */
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+    gtk_tree_selection_unselect_all (selection);
+
+    if (owner == NULL)
+        return;
+
+    s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+    f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+    model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
+
+    path = gnc_tree_model_owner_get_path_from_owner (
+               GNC_TREE_MODEL_OWNER(model), owner);
+    if (path == NULL)
+    {
+        LEAVE("no path");
+        return;
+    }
+    debug_path(DEBUG, path);
+
+    f_path = gtk_tree_model_filter_convert_child_path_to_path (
+                 GTK_TREE_MODEL_FILTER (f_model), path);
+    gtk_tree_path_free(path);
+    if (f_path == NULL)
+    {
+        LEAVE("no filter path");
+        return;
+    }
+    debug_path(DEBUG, f_path);
+
+    s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model),
+             f_path);
+    gtk_tree_path_free(f_path);
+    if (s_path == NULL)
+    {
+        LEAVE("no sort path");
+        return;
+    }
+
+    gtk_tree_selection_select_path (selection, s_path);
+
+    /* give gtk+ a chance to resize the tree view first by handling pending
+     * configure events */
+    while (gtk_events_pending ())
+        gtk_main_iteration ();
+    gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), s_path, NULL, FALSE, 0.0, 0.0);
+    debug_path(LEAVE, s_path);
+    gtk_tree_path_free(s_path);
+}
+
+/* Information re selection process */
+typedef struct
+{
+    GList* return_list;
+    GncTreeViewOwnerPrivate* priv;
+} GncTreeViewSelectionInfo;
+
+/*
+ * This helper function is called once for each row in the tree view
+ * that is currently selected.  Its task is to append the corresponding
+ * owner to the end of a glist.
+ */
+static void
+get_selected_owners_helper (GtkTreeModel *s_model,
+                              GtkTreePath *s_path,
+                              GtkTreeIter *s_iter,
+                              gpointer data)
+{
+    GncTreeViewSelectionInfo *gtvsi = data;
+    GtkTreeModel *f_model;
+    GtkTreeIter iter, f_iter;
+    GncOwner *owner;
+
+    gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
+            &f_iter, s_iter);
+
+    f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+    gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model),
+            &iter, &f_iter);
+    owner = iter.user_data;
+
+    /* Only selected if it passes the filter */
+    if (gtvsi->priv->filter_fn == NULL || gtvsi->priv->filter_fn(owner, gtvsi->priv->filter_data))
+    {
+        gtvsi->return_list = g_list_append(gtvsi->return_list, owner);
+    }
+}
+
+/*
+ * Given an owner tree view, return a list of the selected owners. The
+ * owner tree must be in multiple selection mode.
+ *
+ * Note: It is the responsibility of the caller to free the returned
+ * list.
+ */
+GList *
+gnc_tree_view_owner_get_selected_owners (GncTreeViewOwner *view)
+{
+    GtkTreeSelection *selection;
+    GncTreeViewSelectionInfo info;
+
+    g_return_val_if_fail (GNC_IS_TREE_VIEW_OWNER (view), NULL);
+
+    info.return_list = NULL;
+    info.priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
+    gtk_tree_selection_selected_foreach(selection, get_selected_owners_helper, &info);
+    return info.return_list;
+}
+
+/*
+ * Given an owner tree view and a list of owners, select those
+ * owners in the tree view.
+ */
+void
+gnc_tree_view_owner_set_selected_owners (GncTreeViewOwner *view,
+        GList *owner_list,
+        gboolean show_last)
+{
+    GtkTreeModel *model, *f_model, *s_model;
+    GtkTreePath *path, *f_path, *s_path, *parent_path;
+    GtkTreeSelection *selection;
+    GList *element;
+    GncOwner *owner;
+
+    g_return_if_fail (GNC_IS_TREE_VIEW_OWNER (view));
+
+    s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+    f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+    model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
+
+    /* Clear any existing selection. */
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+    gtk_tree_selection_unselect_all (selection);
+
+    /* Now go select what the user requested. */
+    for (element = owner_list; element; )
+    {
+        owner = element->data;
+        element = g_list_next(element);
+
+        path = gnc_tree_model_owner_get_path_from_owner (GNC_TREE_MODEL_OWNER(model), owner);
+        if (path == NULL)
+        {
+            /*
+             * Oops.  Someone must have deleted this owner and not cleaned
+             * up all references to it.
+             */
+            continue;
+        }
+
+        f_path = gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (f_model),
+                 path);
+        gtk_tree_path_free(path);
+        if (f_path == NULL)
+            continue;
+
+        s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model),
+                 f_path);
+        gtk_tree_path_free(f_path);
+        if (s_path == NULL)
+            continue;
+
+        gtk_tree_selection_select_path (selection, s_path);
+        if (show_last && (element == NULL))
+            gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), s_path, NULL, FALSE, 0.0, 0.0);
+        gtk_tree_path_free(s_path);
+    }
+}
+
+
+/*
+ * Retrieve the owner currently under the cursor.
+ */
+GncOwner *
+gnc_tree_view_owner_get_cursor_owner (GncTreeViewOwner *view)
+{
+    GtkTreeModel *s_model;
+    GtkTreePath *s_path;
+    GncOwner *owner;
+
+    ENTER("view %p", view);
+    g_return_val_if_fail (GNC_IS_TREE_VIEW_OWNER (view), NULL);
+
+    s_model = gtk_tree_view_get_model (GTK_TREE_VIEW(view));
+    gtk_tree_view_get_cursor (GTK_TREE_VIEW(view), &s_path, NULL);
+    if (!s_path)
+    {
+        LEAVE("no owner");
+        return NULL;
+    }
+
+    owner = gnc_tree_view_owner_get_owner_from_path (view, s_path);
+    gtk_tree_path_free(s_path);
+    LEAVE("owner %p (%s)", owner, gncOwnerGetName (owner));
+    return owner;
+}
+
+
+/************************************************************/
+/*         Owner Tree View Add Column Functions           */
+/************************************************************/
+
+static void
+gtvo_update_column_name (GtkTreeViewColumn *column,
+                         const gchar *fmt,
+                         const gchar *mnemonic)
+{
+    gchar *name;
+
+    g_return_if_fail(column);
+
+    name = g_strdup_printf(fmt, mnemonic);
+    gtk_tree_view_column_set_title(column, name);
+    g_free(name);
+}
+
+
+static void
+gtvo_update_column_names (GncTreeView *view)
+{
+    GncTreeViewOwnerPrivate *priv;
+    const gchar *mnemonic;
+
+    priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
+    mnemonic = gnc_commodity_get_mnemonic(gnc_default_report_currency());
+
+    gtvo_update_column_name(priv->balance_report_column,
+                            /* Translators: %s is a currency mnemonic.*/
+                            _("Balance (%s)"), mnemonic);
+    gnc_tree_view_set_show_column_menu(view, FALSE);
+    gnc_tree_view_set_show_column_menu(view, TRUE);
+}
+
+
+static void
+gtvo_currency_changed_cb (void)
+{
+    const GList *views, *ptr;
+
+    views = gnc_gobject_tracking_get_list (GNC_TREE_VIEW_OWNER_NAME);
+    for (ptr = views; ptr; ptr = g_list_next(ptr))
+    {
+        gtvo_update_column_names (ptr->data);
+    }
+}
+/* This function implements a custom mapping between an owner's KVP
+ * and the cell renderer's 'text' property. */
+static void
+owner_cell_kvp_data_func (GtkTreeViewColumn *tree_column,
+                            GtkCellRenderer *cell,
+                            GtkTreeModel *s_model,
+                            GtkTreeIter *s_iter,
+                            gpointer key)
+{
+    GncOwner *owner;
+    kvp_frame * frame;
+
+    g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
+    owner = gnc_tree_view_owner_get_owner_from_iter(s_model, s_iter);
+    frame = gncOwnerGetSlots(owner);
+
+    g_object_set (G_OBJECT (cell),
+                  "text", kvp_frame_get_string(frame, (gchar *)key),
+                  "xalign", 0.0,
+                  NULL);
+
+}
+
+
+GtkTreeViewColumn *
+gnc_tree_view_owner_add_kvp_column (GncTreeViewOwner *view,
+                                      const gchar *column_title,
+                                      const gchar *kvp_key)
+{
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
+
+    g_return_val_if_fail (GNC_IS_TREE_VIEW_OWNER (view), NULL);
+    g_return_val_if_fail (kvp_key != NULL, NULL);
+
+    column = gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), column_title,
+                                           kvp_key, NULL, "Sample text",
+                                           -1, -1, NULL);
+
+    /* This new kvp column has only had one renderer added to it so
+     * far.  Find that renderer. */
+    renderer = gnc_tree_view_column_get_renderer(column);
+    g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
+
+    gtk_tree_view_column_set_cell_data_func (column, renderer,
+            owner_cell_kvp_data_func,
+            g_strdup(kvp_key), g_free);
+    return column;
+}
+
+static void col_edited_helper(GtkCellRendererText *cell, gchar *path_string,
+                              gchar *new_text, gpointer _s_model)
+{
+    GncOwner *owner;
+    GtkTreeModel *s_model;
+    GtkTreeIter s_iter;
+    GncTreeViewOwnerColumnTextEdited col_edited_cb;
+    GtkTreeViewColumn *col;
+
+    col_edited_cb = g_object_get_data(G_OBJECT(cell),
+                                      "column_edited_callback");
+    col = GTK_TREE_VIEW_COLUMN(g_object_get_data(G_OBJECT(cell),
+                               "column_view"));
+    s_model = GTK_TREE_MODEL(_s_model);
+
+    if (!gtk_tree_model_get_iter_from_string(s_model, &s_iter, path_string))
+        return;
+
+    owner = gnc_tree_view_owner_get_owner_from_iter(s_model, &s_iter);
+    col_edited_cb(owner, col, new_text);
+}
+
+static void col_source_helper(GtkTreeViewColumn *col, GtkCellRenderer *cell,
+                              GtkTreeModel *s_model, GtkTreeIter *s_iter,
+                              gpointer _col_source_cb)
+{
+    GncOwner *owner;
+    gchar *text;
+    GncTreeViewOwnerColumnSource col_source_cb;
+
+    g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
+    col_source_cb = (GncTreeViewOwnerColumnSource) _col_source_cb;
+    owner = gnc_tree_view_owner_get_owner_from_iter(s_model, s_iter);
+    text = col_source_cb(owner, col, cell);
+    g_object_set (G_OBJECT (cell), "text", text, "xalign", 1.0, NULL);
+    g_free(text);
+}
+
+/**
+ * If col_edited_cb is null, the editing callback (helper) will be
+ * effectively disconnected.
+ **/
+void
+gtvo_setup_column_renderer_edited_cb(GncTreeViewOwner *owner_view,
+                                     GtkTreeViewColumn *column,
+                                     GtkCellRenderer *renderer,
+                                     GncTreeViewOwnerColumnTextEdited col_edited_cb)
+{
+    GtkTreeModel *s_model;
+
+    if (col_edited_cb == NULL)
+    {
+        g_object_set(G_OBJECT(renderer), "editable", FALSE, NULL);
+        g_object_set_data(G_OBJECT(renderer), "column_edited_callback", col_edited_cb);
+        s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(owner_view));
+        g_signal_handlers_disconnect_by_func(G_OBJECT(renderer), col_edited_cb, s_model);
+        g_object_set_data(G_OBJECT(renderer), "column_view", column);
+    }
+    else
+    {
+        g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
+        g_object_set_data(G_OBJECT(renderer), "column_edited_callback",
+                          col_edited_cb);
+        s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(owner_view));
+        g_signal_connect(G_OBJECT(renderer), "edited",
+                         (GCallback) col_edited_helper, s_model);
+        g_object_set_data(G_OBJECT(renderer), "column_view", column);
+    }
+}
+
+GtkTreeViewColumn *
+gnc_tree_view_owner_add_custom_column(GncTreeViewOwner *owner_view,
+                                      const gchar *column_title,
+                                      GncTreeViewOwnerColumnSource
+                                      col_source_cb,
+                                      GncTreeViewOwnerColumnTextEdited
+                                      col_edited_cb)
+{
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
+
+    g_return_val_if_fail (GNC_IS_TREE_VIEW_OWNER (owner_view), NULL);
+
+    renderer = gtk_cell_renderer_text_new ();
+    g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
+
+    column = gtk_tree_view_column_new_with_attributes (column_title,
+             renderer, NULL);
+    if (col_edited_cb)
+    {
+        gtvo_setup_column_renderer_edited_cb(owner_view, column,
+                                             renderer, col_edited_cb);
+    }
+    gtk_tree_view_column_set_cell_data_func (column, renderer,
+            col_source_helper,
+            col_source_cb, NULL);
+    gnc_tree_view_append_column (GNC_TREE_VIEW(owner_view), column);
+    return column;
+}
+
+
+/* BEGIN FILTER FUNCTIONS */
+#define FILTER_TREE_VIEW "types_tree_view"
+
+/** This function tells the owner tree view whether or not to filter
+ *  out a particular owner.  Owners may be filtered if the user
+ *  has decided not to display inactive owners, or if the
+ *  user has requested that owners with a zero total not be shown.
+ *
+ *  @param owner The owner that is being evaluated.
+ *
+ *  @param user_data A pointer to the OwnerFilterDialog struct.
+ *
+ *  @return TRUE if the owner should be visible.  FALSE if the
+ *  owner should be hidden. */
+gboolean
+gnc_plugin_page_owner_tree_filter_owners (GncOwner *owner,
+                                          gpointer user_data)
+{
+    OwnerFilterDialog *fd = user_data;
+    gnc_numeric total;
+
+    ENTER("owner %p:%s", owner, gncOwnerGetName(owner));
+
+    if (!fd->show_inactive && !gncOwnerGetActive (owner))
+    {
+        LEAVE(" hide: inactive");
+        return FALSE;
+    }
+
+    if (!fd->show_zero_total)
+    {
+        /* FIXME I'm not aware of any functions to get an owner's "balance" yet.
+         *       This should be implemented before this function does anything useful.
+         *       The code below is copied from the tree-view-account source to serve
+         *       as an example.
+        total = gncOwnerGetBalanceInCurrency (owner, NULL, TRUE);
+        */
+        total = gnc_numeric_zero();
+        if (gnc_numeric_zero_p(total))
+        {
+            LEAVE(" hide: zero balance");
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+/** The "only show active" button in the Filter dialog changed state.
+ *  Update the page to reflect these changes.
+ *
+ *  @param button The GtkCheckButton that was toggled.
+ *
+ *  @param fd A pointer to the owner filter dialog struct. */
+void
+gppot_filter_show_inactive_toggled_cb (GtkToggleButton *button,
+                                       OwnerFilterDialog *fd)
+{
+    g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
+
+    ENTER("button %p", button);
+    fd->show_inactive = gtk_toggle_button_get_active(button);
+    gnc_tree_view_owner_refilter(fd->tree_view);
+    LEAVE("show_inactive %d", fd->show_inactive);
+}
+
+/** The "show zero totals" button in the Filter dialog changed state.
+ *  Update the page to reflect these changes.
+ *
+ *  @param button The GtkCheckButton that was toggled.
+ *
+ *  @param fd A pointer to the owner filter dialog struct. */
+void
+gppot_filter_show_zero_toggled_cb (GtkToggleButton *button,
+                                   OwnerFilterDialog *fd)
+{
+    g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
+
+    ENTER("button %p", button);
+    fd->show_zero_total = gtk_toggle_button_get_active(button);
+    gnc_tree_view_owner_refilter(fd->tree_view);
+    LEAVE("show_zero %d", fd->show_zero_total);
+}
+
+/** The Filter dialog was closed.  Check to see if this was done via
+ *  the OK button.  If so, make the changes permanent.  If not, revert
+ *  any changes.
+ *
+ *  @param dialog A pointer to the "Filter By" dialog.
+ *
+ *  @param response The response code from closing the dialog.
+ *
+ *  @param fd A pointer to the owner filter dialog struct. */
+void
+gppot_filter_response_cb (GtkWidget *dialog,
+                          gint       response,
+                          OwnerFilterDialog *fd)
+{
+    GtkWidget *view;
+    gpointer gptemp;
+
+    g_return_if_fail(GTK_IS_DIALOG(dialog));
+
+    ENTER("dialog %p, response %d", dialog, response);
+    view = gnc_glade_lookup_widget(dialog, FILTER_TREE_VIEW);
+
+    if (response != GTK_RESPONSE_OK)
+    {
+        fd->show_inactive = fd->original_show_inactive;
+        fd->show_zero_total = fd->original_show_zero_total;
+        gnc_tree_view_owner_refilter(fd->tree_view);
+    }
+
+    /* Clean up and delete dialog */
+    gptemp = (gpointer *)fd->dialog;
+    g_atomic_pointer_compare_and_exchange(&gptemp,
+                                          dialog, NULL);
+    fd->dialog = gptemp;
+    gtk_widget_destroy(dialog);
+    LEAVE("");
+}
+
+void
+owner_filter_dialog_create(OwnerFilterDialog *fd, GncPluginPage *page)
+{
+    GtkWidget *dialog, *button;
+    GtkBuilder *builder;
+    gchar *title;
+
+    ENTER("(fd %p, page %p)", fd, page);
+
+    if (fd->dialog)
+    {
+        gtk_window_present(GTK_WINDOW(fd->dialog));
+        LEAVE("existing dialog");
+        return;
+    }
+
+    /* Create the dialog */
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file (builder, "owner.ui", "Filter By");
+    dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Filter By"));
+    fd->dialog = dialog;
+    gtk_window_set_transient_for(GTK_WINDOW(dialog),
+                                 GTK_WINDOW(GNC_PLUGIN_PAGE(page)->window));
+    /* Translators: The %s is the name of the plugin page */
+    title = g_strdup_printf(_("Filter %s by..."),
+                            gnc_plugin_page_get_page_name(GNC_PLUGIN_PAGE(page)));
+    gtk_window_set_title(GTK_WINDOW(dialog), title);
+    g_free(title);
+
+    /* Remember current state */
+    fd->original_show_inactive = fd->show_inactive;
+    fd->original_show_zero_total = fd->show_zero_total;
+
+    /* Update the dialog widgets for the current state */
+    button = GTK_WIDGET(gtk_builder_get_object (builder, "show_inactive"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
+                                 fd->show_inactive);
+    button = GTK_WIDGET(gtk_builder_get_object (builder, "show_zero"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
+                                 fd->show_zero_total);
+
+    /* Wire up the rest of the callbacks */
+    gtk_builder_connect_signals (builder, fd);
+    g_object_unref(G_OBJECT(builder));
+
+    /* Show it */
+    gtk_widget_show_all (dialog);
+    LEAVE(" ");
+}
+
+#define OWNER_SELECTED_LABEL "SelectedOwner"
+#define SHOW_INACTIVE_LABEL  "ShowInactive"
+#define SHOW_ZERO_LABEL      "ShowZeroTotal"
+
+typedef struct foo
+{
+    GKeyFile *key_file;
+    const gchar *group_name;
+} bar_t;
+
+/** Save information about the selected row.  Its job is to write the
+ *  full owner name of the row out to the state file.
+ *
+ *  @param view A pointer to the GtkTreeView embedded in an
+ *  owner tree page.
+ *
+ *  @param path A pointer to a particular entry in the tree.
+ *
+ *  @param data A pointer to a data structure holding the information
+ *  related to the state file. */
+static void
+tree_save_selected_row (GncTreeViewOwner *view,
+                        gpointer user_data)
+{
+    GncOwner *owner;
+    GncOwnerType owner_type;
+    bar_t *bar = user_data;
+    const gchar *owner_name;
+
+    owner = gnc_tree_view_owner_get_selected_owner(view);
+    if (owner == NULL)
+        return;
+
+    owner_name = gncOwnerGetName (owner);
+    if (owner_name == NULL)
+        return;
+
+    g_key_file_set_string(bar->key_file, bar->group_name, OWNER_SELECTED_LABEL,
+                          owner_name);
+}
+
+void
+gnc_tree_view_owner_save(GncTreeViewOwner *view,
+                           OwnerFilterDialog *fd,
+                           GKeyFile *key_file, const gchar *group_name)
+{
+    bar_t bar;
+
+    g_return_if_fail (key_file != NULL);
+    g_return_if_fail (group_name != NULL);
+
+    ENTER("view %p, key_file %p, group_name %s", view, key_file,
+          group_name);
+
+    g_key_file_set_boolean(key_file, group_name, SHOW_INACTIVE_LABEL,
+                           fd->show_inactive);
+    g_key_file_set_boolean(key_file, group_name, SHOW_ZERO_LABEL,
+                           fd->show_zero_total);
+
+    bar.key_file = key_file;
+    bar.group_name = group_name;
+    tree_save_selected_row(view, &bar);
+    LEAVE(" ");
+
+}
+
+/** Select the row in the tree that was selected when the user last
+ *  quit gnucash.  Its job is to map from owner name to tree row and
+ *  select the row.
+ *
+ *  @param tree A pointer to the GncTreeViewOwner embedded.
+ *
+ *  @param owner_name A pointer to the full owner name. */
+static void
+tree_restore_selected_row (GncTreeViewOwner *view,
+                           GncOwnerType owner_type,
+                           const gchar *owner_guid_str)
+{
+    GncOwner *owner=gncOwnerCreate();
+    QofBook *book;
+    GncGUID owner_guid;
+
+    book = qof_session_get_book (gnc_get_current_session());
+    if (string_to_guid (owner_guid_str, &owner_guid))
+        if (gncOwnerGetOwnerFromTypeGuid (book, owner, gncOwnerTypeToQofIdType(owner_type), &owner_guid))
+            gnc_tree_view_owner_set_selected_owner(view, owner);
+}
+
+void
+gnc_tree_view_owner_restore(GncTreeViewOwner *view,
+                              OwnerFilterDialog *fd,
+                              GKeyFile *key_file, const gchar *group_name,
+                              GncOwnerType owner_type)
+{
+    GError *error = NULL;
+    gchar *key, *value;
+    gint i, count;
+    gboolean show;
+
+    /* Filter information. Ignore missing keys. */
+    show = g_key_file_get_boolean(key_file, group_name, SHOW_INACTIVE_LABEL, &error);
+    if (error)
+    {
+        g_warning("error reading group %s key %s: %s",
+                  group_name, SHOW_INACTIVE_LABEL, error->message);
+        g_error_free(error);
+        error = NULL;
+        show = TRUE;
+    }
+    fd->show_inactive = show;
+
+    show = g_key_file_get_boolean(key_file, group_name, SHOW_ZERO_LABEL, &error);
+    if (error)
+    {
+        g_warning("error reading group %s key %s: %s",
+                  group_name, SHOW_ZERO_LABEL, error->message);
+        g_error_free(error);
+        error = NULL;
+        show = TRUE;
+    }
+    fd->show_zero_total = show;
+
+    /* Selected owner (if any) */
+    value = g_key_file_get_string(key_file, group_name, OWNER_SELECTED_LABEL, NULL);
+    if (value)
+    {
+        tree_restore_selected_row(view, owner_type, value);
+        g_free(value);
+    }
+
+    /* Update tree view for any changes */
+    gnc_tree_view_owner_refilter(view);
+}
+
+void
+gnc_tree_view_owner_name_edited_cb(GncOwner *owner, GtkTreeViewColumn *col, const gchar *new_name)
+{
+    if (safe_strcmp(gncOwnerGetName(owner), new_name) == 0)
+        return;
+    gncOwnerSetName(owner, new_name);
+}
+
+static void
+gtvo_set_column_editor(GncTreeViewOwner *view,
+                       GtkTreeViewColumn *column,
+                       GncTreeViewOwnerColumnTextEdited edited_cb)
+{
+    GList *renderers_orig, *renderers;
+    GtkCellRenderer *renderer;
+
+    // look for the first text-renderer; on the 0th column of the owner tree,
+    // there are two renderers: pixbuf and text.  So find the text one.
+    for (renderers_orig = renderers = gtk_tree_view_column_get_cell_renderers(column);
+            renderers && !GTK_IS_CELL_RENDERER_TEXT(renderers->data);
+            renderers = renderers->next);
+    renderer = GTK_CELL_RENDERER(renderers->data);
+    g_list_free(renderers_orig);
+    g_return_if_fail(renderer != NULL);
+    gtvo_setup_column_renderer_edited_cb(GNC_TREE_VIEW_OWNER(view), column, renderer, edited_cb);
+}
+
+void
+gnc_tree_view_owner_set_name_edited(GncTreeViewOwner *view,
+                                      GncTreeViewOwnerColumnTextEdited edited_cb)
+{
+    GncTreeViewOwnerPrivate *priv;
+    priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
+    gtvo_set_column_editor(view, priv->name_column, edited_cb);
+}

Added: gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.h	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.h	2011-05-11 21:51:03 UTC (rev 20620)
@@ -0,0 +1,383 @@
+/********************************************************************\
+ * gnc-tree-view-owner.h -- GtkTreeView implementation to display   *
+ *                            owners in a GtkTreeView.              *
+ * Copyright (C) 2011 Geert Janssens <geert at kobaltwit.be>           *
+ *                                                                  *
+ * 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 the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ *                                                                  *
+\********************************************************************/
+
+/** @addtogroup GUI
+    @{ */
+/** @addtogroup GuiTreeModel
+ * @{ */
+/** @file gnc-tree-view-owner.h
+    @brief GtkTreeView implementation for gnucash owner tree.
+    @author Copyright (C) 2003,2005,2006 David Hampton <hampton at employees.org>
+*/
+
+#ifndef __GNC_TREE_VIEW_OWNER_H
+#define __GNC_TREE_VIEW_OWNER_H
+
+#include <gtk/gtk.h>
+#include "gncOwner.h"
+#include "gnc-tree-view.h"
+
+#include "gnc-ui-util.h"
+#include "gnc-plugin-page.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_TREE_VIEW_OWNER            (gnc_tree_view_owner_get_type ())
+#define GNC_TREE_VIEW_OWNER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_TREE_VIEW_OWNER, GncTreeViewOwner))
+#define GNC_TREE_VIEW_OWNER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_TREE_VIEW_OWNER, GncTreeViewOwnerClass))
+#define GNC_IS_TREE_VIEW_OWNER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_TREE_VIEW_OWNER))
+#define GNC_IS_TREE_VIEW_OWNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_TREE_VIEW_OWNER))
+#define GNC_TREE_VIEW_OWNER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_TREE_VIEW_OWNER, GncTreeViewOwnerClass))
+#define GNC_TREE_VIEW_OWNER_NAME            "GncTreeViewOwner"
+
+/* typedefs & structures */
+typedef struct OwnerViewInfo_s     OwnerViewInfo;
+
+
+struct OwnerViewInfo_s
+{
+    gboolean show_inactive;
+};
+
+
+typedef struct
+{
+    GncTreeView gnc_tree_view;
+    int stamp;
+} GncTreeViewOwner;
+
+typedef struct
+{
+    GncTreeViewClass gnc_tree_view;
+} GncTreeViewOwnerClass;
+
+typedef struct
+{
+    GtkWidget    *dialog;
+    GncTreeViewOwner  *tree_view;
+    gboolean     show_inactive;
+    gboolean     original_show_inactive;
+    gboolean     show_zero_total;
+    gboolean     original_show_zero_total;
+} OwnerFilterDialog;
+
+void owner_filter_dialog_create(OwnerFilterDialog *fd,
+                                  GncPluginPage *page);
+
+gboolean gnc_plugin_page_owner_tree_filter_owners (GncOwner *owner,
+        gpointer user_data);
+
+/* "Filter By" dialog callbacks */
+void gppot_filter_show_inactive_toggled_cb (GtkToggleButton *togglebutton,
+        OwnerFilterDialog *fd);
+void gppot_filter_show_zero_toggled_cb (GtkToggleButton *togglebutton,
+                                        OwnerFilterDialog *fd);
+void gppot_filter_response_cb (GtkWidget *dialog, gint response,
+                               OwnerFilterDialog *fd);
+
+/* Saving/Restoring */
+void gnc_tree_view_owner_save(GncTreeViewOwner *tree_view,
+                                OwnerFilterDialog *fd,
+                                GKeyFile *key_file, const gchar *group_name);
+void gnc_tree_view_owner_restore(GncTreeViewOwner *view,
+                                   OwnerFilterDialog *fd,
+                                   GKeyFile *key_file,
+                                   const gchar *group_name,
+                                   GncOwnerType owner_type);
+
+
+/* Get the GType for an GncTreeViewOwner object. */
+GType gnc_tree_view_owner_get_type (void);
+
+
+/** @name Owner Tree View Constructor
+ @{ */
+
+/** Create a new owner tree view for one type of owners.
+ *
+ *  @param owner_type The type of owners to use in the view.
+ *
+ *  @return A pointer to a new owner tree view.
+ */
+GtkTreeView *gnc_tree_view_owner_new (GncOwnerType owner_type);
+
+/** @} */
+
+
+/** @name Owner Tree View Configuration
+ @{ */
+
+typedef gchar * (*GncTreeViewOwnerColumnSource) (GncOwner *owner,
+        GtkTreeViewColumn *col,
+        GtkCellRenderer *cell);
+
+typedef void (*GncTreeViewOwnerColumnTextEdited) (GncOwner *owner,
+        GtkTreeViewColumn *col,
+        const gchar *new_text);
+
+
+/** Add a new custom column to the set of columns in an owner tree
+ *  view.  This column will be visible as soon as it is added and will
+ *  query the provided functions to determine what data to display.
+ *  The TreeView will own the resulting TreeViewColumn, but caller may
+ *  set any additional properties they wish.
+ *
+ *  @param view A pointer to an owner tree view.
+ *
+ *  @param column_title The title for this new column.
+ *
+ *  @param source_cb A callback function that is expected to provide
+ *  the data to be displayed.
+ *
+ *  @param edited_cb A callback function that will be called if the
+ *  user edits the displayed data.
+ */
+GtkTreeViewColumn * gnc_tree_view_owner_add_custom_column(
+    GncTreeViewOwner *view, const gchar *column_title,
+    GncTreeViewOwnerColumnSource source_cb,
+    GncTreeViewOwnerColumnTextEdited edited_cb);
+
+void gnc_tree_view_owner_set_name_edited(GncTreeViewOwner *view,
+        GncTreeViewOwnerColumnTextEdited edited_cb);
+void gnc_tree_view_owner_name_edited_cb(GncOwner *owner, GtkTreeViewColumn *col, const gchar *new_name);
+
+/** Add a new column to the set of columns in an owner tree view.
+ *  This column will be visible as soon as it is added and will
+ *  display the contents of the specified KVP slot.
+ *
+ *  @param view A pointer to an owner tree view.
+ *
+ *  @param column_title The title for this new column.
+ *
+ *  @param kvp_key The lookup key to use for looking up data in the
+ *  owner KVP structures. The value associated with this key is what
+ *  will be displayed in the column.
+ */
+GtkTreeViewColumn *
+gnc_tree_view_owner_add_kvp_column (GncTreeViewOwner *view,
+                                      const gchar *column_title,
+                                      const gchar *kvp_key);
+
+/** @} */
+
+
+/** @name Owner Tree View Filtering
+ @{ */
+
+/** Given pointers to an owner tree and old style filter block, this
+ *  function will copy the current configuration of the owner tree
+ *  widget into the data block.  This may be used in conjunction with
+ *  the gnc_tree_view_owner_set_view_info function to modify the
+ *  filters on an existing owner tree.
+ *
+ *  @param owner_view A pointer to an owner tree view.
+ *
+ *  @param avi A pointer to an old style filter block to fill in.
+ */
+void gnc_tree_view_owner_get_view_info (GncTreeViewOwner *owner_view,
+        OwnerViewInfo *avi);
+
+/** Given pointers to an owner tree and old style filter block, this
+ *  function will applies the settings specified to the current
+ *  configuration of the owner tree widget.  This may be used in
+ *  conjunction with the gnc_tree_view_owner_get_view_info function
+ *  to modify the filters on an existing owner tree.
+ *
+ *  @param owner_view A pointer to an owner tree view.
+ *
+ *  @param avi A pointer to an old style filter block to apply to the
+ *  view.
+ */
+void gnc_tree_view_owner_set_view_info (GncTreeViewOwner *owner_view,
+        OwnerViewInfo *avi);
+
+
+/** This is the description of a filter function used by the owner tree.
+ *
+ *  @param owner The owner to be tested.
+ *
+ *  @param data The data provided when the filter function was added.
+ *
+ *  @return TRUE if the owner should be displayed.
+ */
+typedef gboolean (*gnc_tree_view_owner_filter_func)(GncOwner *owner, gpointer data);
+
+
+/** This function attaches a filter function to the given owner
+ *  tree.  This function will be called for each owner that the view
+ *  thinks should possibly show.  The filter may perform any actions
+ *  necessary on the owner to decide whether it should be shown or
+ *  not.  (I.E. Check type, placeholder status, etc.)  If the filter
+ *  returns TRUE then the owner will be displayed.
+ *
+ *  @param owner_view A pointer to an owner tree view.
+ *
+ *  @param func A filtration function that is called on individual
+ *  elements in the tree.  If this function returns TRUE, the owner
+ *  will be displayed.
+ *
+ *  @param data A data block passed into each instance of the function.
+ *
+ *  @param destroy A function to destroy the data block.  This
+ *  function will be called when the filter is destroyed.  may be
+ *  NULL.
+ */
+void gnc_tree_view_owner_set_filter (GncTreeViewOwner *owner_view,
+                                       gnc_tree_view_owner_filter_func func,
+                                       gpointer data,
+                                       GtkFunction destroy);
+
+
+/** This function forces the owner tree filter to be evaluated.  It
+ *  may be necessary to call this function if the initial state of the
+ *  view is incorrect.  This appears to only be necessary if the
+ *  filter affects one of the top level owners in gnucash.
+ *
+ *  @note This calls a function in gtk that is annotated in the
+ *  sources as being slow.  You have been warned.
+ *
+ *  @param view A pointer to an owner tree view.
+ */
+void gnc_tree_view_owner_refilter (GncTreeViewOwner *view);
+/** @} */
+
+
+/** @name Owner Tree View Get/Set Functions
+ @{ */
+
+/** This function returns the owner associated with the specified
+ *  path.  This function is useful in selection callbacks on an
+ *  owner tree widget.
+ *
+ *  @param view A pointer to an owner tree view.
+ *
+ *  @param path A path specifying a node in the owner tree.
+ *
+ *  @return The owner associated with this path.
+ */
+GncOwner * gnc_tree_view_owner_get_owner_from_path (GncTreeViewOwner *view,
+        GtkTreePath *path);
+
+
+/** This function returns the owner associated with the specified
+ *  iter.  This function is useful in selection callbacks on an
+ *  owner tree widget.
+ *
+ *  @param model The model provided to the callback function.
+ *
+ *  @param iter The iter provided to the callback function.
+ *
+ *  @return The owner associated with this iter.
+ */
+GncOwner * gnc_tree_view_owner_get_owner_from_iter (GtkTreeModel *model,
+        GtkTreeIter  *iter);
+
+
+/** This function returns the owner in the owner tree view at the
+ *  current location of the cursor. (The outline frame. Usually is
+ *  selected and therefore filled in, but not always.)
+ *
+ *  @param view A pointer to an owner tree view.
+ *
+ *  @return The owner at the cursor.
+ */
+GncOwner * gnc_tree_view_owner_get_cursor_owner (GncTreeViewOwner *view);
+
+
+/** This function returns the owner associated with the selected
+ *  item in the owner tree view.
+ *
+ *  @note It only makes sense to call this function when the owner
+ *  tree is set to select a single item.  There is a different
+ *  function to use when the tree supports multiple selections.
+ *
+ *  @param view A pointer to an owner tree view.
+ *
+ *  @return The selected owner, or NULL if no owner was selected.
+ */
+GncOwner * gnc_tree_view_owner_get_selected_owner (GncTreeViewOwner *view);
+
+
+/** This function selects an owner in the owner tree view.  All
+ *  other owners will be unselected.  In addition, this function
+ *  collapses the entitre tree and then expands only the path to the
+ *  selected owner, making the item easy to find.  In general, this
+ *  routine only need be called when initially putting up a window
+ *  containing an owner tree view widget.
+ *
+ *  @note It only makes sense to call this function when the owner
+ *  tree is set to select a single item.  There is a different
+ *  function to use when the tree supports multiple selections.
+ *
+ *  @param view A pointer to an owner tree view.
+ *
+ *  @param owner A pointer to the owner to select.
+ */
+void gnc_tree_view_owner_set_selected_owner (GncTreeViewOwner *view,
+        GncOwner *owner);
+
+
+/** This function returns a list of the owners associated with the
+ *  selected items in the owner tree view.
+ *
+ *  @note It only makes sense to call this function when the owner
+ *  tree is set to select multiple items.  There is a different
+ *  function to use when the tree supports single selection.
+ *
+ *  @param view A pointer to an owner tree view.
+ *
+ *  @return A list of owners, or NULL if no owner was selected.
+ */
+GList * gnc_tree_view_owner_get_selected_owners (GncTreeViewOwner *view);
+
+
+/** This function selects a set of owners in the owner tree view.
+ *  All other owners will be unselected.  In addition, this function
+ *  collapses the entitre tree and then expands only the path to the
+ *  selected owners, making them easy to find.  In general, this
+ *  routine only need be called when initially putting up a window
+ *  containing an owner tree view widget.
+ *
+ *  @note It only makes sense to call this function when the owner
+ *  tree is set to select a single item.  There is a different
+ *  function to use when the tree supports multiple selections.
+ *
+ *  @note It is the responsibility of the caller to free the returned
+ *  list.
+ *
+ *  @param view A pointer to an owner tree view.
+ *
+ *  @param owner_list A list of owners to select.
+ *
+ *  @param show_last Force the window to scroll to the last owner
+ *  selected.
+ */
+void gnc_tree_view_owner_set_selected_owners (GncTreeViewOwner *view,
+        GList *owner_list,
+        gboolean show_last);
+
+G_END_DECLS
+
+#endif /* __GNC_TREE_VIEW_OWNER_H */



More information about the gnucash-changes mailing list