[Gnucash-changes] Chris Shoemaker's fixes to add custom columns to an Account view.

David Hampton hampton at cvs.gnucash.org
Sun May 15 16:57:13 EDT 2005


Log Message:
-----------
Chris Shoemaker's fixes to add custom columns to an Account
view.  Various cleanups and fixes for memory leaks.

Tags:
----
gnucash-gnome2-dev

Modified Files:
--------------
    gnucash:
        ChangeLog
    gnucash/src/gnome:
        druid-hierarchy.c
    gnucash/src/gnome-utils:
        gnc-tree-model-account.c
        gnc-tree-view-account.c
        gnc-tree-view-account.h

Revision Data
-------------
Index: ChangeLog
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/ChangeLog,v
retrieving revision 1.1487.2.205
retrieving revision 1.1487.2.206
diff -LChangeLog -LChangeLog -u -r1.1487.2.205 -r1.1487.2.206
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,11 @@
+2005-05-15  David Hampton  <hampton at employees.org>
+
+	* src/gnome-utils/gnc-tree-view-account.[ch]:
+	* src/gnome-utils/gnc-tree-model-account.c:
+	* src/gnome/druid-hierarchy.c: Chris Shoemaker's fixes to add
+	custom columns to an Account view.  Various cleanups and fixes for
+	memory leaks.
+
 2005-05-10  David Hampton  <hampton at employees.org>
 
 	* src/gnome-search/gncmod-gnome-search.c: Don't try to load code
Index: druid-hierarchy.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/druid-hierarchy.c,v
retrieving revision 1.21.4.11
retrieving revision 1.21.4.12
diff -Lsrc/gnome/druid-hierarchy.c -Lsrc/gnome/druid-hierarchy.c -u -r1.21.4.11 -r1.21.4.12
--- src/gnome/druid-hierarchy.c
+++ src/gnome/druid-hierarchy.c
@@ -621,8 +621,7 @@
 	hierarchy_data *data = (hierarchy_data *)user_data;
 
 	g_return_if_fail (GTK_TREE_MODEL (model));
-	account = gnc_tree_view_account_get_account_from_column (tree_column,
-								 model, iter);
+	account = gnc_tree_view_account_get_account_from_iter (model, iter);
 
 	balance = get_final_balance (data->balance_hash, account);
 	if (gnc_reverse_balance (account))
Index: gnc-tree-view-account.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/Attic/gnc-tree-view-account.c,v
retrieving revision 1.1.2.17
retrieving revision 1.1.2.18
diff -Lsrc/gnome-utils/gnc-tree-view-account.c -Lsrc/gnome-utils/gnc-tree-view-account.c -u -r1.1.2.17 -r1.1.2.18
--- src/gnome-utils/gnc-tree-view-account.c
+++ src/gnome-utils/gnc-tree-view-account.c
@@ -53,9 +53,17 @@
 static void gnc_tree_view_account_finalize (GObject *object);
 static void gnc_tree_view_account_destroy (GtkObject *object);
 
+static gboolean gnc_tree_view_account_filter_helper (GtkTreeModel *model,
+                                                     GtkTreeIter *iter,
+                                                     gpointer data);
+
 struct GncTreeViewAccountPrivate
 {
-  AccountViewInfo avi;
+    AccountViewInfo avi;
+
+    gnc_tree_view_account_filter_func filter_fn;
+    gpointer                          filter_data;
+    GtkDestroyNotify                  filter_destroy;
 };
 
 /* Defined at the end of the file */
@@ -170,6 +178,7 @@
 gnc_tree_view_account_finalize (GObject *object)
 {
   GncTreeViewAccount *account_view;
+  GncTreeViewAccountPrivate *priv;
 
   ENTER("view %p", object);
   g_return_if_fail (object != NULL);
@@ -178,6 +187,12 @@
   account_view = GNC_TREE_VIEW_ACCOUNT (object);
   active_views = g_list_remove (active_views, account_view);
 
+  priv = account_view->priv;
+  if (priv->filter_destroy) {
+      priv->filter_destroy(priv->filter_data);
+      priv->filter_destroy = NULL;
+  }
+
   g_free (account_view->priv);
 
   if (G_OBJECT_CLASS (parent_class)->finalize)
@@ -403,8 +418,13 @@
   gtk_tree_view_set_headers_visible (tree_view, FALSE);
   gnc_tree_view_account_init_view_info(&account_view->priv->avi);
 
-  gnc_tree_view_common_create_columns (tree_view, "Accounts", GNC_STOCK_ACCOUNT,
+  gnc_tree_view_common_create_columns (tree_view, "Accounts", 
+                                       GNC_STOCK_ACCOUNT,
 				       view_column_defaults);
+  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (f_model),
+					  gnc_tree_view_account_filter_helper,
+					  account_view,
+					  NULL);
 
   gtk_widget_show(GTK_WIDGET(tree_view));
   LEAVE("%p", tree_view);
@@ -537,51 +557,29 @@
 }
 
 
-Account *
-gnc_tree_view_account_get_account_from_column (GtkTreeViewColumn *column,
-					       GtkTreeModel *s_model,
-					       GtkTreeIter  *s_iter)
-{
-  GtkTreeModel *model, *f_model;
-  GtkTreeIter iter, f_iter;
-  Account *account;
-
-  g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN(column), NULL);
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT(s_model), NULL);
-  g_return_val_if_fail (s_iter != NULL, NULL);
-
-  ENTER("column %p, s_model %p, s_iter %p", column, s_model, s_iter);
-  gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT(s_model),
-						  &f_iter,
-						  s_iter);
-  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
-						    &iter,
-						    &f_iter);
-  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
-  account = gnc_tree_model_account_get_account (GNC_TREE_MODEL_ACCOUNT(model), &iter);
-  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
-  return account;
-}
-
 /************************************************************/
 /*            Account Tree View Filter Functions            */
 /************************************************************/
 
 /*
- * Convert a column name to a numeric identifier.  This is a
- * helper routine for the following function.
+ * Convert a column name to a column index.  This index valid for the
+ * TreeView's list of TreeViewColumns.  When the column is a "builtin"
+ * TreeViewAccount column, then the index is also valid for the
+ * gnc_tree_view_account_defaults[] array.
+ *
+ *  Returns -1 when column is not found.
  */
 static gint
 gnc_tree_view_account_pref_name_to_field (const char *pref_name)
 {
   gint i;
-  g_return_val_if_fail ((pref_name != NULL), GNC_TREE_MODEL_ACCOUNT_COL_NAME);
+  g_return_val_if_fail (pref_name, -1);
 
   for (i = 0; i <= GNC_TREE_MODEL_ACCOUNT_COL_LAST_VISIBLE; i++)
     if (safe_strcmp(view_column_defaults[i].pref_name, pref_name) == 0)
       return i;
-  return(GNC_TREE_MODEL_ACCOUNT_COL_NAME);
+
+  return -1;
 }
 
 const char *
@@ -609,7 +607,7 @@
   ENTER(" ");
   memset (&new_avi, 0, sizeof(new_avi));
 
-  for (node = column_names; node != NULL; node = node->next)
+  for (node = column_names; node; node = node->next)
   {
     field = gnc_tree_view_account_pref_name_to_field(node->data);
     if (field <= GNC_TREE_MODEL_ACCOUNT_COL_LAST_VISIBLE)
@@ -664,6 +662,9 @@
  * Should there be a automatic filter for backward compatability
  * that uses these flags, or should all uses of this be converted to
  * a GtkTreeModelFilter?
+ *
+ * CAS - For now, I'll try the automatic filter approach by making
+ * this function use GtkTreeModelFilter.
  */
 void
 gnc_tree_view_account_set_view_info (GncTreeViewAccount *account_view,
@@ -671,6 +672,7 @@
 {
   GtkTreeViewColumn *column;
   gint i;
+  guint sel_bits = 0;
 
   ENTER("%p", account_view);
   g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(account_view));
@@ -683,23 +685,19 @@
     gtk_tree_view_column_set_visible (column, avi->show_field[i]);
   }
 
-  LEAVE(" ");
-}
-
-typedef struct {
-  gnc_tree_view_account_filter_func user_fn;
-  gpointer                          user_data;
-  GtkDestroyNotify                  user_destroy;
-} filter_user_data;
+  for (i = 0; i < NUM_ACCOUNT_TYPES; i++) {
+      sel_bits |= avi->include_type[i] ? (1 << i): 0;
+  }
 
-static void
-gnc_tree_view_account_filter_destroy (gpointer data)
-{
-  filter_user_data *fd = data;
+  /* FIXME: if we want to allow a truly empty bitfield, we'll have to fix
+     the callers who don't set the include_type fields. */
+  if (sel_bits) {
+      gnc_tree_view_account_set_filter(
+          account_view, gnc_tree_view_account_filter_by_type_selection, 
+          GUINT_TO_POINTER(sel_bits), NULL);
+  }
 
-  if (fd->user_destroy)
-    fd->user_destroy(fd->user_data);
-  g_free(fd);
+  LEAVE(" ");
 }
 
 static gboolean
@@ -708,19 +706,25 @@
 				     gpointer data)
 {
   Account *account;
-  filter_user_data *fd = data;
+  GncTreeViewAccount *view = data;
 
   g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), FALSE);
   g_return_val_if_fail (iter != NULL, FALSE);
 
-  account = gnc_tree_model_account_get_account (GNC_TREE_MODEL_ACCOUNT(model), iter);
-  return fd->user_fn(account, fd->user_data);
+  account = gnc_tree_model_account_get_account (
+      GNC_TREE_MODEL_ACCOUNT(model), iter);
+  
+  if (view->priv->filter_fn)
+      return view->priv->filter_fn(account, view->priv->filter_data);
+  else return TRUE;
 }
 
 /*
  * Set an GtkTreeModel 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.
+ *
+ * Use NULL as func to remove filter. 
  */
 void
 gnc_tree_view_account_set_filter (GncTreeViewAccount *view,
@@ -728,30 +732,22 @@
 				  gpointer data,
 				  GtkDestroyNotify destroy)
 {
-  GtkTreeModel *f_model, *s_model;
-  filter_user_data *fd = data;
+  GncTreeViewAccountPrivate *priv;
 
   ENTER("view %p, filter func %p, data %p, destroy %p",
 	view, func, data, destroy);
 
   g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
-  g_return_if_fail(func != NULL);
 
-  fd = g_malloc(sizeof(filter_user_data));
-  fd->user_fn      = func;
-  fd->user_data    = data;
-  fd->user_destroy = destroy;
-
-  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
-  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
-  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (f_model),
-					  gnc_tree_view_account_filter_helper,
-					  fd,
-					  gnc_tree_view_account_filter_destroy);
+  priv = view->priv;
+  if (priv->filter_destroy) {
+      priv->filter_destroy(priv->filter_data);
+  }
+  priv->filter_destroy = destroy;
+  priv->filter_data = data;
+  priv->filter_fn = func;  
 
-  /* Whack any existing levels. The top two levels have been created
-   * before this routine can be called. */
-  gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
+  gnc_tree_view_account_refilter(view);
   LEAVE(" ");
 }
 
@@ -770,6 +766,19 @@
   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
 }
 
+gboolean 
+gnc_tree_view_account_filter_by_type_selection(Account* acct, gpointer data)
+{
+    GNCAccountType acct_type;
+    guint sel_bits = GPOINTER_TO_UINT(data);
+
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acct), FALSE);
+    acct_type = xaccAccountGetType(acct);
+
+    /* Because of some silly '== TRUE' comparisons in treemodelfilter,
+       we have to return exactly TRUE */
+    return (sel_bits & (1 << acct_type)) ? TRUE : FALSE;
+}
 
 /************************************************************/
 /*           Account Tree View Get/Set Functions            */
@@ -837,6 +846,32 @@
     return account;
 }
 
+
+Account *
+gnc_tree_view_account_get_account_from_iter (GtkTreeModel *s_model,
+					     GtkTreeIter  *s_iter)
+{
+  GtkTreeModel *model, *f_model;
+  GtkTreeIter iter, f_iter;
+  Account *account;
+
+  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT(s_model), NULL);
+  g_return_val_if_fail (s_iter != NULL, NULL);
+
+  gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT(s_model),
+						  &f_iter,
+						  s_iter);
+  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
+  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
+						    &iter,
+						    &f_iter);
+  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
+  account = gnc_tree_model_account_get_account (GNC_TREE_MODEL_ACCOUNT(model), &iter);
+  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
+  return account;
+}
+
+
 /*
  * Retrieve the selected account from an account tree view.  The
  * account tree must be in single selection mode.
@@ -939,7 +974,7 @@
 
 /*
  * This helper function is called once for each row in the tree view
- * that is currently selected.  Its task is to an the corresponding
+ * that is currently selected.  Its task is to append the corresponding
  * account to the end of a glist.
  */
 static void
@@ -1140,6 +1175,8 @@
 /*         Account Tree View Add Column Functions           */
 /************************************************************/
 
+/* This function implements a custom mapping between an account's KVP
+ * and the cell renderer's 'text' property. */
 static void
 account_cell_kvp_data_func (GtkTreeViewColumn *tree_column,
 			    GtkCellRenderer *cell,
@@ -1147,29 +1184,18 @@
 			    GtkTreeIter *s_iter,
 			    gpointer key)
 {
-	GtkTreeModel *model, *f_model;
-	GtkTreeIter iter, f_iter;
-	Account *account;
-	kvp_frame * frame;
-
-	g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
-
-	gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
-							&f_iter, s_iter);
-
-	f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
-	gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
-							  &iter,
-							  &f_iter);
-
-	model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
-	account = gnc_tree_model_account_get_account (GNC_TREE_MODEL_ACCOUNT(model), &iter);
-	frame = xaccAccountGetSlots(account);
-
-	g_object_set (G_OBJECT (cell),
-		      "text", kvp_frame_get_string(frame, (gchar *)key),
-		      "xalign", 0.0,
-		      NULL);
+    Account *account;
+    kvp_frame * frame;
+    
+    g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
+    account = gnc_tree_view_account_get_account_from_iter(s_model, s_iter);
+    frame = xaccAccountGetSlots(account);
+    
+    g_object_set (G_OBJECT (cell),
+                  "text", kvp_frame_get_string(frame, (gchar *)key),
+                  "xalign", 0.0,
+                  NULL);
+    
 }
 
 
@@ -1178,21 +1204,95 @@
 				      const gchar *column_title,
 				      const gchar *kvp_key)
 {
-  GtkCellRenderer *renderer;
-  GtkTreeViewColumn *column;
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
 
-  g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view));
-  g_return_if_fail (kvp_key != NULL);
+    g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view));
+    g_return_if_fail (kvp_key != NULL);
+
+    renderer = gtk_cell_renderer_text_new ();
+    g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
 
-  renderer = gtk_cell_renderer_text_new ();
-  g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
-  column = gtk_tree_view_column_new_with_attributes (column_title,
-						     renderer,
-						     NULL);
-  gtk_tree_view_column_set_cell_data_func (column, renderer, 
-					   account_cell_kvp_data_func,
-					   g_strdup(kvp_key), g_free);
-  gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
+    column = gtk_tree_view_column_new_with_attributes (column_title,
+						       renderer, NULL);
+    gtk_tree_view_column_set_cell_data_func (column, renderer, 
+					     account_cell_kvp_data_func,
+					     g_strdup(kvp_key), g_free);
+    gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
+}
+
+static void col_edited_helper(GtkCellRendererText *cell, gchar *path_string, 
+                              gchar *new_text, gpointer _s_model)
+{
+    Account *account;
+    GtkTreeModel *s_model;
+    GtkTreeIter s_iter;
+    GncTreeViewAccountColumnTextEdited col_edited_cb;
+    GtkTreeViewColumn *col;
+
+    col_edited_cb = g_object_get_data(G_OBJECT(cell), 
+                                      "column_edited_callback");
+    col = GTK_TREE_VIEW_COLUMN(g_object_get_data(G_OBJECT(cell), 
+                                                 "column_view"));
+    s_model = GTK_TREE_MODEL(_s_model);
+
+    if (!gtk_tree_model_get_iter_from_string(s_model, &s_iter, path_string))
+        return;
+        
+    account = gnc_tree_view_account_get_account_from_iter(s_model, &s_iter);
+    col_edited_cb(account, col, new_text);
+}
+
+static void col_source_helper(GtkTreeViewColumn *col, GtkCellRenderer *cell,
+                              GtkTreeModel *s_model, GtkTreeIter *s_iter,
+                              gpointer _col_source_cb)
+{
+    Account *account;
+    gchar *text;
+    GncTreeViewAccountColumnSource col_source_cb;
+    
+    g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
+    col_source_cb = (GncTreeViewAccountColumnSource) _col_source_cb;
+    account = gnc_tree_view_account_get_account_from_iter(s_model, s_iter);
+    text = col_source_cb(account, col, cell);
+    g_object_set (G_OBJECT (cell), "text", text, "xalign", 0.0, NULL);
+    g_free(text);
+}
+
+ 
+GtkTreeViewColumn *
+gnc_tree_view_account_add_custom_column(GncTreeViewAccount *account_view,
+                                        const gchar *column_title,
+                                        GncTreeViewAccountColumnSource
+                                        col_source_cb,
+                                        GncTreeViewAccountColumnTextEdited
+                                        col_edited_cb)
+{
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
+    GtkTreeModel *s_model;
+    
+    g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (account_view), NULL);
+    
+    renderer = gtk_cell_renderer_text_new ();
+    g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
+    
+    column = gtk_tree_view_column_new_with_attributes (column_title,
+                                                       renderer, NULL);
+    if (col_edited_cb) {
+        g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
+        g_object_set_data(G_OBJECT(renderer), "column_edited_callback",
+                          col_edited_cb);
+        s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(account_view));
+        g_signal_connect(G_OBJECT(renderer), "edited", 
+                         (GCallback) col_edited_helper, s_model);
+        g_object_set_data(G_OBJECT(renderer), "column_view", column);
+    }
+    gtk_tree_view_column_set_cell_data_func (column, renderer, 
+                                             col_source_helper,
+                                             col_source_cb, NULL);
+    gtk_tree_view_append_column (GTK_TREE_VIEW(account_view), column);
+    return column;
 }
 
 
Index: gnc-tree-view-account.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/Attic/gnc-tree-view-account.h,v
retrieving revision 1.1.2.12
retrieving revision 1.1.2.13
diff -Lsrc/gnome-utils/gnc-tree-view-account.h -Lsrc/gnome-utils/gnc-tree-view-account.h -u -r1.1.2.12 -r1.1.2.13
--- src/gnome-utils/gnc-tree-view-account.h
+++ src/gnome-utils/gnc-tree-view-account.h
@@ -94,8 +94,9 @@
  *
  *  @return A pointer to a new account tree view.
  */
-GtkTreeView * gnc_tree_view_account_new_with_group (AccountGroup *group, gboolean show_root);
-GtkTreeView  *gnc_tree_view_account_new                   (gboolean show_root);
+GtkTreeView *gnc_tree_view_account_new_with_group (AccountGroup *group, 
+                                                   gboolean show_root);
+GtkTreeView *gnc_tree_view_account_new (gboolean show_root);
 /** @} */
 
 
@@ -105,20 +106,42 @@
 const char *gnc_tree_view_account_get_field_name (AccountFieldCode field);
 
 /** 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
+ *  view.  By default, when a GncTreeViewAccount is created, all
+ *  columns are shown, but if you call this function with a NULL list,
+ *  only the account name column will be shown.  Unrecognized column
+ *  names are silently ignored.  The avalible list of columns can be
+ *  found in the file gnc-tree-view-account.c.  NOTE: This function
+ *  does not handle columns added with
+ *  gnc_tree_view_account_add_kvp_column() -- it only handles the
+ *  "builtin" columns.
  *
  *  @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);
+void gnc_tree_view_account_configure_columns (GncTreeViewAccount *account_view,
+                                              GSList *column_names);
+
+typedef gchar * (*GncTreeViewAccountColumnSource) (Account *account, 
+                                                   GtkTreeViewColumn *col,
+                                                   GtkCellRenderer *cell);
+
+typedef void (*GncTreeViewAccountColumnTextEdited) (Account *account, 
+                                                    GtkTreeViewColumn *col, 
+                                                    const gchar *new_text);
+
+
+/* The TreeView owns the TreeViewColumn, but caller may set properties. */
+GtkTreeViewColumn * gnc_tree_view_account_add_custom_column(
+    GncTreeViewAccount *account_view, const gchar *column_title,
+    GncTreeViewAccountColumnSource source_cb, 
+    GncTreeViewAccountColumnTextEdited edited_cb);
+
 
 
 /** Add a new column to the set of columns in an account tree view.
- *  This column will display the contents of a specified KVP slot.
+ *  This column will be visible as soon as it is added and will
+ *  display the contents of the specified KVP slot.
  *
  *  @param view A pointer to an account tree view.
  *
@@ -147,8 +170,8 @@
  *
  *  @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_account_get_view_info (GncTreeViewAccount *account_view,
+                                          AccountViewInfo *avi);
 
 /** Given pointers to an account tree and old style filter block, this
  *  function will applies the settings specified to the current
@@ -159,10 +182,10 @@
  *  @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..
+ *  view.
  */
-void          gnc_tree_view_account_set_view_info         (GncTreeViewAccount *account_view,
-							   AccountViewInfo *avi);
+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
@@ -170,7 +193,7 @@
  *
  *  @param avi A pointer to an old style filter block.
  */
-void          gnc_tree_view_account_init_view_info        (AccountViewInfo *avi);
+void gnc_tree_view_account_init_view_info (AccountViewInfo *avi);
 
 
 /** This function attaches a filter function to the given account
@@ -198,6 +221,25 @@
 				       gpointer data,
 				       GtkDestroyNotify destroy);
 
+/*  This is a convenient filter function for use with
+ *  gnc_tree_view_account_set_filter() and the functions in
+ *  gnc-tree-model-account-types.h.  If you have some view that is
+ *  backed by the "account types" tree model, you can get a guint32
+ *  from that view's tree selection.  Then, you can use that account
+ *  type selection as a filter for the account tree view.  For
+ *  example:
+ *
+ *  guint sel_mask;
+ *
+ *  sel_mask = gnc_tree_model_account_types_get_selection(view);
+ *
+ *  gnc_tree_view_account_set_filter(account_view, 
+ *    gnc_tree_view_account_filter_by_type_selection, 
+ *    GUINT_TO_POINTER(sel_mask), NULL);
+ * 
+ */
+gboolean gnc_tree_view_account_filter_by_type_selection(
+    Account* acct, gpointer data);
 
 /** This function forces the account tree filter to be evaluated.  It
  *  may be necessary to call this function if the initial state of the
@@ -209,7 +251,7 @@
  *
  *  @param account_view A pointer to an account tree view.
  */
-void          gnc_tree_view_account_refilter              (GncTreeViewAccount *view);
+void gnc_tree_view_account_refilter (GncTreeViewAccount *view);
 /** @} */
 
 
@@ -231,11 +273,6 @@
 
 
 
-Account     * gnc_tree_view_account_get_account_from_column (GtkTreeViewColumn *column,
-							     GtkTreeModel *f_model,
-							     GtkTreeIter  *f_iter);
-
-
 /** 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
@@ -268,6 +305,20 @@
 							   GtkTreePath *path);
 
 
+/** This function returns the account associated with the specified
+ *  iter.  This function is useful in selection callbacks on an
+ *  account tree widget.
+ *
+ *  @param model The model provided to the callback function.
+ *
+ *  @param iter The iter provided to the callback function.
+ *
+ *  @return The account associated with this iter.
+ */
+Account     * gnc_tree_view_account_get_account_from_iter (GtkTreeModel *model,
+							   GtkTreeIter  *iter);
+
+
 /** This function returns the account in the account tree view at the
  *  current location of the cursor. (The outline frame. Usually is
  *  selected and therefore filled in, but not always.)
Index: gnc-tree-model-account.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/Attic/gnc-tree-model-account.c,v
retrieving revision 1.1.2.14
retrieving revision 1.1.2.15
diff -Lsrc/gnome-utils/gnc-tree-model-account.c -Lsrc/gnome-utils/gnc-tree-model-account.c -u -r1.1.2.14 -r1.1.2.15
--- src/gnome-utils/gnc-tree-model-account.c
+++ src/gnome-utils/gnc-tree-model-account.c
@@ -342,6 +342,8 @@
 static int
 gnc_tree_model_account_get_n_columns (GtkTreeModel *tree_model)
 {
+	g_return_val_if_fail(GNC_IS_TREE_MODEL_ACCOUNT(tree_model), -1);
+    
 	return GNC_TREE_MODEL_ACCOUNT_NUM_COLUMNS;
 }
 
@@ -551,8 +553,8 @@
 	gboolean negative; /* used to set "defecit style" aka red numbers */
 	gchar *string;
 
-	// ENTER("model %p, iter %s, col %d", tree_model,
-	//       iter_to_string(iter), 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);
@@ -604,6 +606,7 @@
 			string = gnc_ui_account_get_print_balance(xaccAccountGetPresentBalanceInCurrency,
 								  account, FALSE, &negative);
 			g_value_set_static_string (value, negative ? "red" : "black");
+			g_free(string);
 			break;
 
 		case GNC_TREE_MODEL_ACCOUNT_COL_BALANCE:
@@ -623,6 +626,7 @@
 			string = gnc_ui_account_get_print_balance(xaccAccountGetBalanceInCurrency,
 								  account, FALSE, &negative);
 			g_value_set_static_string (value, negative ? "red" : "black");
+			g_free(string);
 			break;
 
 		case GNC_TREE_MODEL_ACCOUNT_COL_CLEARED:
@@ -642,6 +646,7 @@
 			string = gnc_ui_account_get_print_balance(xaccAccountGetClearedBalanceInCurrency,
 								  account, FALSE, &negative);
 			g_value_set_static_string (value, negative ? "red" : "black");
+			g_free(string);
 			break;
 
 		case GNC_TREE_MODEL_ACCOUNT_COL_RECONCILED:
@@ -711,7 +716,7 @@
 
 		case GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO:
 			g_value_init (value, G_TYPE_STRING);
-			g_value_set_string (value, gnc_ui_account_get_tax_info_string (account));
+			g_value_take_string (value, gnc_ui_account_get_tax_info_string (account));
 			break;
 
 		case GNC_TREE_MODEL_ACCOUNT_COL_LASTNUM:
@@ -732,7 +737,7 @@
 		default:
 			g_assert_not_reached ();
 	}
-	//LEAVE(" ");
+	LEAVE(" ");
 }
 
 static gboolean
@@ -813,9 +818,10 @@
 		}
 	}
 
-	if (model->priv->root == NULL || xaccGroupGetNumAccounts (model->priv->root) == 0) {
+	if (model->priv->root == NULL || 
+            xaccGroupGetNumAccounts (model->priv->root) == 0) {
 		iter->stamp = 0;
-		LEAVE("failed (1)");
+		LEAVE("failed (either no group or group has no accounts)");
 		return FALSE;
 	}
 
@@ -824,7 +830,7 @@
 		
 		if (account == NULL) {
 			iter->stamp = 0;
-			LEAVE("failed (2)");
+			LEAVE("failed (couldn't get account from group)");
 			return FALSE;
 		}
 
@@ -844,7 +850,8 @@
 
 	if (group == NULL || xaccGroupGetNumAccounts (group) == 0) {
 		iter->stamp = 0;
-		LEAVE("failed (3)");
+		LEAVE("failed (chilren group was %s)", 
+                      group ? "empty" : "null");
 		return FALSE;
 	}
 
@@ -852,7 +859,7 @@
 	
 	if (account == NULL) {
 		iter->stamp = 0;
-		LEAVE("failed (4)");
+		LEAVE("failed (group's account is null)");
 		return FALSE;
 	}
 
@@ -1114,7 +1121,8 @@
 
 	ENTER("account %p (%s), model %p",
 	      account, xaccAccountGetName(account), data);
-	if (!gnc_tree_model_account_get_iter_from_account (GNC_TREE_MODEL_ACCOUNT (data), account, &iter))
+	if (!gnc_tree_model_account_get_iter_from_account
+            (GNC_TREE_MODEL_ACCOUNT (data), account, &iter))
 	  return NULL;
 
 	path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter);
@@ -1128,7 +1136,7 @@
 }
 
 /*
- * Add a new top node to the model.  This node is for a pseudo-account
+ * Gets the top node of the model.  This node is for a pseudo-account
  * that lives above the main level accounts in the engine.
  */
 Account *
@@ -1156,10 +1164,15 @@
 
 	DEBUG("old toplevel %p", model->priv->toplevel);
 	if (model->priv->toplevel != NULL) {
+            /* CAS: this can't happen because we only set toplevel on
+             * new tree models. */
 		path = gtk_tree_path_new_first ();
 		gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
 		gtk_tree_path_free (path);
 	} else {
+            /* CAS: I think this is bogus for the same reason - we'll
+             * have no rows, so why are we emitting a bunch of
+             * "row_deleted" signals when no rows can exist? */
 		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);
@@ -1238,7 +1251,8 @@
 	}
 
 	group = xaccAccountGetParent (account);
-	DEBUG("Looking through %d accounts at this level", xaccGroupGetNumAccounts (group));
+	DEBUG("Looking through %d accounts at this level", 
+              xaccGroupGetNumAccounts (group));
 	for (i = 0; i < xaccGroupGetNumAccounts (group); i++) {
 		if (xaccGroupGetAccount (group, i) == account) {
 			found = TRUE;
@@ -1268,7 +1282,8 @@
 	g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL);
 	g_return_val_if_fail (account != NULL, NULL);
 
-	if (!gnc_tree_model_account_get_iter_from_account (model, account, &tree_iter)) {
+	if (!gnc_tree_model_account_get_iter_from_account (model, account, 
+                                                           &tree_iter)) {
 	  LEAVE("no iter");
 	  return NULL;
 	}


More information about the gnucash-changes mailing list