/*
 * gnc-plugin-page-owner-tree.c --
 *
 * Copyright (C) 2011 Geert Janssens <geert@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@gnu.org
 */

/** @addtogroup ContentPlugins
    @{ */
/** @addtogroup GncPluginPageOwnerTree An Owner Tree Plugin
    @{ */
/** @file gnc-plugin-page-owner-tree.c
    @brief Functions providing a page which lists owners of one type. This type
           can be vendors, customers or employees.
    @author Copyright (C) 2011 Geert Janssens <geert@kobaltwit.be>
*/

#include <config.h>

#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "swig-runtime.h"

#include "gnc-plugin.h"
#include "gnc-plugin-page-owner-tree.h"
#include "gnc-plugin-page-report.h"

#include "dialog-vendor.h"
#include "dialog-customer.h"
#include "dialog-employee.h"
#include "dialog-invoice.h"
#include "dialog-job.h"
#include "dialog-payment.h"

#include "gncOwner.h"
#include "dialog-utils.h"
#include "gnc-component-manager.h"
#include "gnc-engine.h"
#include "gnc-gnome-utils.h"
#include "gnc-gobject-utils.h"
#include "gnc-icons.h"
#include "gnc-session.h"
#include "gnc-tree-view-owner.h"
#include "gnc-ui.h"
#include "gnc-ui-util.h"
#include "gnc-window.h"
#include "guile-mappings.h"
#include "dialog-lot-viewer.h"
#include "dialog-object-references.h"

/* This static indicates the debugging module that this .o belongs to.  */
static QofLogModule log_module = GNC_MOD_GUI;

#define PLUGIN_PAGE_ACCT_TREE_CM_CLASS "plugin-page-owner-tree"

#define DELETE_DIALOG_FILTER  "filter"
#define DELETE_DIALOG_OWNER   "owner"

enum
{
    OWNER_SELECTED,
    LAST_SIGNAL
};

typedef struct GncPluginPageOwnerTreePrivate
{
    GtkWidget   *widget;
    GtkTreeView *tree_view;
    gint         component_id;
    GncOwnerType owner_type;
    OwnerFilterDialog fd;
} GncPluginPageOwnerTreePrivate;

G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageOwnerTree, gnc_plugin_page_owner_tree, GNC_TYPE_PLUGIN_PAGE)

#define GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(o)  \
   ((GncPluginPageOwnerTreePrivate*)gnc_plugin_page_owner_tree_get_instance_private((GncPluginPageOwnerTree*)o))

static GObjectClass *parent_class = NULL;

/************************************************************
 *                        Prototypes                        *
 ************************************************************/
/* Plugin Actions */
static void gnc_plugin_page_owner_tree_class_init (GncPluginPageOwnerTreeClass *klass);
static void gnc_plugin_page_owner_tree_init (GncPluginPageOwnerTree *plugin_page);
static void gnc_plugin_page_owner_tree_finalize (GObject *object);
static void gnc_plugin_page_owner_tree_selected (GObject *object, gpointer user_data);

static GtkWidget *gnc_plugin_page_owner_tree_create_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_owner_tree_destroy_widget (GncPluginPage *plugin_page);
static void gnc_plugin_page_owner_tree_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
static GncPluginPage *gnc_plugin_page_owner_tree_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
static void set_menu_and_toolbar_qualifier (GncPluginPage *plugin_page);

/* Callbacks */
static gboolean gnc_plugin_page_owner_tree_button_press_cb (GtkWidget *widget,
                                                            GdkEventButton *event,
                                                            GncPluginPage *page);
static void gnc_plugin_page_owner_tree_double_click_cb (GtkTreeView *treeview,
                                                        GtkTreePath *path,
                                                        GtkTreeViewColumn  *col,
                                                        GncPluginPageOwnerTree *page);

static void gnc_plugin_page_owner_tree_selection_changed_cb (GtkTreeSelection *selection,
                                                             GncPluginPageOwnerTree *page);

/* Command callbacks */
static void gnc_plugin_page_owner_tree_cmd_new_owner (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
static void gnc_plugin_page_owner_tree_cmd_edit_owner (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
#if 0 /* Disabled due to crash */
static void gnc_plugin_page_owner_tree_cmd_delete_owner (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
#endif
static void gnc_plugin_page_owner_tree_cmd_view_filter_by (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
static void gnc_plugin_page_owner_tree_cmd_refresh (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
static void gnc_plugin_page_owner_tree_cmd_new_invoice (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
static void gnc_plugin_page_owner_tree_cmd_owners_report (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
static void gnc_plugin_page_owner_tree_cmd_owner_report (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
static void gnc_plugin_page_owner_tree_cmd_process_payment (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
static void gnc_plugin_page_owner_tree_cmd_edit_tax (GSimpleAction *simple, GVariant *parameter, gpointer user_data);

static guint plugin_page_signals[LAST_SIGNAL] = { 0 };


static GActionEntry gnc_plugin_page_owner_tree_actions [] =
{
    { "OTEditVendorAction", gnc_plugin_page_owner_tree_cmd_edit_owner, NULL, NULL, NULL },
    { "OTEditCustomerAction", gnc_plugin_page_owner_tree_cmd_edit_owner, NULL, NULL, NULL },
    { "OTEditEmployeeAction", gnc_plugin_page_owner_tree_cmd_edit_owner, NULL, NULL, NULL },
    { "OTNewVendorAction", gnc_plugin_page_owner_tree_cmd_new_owner, NULL, NULL, NULL },
    { "OTNewCustomerAction", gnc_plugin_page_owner_tree_cmd_new_owner, NULL, NULL, NULL },
    { "OTNewEmployeeAction", gnc_plugin_page_owner_tree_cmd_new_owner, NULL, NULL, NULL },

#if 0 /* Disabled due to crash */
    { "EditDeleteOwnerAction", gnc_plugin_page_owner_tree_cmd_delete_owner, NULL, NULL, NULL },
#endif /* Disabled due to crash */

    { "ViewFilterByAction", gnc_plugin_page_owner_tree_cmd_view_filter_by, NULL, NULL, NULL },
    { "ViewRefreshAction", gnc_plugin_page_owner_tree_cmd_refresh, NULL, NULL, NULL },
    { "EditTaxOptionsAction", gnc_plugin_page_owner_tree_cmd_edit_tax, NULL, NULL, NULL },
    { "OTNewBillAction", gnc_plugin_page_owner_tree_cmd_new_invoice, NULL, NULL, NULL },
    { "OTNewInvoiceAction", gnc_plugin_page_owner_tree_cmd_new_invoice, NULL, NULL, NULL },
    { "OTNewVoucherAction", gnc_plugin_page_owner_tree_cmd_new_invoice, NULL, NULL, NULL },
    { "OTVendorListingReportAction", gnc_plugin_page_owner_tree_cmd_owners_report, NULL, NULL, NULL },
    { "OTCustomerListingReportAction", gnc_plugin_page_owner_tree_cmd_owners_report, NULL, NULL, NULL },
    { "OTVendorReportAction", gnc_plugin_page_owner_tree_cmd_owner_report, NULL, NULL, NULL },
    { "OTCustomerReportAction", gnc_plugin_page_owner_tree_cmd_owner_report, NULL, NULL, NULL },
    { "OTEmployeeReportAction", gnc_plugin_page_owner_tree_cmd_owner_report, NULL, NULL, NULL },
    { "OTProcessPaymentAction", gnc_plugin_page_owner_tree_cmd_process_payment, NULL, NULL, NULL },
};
/** The number of actions provided by this plugin. */
static guint gnc_plugin_page_owner_tree_n_actions = G_N_ELEMENTS(gnc_plugin_page_owner_tree_actions);

/** The default menu items that need to be add to the menu */
static const gchar *gnc_plugin_load_ui_items [] =
{
    "FilePlaceholder3",
    "EditPlaceholder2",
    "EditPlaceholder3",
    "EditPlaceholder5",
    "ViewPlaceholder1",
    "ViewPlaceholder4",
    "ReportsPlaceholder1",
    NULL,
};

/** Actions that require an owner to be selected before they are
 *  enabled. These ones are only sensitive in a read-write book. */
static const gchar *actions_requiring_owner_rw[] =
{
    "OTEditVendorAction",
    "OTEditCustomerAction",
    "OTEditEmployeeAction",
    "OTProcessPaymentAction",
/* FIXME disabled due to crash    "EditDeleteOwnerAction", */
    NULL
};

/** Actions that require an owner to be selected before they are
 *  enabled. These are sensitive always. */
static const gchar *actions_requiring_owner_always[] =
{
    "OTVendorReportAction",
    "OTCustomerReportAction",
    "OTEmployeeReportAction",
    "OTProcessPaymentAction",
    NULL
};

/* This is the list of actions which are switched inactive in a read-only book. */
static const gchar* readonly_inactive_actions[] =
{
    "OTNewVendorAction",
    "OTNewCustomerAction",
    "OTNewEmployeeAction",
    "OTNewBillAction",
    "OTNewInvoiceAction",
    "OTNewVoucherAction",
    "OTProcessPaymentAction",
    NULL
};


/** Short labels for use on the toolbar buttons. */
static GncToolBarShortNames toolbar_labels[] =
{
    { "OTEditVendorAction",             N_("Edit") },
    { "OTEditCustomerAction",           N_("Edit") },
    { "OTEditEmployeeAction",           N_("Edit") },
    { "OTNewVendorAction",              N_("New") },
    { "OTNewCustomerAction",            N_("New") },
    { "OTNewEmployeeAction",            N_("New") },
    { "OTNewBillAction",                N_("New Bill") },
    { "OTNewInvoiceAction",             N_("New Invoice") },
    { "OTNewVoucherAction",             N_("New Voucher") },
    { "OTVendorListingReportAction",    N_("Vendor Listing") },
    { "OTCustomerListingReportAction",  N_("Customer Listing") },
    { "OTProcessPaymentAction",         N_("Process Payment") },
/* FIXME disable due to crash   { "EditDeleteOwnerAction",   N_("Delete") },*/
    { NULL, NULL },
};

/** Map actions to owners. Will be used to hide actions that are
 *  not relevant on the active owner overview page
 */
typedef struct
{
    /** The name of the action. */
    const char *action_name;
    /** The owner type to show this action for */
    GncOwnerType owner_type;
} action_owners_struct;

GncPluginPage *
gnc_plugin_page_owner_tree_new (GncOwnerType owner_type)
{
    GncPluginPageOwnerTree *plugin_page;
    GncPluginPageOwnerTreePrivate *priv;
    const GList *item;

    g_return_val_if_fail( (owner_type != GNC_OWNER_UNDEFINED)
                          && (owner_type != GNC_OWNER_NONE), NULL);
    ENTER(" ");

    /* Is there an existing page? */
    item = gnc_gobject_tracking_get_list(GNC_PLUGIN_PAGE_OWNER_TREE_NAME);
    for ( ; item; item = g_list_next(item))
    {
        plugin_page = (GncPluginPageOwnerTree *)item->data;
        priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(plugin_page);
        if (priv->owner_type == owner_type)
        {
            LEAVE("existing %s tree page %p", gncOwnerTypeToQofIdType(owner_type), plugin_page);
            return GNC_PLUGIN_PAGE(plugin_page);
        }
    }

    plugin_page = g_object_new(GNC_TYPE_PLUGIN_PAGE_OWNER_TREE, NULL);

    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(plugin_page);
    priv->owner_type = owner_type;

    LEAVE("new %s tree page %p", gncOwnerTypeToQofIdType(owner_type), plugin_page);
    return GNC_PLUGIN_PAGE(plugin_page);
}

/**
 * Whenever the current page is changed, if an owner page is
 * the current page, set focus on the tree view.
 */
static gboolean
gnc_plugin_page_owner_focus_widget (GncPluginPage *owner_plugin_page)
{
    if (GNC_IS_PLUGIN_PAGE_OWNER_TREE(owner_plugin_page))
    {
        GncPluginPageOwnerTreePrivate *priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(owner_plugin_page);
        GtkTreeView *tree_view = priv->tree_view;

        /* Disable the Transaction Menu */
        GAction *action = gnc_main_window_find_action (GNC_MAIN_WINDOW(owner_plugin_page->window), "TransactionAction");
        g_simple_action_set_enabled (G_SIMPLE_ACTION(action), FALSE);
        /* Disable the Schedule menu */
        action = gnc_main_window_find_action (GNC_MAIN_WINDOW(owner_plugin_page->window), "ScheduledAction");
        g_simple_action_set_enabled (G_SIMPLE_ACTION(action), FALSE);
        /* Disable the FilePrintAction */
        action = gnc_main_window_find_action (GNC_MAIN_WINDOW(owner_plugin_page->window), "FilePrintAction");
        g_simple_action_set_enabled (G_SIMPLE_ACTION(action), FALSE);

        set_menu_and_toolbar_qualifier (owner_plugin_page);

        gnc_main_window_update_menu_and_toolbar (GNC_MAIN_WINDOW(owner_plugin_page->window),
                                                 owner_plugin_page,
                                                 gnc_plugin_load_ui_items);

         // setup any short toolbar names
        gnc_main_window_init_short_names (GNC_MAIN_WINDOW(owner_plugin_page->window), toolbar_labels);

        if (GTK_IS_TREE_VIEW(tree_view))
        {
            if (!gtk_widget_is_focus (GTK_WIDGET(tree_view)))
                gtk_widget_grab_focus (GTK_WIDGET(tree_view));
        }
    }
    return FALSE;
}

static void
gnc_plugin_page_owner_tree_class_init (GncPluginPageOwnerTreeClass *klass)
{
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
    GncPluginPageClass *gnc_plugin_class = GNC_PLUGIN_PAGE_CLASS(klass);

    parent_class = g_type_class_peek_parent (klass);

    object_class->finalize = gnc_plugin_page_owner_tree_finalize;

    gnc_plugin_class->tab_icon        = GNC_ICON_ACCOUNT;
    gnc_plugin_class->plugin_name     = GNC_PLUGIN_PAGE_OWNER_TREE_NAME;
    gnc_plugin_class->create_widget   = gnc_plugin_page_owner_tree_create_widget;
    gnc_plugin_class->destroy_widget  = gnc_plugin_page_owner_tree_destroy_widget;
    gnc_plugin_class->save_page       = gnc_plugin_page_owner_tree_save_page;
    gnc_plugin_class->recreate_page   = gnc_plugin_page_owner_tree_recreate_page;
    gnc_plugin_class->focus_page_function = gnc_plugin_page_owner_focus_widget;

    plugin_page_signals[OWNER_SELECTED] =
        g_signal_new ("owner_selected",
                      G_OBJECT_CLASS_TYPE (object_class),
                      G_SIGNAL_RUN_FIRST,
                      G_STRUCT_OFFSET (GncPluginPageOwnerTreeClass, owner_selected),
                      NULL, NULL,
                      g_cclosure_marshal_VOID__POINTER,
                      G_TYPE_NONE, 1,
                      G_TYPE_POINTER);
}

static void
gnc_plugin_page_owner_tree_init (GncPluginPageOwnerTree *plugin_page)
{
    GSimpleActionGroup *simple_action_group;
    GncPluginPageOwnerTreePrivate *priv;
    GncPluginPage *parent;

    ENTER("page %p", plugin_page);
    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(plugin_page);

    /* Init parent declared variables */
    parent = GNC_PLUGIN_PAGE(plugin_page);
    g_object_set(G_OBJECT(plugin_page),
                 "page-name",      _("Owners"),
                 "ui-description", "gnc-plugin-page-owner-tree.ui",
                 NULL);
    g_signal_connect (G_OBJECT (plugin_page), "selected",
                      G_CALLBACK (gnc_plugin_page_owner_tree_selected), plugin_page);

    /* change me when the system supports multiple books */
    gnc_plugin_page_add_book (parent, gnc_get_current_book());

    /* Create menu and toolbar information */
    simple_action_group = gnc_plugin_page_create_action_group (parent, "GncPluginPageOwnerTreeActions");
    g_action_map_add_action_entries (G_ACTION_MAP(simple_action_group),
                                     gnc_plugin_page_owner_tree_actions,
                                     gnc_plugin_page_owner_tree_n_actions,
                                     plugin_page);

    /* Init filter */
    priv->fd.show_inactive = TRUE;
    priv->fd.show_zero_total = TRUE;

    LEAVE("page %p, priv %p, action group %p",
          plugin_page, priv, simple_action_group);
}

static void
gnc_plugin_page_owner_tree_finalize (GObject *object)
{
    GncPluginPageOwnerTree *page;
    GncPluginPageOwnerTreePrivate *priv;

    ENTER("object %p", object);
    page = GNC_PLUGIN_PAGE_OWNER_TREE (object);
    g_return_if_fail (GNC_IS_PLUGIN_PAGE_OWNER_TREE (page));
    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(page);
    g_return_if_fail (priv != NULL);

    G_OBJECT_CLASS (parent_class)->finalize (object);
    LEAVE(" ");
}

static void
update_inactive_actions(GncPluginPage *plugin_page)
{
    GSimpleActionGroup *simple_action_group;
    gboolean is_sensitive = !qof_book_is_readonly(gnc_get_current_book());

    // We are readonly - so we have to switch particular actions to inactive.
    g_return_if_fail(plugin_page);
    g_return_if_fail(GNC_IS_PLUGIN_PAGE(plugin_page));

    /* Get the action group */
    simple_action_group = gnc_plugin_page_get_action_group (plugin_page);
    g_return_if_fail (G_IS_SIMPLE_ACTION_GROUP(simple_action_group));

    /* Set the action's sensitivity */
    gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), readonly_inactive_actions,
                                    is_sensitive);
}

static void
set_menu_and_toolbar_qualifier (GncPluginPage *plugin_page)
{
    GncPluginPageOwnerTree *page = GNC_PLUGIN_PAGE_OWNER_TREE(plugin_page);
    GncPluginPageOwnerTreePrivate *priv;

    g_return_if_fail (GNC_IS_PLUGIN_PAGE_OWNER_TREE(page));

    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(page);

    if (priv->owner_type == GNC_OWNER_CUSTOMER)
        gnc_plugin_page_set_menu_qualifier (plugin_page, "c");
    else if (priv->owner_type == GNC_OWNER_VENDOR)
        gnc_plugin_page_set_menu_qualifier (plugin_page, "v");
    else if (priv->owner_type == GNC_OWNER_EMPLOYEE)
        gnc_plugin_page_set_menu_qualifier (plugin_page, "e");
    else
        gnc_plugin_page_set_menu_qualifier (plugin_page, NULL);
}

static void
gnc_plugin_page_owner_tree_selected (GObject *object, gpointer user_data)
{
    GncPluginPage *page = GNC_PLUGIN_PAGE (object);
    g_return_if_fail (GNC_IS_PLUGIN_PAGE (page));
    update_inactive_actions(page);
}


GncOwner *
gnc_plugin_page_owner_tree_get_current_owner (GncPluginPageOwnerTree *page)
{
    GncPluginPageOwnerTreePrivate *priv;
    GncOwner *owner;

    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(page);
    ENTER("page %p (tree view %p)", page, priv->tree_view);
    owner = gnc_tree_view_owner_get_selected_owner (GNC_TREE_VIEW_OWNER(priv->tree_view));
    if (owner == NULL)
    {
        LEAVE("no owner");
        return NULL;
    }

    LEAVE("owner %p", owner);
    return owner;
}


/* Virtual Functions */

static void
gnc_plugin_page_owner_refresh_cb (GHashTable *changes, gpointer user_data)
{
    GncPluginPageOwnerTree *page = user_data;
    GncPluginPageOwnerTreePrivate *priv;

    g_return_if_fail(GNC_IS_PLUGIN_PAGE_OWNER_TREE(page));

    /* We're only looking for forced updates here. */
    if (changes)
        return;

    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(page);
    gtk_widget_queue_draw(priv->widget);
}

static void
gnc_plugin_page_owner_tree_close_cb (gpointer user_data)
{
    GncPluginPage *plugin_page;

    plugin_page = GNC_PLUGIN_PAGE(user_data);
    gnc_main_window_close_page(plugin_page);
}

static GtkWidget *
gnc_plugin_page_owner_tree_create_widget (GncPluginPage *plugin_page)
{
    GncPluginPageOwnerTree *page;
    GncPluginPageOwnerTreePrivate *priv;
    GtkTreeSelection *selection;
    GtkTreeView *tree_view;
    GtkWidget *scrolled_window;
    GtkTreeViewColumn *col;
    const gchar *state_section = NULL;
    gchar* label = "";
    const gchar *style_label = NULL;

    ENTER("page %p", plugin_page);
    page = GNC_PLUGIN_PAGE_OWNER_TREE (plugin_page);
    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(page);
    if (priv->widget != NULL)
    {
        LEAVE("widget = %p", priv->widget);
        return priv->widget;
    }

    priv->widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_box_set_homogeneous (GTK_BOX (priv->widget), FALSE);
    gtk_widget_show (priv->widget);

    // Set the name for this widget so it can be easily manipulated with css
    gtk_widget_set_name (GTK_WIDGET(priv->widget), "gnc-id-owner-page");

    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_widget_show (scrolled_window);
    gtk_box_pack_start (GTK_BOX (priv->widget), scrolled_window,
                        TRUE, TRUE, 0);

    tree_view = gnc_tree_view_owner_new(priv->owner_type);

    /* Show default columns */
    col = gnc_tree_view_find_column_by_name(
              GNC_TREE_VIEW(tree_view), GNC_OWNER_TREE_ID_COL);
    g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
    col = gnc_tree_view_find_column_by_name(
              GNC_TREE_VIEW(tree_view), GNC_OWNER_TREE_ADDRESS_1_COL);
    g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
    col = gnc_tree_view_find_column_by_name(
              GNC_TREE_VIEW(tree_view), GNC_OWNER_TREE_ADDRESS_2_COL);
    g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
    col = gnc_tree_view_find_column_by_name(
              GNC_TREE_VIEW(tree_view), GNC_OWNER_TREE_PHONE_COL);
    g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
    gnc_tree_view_configure_columns(GNC_TREE_VIEW(tree_view));

    switch (priv->owner_type)
    {
    case GNC_OWNER_NONE :
    case GNC_OWNER_UNDEFINED :
        PWARN("missing owner_type");
        label = _("Unknown");
        style_label = "gnc-class-unknown";
        break;
    case GNC_OWNER_CUSTOMER :
        label = _("Customers");
        state_section = "Customers Overview";
        style_label = "gnc-class-customers";
        break;
    case GNC_OWNER_JOB :
        label = _("Jobs");
        state_section = "Jobs Overview";
        style_label = "gnc-class-jobs";
        break;
    case GNC_OWNER_VENDOR :
        label = _("Vendors");
        state_section = "Vendors Overview";
        style_label = "gnc-class-vendors";
        break;
    case GNC_OWNER_EMPLOYEE :
        label = _("Employees");
        state_section = "Employees Overview";
        style_label = "gnc-class-employees";
        break;
    }

    // Set a secondary style context for this page so it can be easily manipulated with css
    gnc_widget_style_context_add_class (GTK_WIDGET(priv->widget), style_label);

    g_object_set(G_OBJECT(tree_view), "state-section", state_section,
                                      "show-column-menu", TRUE,
                                      NULL);

    g_object_set(G_OBJECT(plugin_page), "page-name", label, NULL);

    priv->tree_view = tree_view;
    selection = gtk_tree_view_get_selection(tree_view);
    g_signal_connect (G_OBJECT (selection), "changed",
                      G_CALLBACK (gnc_plugin_page_owner_tree_selection_changed_cb), page);
    g_signal_connect (G_OBJECT (tree_view), "button-press-event",
                      G_CALLBACK (gnc_plugin_page_owner_tree_button_press_cb), page);
    g_signal_connect (G_OBJECT (tree_view), "row-activated",
                      G_CALLBACK (gnc_plugin_page_owner_tree_double_click_cb), page);

    gtk_tree_view_set_headers_visible(tree_view, TRUE);
    gnc_plugin_page_owner_tree_selection_changed_cb (NULL, page);
    gtk_widget_show (GTK_WIDGET (tree_view));
    gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET(tree_view));

    priv->fd.tree_view = GNC_TREE_VIEW_OWNER(priv->tree_view);
    gnc_tree_view_owner_set_filter (
        GNC_TREE_VIEW_OWNER(tree_view),
        gnc_plugin_page_owner_tree_filter_owners, &priv->fd, NULL);

    priv->component_id =
        gnc_register_gui_component(PLUGIN_PAGE_ACCT_TREE_CM_CLASS,
                                   gnc_plugin_page_owner_refresh_cb,
                                   gnc_plugin_page_owner_tree_close_cb,
                                   page);
    gnc_gui_component_set_session (priv->component_id,
                                   gnc_get_current_session());

    g_signal_connect (G_OBJECT(plugin_page), "inserted",
                      G_CALLBACK(gnc_plugin_page_inserted_cb),
                      NULL);

    set_menu_and_toolbar_qualifier (plugin_page);

    LEAVE("widget = %p", priv->widget);
    return priv->widget;
}

static void
gnc_plugin_page_owner_tree_destroy_widget (GncPluginPage *plugin_page)
{
    GncPluginPageOwnerTree *page;
    GncPluginPageOwnerTreePrivate *priv;

    ENTER("page %p", plugin_page);
    page = GNC_PLUGIN_PAGE_OWNER_TREE (plugin_page);
    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(page);

    // Remove the page_changed signal callback
    gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));

    // Remove the page focus idle function if present
    g_idle_remove_by_data (plugin_page);

    if (priv->widget)
    {
        g_object_unref(G_OBJECT(priv->widget));
        priv->widget = NULL;
    }

    if (priv->component_id)
    {
        gnc_unregister_gui_component(priv->component_id);
        priv->component_id = 0;
    }

    LEAVE("widget destroyed");
}

#define OWNER_TYPE_LABEL     "OwnerType"

/** Save enough information about this owner tree page that it can
 *  be recreated next time the user starts gnucash.
 *
 *  @param plugin_page The page to save.
 *
 *  @param key_file A pointer to the GKeyFile data structure where the
 *  page information should be written.
 *
 *  @param group_name The group name to use when saving data. */
static void
gnc_plugin_page_owner_tree_save_page (GncPluginPage *plugin_page,
                                      GKeyFile *key_file,
                                      const gchar *group_name)
{
    GncPluginPageOwnerTree *owner_page;
    GncPluginPageOwnerTreePrivate *priv;

    g_return_if_fail (GNC_IS_PLUGIN_PAGE_OWNER_TREE(plugin_page));
    g_return_if_fail (key_file != NULL);
    g_return_if_fail (group_name != NULL);

    ENTER("page %p, key_file %p, group_name %s", plugin_page, key_file,
          group_name);

    owner_page = GNC_PLUGIN_PAGE_OWNER_TREE(plugin_page);
    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(owner_page);

    g_key_file_set_integer(key_file, group_name, OWNER_TYPE_LABEL,
                           priv->owner_type);

    gnc_tree_view_owner_save(GNC_TREE_VIEW_OWNER(priv->tree_view),
                             &priv->fd, key_file, group_name);
    LEAVE(" ");
}



/** Create a new owner tree page based on the information saved
 *  during a previous instantiation of gnucash.
 *
 *  @param window The window where this page should be installed.
 *
 *  @param key_file A pointer to the GKeyFile data structure where the
 *  page information should be read.
 *
 *  @param group_name The group name to use when restoring data. */
static GncPluginPage *
gnc_plugin_page_owner_tree_recreate_page (GtkWidget *window,
                                          GKeyFile *key_file,
                                          const gchar *group_name)
{
    GncPluginPageOwnerTree *owner_page;
    GncPluginPageOwnerTreePrivate *priv;
    GncPluginPage *page;
    GncOwnerType owner_type;

    g_return_val_if_fail(key_file, NULL);
    g_return_val_if_fail(group_name, NULL);
    ENTER("key_file %p, group_name %s", key_file, group_name);

    /* Create the new page. */
    owner_type = g_key_file_get_integer(key_file, group_name, OWNER_TYPE_LABEL, NULL);
    page = gnc_plugin_page_owner_tree_new(owner_type);
    owner_page = GNC_PLUGIN_PAGE_OWNER_TREE(page);
    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(owner_page);

    /* Install it now so we can then manipulate the created widget */
    gnc_main_window_open_page(GNC_MAIN_WINDOW(window), page);

    gnc_tree_view_owner_restore(GNC_TREE_VIEW_OWNER(priv->tree_view),
                                &priv->fd, key_file, group_name, owner_type);
    LEAVE(" ");
    return page;
}

/* Wrapper function to open the proper edit dialog, depending on the owner type */
static void gnc_ui_owner_edit (GtkWindow *parent, GncOwner *owner)
{
    if (NULL == owner) return;

    switch (owner->type)
    {
    case GNC_OWNER_NONE :
    case GNC_OWNER_UNDEFINED :
        break;
    case GNC_OWNER_CUSTOMER :
    {
        gnc_ui_customer_edit (parent, owner->owner.customer);
        break;
    }
    case GNC_OWNER_JOB :
    {
        gnc_ui_job_edit (parent, owner->owner.job);
        break;
    }
    case GNC_OWNER_VENDOR :
    {
        gnc_ui_vendor_edit (parent, owner->owner.vendor);
        break;
    }
    case GNC_OWNER_EMPLOYEE :
    {
        gnc_ui_employee_edit (parent, owner->owner.employee);
        break;
    }
    }
}


/* Callbacks */

/** This button press handler calls the common button press handler
 *  for all pages.  The GtkTreeView eats all button presses and
 *  doesn't pass them up the widget tree, even when doesn't do
 *  anything with them.  The only way to get access to the button
 *  presses in an owner tree page is here on the tree view widget.
 *  Button presses on all other pages are caught by the signal
 *  registered in gnc-main-window.c. */
static gboolean
gnc_plugin_page_owner_tree_button_press_cb (GtkWidget *widget,
                                            GdkEventButton *event,
                                            GncPluginPage *page)
{
    g_return_val_if_fail(GNC_IS_PLUGIN_PAGE(page), FALSE);

    ENTER("widget %p, event %p, page %p", widget, event, page);
    gnc_main_window_button_press_cb(widget, event, page);
    LEAVE(" ");

    /* Always return FALSE.  This will let the tree view callback run as
     * well which will select the item under the cursor.  By the time
     * the user sees the menu both callbacks will have run and the menu
     * actions will operate on the just-selected owner. */
    return FALSE;
}

static void
gnc_plugin_page_owner_tree_double_click_cb (GtkTreeView *treeview,
                                            GtkTreePath *path,
                                            GtkTreeViewColumn *col,
                                            GncPluginPageOwnerTree *page)
{
    gnc_plugin_page_owner_tree_cmd_owner_report (NULL, NULL, (gpointer*)page);
}

static void
gnc_plugin_page_owner_tree_selection_changed_cb (GtkTreeSelection *selection,
                                                 GncPluginPageOwnerTree *page)
{
    GSimpleActionGroup *simple_action_group;
    GtkTreeView *view;
    GncOwner *owner = NULL;
    gboolean sensitive;
    gboolean is_readwrite = !qof_book_is_readonly(gnc_get_current_book());

    g_return_if_fail(GNC_IS_PLUGIN_PAGE_OWNER_TREE(page));

    if (!selection)
    {
        sensitive = FALSE;
    }
    else
    {
        g_return_if_fail(GTK_IS_TREE_SELECTION(selection));
        view = gtk_tree_selection_get_tree_view (selection);
        owner = gnc_tree_view_owner_get_selected_owner (GNC_TREE_VIEW_OWNER(view));
        sensitive = (owner != NULL);
    }

    simple_action_group = gnc_plugin_page_get_action_group (GNC_PLUGIN_PAGE(page));
    gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), actions_requiring_owner_always,
                                    sensitive);
    gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), actions_requiring_owner_rw,
                                    sensitive && is_readwrite);
    g_signal_emit (page, plugin_page_signals[OWNER_SELECTED], 0, owner);
}

/******************************************************************/
/*                     Report helper functions                    */
/******************************************************************/

static int
build_aging_report (GncOwnerType owner_type)
{
    gchar *report_name = NULL;
    gchar *report_title = NULL;
    SCM args;
    SCM func;
    SCM arg;

    args = SCM_EOL;

    switch (owner_type)
    {
    case GNC_OWNER_NONE :
    case GNC_OWNER_UNDEFINED :
    case GNC_OWNER_EMPLOYEE :
    case GNC_OWNER_JOB :
    {
        return -1;
    }
    case GNC_OWNER_VENDOR :
    {
        report_name  = "gnc:payables-report-create";
        report_title = _("Vendor Listing");
        break;
    }
    case GNC_OWNER_CUSTOMER :
    {
        report_name = "gnc:receivables-report-create";
        report_title = _("Customer Listing");
        break;
    }
    }

    /* Find report generator function in guile */
    func = scm_c_eval_string (report_name);
    g_return_val_if_fail (scm_is_procedure (func), -1);

    /* Option Show zero's ? - Yes for the listing report */
    arg = SCM_BOOL_T;
    args = scm_cons (arg, args);
    g_return_val_if_fail (arg != SCM_UNDEFINED, -1);

    /* Option Report title */
    arg = scm_from_utf8_string (report_title);
    args = scm_cons (arg, args);

    /* Option Account - Using False to select default account
     *
     * XXX I'm not sure if it would make sense to use another
     *     account than default */
    arg = SCM_BOOL_F;
    args = scm_cons (arg, args);
    g_return_val_if_fail (arg != SCM_UNDEFINED, -1);


    /* Apply the function to the args */
    arg = scm_apply (func, args, SCM_EOL);
    g_return_val_if_fail (scm_is_exact (arg), -1);

    return scm_to_int (arg);
}

static int build_owner_report (GncOwner *owner, Account *acc)
{
    SCM args;
    SCM func;
    SCM arg;

    g_return_val_if_fail (owner, -1);

    args = SCM_EOL;

    func = scm_c_eval_string ("gnc:owner-report-create-with-enddate");
    g_return_val_if_fail (scm_is_procedure (func), -1);

    args = scm_cons (SCM_BOOL_F, args); /* enddate is #f */

    if (acc)
    {
        swig_type_info * qtype = SWIG_TypeQuery("_p_Account");
        g_return_val_if_fail (qtype, -1);

        arg = SWIG_NewPointerObj(acc, qtype, 0);
        g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
        args = scm_cons (arg, args);
    }
    else
    {
        args = scm_cons (SCM_BOOL_F, args);
    }

    swig_type_info * qtype = SWIG_TypeQuery("_p__gncOwner");
    g_return_val_if_fail (qtype, -1);

    arg = SWIG_NewPointerObj(owner, qtype, 0);

    g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
    args = scm_cons (arg, args);

    /* Apply the function to the args */
    arg = scm_apply (func, args, SCM_EOL);
    g_return_val_if_fail (scm_is_exact (arg), -1);
    return scm_to_int (arg);
}


/************************************************************/
/*                     Command callbacks                    */
/************************************************************/

static void
gnc_plugin_page_owner_tree_cmd_new_owner (GSimpleAction *simple,
                                          GVariant *parameter,
                                          gpointer user_data)

{
    GncPluginPageOwnerTree *page = user_data;
    GncPluginPageOwnerTreePrivate *priv;
    GtkWindow *parent;

    g_return_if_fail(GNC_IS_PLUGIN_PAGE_OWNER_TREE(page));

    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE (page);
    parent = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));

    switch (priv->owner_type)
    {
    case GNC_OWNER_NONE :
    case GNC_OWNER_UNDEFINED :
        break;
    case GNC_OWNER_CUSTOMER :
    {
        gnc_ui_customer_new (parent, gnc_get_current_book ());
        break;
    }
    case GNC_OWNER_JOB :
    {
        /* XXX currently not properly implemented, so disabled for now
        gnc_ui_job_new (owner, gnc_get_current_book ()); */
        break;
    }
    case GNC_OWNER_VENDOR :
    {
        gnc_ui_vendor_new (parent, gnc_get_current_book ());
        break;
    }
    case GNC_OWNER_EMPLOYEE :
    {
        gnc_ui_employee_new (parent, gnc_get_current_book ());
        break;
    }
    }
}

static void
gnc_plugin_page_owner_tree_cmd_edit_owner (GSimpleAction *simple,
                                           GVariant *parameter,
                                           gpointer user_data)

{
    GncPluginPageOwnerTree *page = user_data;
    GtkWindow *parent;
    GncOwner *owner = gnc_plugin_page_owner_tree_get_current_owner (page);
    if (NULL == owner) return;

    ENTER("action %p, page %p", simple, page);

    parent = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
    gnc_ui_owner_edit (parent, owner);

    LEAVE(" ");
}

#if 0 /* Disabled due to crash */
static void
gnc_plugin_page_owner_tree_cmd_delete_owner (GSimpleAction *simple,
                                             GVariant *parameter,
                                             gpointer user_data)

{
    GncPluginPageOwnerTree *page = user_data;
    GncOwner *owner = gnc_plugin_page_owner_tree_get_current_owner (page);
    gchar *owner_name;
    GtkWidget *window;
    GtkWidget *dialog = NULL;
    gint response;
    GList* list;

    if (NULL == owner) return;

    /* If the owner has objects referring to it, show the list - the owner can't be deleted until these
       references are dealt with. */
    list = qof_instance_get_referring_object_list(QOF_INSTANCE(gncOwnerGetUndefined(owner)));
    if (list != NULL)
    {
#define EXPLANATION "The list below shows objects which make use of the owner which you want to delete.\nBefore you can delete it, you must either delete those objects or else modify them so they make use\nof another owner"

        gnc_ui_object_references_show( _(EXPLANATION), list);
        g_list_free(list);
        return;
    }

    window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
    owner_name = g_strdup (gncOwnerGetName(owner));
    if (!owner_name)
    {
        owner_name = g_strdup (_("(no name)"));
    }

    /*
     * Present a message to the user which specifies what will be
     * deleted, then ask for verification.
     */
    {
        char *message = g_strdup_printf(_("The owner %s will be deleted.\nAre you sure you want to do this?"), owner_name);

        dialog =  gtk_message_dialog_new(GTK_WINDOW(window),
                                         GTK_DIALOG_DESTROY_WITH_PARENT,
                                         GTK_MESSAGE_QUESTION,
                                         GTK_BUTTONS_NONE,
                                         "%s", message);
        g_free(message);
        gtk_dialog_add_buttons(GTK_DIALOG(dialog),
                               _("_Cancel"), GTK_RESPONSE_CANCEL,
                               _("_Delete"), GTK_RESPONSE_ACCEPT,
                               (gchar *)NULL);
        gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
        response = gtk_dialog_run(GTK_DIALOG(dialog));
        gtk_widget_destroy(dialog);

        if (GTK_RESPONSE_ACCEPT == response)
        {
            /* FIXME The code below results in a crash.
             *       The corresponding menu item/toolbar button is disabled until this is fixed. */
            gnc_set_busy_cursor(NULL, TRUE);
            gnc_suspend_gui_refresh ();
            gncOwnerBeginEdit (owner);
            gncOwnerDestroy (owner);
            gnc_resume_gui_refresh ();
            gnc_unset_busy_cursor(NULL);
        }
    }
    g_free(owner_name);
}
#endif /* Disabled due to crash */

/*********************/

static void
gnc_plugin_page_owner_tree_cmd_view_filter_by (GSimpleAction *simple,
                                               GVariant *parameter,
                                               gpointer user_data)

{
    GncPluginPageOwnerTree *plugin_page = user_data;
    GncPluginPageOwnerTreePrivate *priv;

    g_return_if_fail(GNC_IS_PLUGIN_PAGE_OWNER_TREE(plugin_page));
    ENTER("(action %p, page %p)", simple, plugin_page);

    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(plugin_page);
    owner_filter_dialog_create(&priv->fd, GNC_PLUGIN_PAGE(plugin_page));
    LEAVE(" ");
}

static void
gnc_plugin_page_owner_tree_cmd_refresh (GSimpleAction *simple,
                                        GVariant *parameter,
                                        gpointer user_data)

{
    GncPluginPageOwnerTree *plugin_page = user_data;
    GncPluginPageOwnerTreePrivate *priv;

    g_return_if_fail(GNC_IS_PLUGIN_PAGE_OWNER_TREE(plugin_page));

    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(plugin_page);
    gtk_widget_queue_draw (priv->widget);
}

static void
gnc_plugin_page_owner_tree_cmd_edit_tax (GSimpleAction *simple,
                                         GVariant *parameter,
                                         gpointer user_data)
{
    GncPluginPageOwnerTree *plugin_page = user_data;
    GtkWidget *parent;

    g_return_if_fail (GNC_IS_PLUGIN_PAGE_OWNER_TREE(plugin_page));

    parent = GTK_WIDGET(gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(plugin_page)));

    gnc_tax_info_dialog (parent, NULL);
}

static void
gnc_plugin_page_owner_tree_cmd_new_invoice (GSimpleAction *simple,
                                            GVariant *parameter,
                                            gpointer user_data)

{
    GncPluginPageOwnerTree *plugin_page = user_data;
    GncPluginPageOwnerTreePrivate *priv;
    GncOwner current_owner;
    GtkWindow *parent;

    ENTER("action %p, plugin_page %p", simple, plugin_page);

    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(plugin_page);
    switch (priv->owner_type)
    {
    case GNC_OWNER_NONE :
    case GNC_OWNER_UNDEFINED :
        gncOwnerInitUndefined(&current_owner, NULL);
        break;
    case GNC_OWNER_CUSTOMER :
    {
        gncOwnerInitCustomer(&current_owner,
                             gncOwnerGetCustomer(gnc_plugin_page_owner_tree_get_current_owner (plugin_page)));
        break;
    }
    case GNC_OWNER_JOB :
    {
        gncOwnerInitJob(&current_owner,
                        gncOwnerGetJob(gnc_plugin_page_owner_tree_get_current_owner (plugin_page)));
        break;
    }
    case GNC_OWNER_VENDOR :
    {
        gncOwnerInitVendor(&current_owner,
                           gncOwnerGetVendor(gnc_plugin_page_owner_tree_get_current_owner (plugin_page)));
        break;
    }
    case GNC_OWNER_EMPLOYEE :
    {
        gncOwnerInitEmployee(&current_owner,
                             gncOwnerGetEmployee(gnc_plugin_page_owner_tree_get_current_owner (plugin_page)));
        break;
    }
    }

    parent = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(plugin_page)));
    if (gncOwnerGetType(&current_owner) != GNC_OWNER_UNDEFINED)
        gnc_ui_invoice_new (parent, &current_owner, gnc_get_current_book ());

    LEAVE(" ");
}

static void
gnc_plugin_page_owner_tree_cmd_owners_report (GSimpleAction *simple,
                                              GVariant *parameter,
                                              gpointer user_data)

{
    GncPluginPageOwnerTree *plugin_page = user_data;
    GncPluginPageOwnerTreePrivate *priv;
    int id;

    ENTER("(action %p, plugin_page %p)", simple, plugin_page);

    g_return_if_fail(GNC_IS_PLUGIN_PAGE_OWNER_TREE(plugin_page));

    priv = GNC_PLUGIN_PAGE_OWNER_TREE_GET_PRIVATE(plugin_page);
    id = build_aging_report (priv->owner_type);
    if (id >= 0)
    {
        GncMainWindow *window;
        window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
        gnc_main_window_open_report(id, window);
    }

    LEAVE(" ");
}

static void
gnc_plugin_page_owner_tree_cmd_owner_report (GSimpleAction *simple,
                                             GVariant *parameter,
                                             gpointer user_data)

{
    GncPluginPageOwnerTree *plugin_page = user_data;
    GncOwner *current_owner;
    int id;

    ENTER("(action %p, plugin_page %p)", simple, plugin_page);

    g_return_if_fail(GNC_IS_PLUGIN_PAGE_OWNER_TREE(plugin_page));

    current_owner = gnc_plugin_page_owner_tree_get_current_owner (plugin_page);
    id = build_owner_report (current_owner, NULL);
    if (id >= 0)
    {
        GncMainWindow *window;
        window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
        gnc_main_window_open_report(id, window);
    }

    LEAVE(" ");
}


static void
gnc_plugin_page_owner_tree_cmd_process_payment (GSimpleAction *simple,
                                                GVariant *parameter,
                                                gpointer user_data)

{
    GncPluginPageOwnerTree *plugin_page = user_data;
    ENTER("(action %p, plugin_page %p)", simple, plugin_page);

    g_return_if_fail(GNC_IS_PLUGIN_PAGE_OWNER_TREE(plugin_page));

    gnc_ui_payment_new (GTK_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window),
                        gnc_plugin_page_owner_tree_get_current_owner (plugin_page),
                        gnc_get_current_book ());

    LEAVE(" ");
}
/** @} */
/** @} */
