mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Rework/clean the code. Add features needed by the code that embeds a
gnc-tree-view-account into a window. I.E. Filters, pseudo top-level account, etc. Add documentation. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/branches/gnucash-gnome2-dev@9239 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
* display accounts in a GtkTreeView.
|
||||
*
|
||||
* Copyright (C) 2003 Jan Arne Petersen
|
||||
* Author: Jan Arne Petersen <jpetersen@uni-bonn.de>
|
||||
* Authors: Jan Arne Petersen <jpetersen@uni-bonn.de>
|
||||
* David Hampton <hampton@employees.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -24,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "gnc-tree-model-account.h"
|
||||
|
||||
@@ -33,6 +35,7 @@
|
||||
#include "gnc-commodity.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-ui-util.h"
|
||||
#include "messages.h"
|
||||
|
||||
#define TREE_MODEL_ACCOUNT_CM_CLASS "tree-model-account"
|
||||
|
||||
@@ -77,11 +80,12 @@ static gboolean gnc_tree_model_account_iter_parent (GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
GtkTreeIter *child);
|
||||
|
||||
static gpointer account_row_inserted (Account *account,
|
||||
gpointer data);
|
||||
void gnc_tree_model_account_event_handler (GUID *entity, QofIdType type,
|
||||
GNCEngineEventType event_type,
|
||||
gpointer user_data);
|
||||
static void gnc_tree_model_account_set_toplevel (GncTreeModelAccount *model,
|
||||
Account *toplevel);
|
||||
|
||||
static void gnc_tree_model_account_event_handler (GUID *entity, QofIdType type,
|
||||
GNCEngineEventType event_type,
|
||||
gpointer user_data);
|
||||
|
||||
struct GncTreeModelAccountPrivate
|
||||
{
|
||||
@@ -90,6 +94,11 @@ struct GncTreeModelAccountPrivate
|
||||
gint event_handler_id;
|
||||
};
|
||||
|
||||
|
||||
/************************************************************/
|
||||
/* g_object required functions */
|
||||
/************************************************************/
|
||||
|
||||
static GtkObjectClass *parent_class = NULL;
|
||||
|
||||
GType
|
||||
@@ -200,6 +209,11 @@ gnc_tree_model_account_destroy (GtkObject *object)
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
|
||||
/************************************************************/
|
||||
/* New Model Creation */
|
||||
/************************************************************/
|
||||
|
||||
GtkTreeModel *
|
||||
gnc_tree_model_account_new (AccountGroup *group)
|
||||
{
|
||||
@@ -222,6 +236,13 @@ gnc_tree_model_account_new (AccountGroup *group)
|
||||
priv = model->priv;
|
||||
priv->root = group;
|
||||
|
||||
{
|
||||
Account *account;
|
||||
|
||||
account = xaccMallocAccount(gnc_get_current_book());
|
||||
gnc_tree_model_account_set_toplevel (model, account);
|
||||
}
|
||||
|
||||
priv->event_handler_id =
|
||||
gnc_engine_register_event_handler (gnc_tree_model_account_event_handler, model);
|
||||
|
||||
@@ -230,152 +251,44 @@ gnc_tree_model_account_new (AccountGroup *group)
|
||||
return GTK_TREE_MODEL (model);
|
||||
}
|
||||
|
||||
void
|
||||
gnc_tree_model_account_set_root (GncTreeModelAccount *model,
|
||||
AccountGroup *group)
|
||||
|
||||
/************************************************************/
|
||||
/* Gnc Tree Model Debugging Utility Function */
|
||||
/************************************************************/
|
||||
|
||||
#define ITER_STRING_LEN 128
|
||||
|
||||
static const gchar *
|
||||
iter_to_string (GtkTreeIter *iter)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
gint i;
|
||||
#ifdef G_THREADS_ENABLED
|
||||
static GStaticPrivate gtmits_buffer_key = G_STATIC_PRIVATE_INIT;
|
||||
gchar *string;
|
||||
|
||||
ENTER("model %p, group %p", model, group);
|
||||
g_return_if_fail (model != NULL);
|
||||
g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model));
|
||||
string = g_static_private_get (>mits_buffer_key);
|
||||
if (string == NULL) {
|
||||
string = malloc(ITER_STRING_LEN + 1);
|
||||
g_static_private_set (>mits_buffer_key, string, g_free);
|
||||
}
|
||||
#else
|
||||
static char string[ITER_STRING_LEN + 1];
|
||||
#endif
|
||||
|
||||
DEBUG("old root %p", model->priv->root);
|
||||
if (model->priv->root != NULL) {
|
||||
path = gtk_tree_path_new_first ();
|
||||
if (model->priv->toplevel != NULL) {
|
||||
gtk_tree_path_append_index (path, 0);
|
||||
}
|
||||
for (i = 0; i < xaccGroupGetNumAccounts (model->priv->root); i++) {
|
||||
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
|
||||
}
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
model->priv->root = group;
|
||||
|
||||
if (model->priv->root != NULL) {
|
||||
xaccGroupForEachAccount (model->priv->root, account_row_inserted, model, TRUE);
|
||||
}
|
||||
LEAVE("new root %p", model->priv->root);
|
||||
if (iter)
|
||||
snprintf(string, ITER_STRING_LEN,
|
||||
"[stamp:%x data:%p (%s), %p, %d]",
|
||||
iter->stamp, iter->user_data,
|
||||
xaccAccountGetName ((Account *) iter->user_data),
|
||||
iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
else
|
||||
strcpy(string, "(null)");
|
||||
return string;
|
||||
}
|
||||
|
||||
Account *
|
||||
gnc_tree_model_account_get_account (GncTreeModelAccount *model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL);
|
||||
g_return_val_if_fail (iter != NULL, NULL);
|
||||
g_return_val_if_fail (iter->user_data != NULL, NULL);
|
||||
g_return_val_if_fail (iter->stamp == model->stamp, NULL);
|
||||
|
||||
return (Account *) iter->user_data;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_tree_model_account_set_toplevel (GncTreeModelAccount *model,
|
||||
Account *toplevel)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
gint i;
|
||||
GtkTreeIter iter;
|
||||
|
||||
ENTER("model %p, toplevel %p", model, toplevel);
|
||||
g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model));
|
||||
|
||||
DEBUG("old toplevel %p", model->priv->toplevel);
|
||||
if (model->priv->toplevel != NULL) {
|
||||
path = gtk_tree_path_new_first ();
|
||||
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
|
||||
gtk_tree_path_free (path);
|
||||
} else {
|
||||
path = gtk_tree_path_new_first ();
|
||||
for (i = 0; i < xaccGroupGetNumAccounts (model->priv->root); i++) {
|
||||
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
|
||||
}
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
model->priv->toplevel = toplevel;
|
||||
|
||||
if (model->priv->toplevel != NULL) {
|
||||
path = gtk_tree_path_new_first ();
|
||||
gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
|
||||
gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
if (model->priv->root != NULL) {
|
||||
xaccGroupForEachAccount (model->priv->root, account_row_inserted, model, TRUE);
|
||||
}
|
||||
LEAVE("new toplevel %p", model->priv->root);
|
||||
}
|
||||
|
||||
Account *
|
||||
gnc_tree_model_account_get_toplevel (GncTreeModelAccount *model)
|
||||
{
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL);
|
||||
|
||||
return model->priv->toplevel;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_tree_model_account_get_iter_from_account (GncTreeModelAccount *model,
|
||||
Account *account,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
AccountGroup *group;
|
||||
gint i;
|
||||
|
||||
ENTER("model %p, account %p, iter %p", model, account, iter);
|
||||
g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model));
|
||||
g_return_if_fail (account != NULL);
|
||||
g_return_if_fail (iter != NULL);
|
||||
|
||||
iter->user_data = account;
|
||||
iter->stamp = model->stamp;
|
||||
|
||||
if (account == model->priv->toplevel) {
|
||||
iter->user_data2 = NULL;
|
||||
iter->user_data3 = GINT_TO_POINTER (0);
|
||||
return;
|
||||
}
|
||||
|
||||
group = xaccAccountGetParent (account);
|
||||
|
||||
for (i = 0; i < xaccGroupGetNumAccounts (group); i++) {
|
||||
if (xaccGroupGetAccount (group, i) == account) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iter->user_data2 = group;
|
||||
iter->user_data3 = GINT_TO_POINTER (i);
|
||||
LEAVE("iter [stamp:%x data:%p, %p, %d]", iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
}
|
||||
|
||||
GtkTreePath *
|
||||
gnc_tree_model_account_get_path_from_account (GncTreeModelAccount *model,
|
||||
Account *account)
|
||||
{
|
||||
GtkTreeIter tree_iter;
|
||||
GtkTreePath *tree_path;
|
||||
|
||||
ENTER("model %p, account %p", model, account);
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL);
|
||||
g_return_val_if_fail (account != NULL, NULL);
|
||||
|
||||
gnc_tree_model_account_get_iter_from_account (model, account, &tree_iter);
|
||||
tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &tree_iter);
|
||||
if (tree_path) {
|
||||
gchar *path_string = gtk_tree_path_to_string(tree_path);
|
||||
LEAVE("path (2) %s", path_string);
|
||||
g_free(path_string);
|
||||
}
|
||||
return tree_path;
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
/* Gtk Tree Model Required Interface Functions */
|
||||
/************************************************************/
|
||||
|
||||
static void
|
||||
gnc_tree_model_account_tree_model_init (GtkTreeModelIface *iface)
|
||||
@@ -487,7 +400,7 @@ gnc_tree_model_account_get_iter (GtkTreeModel *tree_model,
|
||||
iter->user_data3 = GINT_TO_POINTER (0);
|
||||
iter->stamp = model->stamp;
|
||||
|
||||
LEAVE("iter (1) [stamp:%x data:%p, %p, %d]", iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (1) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -525,7 +438,7 @@ gnc_tree_model_account_get_iter (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = group;
|
||||
iter->user_data3 = GINT_TO_POINTER (indices[i - 1]);
|
||||
|
||||
LEAVE("iter (5) [stamp:%x data:%p, %p, %d]", iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (5) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -540,8 +453,7 @@ gnc_tree_model_account_get_path (GtkTreeModel *tree_model,
|
||||
gint i;
|
||||
gboolean found, finished = FALSE;
|
||||
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d]", model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
ENTER("model %p, iter %s", model, iter_to_string(iter));
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL);
|
||||
g_return_val_if_fail (iter != NULL, NULL);
|
||||
g_return_val_if_fail (iter->user_data != NULL, NULL);
|
||||
@@ -616,8 +528,8 @@ gnc_tree_model_account_get_value (GtkTreeModel *tree_model,
|
||||
gboolean negative; /* used to set "defecit style" aka red numbers */
|
||||
gchar *string;
|
||||
|
||||
//ENTER("model %p, iter [stamp:%x data:%p, %p, %d], col %d", tree_model,
|
||||
// iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3), column);
|
||||
// ENTER("model %p, iter %s, col %d", tree_model,
|
||||
// iter_to_string(iter), column);
|
||||
g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model));
|
||||
g_return_if_fail (iter != NULL);
|
||||
g_return_if_fail (iter->user_data != NULL);
|
||||
@@ -628,7 +540,10 @@ gnc_tree_model_account_get_value (GtkTreeModel *tree_model,
|
||||
switch (column) {
|
||||
case GNC_TREE_MODEL_ACCOUNT_COL_NAME:
|
||||
g_value_init (value, G_TYPE_STRING);
|
||||
g_value_set_string (value, xaccAccountGetName (account));
|
||||
if (account == model->priv->toplevel)
|
||||
g_value_set_string (value, _("New top level account"));
|
||||
else
|
||||
g_value_set_string (value, xaccAccountGetName (account));
|
||||
break;
|
||||
case GNC_TREE_MODEL_ACCOUNT_COL_TYPE:
|
||||
g_value_init (value, G_TYPE_STRING);
|
||||
@@ -802,8 +717,7 @@ gnc_tree_model_account_iter_next (GtkTreeModel *tree_model,
|
||||
AccountGroup *group;
|
||||
gint i;
|
||||
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d]", tree_model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
ENTER("model %p, iter %s", tree_model, iter_to_string(iter));
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), FALSE);
|
||||
g_return_val_if_fail (iter != NULL, FALSE);
|
||||
g_return_val_if_fail (iter->user_data != NULL, FALSE);
|
||||
@@ -836,8 +750,7 @@ gnc_tree_model_account_iter_next (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = group;
|
||||
iter->user_data3 = GINT_TO_POINTER (i + 1);
|
||||
|
||||
LEAVE("iter [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -851,12 +764,10 @@ gnc_tree_model_account_iter_children (GtkTreeModel *tree_model,
|
||||
AccountGroup *group;
|
||||
|
||||
if (parent) {
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d], parent [stamp:%x data:%p, %p, %d]", tree_model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3),
|
||||
parent->stamp, parent->user_data, parent->user_data2, GPOINTER_TO_INT(parent->user_data3));
|
||||
ENTER("model %p, iter %p (to be filed in), parent %s",
|
||||
tree_model, iter, iter_to_string(parent));
|
||||
} else {
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d], parent (null)", tree_model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
ENTER("model %p, iter %p (to be filed in), parent (null)", tree_model, iter);
|
||||
}
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (tree_model), FALSE);
|
||||
|
||||
@@ -868,8 +779,7 @@ gnc_tree_model_account_iter_children (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = NULL;
|
||||
iter->user_data3 = GINT_TO_POINTER (0);
|
||||
iter->stamp = model->stamp;
|
||||
LEAVE("iter (1) [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (1) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
} else if (parent->user_data == model->priv->toplevel) {
|
||||
parent = NULL;
|
||||
@@ -895,8 +805,7 @@ gnc_tree_model_account_iter_children (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = model->priv->root;
|
||||
iter->user_data3 = GINT_TO_POINTER (0);
|
||||
iter->stamp = model->stamp;
|
||||
LEAVE("iter (2) [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (2) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -924,8 +833,7 @@ gnc_tree_model_account_iter_children (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = group;
|
||||
iter->user_data3 = GINT_TO_POINTER (0);
|
||||
iter->stamp = model->stamp;
|
||||
LEAVE("iter (3) [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (3) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -936,8 +844,7 @@ gnc_tree_model_account_iter_has_child (GtkTreeModel *tree_model,
|
||||
GncTreeModelAccount *model;
|
||||
AccountGroup *group;
|
||||
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d]", tree_model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
ENTER("model %p, iter %s", tree_model, iter_to_string(iter));
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (tree_model), FALSE);
|
||||
|
||||
model = GNC_TREE_MODEL_ACCOUNT (tree_model);
|
||||
@@ -968,8 +875,7 @@ gnc_tree_model_account_iter_n_children (GtkTreeModel *tree_model,
|
||||
GncTreeModelAccount *model;
|
||||
AccountGroup *group;
|
||||
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d]", tree_model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
ENTER("model %p, iter %s", tree_model, iter_to_string(iter));
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (tree_model), FALSE);
|
||||
|
||||
model = GNC_TREE_MODEL_ACCOUNT (tree_model);
|
||||
@@ -1009,14 +915,16 @@ gnc_tree_model_account_iter_nth_child (GtkTreeModel *tree_model,
|
||||
AccountGroup *group;
|
||||
|
||||
if (parent) {
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d], parent [stamp:%x data:%p, %p, %d], n %d",
|
||||
tree_model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3),
|
||||
parent->stamp, parent->user_data, parent->user_data2, GPOINTER_TO_INT(parent->user_data3), n);
|
||||
gchar *parent_string;
|
||||
|
||||
parent_string = strdup(iter_to_string(parent));
|
||||
ENTER("model %p, iter %s, parent %s, n %d",
|
||||
tree_model, iter_to_string(iter),
|
||||
parent_string, n);
|
||||
g_free(parent_string);
|
||||
} else {
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d], parent (null), n %d",
|
||||
tree_model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3), n);
|
||||
ENTER("model %p, iter %s, parent (null), n %d",
|
||||
tree_model, iter_to_string(iter), n);
|
||||
}
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (tree_model), FALSE);
|
||||
|
||||
@@ -1033,8 +941,7 @@ gnc_tree_model_account_iter_nth_child (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = NULL;
|
||||
iter->user_data3 = GINT_TO_POINTER (0);
|
||||
iter->stamp = model->stamp;
|
||||
LEAVE("iter (1) [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (1) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -1051,8 +958,7 @@ gnc_tree_model_account_iter_nth_child (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = model->priv->root;
|
||||
iter->user_data3 = GINT_TO_POINTER (n);
|
||||
iter->stamp = model->stamp;
|
||||
LEAVE("iter (2) [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (2) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1083,8 +989,7 @@ gnc_tree_model_account_iter_nth_child (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = group;
|
||||
iter->user_data3 = GINT_TO_POINTER (n);
|
||||
iter->stamp = model->stamp;
|
||||
LEAVE("iter (3) [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (3) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1099,14 +1004,16 @@ gnc_tree_model_account_iter_parent (GtkTreeModel *tree_model,
|
||||
gint i;
|
||||
|
||||
if (child) {
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d], child [stamp:%x data:%p, %p, %d]",
|
||||
tree_model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3),
|
||||
child->stamp, child->user_data, child->user_data2, GPOINTER_TO_INT(child->user_data3));
|
||||
gchar *child_string;
|
||||
|
||||
child_string = strdup(iter_to_string(child));
|
||||
ENTER("model %p, iter %s, child %s",
|
||||
tree_model, iter_to_string(iter),
|
||||
child_string);
|
||||
g_free(child_string);
|
||||
} else {
|
||||
ENTER("model %p, iter [stamp:%x data:%p, %p, %d], child (null)",
|
||||
tree_model,
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
ENTER("model %p, iter %s, child (null)",
|
||||
tree_model, iter_to_string(iter));
|
||||
}
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (tree_model), FALSE);
|
||||
|
||||
@@ -1133,8 +1040,7 @@ gnc_tree_model_account_iter_parent (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = NULL;
|
||||
iter->user_data3 = GINT_TO_POINTER (0);
|
||||
iter->stamp = model->stamp;
|
||||
LEAVE("iter (1) [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (1) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
} else {
|
||||
iter->stamp = 0;
|
||||
@@ -1149,8 +1055,7 @@ gnc_tree_model_account_iter_parent (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = group;
|
||||
iter->user_data3 = GINT_TO_POINTER (i);
|
||||
iter->stamp = model->stamp;
|
||||
LEAVE("iter (2) [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (2) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -1160,8 +1065,7 @@ gnc_tree_model_account_iter_parent (GtkTreeModel *tree_model,
|
||||
iter->user_data2 = NULL;
|
||||
iter->user_data3 = GINT_TO_POINTER (0);
|
||||
iter->stamp = model->stamp;
|
||||
LEAVE("iter (2) [stamp:%x data:%p, %p, %d]",
|
||||
iter->stamp, iter->user_data, iter->user_data2, GPOINTER_TO_INT(iter->user_data3));
|
||||
LEAVE("iter (3) %s", iter_to_string(iter));
|
||||
return TRUE;
|
||||
}
|
||||
iter->stamp = 0;
|
||||
@@ -1169,6 +1073,11 @@ gnc_tree_model_account_iter_parent (GtkTreeModel *tree_model,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************/
|
||||
/* Account Tree View Root Functions */
|
||||
/************************************************************/
|
||||
|
||||
static gpointer
|
||||
account_row_inserted (Account *account,
|
||||
gpointer data)
|
||||
@@ -1176,7 +1085,8 @@ account_row_inserted (Account *account,
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
ENTER("account %p, model %p", account, data);
|
||||
ENTER("account %p (%s), model %p",
|
||||
account, xaccAccountGetName(account), data);
|
||||
gnc_tree_model_account_get_iter_from_account (GNC_TREE_MODEL_ACCOUNT (data), account, &iter);
|
||||
|
||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter);
|
||||
@@ -1189,16 +1099,352 @@ account_row_inserted (Account *account,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new top node to the model. This node is for a pseudo-account
|
||||
* that lives above the main level accounts in the engine.
|
||||
*/
|
||||
Account *
|
||||
gnc_tree_model_account_get_toplevel (GncTreeModelAccount *model)
|
||||
{
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL);
|
||||
|
||||
return model->priv->toplevel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new top node to the model. This node is for a pseudo-account
|
||||
* that lives above the main level accounts in the engine.
|
||||
*/
|
||||
static void
|
||||
gnc_tree_model_account_set_toplevel (GncTreeModelAccount *model,
|
||||
Account *toplevel)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
gint i;
|
||||
GtkTreeIter iter;
|
||||
|
||||
ENTER("model %p, toplevel %p", model, toplevel);
|
||||
g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model));
|
||||
|
||||
DEBUG("old toplevel %p", model->priv->toplevel);
|
||||
if (model->priv->toplevel != NULL) {
|
||||
path = gtk_tree_path_new_first ();
|
||||
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
|
||||
gtk_tree_path_free (path);
|
||||
} else {
|
||||
path = gtk_tree_path_new_first ();
|
||||
for (i = 0; i < xaccGroupGetNumAccounts (model->priv->root); i++) {
|
||||
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
|
||||
}
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
DEBUG("set new toplevel %p", toplevel);
|
||||
model->priv->toplevel = toplevel;
|
||||
|
||||
if (model->priv->toplevel != NULL) {
|
||||
path = gtk_tree_path_new_first ();
|
||||
gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
|
||||
gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
if (model->priv->root != NULL) {
|
||||
xaccGroupForEachAccount (model->priv->root, account_row_inserted, model, TRUE);
|
||||
}
|
||||
LEAVE("new toplevel %p", model->priv->root);
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
/* Account Tree View Filter Functions */
|
||||
/************************************************************/
|
||||
|
||||
/*
|
||||
* DRH - THIS FUNCTION SHOULD BE REMOVED.
|
||||
*
|
||||
* This function is from before the account tree view existed. This
|
||||
* functionality should migrate there.
|
||||
*/
|
||||
void
|
||||
gnc_tree_model_account_set_root (GncTreeModelAccount *model,
|
||||
AccountGroup *group)
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
#if 0
|
||||
GtkTreePath *path;
|
||||
gint i;
|
||||
|
||||
ENTER("model %p, group %p", model, group);
|
||||
g_return_if_fail (model != NULL);
|
||||
g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model));
|
||||
|
||||
DEBUG("old root %p", model->priv->root);
|
||||
if (model->priv->root != NULL) {
|
||||
path = gtk_tree_path_new_first ();
|
||||
if (model->priv->toplevel != NULL) {
|
||||
gtk_tree_path_append_index (path, 0);
|
||||
}
|
||||
for (i = 0; i < xaccGroupGetNumAccounts (model->priv->root); i++) {
|
||||
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
|
||||
}
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
model->priv->root = group;
|
||||
|
||||
if (model->priv->root != NULL) {
|
||||
xaccGroupForEachAccount (model->priv->root, account_row_inserted, model, TRUE);
|
||||
}
|
||||
LEAVE("new root %p", model->priv->root);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a model/iter pair to a gnucash account. This routine should
|
||||
* only be called from an account tree view filter function.
|
||||
*/
|
||||
Account *
|
||||
gnc_tree_model_account_get_account (GncTreeModelAccount *model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL);
|
||||
g_return_val_if_fail (iter != NULL, NULL);
|
||||
g_return_val_if_fail (iter->user_data != NULL, NULL);
|
||||
g_return_val_if_fail (iter->stamp == model->stamp, NULL);
|
||||
|
||||
return (Account *) iter->user_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a model/account pair into a gtk_tree_model_iter. This
|
||||
* routine should only be called from the file
|
||||
* gnc-tree-view-account.c.
|
||||
*/
|
||||
void
|
||||
gnc_tree_model_account_get_iter_from_account (GncTreeModelAccount *model,
|
||||
Account *account,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
AccountGroup *group;
|
||||
gint i;
|
||||
|
||||
ENTER("model %p, account %p, iter %p", model, account, iter);
|
||||
g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model));
|
||||
g_return_if_fail (account != NULL);
|
||||
g_return_if_fail (iter != NULL);
|
||||
|
||||
iter->user_data = account;
|
||||
iter->stamp = model->stamp;
|
||||
|
||||
if (account == model->priv->toplevel) {
|
||||
iter->user_data2 = NULL;
|
||||
iter->user_data3 = GINT_TO_POINTER (0);
|
||||
return;
|
||||
}
|
||||
|
||||
group = xaccAccountGetParent (account);
|
||||
|
||||
for (i = 0; i < xaccGroupGetNumAccounts (group); i++) {
|
||||
if (xaccGroupGetAccount (group, i) == account) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iter->user_data2 = group;
|
||||
iter->user_data3 = GINT_TO_POINTER (i);
|
||||
LEAVE("iter %s", iter_to_string(iter));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a model/account pair into a gtk_tree_model_path. This
|
||||
* routine should only be called from the file
|
||||
* gnc-tree-view-account.c.
|
||||
*/
|
||||
GtkTreePath *
|
||||
gnc_tree_model_account_get_path_from_account (GncTreeModelAccount *model,
|
||||
Account *account)
|
||||
{
|
||||
GtkTreeIter tree_iter;
|
||||
GtkTreePath *tree_path;
|
||||
|
||||
ENTER("model %p, account %p", model, account);
|
||||
g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL);
|
||||
g_return_val_if_fail (account != NULL, NULL);
|
||||
|
||||
gnc_tree_model_account_get_iter_from_account (model, account, &tree_iter);
|
||||
tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &tree_iter);
|
||||
if (tree_path) {
|
||||
gchar *path_string = gtk_tree_path_to_string(tree_path);
|
||||
LEAVE("path (2) %s", path_string);
|
||||
g_free(path_string);
|
||||
}
|
||||
return tree_path;
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
/* Account Tree Model - Engine Event Handling Functions */
|
||||
/************************************************************/
|
||||
|
||||
typedef struct _remove_data {
|
||||
GUID guid;
|
||||
GncTreeModelAccount *model;
|
||||
GtkTreePath *path;
|
||||
} remove_data;
|
||||
|
||||
static GSList *pending_removals = NULL;
|
||||
|
||||
/** This function performs common updating to the model after an
|
||||
* account has been added or removed. The parent entry needs to be
|
||||
* tapped on the shoulder so that it can correctly update the
|
||||
* disclosure triangle (first added child/last removed child) or
|
||||
* possibly rebuild its child list of that level of accounts is
|
||||
* visible.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param model The account tree model containing the account that
|
||||
* has been added or deleted.
|
||||
*
|
||||
* @param path The path to the newly added item, or the just removed
|
||||
* item.
|
||||
*/
|
||||
static void
|
||||
gnc_tree_model_account_path_changed (GncTreeModelAccount *model,
|
||||
GtkTreePath *path)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_path_up (path)) {
|
||||
gtk_tree_model_get_iter (GTK_TREE_MODEL(model), &iter, path);
|
||||
gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL(model), path, &iter);
|
||||
}
|
||||
|
||||
do {
|
||||
model->stamp++;
|
||||
} while (model->stamp == 0);
|
||||
}
|
||||
|
||||
|
||||
/** This function is a helper routine for the following
|
||||
* gnc_tree_model_account_event_handler() function. It is called
|
||||
* from an iterator over all the pending account removals, and is
|
||||
* responsible for selecting the right item(s), deleting it from the
|
||||
* pending list, and then sending the "row_deleted" signal to any/all
|
||||
* parent models.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param data An item in the pending deletion list.
|
||||
*
|
||||
* @param entity The guid value of the destroyed item.
|
||||
*/
|
||||
static void
|
||||
gnc_tree_model_account_delete_event_helper (remove_data *data,
|
||||
GUID *entity)
|
||||
{
|
||||
if (!guid_equal(&data->guid, entity))
|
||||
return;
|
||||
|
||||
pending_removals = g_slist_remove (pending_removals, data);
|
||||
|
||||
gtk_tree_model_row_deleted (GTK_TREE_MODEL(data->model), data->path);
|
||||
gnc_tree_model_account_path_changed (data->model, data->path);
|
||||
gtk_tree_path_free(data->path);
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
|
||||
/** This function is the handler for all event messages from the
|
||||
* engine. Its purpose is to update the account tree model any time
|
||||
* an account is added to the engine or deleted from the engine.
|
||||
* This change to the model is then propagated to any/all overlying
|
||||
* filters and views. This function listens to the ADD, REMOVE, and
|
||||
* DESTROY events.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @warning There is a "Catch 22" situation here.
|
||||
* gtk_tree_model_row_deleted() can't be called until after the item
|
||||
* has been deleted from the real model (which is the engine's
|
||||
* account tree for us), but once the account has been deleted from
|
||||
* the engine we have no way to determine the path to pass to
|
||||
* row_deleted(). This is a PITA, but the only ither choice is to
|
||||
* have this model mirror the engine's accounts instead of
|
||||
* referencing them directly.
|
||||
*
|
||||
* @param entity The guid of the affected item.
|
||||
*
|
||||
* @param type The type of the affected item. This function only
|
||||
* cares about items of type "account".
|
||||
*
|
||||
* @param event type The type of the event. This function only cares
|
||||
* about items of type ADD, REMOVE, and DESTROY.
|
||||
*
|
||||
* @param user_data A pointer to the account tree model.
|
||||
*/
|
||||
void gnc_tree_model_account_event_handler (GUID *entity, QofIdType type,
|
||||
GNCEngineEventType event_type,
|
||||
gpointer user_data)
|
||||
{
|
||||
GncTreeModelAccount *model;
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
Account *account;
|
||||
remove_data *data;
|
||||
const gchar *account_name;
|
||||
|
||||
/* hard failures */
|
||||
g_return_if_fail(GNC_IS_TREE_MODEL_ACCOUNT(user_data));
|
||||
|
||||
/* soft failures */
|
||||
if (safe_strcmp(type, GNC_ID_ACCOUNT) != 0)
|
||||
return;
|
||||
|
||||
ENTER("entity %p of type %s, event %d, model %p",
|
||||
entity, type, event_type, user_data);
|
||||
model = (GncTreeModelAccount *)user_data;
|
||||
do {
|
||||
model->stamp++;
|
||||
} while (model->stamp == 0);
|
||||
|
||||
/* Get the account.*/
|
||||
/* DRH - Put the book in the model private data so this code
|
||||
* supports multiple simultaneous books. */
|
||||
account = xaccAccountLookup (entity, gnc_get_current_book ());
|
||||
account_name = xaccAccountGetName(account);
|
||||
|
||||
switch (event_type) {
|
||||
case GNC_EVENT_ADD:
|
||||
/* Tell the filters/views where the new account was added. */
|
||||
DEBUG("create account %p (%s)", account, account_name);
|
||||
gnc_tree_model_account_get_iter_from_account (model, account, &iter);
|
||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter);
|
||||
gtk_tree_model_row_inserted (GTK_TREE_MODEL(model), path, &iter);
|
||||
gnc_tree_model_account_path_changed (model, path);
|
||||
gtk_tree_path_free(path);
|
||||
break;
|
||||
|
||||
case GNC_EVENT_REMOVE:
|
||||
/* Record the path of this account for later use in destruction */
|
||||
DEBUG("remove account %p (%s)", account, account_name);
|
||||
data = malloc(sizeof(*data));
|
||||
data->guid = *entity;
|
||||
data->model = model;
|
||||
data->path = gnc_tree_model_account_get_path_from_account (model,
|
||||
account);
|
||||
pending_removals = g_slist_append (pending_removals, data);
|
||||
LEAVE(" ");
|
||||
return;
|
||||
|
||||
case GNC_EVENT_DESTROY:
|
||||
/* Tell the filters/view the account has been deleted. */
|
||||
DEBUG("destroy account %p (%s)", account, account_name);
|
||||
g_slist_foreach (pending_removals,
|
||||
(GFunc)gnc_tree_model_account_delete_event_helper,
|
||||
entity);
|
||||
break;
|
||||
|
||||
default:
|
||||
LEAVE("ignored event for %p (%s)", account, account_name);
|
||||
return;
|
||||
}
|
||||
LEAVE(" new stamp %u", model->stamp);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org
|
||||
*/
|
||||
|
||||
/** @addtogroup Engine
|
||||
@{ */
|
||||
/** @file gnc-tree-model-account.h
|
||||
@brief GtkTreeModel implementation for gnucash account tree.
|
||||
@author Jan Arne Petersen <jpetersen@uni-bonn.de>
|
||||
@author David Hampton <hampton@employees.org>
|
||||
*/
|
||||
|
||||
#ifndef __GNC_TREE_MODEL_ACCOUNT_H
|
||||
#define __GNC_TREE_MODEL_ACCOUNT_H
|
||||
|
||||
@@ -91,26 +99,92 @@ typedef struct {
|
||||
GtkObjectClass parent;
|
||||
} GncTreeModelAccountClass;
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
|
||||
/* Standard g_object type */
|
||||
GType gnc_tree_model_account_get_type (void);
|
||||
|
||||
|
||||
/** @name Account Tree Model Constructors */
|
||||
/** @{ */
|
||||
|
||||
GtkTreeModel *gnc_tree_model_account_new (AccountGroup *group);
|
||||
/** @} */
|
||||
|
||||
|
||||
/* OBSOLETE */
|
||||
void gnc_tree_model_account_set_root (GncTreeModelAccount *model,
|
||||
AccountGroup *group);
|
||||
|
||||
/** This function returns the account associated with the top level
|
||||
* pseudo-account. The gnucash engine does not have a single top
|
||||
* level account (it has a list of top level accounts), but this code
|
||||
* provides one so that it can be used with all parts of the gnucash
|
||||
* gui.
|
||||
*
|
||||
* @internal This function should only be called from gnc-tree-view-account.c.
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*
|
||||
* @return The top-level pseudo-account.
|
||||
*/
|
||||
Account *gnc_tree_model_account_get_toplevel (GncTreeModelAccount *model);
|
||||
|
||||
|
||||
/** @name Account Tree Model Get/Set Functions */
|
||||
/** @{ */
|
||||
|
||||
/** Convert a model/iter pair to a gnucash account. This routine should
|
||||
* only be called from an account tree view filter function. The
|
||||
* model and iter values will be provided as part of the call to the
|
||||
* filter.
|
||||
*
|
||||
* @param model A pointer to the account tree model.
|
||||
*
|
||||
* @param iter A gtk_tree_iter corresponding to a single account in
|
||||
* the model.
|
||||
*
|
||||
* @return A pointer to the corresponding account.
|
||||
*/
|
||||
Account *gnc_tree_model_account_get_account (GncTreeModelAccount *model,
|
||||
GtkTreeIter *iter);
|
||||
|
||||
void gnc_tree_model_account_set_toplevel (GncTreeModelAccount *model,
|
||||
Account *toplevel);
|
||||
Account *gnc_tree_model_account_get_toplevel (GncTreeModelAccount *model);
|
||||
|
||||
GtkTreePath *gnc_tree_model_account_get_path_from_account (GncTreeModelAccount *model,
|
||||
Account *account);
|
||||
/** Convert a model/account pair into a gtk_tree_model_iter. This
|
||||
* routine should only be called from the file
|
||||
* gnc-tree-view-account.c.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param model The model that an account belongs to.
|
||||
*
|
||||
* @param account The account to convert.
|
||||
*
|
||||
* @param iter A pointer to an iter. This iter will be rewritten to
|
||||
* contain the results of the query.
|
||||
*/
|
||||
void gnc_tree_model_account_get_iter_from_account (GncTreeModelAccount *model,
|
||||
Account *account,
|
||||
GtkTreeIter *iter);
|
||||
|
||||
|
||||
/** Convert a model/account pair into a gtk_tree_model_path. This
|
||||
* routine should only be called from the file
|
||||
* gnc-tree-view-account.c.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param model The model that an account belongs to.
|
||||
*
|
||||
* @param account The account to convert.
|
||||
*
|
||||
* @return A pointer to a path describing the account. It is the
|
||||
* responsibility of the caller to free this path when done.
|
||||
*/
|
||||
GtkTreePath *gnc_tree_model_account_get_path_from_account (GncTreeModelAccount *model,
|
||||
Account *account);
|
||||
/** @} */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GNC_TREE_MODEL_ACCOUNT_H */
|
||||
|
||||
@@ -39,26 +39,22 @@
|
||||
#include "gnc-ui-util.h"
|
||||
#include "messages.h"
|
||||
|
||||
#define TREE_VIEW_ACCOUNT_CM_CLASS "tree-view-account"
|
||||
|
||||
/** Static Globals *******************************************************/
|
||||
|
||||
/* This static indicates the debugging module that this .o belongs to. */
|
||||
static short module = MOD_GUI;
|
||||
|
||||
/** Declarations *********************************************************/
|
||||
static void gnc_tree_view_account_class_init (GncTreeViewAccountClass *klass);
|
||||
static void gnc_tree_view_account_init (GncTreeViewAccount *view);
|
||||
static void gnc_tree_view_account_finalize (GObject *object);
|
||||
static void gnc_tree_view_account_destroy (GtkObject *object);
|
||||
|
||||
#if 0
|
||||
static void gnc_tree_model_account_refresh_handler (GHashTable *changes,
|
||||
gpointer data);
|
||||
static void gnc_tree_model_account_refresh (GncTreeModelAccount *model);
|
||||
#endif
|
||||
|
||||
struct GncTreeViewAccountPrivate
|
||||
{
|
||||
AccountViewInfo avi;
|
||||
gboolean has_filter;
|
||||
};
|
||||
|
||||
typedef struct _gnc_tree_view_account_default {
|
||||
@@ -92,6 +88,10 @@ static gnc_tree_view_account_default gnc_tree_view_account_defaults[] = {
|
||||
};
|
||||
|
||||
|
||||
/************************************************************/
|
||||
/* g_object required functions */
|
||||
/************************************************************/
|
||||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
|
||||
GType
|
||||
@@ -141,11 +141,9 @@ gnc_tree_view_account_class_init (GncTreeViewAccountClass *klass)
|
||||
static void
|
||||
gnc_tree_view_account_init (GncTreeViewAccount *view)
|
||||
{
|
||||
ENTER(" ");
|
||||
view->priv = g_new0 (GncTreeViewAccountPrivate, 1);
|
||||
|
||||
gnc_init_account_view_info(&view->priv->avi);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -156,13 +154,11 @@ gnc_tree_view_account_finalize (GObject *object)
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (object));
|
||||
|
||||
ENTER("view %p", object);
|
||||
account_view = GNC_TREE_VIEW_ACCOUNT (object);
|
||||
g_free (account_view->priv);
|
||||
|
||||
if (G_OBJECT_CLASS (parent_class)->finalize)
|
||||
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -173,60 +169,56 @@ gnc_tree_view_account_destroy (GtkObject *object)
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (object));
|
||||
|
||||
ENTER("view %p", object);
|
||||
account_view = GNC_TREE_VIEW_ACCOUNT (object);
|
||||
|
||||
if (GTK_OBJECT_CLASS (parent_class)->destroy)
|
||||
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_tree_view_update_column_visibility_internal (GncTreeViewAccount *account_view)
|
||||
{
|
||||
GtkTreeView *tree_view;
|
||||
GtkTreeViewColumn *column;
|
||||
gint i;
|
||||
|
||||
ENTER(" ");
|
||||
tree_view = GTK_TREE_VIEW (account_view);
|
||||
/************************************************************/
|
||||
/* New View Creation */
|
||||
/************************************************************/
|
||||
|
||||
for (i = 0; i < NUM_ACCOUNT_FIELDS; i++) {
|
||||
DEBUG("setting column %d to %s", i, account_view->priv->avi.show_field[i] ? "visible" : "invisible");
|
||||
column = gtk_tree_view_get_column (tree_view, i);
|
||||
gtk_tree_view_column_set_visible (column, account_view->priv->avi.show_field[i]);
|
||||
}
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
static GtkTreeView *
|
||||
gnc_tree_view_account_new_internal (gboolean filterable)
|
||||
/*
|
||||
* Create a new account tree view with (optional) top level root node.
|
||||
* This view will be based on a model that is common to all view of
|
||||
* the same set of books, but will have its own private filter on that
|
||||
* model.
|
||||
*/
|
||||
GtkTreeView *
|
||||
gnc_tree_view_account_new (gboolean show_root)
|
||||
{
|
||||
GncTreeViewAccount *account_view;
|
||||
GtkTreeView *tree_view;
|
||||
GtkTreeModel *model, *filter_model;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkTreePath *virtual_root_path = NULL;
|
||||
gint i;
|
||||
|
||||
ENTER(" ");
|
||||
/* Create our view */
|
||||
account_view = g_object_new (GNC_TYPE_TREE_VIEW_ACCOUNT, NULL);
|
||||
tree_view = GTK_TREE_VIEW (account_view);
|
||||
|
||||
/* Create/get a pointer to the existing model for this set of books. */
|
||||
model = gnc_tree_model_account_new (gnc_book_get_group (gnc_get_current_book ()));
|
||||
if (filterable) {
|
||||
filter_model = egg_tree_model_filter_new (model, NULL);
|
||||
gtk_tree_view_set_model (tree_view, filter_model);
|
||||
} else {
|
||||
gtk_tree_view_set_model (tree_view, model);
|
||||
}
|
||||
|
||||
/* Set up the view private filter on the common model. */
|
||||
if (!show_root)
|
||||
virtual_root_path = gtk_tree_path_new_first ();
|
||||
filter_model = egg_tree_model_filter_new (model, virtual_root_path);
|
||||
gtk_tree_view_set_model (tree_view, filter_model);
|
||||
gtk_object_sink(GTK_OBJECT(model));
|
||||
account_view->priv->has_filter = filterable;
|
||||
if (virtual_root_path)
|
||||
gtk_tree_path_free(virtual_root_path);
|
||||
|
||||
/* Set column visibilities */
|
||||
gnc_tree_view_init_default_visibility(&account_view->priv->avi);
|
||||
/* Set default visibilities */
|
||||
gtk_tree_view_set_headers_visible (tree_view, FALSE);
|
||||
gnc_tree_view_account_init_view_info(&account_view->priv->avi);
|
||||
|
||||
/* Account name */
|
||||
/* Set up the "account name" column */
|
||||
column = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_title (column, gettext(gnc_tree_view_account_defaults[0].field_name));
|
||||
renderer = gtk_cell_renderer_pixbuf_new ();
|
||||
@@ -241,7 +233,7 @@ gnc_tree_view_account_new_internal (gboolean filterable)
|
||||
gtk_tree_view_column_set_resizable (column, TRUE);
|
||||
gtk_tree_view_set_expander_column (tree_view, column);
|
||||
|
||||
/* All other columns */
|
||||
/* Set up all other columns */
|
||||
for (i = 1; i < NUM_ACCOUNT_FIELDS; i++) {
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes (gettext(gnc_tree_view_account_defaults[i].field_name),
|
||||
@@ -266,69 +258,19 @@ gnc_tree_view_account_new_internal (gboolean filterable)
|
||||
gtk_tree_view_column_set_resizable (column, TRUE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
priv->component_id = gnc_register_gui_component (TREE_MODEL_ACCOUNT_CM_CLASS,
|
||||
gnc_tree_model_account_refresh_handler,
|
||||
NULL,
|
||||
model);
|
||||
|
||||
gnc_gui_component_watch_entity_type (priv->component_id,
|
||||
GNC_ID_ACCOUNT,
|
||||
GNC_EVENT_CREATE | GNC_EVENT_DESTROY);
|
||||
#endif
|
||||
|
||||
LEAVE("%p", tree_view);
|
||||
return tree_view;
|
||||
}
|
||||
|
||||
GtkTreeView *
|
||||
gnc_tree_view_account_new (void)
|
||||
{
|
||||
return gnc_tree_view_account_new_internal (FALSE);
|
||||
}
|
||||
|
||||
GtkTreeView *
|
||||
gnc_tree_view_account_new_filterable (void)
|
||||
{
|
||||
return gnc_tree_view_account_new_internal (TRUE);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* gnc_init_account_view_info *
|
||||
* initialize an account view info structure with default values *
|
||||
* *
|
||||
* Args: avi - structure to initialize *
|
||||
* Returns: nothing *
|
||||
\********************************************************************/
|
||||
void
|
||||
gnc_tree_view_init_default_visibility(AccountViewInfo *avi)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_ACCOUNT_FIELDS; i++)
|
||||
avi->show_field[i] = FALSE;
|
||||
|
||||
avi->show_field[ACCOUNT_NAME] = TRUE;
|
||||
avi->show_field[ACCOUNT_DESCRIPTION] = TRUE;
|
||||
avi->show_field[ACCOUNT_TOTAL] = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_tree_view_update_column_visibility (GncTreeViewAccount *account_view,
|
||||
AccountViewInfo *avi)
|
||||
{
|
||||
GncTreeViewAccountPrivate *priv;
|
||||
|
||||
ENTER("%p", account_view);
|
||||
g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(account_view));
|
||||
priv = account_view->priv;
|
||||
|
||||
priv->avi = *avi;
|
||||
|
||||
gnc_tree_view_update_column_visibility_internal (account_view);
|
||||
LEAVE(" ");
|
||||
}
|
||||
/************************************************************/
|
||||
/* Account Tree View Filter Functions */
|
||||
/************************************************************/
|
||||
|
||||
/*
|
||||
* Convert a column name to a numeric identifier. This is a
|
||||
* helper routine for the following function.
|
||||
*/
|
||||
static gint
|
||||
gnc_tree_view_account_pref_name_to_field (const char *pref_name)
|
||||
{
|
||||
@@ -341,8 +283,12 @@ gnc_tree_view_account_pref_name_to_field (const char *pref_name)
|
||||
return(GNC_TREE_MODEL_ACCOUNT_COL_NAME);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the list of columns that will be visible in an account tree view.
|
||||
*/
|
||||
void
|
||||
gnc_tree_view_account_configure_columns (GncTreeViewAccount *account_view, GSList *list)
|
||||
gnc_tree_view_account_configure_columns (GncTreeViewAccount *account_view,
|
||||
GSList *column_names)
|
||||
{
|
||||
AccountViewInfo new_avi;
|
||||
AccountFieldCode field;
|
||||
@@ -351,7 +297,7 @@ gnc_tree_view_account_configure_columns (GncTreeViewAccount *account_view, GSLis
|
||||
ENTER(" ");
|
||||
memset (&new_avi, 0, sizeof(new_avi));
|
||||
|
||||
for (node = list; node != NULL; node = node->next)
|
||||
for (node = column_names; node != NULL; node = node->next)
|
||||
{
|
||||
field = gnc_tree_view_account_pref_name_to_field(node->data);
|
||||
if (field < NUM_ACCOUNT_FIELDS)
|
||||
@@ -360,10 +306,76 @@ gnc_tree_view_account_configure_columns (GncTreeViewAccount *account_view, GSLis
|
||||
|
||||
new_avi.show_field[ACCOUNT_NAME] = TRUE;
|
||||
|
||||
gnc_tree_view_update_column_visibility (account_view, &new_avi);
|
||||
gnc_tree_view_account_set_view_info (account_view, &new_avi);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize an account view info structure with default values.
|
||||
*/
|
||||
void
|
||||
gnc_tree_view_account_init_view_info(AccountViewInfo *avi)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_ACCOUNT_FIELDS; i++)
|
||||
avi->show_field[i] = FALSE;
|
||||
|
||||
avi->show_field[ACCOUNT_NAME] = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a copy of the account view info structure in use by the
|
||||
* specified tree.
|
||||
*/
|
||||
void
|
||||
gnc_tree_view_account_get_view_info (GncTreeViewAccount *account_view,
|
||||
AccountViewInfo *avi)
|
||||
{
|
||||
GncTreeViewAccountPrivate *priv;
|
||||
|
||||
g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(account_view));
|
||||
priv = account_view->priv;
|
||||
|
||||
*avi = priv->avi;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the account view info data in use by the specified tree to
|
||||
* match the callers request.
|
||||
*
|
||||
* DRH - COMPATABILITY WARNING
|
||||
*
|
||||
* This function does not do anything with the 'include_type' field.
|
||||
* Should there be a automatic filter for backward compatability
|
||||
* that uses these flags, or should all uses of this be converted to
|
||||
* a eggtreemodelfilter?
|
||||
*/
|
||||
void
|
||||
gnc_tree_view_account_set_view_info (GncTreeViewAccount *account_view,
|
||||
AccountViewInfo *avi)
|
||||
{
|
||||
GtkTreeViewColumn *column;
|
||||
gint i;
|
||||
|
||||
ENTER("%p", account_view);
|
||||
g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(account_view));
|
||||
|
||||
account_view->priv->avi = *avi;
|
||||
|
||||
for (i = 0; i < NUM_ACCOUNT_FIELDS; i++) {
|
||||
column = gtk_tree_view_get_column (GTK_TREE_VIEW(account_view), i);
|
||||
gtk_tree_view_column_set_visible (column, avi->show_field[i]);
|
||||
}
|
||||
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an eggtreemodel visible filter on this account. This filter will be
|
||||
* called for each account that the tree is about to show, and the
|
||||
* account will be passed to the callback function.
|
||||
*/
|
||||
void
|
||||
gnc_tree_view_account_set_filter (GncTreeViewAccount *account_view,
|
||||
EggTreeModelFilterVisibleFunc func,
|
||||
@@ -372,71 +384,222 @@ gnc_tree_view_account_set_filter (GncTreeViewAccount *account_view,
|
||||
{
|
||||
GtkTreeModel *filter_model;
|
||||
|
||||
g_return_if_fail (account_view->priv->has_filter == TRUE);
|
||||
|
||||
ENTER("view %p, filter func %p, data %p, destroy %p",
|
||||
account_view, func, data, destroy);
|
||||
filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (account_view));
|
||||
egg_tree_model_filter_set_visible_func (EGG_TREE_MODEL_FILTER (filter_model),
|
||||
func, data, destroy);
|
||||
LEAVE(" ");
|
||||
}
|
||||
|
||||
gboolean
|
||||
gnc_tree_view_account_get_selected_account (GncTreeViewAccount *view,
|
||||
Account **account)
|
||||
/*
|
||||
* Forces the entire account tree to be re-evaluated for visibility.
|
||||
*/
|
||||
void
|
||||
gnc_tree_view_account_refilter (GncTreeViewAccount *view)
|
||||
{
|
||||
GtkTreeModel *filter_model;
|
||||
|
||||
g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
|
||||
|
||||
filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW(view));
|
||||
egg_tree_model_filter_refilter (EGG_TREE_MODEL_FILTER (filter_model));
|
||||
}
|
||||
|
||||
|
||||
/************************************************************/
|
||||
/* Account Tree View Get/Set Functions */
|
||||
/************************************************************/
|
||||
|
||||
/*
|
||||
* Return the account associated with the top level pseudo-account for
|
||||
* the tree.
|
||||
*/
|
||||
Account *
|
||||
gnc_tree_view_account_get_top_level (GncTreeViewAccount *view)
|
||||
{
|
||||
GtkTreeModel *model, *filter_model;
|
||||
|
||||
filter_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
|
||||
model = egg_tree_model_filter_get_model (EGG_TREE_MODEL_FILTER (filter_model));
|
||||
|
||||
return gnc_tree_model_account_get_toplevel (GNC_TREE_MODEL_ACCOUNT(model));
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the selected account from an account tree view. The
|
||||
* account tree must be in single selection mode.
|
||||
*/
|
||||
Account *
|
||||
gnc_tree_view_account_get_selected_account (GncTreeViewAccount *view)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter, child_iter;
|
||||
Account *account;
|
||||
|
||||
g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), FALSE);
|
||||
ENTER("view %p", view);
|
||||
g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
|
||||
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
|
||||
LEAVE("no account, get_selected failed");
|
||||
return FALSE;
|
||||
|
||||
if (!view->priv->has_filter) {
|
||||
*account = iter.user_data;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
egg_tree_model_filter_convert_iter_to_child_iter (EGG_TREE_MODEL_FILTER (model),
|
||||
&child_iter, &iter);
|
||||
account = child_iter.user_data;
|
||||
return TRUE;
|
||||
LEAVE("account %p (%s)", account, xaccAccountGetName (account));
|
||||
return account;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
gnc_tree_view_account_refresh_handler (GHashTable *changes, gpointer user_data)
|
||||
/*
|
||||
* Selects a single account in the account tree view. The account
|
||||
* tree must be in single selection mode.
|
||||
*/
|
||||
void
|
||||
gnc_tree_view_account_set_selected_account (GncTreeViewAccount *view,
|
||||
Account *account)
|
||||
{
|
||||
ENTER("changes %p, view %p", changes, user_data);
|
||||
g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (user_data));
|
||||
GtkTreeModel *model, *filter_model;
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreePath *path, *filter_path, *parent_path;
|
||||
|
||||
gnc_tree_view_account_refresh (GNC_TREE_VIEW_ACCOUNT (user_data));
|
||||
LEAVE(" ");
|
||||
ENTER("view %p, account %p (%s)", view,
|
||||
account, xaccAccountGetName (account));
|
||||
|
||||
/* Clear any existing selection. */
|
||||
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
|
||||
gtk_tree_selection_unselect_all (selection);
|
||||
|
||||
filter_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
|
||||
model = egg_tree_model_filter_get_model (EGG_TREE_MODEL_FILTER (filter_model));
|
||||
|
||||
path = gnc_tree_model_account_get_path_from_account (GNC_TREE_MODEL_ACCOUNT(model), account);
|
||||
if (path == NULL) {
|
||||
LEAVE("get_path_from_account failed");
|
||||
return;
|
||||
}
|
||||
{
|
||||
gchar *path_string = gtk_tree_path_to_string(path);
|
||||
DEBUG("tree path %s", path_string);
|
||||
g_free(path_string);
|
||||
}
|
||||
filter_path =
|
||||
egg_tree_model_filter_convert_child_path_to_path (EGG_TREE_MODEL_FILTER (filter_model),
|
||||
path);
|
||||
gtk_tree_path_free(path);
|
||||
if (filter_path == NULL) {
|
||||
LEAVE("convert_child_path_to_path failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* gtk_tree_view requires that a row be visible before it can be selected */
|
||||
parent_path = gtk_tree_path_copy (filter_path);
|
||||
if (gtk_tree_path_up (parent_path)) {
|
||||
/* This function is misnamed. It expands the actual item
|
||||
* specified, not the path to the item specified. I.E. It expands
|
||||
* one level too many, thus the get of the parent. */
|
||||
gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), parent_path);
|
||||
}
|
||||
gtk_tree_path_free(parent_path);
|
||||
|
||||
gtk_tree_selection_select_path (selection, filter_path);
|
||||
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), filter_path, NULL, FALSE, 0.0, 0.0);
|
||||
{
|
||||
gchar *path_string = gtk_tree_path_to_string(filter_path);
|
||||
LEAVE("filter path %s", path_string);
|
||||
g_free(path_string);
|
||||
}
|
||||
gtk_tree_path_free(filter_path);
|
||||
}
|
||||
|
||||
/*
|
||||
* This helper function is called once for each row in the tree view
|
||||
* that is currently selected. Its task is to an the corresponding
|
||||
* account to the end of a glist.
|
||||
*/
|
||||
static void
|
||||
gnc_tree_view_account_refresh (GncTreeViewAccount *view)
|
||||
get_selected_accounts_helper (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
gint i;
|
||||
|
||||
ENTER("view %p", view);
|
||||
if (view->priv->root == NULL) {
|
||||
return;
|
||||
}
|
||||
GList **return_list = data;
|
||||
Account *account;
|
||||
|
||||
path = gtk_tree_path_new_first ();
|
||||
if (view->priv->toplevel != NULL) {
|
||||
gtk_tree_path_append_index (path, 0);
|
||||
}
|
||||
for (i = 0; i < xaccGroupGetNumAccounts (view->priv->root); i++) {
|
||||
gtk_tree_view_row_deleted (GTK_TREE_VIEW (view), path);
|
||||
}
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
xaccGroupForEachAccount (view->priv->root, account_row_inserted, view, TRUE);
|
||||
LEAVE(" ");
|
||||
account = iter->user_data;
|
||||
*return_list = g_list_append(*return_list, account);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Given an account tree view, return a list of the selected accounts. The
|
||||
* account tree must be in multiple selection mode.
|
||||
*
|
||||
* Note: It is the responsibility of the caller to free the returned
|
||||
* list.
|
||||
*/
|
||||
GList *
|
||||
gnc_tree_view_account_get_selected_accounts (GncTreeViewAccount *view)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GList *return_list = NULL;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
|
||||
gtk_tree_selection_selected_foreach(selection, get_selected_accounts_helper, &return_list);
|
||||
return return_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an account tree view and a list of accounts, select those
|
||||
* accounts in the tree view.
|
||||
*/
|
||||
void
|
||||
gnc_tree_view_account_set_selected_accounts (GncTreeViewAccount *view,
|
||||
GList *account_list,
|
||||
gboolean show_last)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreePath *path, *parent_path;
|
||||
GtkTreeSelection *selection;
|
||||
GList *element;
|
||||
Account *account;
|
||||
|
||||
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
|
||||
model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
|
||||
|
||||
/* Clear any existing selection. */
|
||||
gtk_tree_selection_unselect_all (selection);
|
||||
gtk_tree_view_collapse_all (GTK_TREE_VIEW(view));
|
||||
|
||||
/* Now go select what the user requested. */
|
||||
for (element = account_list; element; ) {
|
||||
account = element->data;
|
||||
element = g_list_next(element);
|
||||
|
||||
path = gnc_tree_model_account_get_path_from_account (GNC_TREE_MODEL_ACCOUNT(model), account);
|
||||
if (path == NULL) {
|
||||
/*
|
||||
* Oops. Someone must have deleted this account and not cleaned
|
||||
* up all references to it.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/* gtk_tree_view requires that a row be visible before it can be selected */
|
||||
parent_path = gtk_tree_path_copy (path);
|
||||
if (gtk_tree_path_up (parent_path)) {
|
||||
/* This function is misnamed. It expands the actual item
|
||||
* specified, not the path to the item specified. I.E. It
|
||||
* expands one level too many, thus the get of the parent. */
|
||||
gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), parent_path);
|
||||
}
|
||||
gtk_tree_path_free(parent_path);
|
||||
|
||||
gtk_tree_selection_select_path (selection, path);
|
||||
if (show_last && (element == NULL))
|
||||
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), path, NULL, FALSE, 0.0, 0.0);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,13 @@
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @addtogroup Engine
|
||||
@{ */
|
||||
/** @file gnc-tree-view-account.h
|
||||
@brief GtkTreeView implementation for gnucash account tree.
|
||||
@author David Hampton <hampton@employees.org>
|
||||
*/
|
||||
|
||||
#ifndef __GNC_TREE_VIEW_ACCOUNT_H
|
||||
#define __GNC_TREE_VIEW_ACCOUNT_H
|
||||
|
||||
@@ -57,22 +64,218 @@ typedef struct {
|
||||
GtkTreeViewClass parent;
|
||||
} GncTreeViewAccountClass;
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
|
||||
/* Standard g_object type */
|
||||
GType gnc_tree_view_account_get_type (void);
|
||||
|
||||
GtkTreeView *gnc_tree_view_account_new (void);
|
||||
GtkTreeView *gnc_tree_view_account_new_filterable (void);
|
||||
|
||||
void gnc_tree_view_update_column_visibility (GncTreeViewAccount *account_view,
|
||||
/** @name Account Tree View Constructors */
|
||||
/** @{ */
|
||||
|
||||
/** Create a new account tree view. This view may or may not show a
|
||||
* pseudo top-level account. The gnucash engine does not have a
|
||||
* single top level account (it has a list of top level accounts),
|
||||
* but this code provides one so that it can be used with all parts
|
||||
* of the gnucash gui.
|
||||
*
|
||||
* @param show_root Show the pseudo top-level account in this view.
|
||||
*
|
||||
* @return A pointer to a new account tree view.
|
||||
*/
|
||||
GtkTreeView *gnc_tree_view_account_new (gboolean show_root);
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @name Account Tree View Configuration */
|
||||
/** @{ */
|
||||
|
||||
/** Configure (by name) the set of visible columns in an account tree
|
||||
* view. By default, only the account name column is show. The
|
||||
* avalible list of columns can be found in the file
|
||||
* gnc-tree-view-account.c
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*
|
||||
* @param column_names A list of column names to make visible.
|
||||
*/
|
||||
void gnc_tree_view_account_configure_columns (GncTreeViewAccount *account_view,
|
||||
GSList *column_names);
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @name Account Tree View Filtering */
|
||||
/** @{ */
|
||||
|
||||
/** Given pointers to an account tree and old style filter block, this
|
||||
* function will copy the current configuration of the account tree
|
||||
* widget into the data block. This may be used in conjunction with
|
||||
* the gnc_tree_view_account_set_view_info function to modify the
|
||||
* filters on an existing account tree.
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*
|
||||
* @param avi A pointer to an old style filter block to fill in.
|
||||
*/
|
||||
void gnc_tree_view_account_get_view_info (GncTreeViewAccount *account_view,
|
||||
AccountViewInfo *avi);
|
||||
void gnc_tree_view_init_default_visibility (AccountViewInfo *avi);
|
||||
void gnc_tree_view_account_configure_columns (GncTreeViewAccount *account_view, GSList *list);
|
||||
|
||||
/** Given pointers to an account tree and old style filter block, this
|
||||
* function will applies the settings specified to the current
|
||||
* configuration of the account tree widget. This may be used in
|
||||
* conjunction with the gnc_tree_view_account_get_view_info function
|
||||
* to modify the filters on an existing account tree.
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*
|
||||
* @param avi A pointer to an old style filter block to apply to the
|
||||
* view..
|
||||
*/
|
||||
void gnc_tree_view_account_set_view_info (GncTreeViewAccount *account_view,
|
||||
AccountViewInfo *avi);
|
||||
|
||||
/** Given a pointer to an old style filter block, initialize it to the
|
||||
* default values for an account tree. The defaults are to show all
|
||||
* types of accounts, and show only the account name column.
|
||||
*
|
||||
* @param avi A pointer to an old style filter block.
|
||||
*/
|
||||
void gnc_tree_view_account_init_view_info (AccountViewInfo *avi);
|
||||
|
||||
|
||||
/** This function attaches a filter function to the given account
|
||||
* tree. This function will be called for each account that the view
|
||||
* thinks should possibly show. The filter may perform any actions
|
||||
* necessary on the account to decide whether it should be shown or
|
||||
* not. (I.E. Check type, placeholder status, etc.) If the filter
|
||||
* returns TRUE then the account wil be displayed.
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*
|
||||
* @param func A filtration function that is called on individual
|
||||
* elements in the tree. If this function returns TRUE, the account
|
||||
* 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_account_set_filter (GncTreeViewAccount *account_view,
|
||||
EggTreeModelFilterVisibleFunc func,
|
||||
gpointer data,
|
||||
GtkDestroyNotify destroy);
|
||||
gboolean gnc_tree_view_account_get_selected_account (GncTreeViewAccount *view,
|
||||
Account **account);
|
||||
|
||||
|
||||
/** This function forces the account 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 accounts in gnucash.
|
||||
*
|
||||
* @note This calls a function in libegg that is annotated as being
|
||||
* slow. You have been warned.
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*/
|
||||
void gnc_tree_view_account_refilter (GncTreeViewAccount *view);
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @name Account Tree View Get/Set Functions */
|
||||
/** @{ */
|
||||
|
||||
/** This function returns the account associated with the top level
|
||||
* pseudo-account. The gnucash engine does not have a single top
|
||||
* level account (it has a list of top level accounts), but this code
|
||||
* provides one so that it can be used with all parts of the gnucash
|
||||
* gui.
|
||||
*
|
||||
* @note It only makes sense to call this function when the account
|
||||
* tree is created such that the "top level account" is visible. At
|
||||
* the time this was written, only the "New/Edit Account" dialog does
|
||||
* that.
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*
|
||||
* @return The top-level pseudo-account.
|
||||
*/
|
||||
Account * gnc_tree_view_account_get_top_level (GncTreeViewAccount *view);
|
||||
|
||||
|
||||
/** This function returns the account associated with the selected
|
||||
* item in the account tree view.
|
||||
*
|
||||
* @note It only makes sense to call this function when the account
|
||||
* tree is set to select a single item. There is a different
|
||||
* function to use when the tree supports multiple selections.
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*
|
||||
* @return The selected account, or NULL if no account was selected.
|
||||
*/
|
||||
Account * gnc_tree_view_account_get_selected_account (GncTreeViewAccount *view);
|
||||
|
||||
|
||||
/** This function selects an account in the account tree view. All
|
||||
* other accounts will be unselected. In addition, this function
|
||||
* collapses the entitre tree and then expands only the path to the
|
||||
* selected account, making the item easy to find. In general, this
|
||||
* routine only need be called when initially putting up a window
|
||||
* containing an account tree view widget.
|
||||
*
|
||||
* @note It only makes sense to call this function when the account
|
||||
* tree is set to select a single item. There is a different
|
||||
* function to use when the tree supports multiple selections.
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*
|
||||
* @param account A pointer to the account to select.
|
||||
*/
|
||||
void gnc_tree_view_account_set_selected_account (GncTreeViewAccount *view,
|
||||
Account *account);
|
||||
|
||||
|
||||
/** This function returns a list of the accounts associated with the
|
||||
* selected items in the account tree view.
|
||||
*
|
||||
* @note It only makes sense to call this function when the account
|
||||
* tree is set to select multiple items. There is a different
|
||||
* function to use when the tree supports single selection.
|
||||
*
|
||||
* @param account_view A pointer to an account tree view.
|
||||
*
|
||||
* @return A list of accounts, or NULL if no account was selected.
|
||||
*/
|
||||
GList * gnc_tree_view_account_get_selected_accounts (GncTreeViewAccount *view);
|
||||
|
||||
|
||||
/** This function selects a set of accounts in the account tree view.
|
||||
* All other accounts will be unselected. In addition, this function
|
||||
* collapses the entitre tree and then expands only the path to the
|
||||
* selected accounts, making them easy to find. In general, this
|
||||
* routine only need be called when initially putting up a window
|
||||
* containing an account tree view widget.
|
||||
*
|
||||
* @note It only makes sense to call this function when the account
|
||||
* 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 account_view A pointer to an account tree view.
|
||||
*
|
||||
* @param account A pointer to the account to select.
|
||||
*
|
||||
* @param show_last Force the window to scroll to the last account
|
||||
* selected.
|
||||
*/
|
||||
void gnc_tree_view_account_set_selected_accounts (GncTreeViewAccount *view,
|
||||
GList *account_list,
|
||||
gboolean show_last);
|
||||
/** @} */
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
Reference in New Issue
Block a user