[Gnucash-changes] Convert common functions into a new base
gnc-tree-view object.
David Hampton
hampton at cvs.gnucash.org
Sat May 21 00:54:07 EDT 2005
Log Message:
-----------
Convert common functions into a new base gnc-tree-view object.
Integrate the object with gconf for tracking sizes and visibilities of
columns within a view. Add a new popup menu for selecting column
visibilities. Make it easier to add new columns after a view has been
created.
Tags:
----
gnucash-gnome2-dev
Modified Files:
--------------
gnucash:
ChangeLog
GNOME2_STATUS
gnucash/src/gnome-utils:
Makefile.am
Added Files:
-----------
gnucash/src/gnome-utils:
gnc-tree-view.c
gnc-tree-view.h
Removed Files:
-------------
gnucash/src/gnome-utils:
gnc-tree-view-common.c
gnc-tree-view-common.h
Revision Data
-------------
Index: ChangeLog
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/ChangeLog,v
retrieving revision 1.1487.2.206
retrieving revision 1.1487.2.207
diff -LChangeLog -LChangeLog -u -r1.1487.2.206 -r1.1487.2.207
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,50 @@
+2005-05-21 David Hampton <hampton at employees.org>
+
+ * src/gnome-utils/Makefile.am:
+ * src/gnome-utils/gnc-tree-view-common.[ch]:
+ * src/gnome-utils/gnc-tree-view.[ch]: Convert common functions
+ into a new base gnc-tree-view object. Integrate the object with
+ gconf for tracking sizes and visibilities of columns within a
+ view. Add a new popup menu for selecting column visibilities.
+ Make it easier to add new columns after a view has been created.
+
+ * src/gnome-utils/gnc-tree-view-*: Base these views on the new
+ common gnc-tree-view class.
+
+ * src/gnome-utils/gnc-tree-model-*: Remove the dedicated column
+ for right aligning numbers. This is done by a simpler method now.
+
+ * src/gnome/dialog-budget-category.c:
+ * src/gnome/dialog-commodities.c:
+ * src/gnome/dialog-price-edit-db.c:
+ * src/gnome/druid-hierarchy.c:
+ * src/gnome/gnc-plugin-page-account-tree.c:
+ * src/import-export/import-account-matcher.c: Changes because
+ called functions have moved in to the base gnc tree view.
+
+ * src/app-utils/gnc-ui-util.[ch]:
+ * src/gnome-utils/dialog-account.c:
+ * src/scm/main-window.scm: Prune three or four layers of
+ complicated code that is only ever used to extract a single value
+ from an account.
+
+2005-05-20 David Hampton <hampton at employees.org>
+
+ * src/gnome-utils/gnc-tree-model-account.c: Store the book as part
+ of the model private data. In the event handler for the model,
+ ensure that events are for accounts that are in the model.
+
+2005-05-19 David Hampton <hampton at employees.org>
+
+ * src/core-utils/gnc-gconf-utils.[ch]: Add some more utility
+ functions.
+
+ * src/gnome/schemas/apps_gnucash_dialog_commodities.schemas:
+ * src/gnome-utils/gnc-tree-view-commodity.c: Renamed "exchange
+ code" to "cusip code". The former seems like it is referring to
+ NASDAQ, NYSE, etc, not a code that is unique to a specific
+ security. The latter is by definition security specific.
+
2005-05-15 David Hampton <hampton at employees.org>
* src/gnome-utils/gnc-tree-view-account.[ch]:
Index: GNOME2_STATUS
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/Attic/GNOME2_STATUS,v
retrieving revision 1.1.2.51
retrieving revision 1.1.2.52
diff -LGNOME2_STATUS -LGNOME2_STATUS -u -r1.1.2.51 -r1.1.2.52
--- GNOME2_STATUS
+++ GNOME2_STATUS
@@ -216,9 +216,6 @@
- dialog doesn't expand/fill on resize
- - changing displayed columns has strange effects (some columns being
- added, some not, some seeming off-by-one errors, &c.)
-
- Stylesheets
- Dialog opens with inappropriate scrollbars.
--- src/gnome-utils/gnc-tree-view-common.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * gnc-tree-view-common.c -- common utilities for manipulating a
- * GtkTreeView within gnucash
- *
- * Copyright (C) 2003,2005 David Hampton <hampton at 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
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, contact:
- *
- * Free Software Foundation Voice: +1-617-542-5942
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652
- * Boston, MA 02111-1307, USA gnu at gnu.org
- */
-
-#include "config.h"
-
-#include <gtk/gtk.h>
-#include <libgnome/libgnome.h>
-#include <string.h>
-
-#include "gnc-tree-view-common.h"
-#include "gnc-engine-util.h"
-#include "gnc-gconf-utils.h"
-#include "gnc-gnome-utils.h"
-
-#define COLUMN_NUM "column"
-#define TREE_NAME "tree-name"
-
-/** Static Globals *******************************************************/
-
-/* This static indicates the debugging module that this .o belongs to. */
-static short module = MOD_GUI;
-
-
-/************************************************************/
-/* Auxiliary Functions */
-/************************************************************/
-
-static gint
-view_column_find_by_name(gnc_view_column *defaults,
- const gchar *name)
-{
- gint i;
-
- g_return_val_if_fail (name != NULL, -1);
-
- for (i = 0; defaults[i].pref_name != NULL; i++) {
- if (strcmp(defaults[i].pref_name, name) == 0)
- return i;
- }
- return -1;
-}
-
-
-/************************************************************/
-/* Tree View Creation */
-/************************************************************/
-
-void
-gnc_tree_view_common_create_columns (GtkTreeView *view,
- const gchar *tree_name,
- const gchar *stock_icon,
- gnc_view_column *defaults)
-{
- GtkTreeModel *s_model;
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
- gboolean is_sortable;
- gint i;
-
- ENTER("view %p, name %s, icon %s, defaults %p",
- view, tree_name, stock_icon, defaults);
- g_object_set_data(G_OBJECT(view), TREE_NAME, g_strdup(tree_name));
-
- /*
- * Get the model
- */
- s_model = gtk_tree_view_get_model(view);
- is_sortable = GTK_IS_TREE_MODEL_SORT(s_model);
-
- /*
- * Create the first column. This column is special in that it will
- * have the disclosure triangle to expand the tree, and it may have
- * an icon in it.
- */
- column = gtk_tree_view_column_new ();
- g_object_set_data(G_OBJECT(column), COLUMN_NUM, GINT_TO_POINTER(0));
- gtk_tree_view_column_set_title (column, gettext(defaults[0].field_name));
- if (stock_icon) {
- renderer = gtk_cell_renderer_pixbuf_new ();
- g_object_set (renderer, "stock-id", stock_icon, NULL);
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- }
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_add_attribute (column,
- renderer,
- "text", defaults[0].column);
- if (defaults[0].visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
- gtk_tree_view_column_add_attribute (column, renderer,
- "visible", defaults[0].visibility_column);
- if (defaults[0].color_column != GNC_TREE_VIEW_COLUMN_COLOR_NONE)
- gtk_tree_view_column_add_attribute (column, renderer,
- "foreground", defaults[0].color_column);
- if (defaults[0].align_column != GNC_TREE_VIEW_COLUMN_ALIGN_NONE)
- gtk_tree_view_column_add_attribute (column, renderer,
- "xalign", defaults[0].align_column);
- gtk_tree_view_append_column (view, column);
-
- /*
- * Set the attributes of this first column
- */
- g_object_set(G_OBJECT(column),
- "visible", TRUE,
- "alignment", defaults[0].label_align,
- "min-width", 50, /* DRH - Should be based on title width */
- "resizable", TRUE,
- "reorderable", TRUE,
- "sizing", defaults[0].sizing,
- NULL);
- gtk_tree_view_set_expander_column (view, column);
- if (is_sortable) {
- gtk_tree_view_column_set_sort_column_id (column, 0);
- if (defaults[0].sort_fn)
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(s_model), 0,
- defaults[0].sort_fn,
- NULL /* user_data */,
- NULL /* destroy fn */);
- }
- DEBUG("Created %s column", defaults[0].pref_name);
-
-
- /*
- * Now create any additional columns. These columns may contain
- * regular text or toggle buttons.
- */
- for (i = 1; defaults[i].pref_name != NULL; i++) {
- if (defaults[i].is_toggle) {
- renderer = gtk_cell_renderer_toggle_new ();
- column = gtk_tree_view_column_new_with_attributes (gettext(defaults[i].field_name),
- renderer,
- "active", defaults[i].column,
- NULL);
- if (defaults[i].toggle_edited)
- g_signal_connect (G_OBJECT (renderer), "toggled",
- G_CALLBACK (defaults[i].toggle_edited),
- view);
- } else {
- renderer = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new_with_attributes (gettext(defaults[i].field_name),
- renderer,
- "text", defaults[i].column,
- NULL);
- if (defaults[i].color_column != GNC_TREE_VIEW_COLUMN_COLOR_NONE)
- gtk_tree_view_column_add_attribute (column, renderer,
- "foreground", defaults[i].color_column);
- if (defaults[i].align_column != GNC_TREE_VIEW_COLUMN_ALIGN_NONE)
- gtk_tree_view_column_add_attribute (column, renderer,
- "xalign", defaults[i].align_column);
- }
- if (defaults[i].visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
- gtk_tree_view_column_add_attribute (column, renderer,
- "visible", defaults[i].visibility_column);
-
- g_object_set_data(G_OBJECT(column), COLUMN_NUM, GINT_TO_POINTER(i));
- gtk_tree_view_append_column (view, column);
-
- /*
- * Set the attributes of this column
- */
- g_object_set(G_OBJECT(column),
- "visible", TRUE,
- "alignment", defaults[i].label_align,
- "min-width", 50, /* DRH - Should be based on title width */
- "resizable", TRUE,
- "reorderable", TRUE,
- "sizing", defaults[i].sizing,
- NULL);
-
- if (is_sortable) {
- gtk_tree_view_column_set_sort_column_id (column, i);
- if (defaults[i].sort_fn)
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(s_model), i,
- defaults[i].sort_fn,
- NULL /* user_data */,
- NULL /* destroy fn */);
- }
-
- DEBUG("Created %s column", defaults[i].pref_name);
- }
- LEAVE(" ");
-}
-
-
-
-/************************************************************/
-/* Commodity Tree View Get/Save Settings */
-/************************************************************/
-
-static void
-gnc_tree_view_common_save_sort_info (GtkTreeView *view,
- const gchar *section,
- gnc_view_column *defaults)
-{
- GtkTreeViewColumn *column;
- GtkTreeModel *s_model;
- gboolean has_sort_column;
- gint sort_column_id;
- GtkSortType order;
- GEnumClass *enum_class;
- GEnumValue *enum_value;
- const gchar *col_name, *enum_name;
-
- s_model = gtk_tree_view_get_model (view);
- has_sort_column = gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE(s_model),
- &sort_column_id,
- &order);
-
- if (has_sort_column) {
- column = gtk_tree_view_get_column (view, sort_column_id);
- col_name = defaults[sort_column_id].pref_name;
- } else {
- col_name = "none";
- order = GTK_SORT_ASCENDING;
- }
-
- enum_class = g_type_class_ref (GTK_TYPE_SORT_TYPE);
- enum_value = g_enum_get_value (enum_class, order);
- enum_name = enum_value->value_nick;
-
- gnc_gconf_set_string(section, "sort_column", col_name, NULL);
- gnc_gconf_set_string(section, "sort_order", enum_name, NULL);
-}
-
-void
-gnc_tree_view_common_save_settings (GtkTreeView *view,
- const gchar *section,
- gnc_view_column *defaults)
-{
- GtkTreeViewColumn *column;
- GSList *column_names = NULL;
- gchar *key;
- const gchar *tree_name;
- const gchar *name;
- gint i, num;
-
- g_return_if_fail (GTK_IS_TREE_VIEW(view));
- g_return_if_fail (section != NULL);
- g_return_if_fail (defaults != NULL);
-
- tree_name = g_object_get_data(G_OBJECT(view), TREE_NAME);
- ENTER("view %p, name %s, section %s, defaults %p",
- view, tree_name, section, defaults);
-
- for (i = 0; defaults[i].pref_name != NULL; i++) {
- column = gtk_tree_view_get_column (view, i);
- num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), COLUMN_NUM));
-
- /* Save up the column names */
- name = defaults[num].pref_name;
- column_names = g_slist_append(column_names, (gpointer)name);
-
- /* Remember whether the column is visible */
- key = g_strdup_printf("%s_visible", name);
- gnc_gconf_set_bool(section, key,
- gtk_tree_view_column_get_visible(column), NULL);
- g_free(key);
-
- /* Remember whether the column width */
- key = g_strdup_printf("%s_width", name);
- gnc_gconf_set_int(section, key,
- gtk_tree_view_column_get_width(column), NULL);
- g_free(key);
- }
-
- gnc_tree_view_common_save_sort_info (view, section, defaults);
-
- gnc_gconf_set_list(section, "column_order", GCONF_VALUE_STRING,
- column_names, NULL);
- gnc_gconf_suggest_sync();
- LEAVE(" ");
-}
-
-static void
-gnc_tree_view_common_restore_sort_info (GtkTreeView *view,
- const gchar *section,
- gnc_view_column *defaults)
-{
- GtkTreeModel *s_model;
- gchar *value;
- gint sort_column_id = -1;
- GtkSortType order = GTK_SORT_ASCENDING;
- GEnumClass *enum_class;
- GEnumValue *enum_value;
-
- value = gnc_gconf_get_string(section, "sort_column", NULL);
- if (value) {
- sort_column_id = view_column_find_by_name(defaults, value);
- g_free(value);
- }
-
- value = gnc_gconf_get_string(section, "sort_order", NULL);
- if (value) {
- enum_class = g_type_class_ref (GTK_TYPE_SORT_TYPE);
- enum_value = g_enum_get_value_by_nick (enum_class, value);
- if (enum_value)
- order = enum_value->value;
- g_free(value);
- }
-
- s_model = gtk_tree_view_get_model (view);
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(s_model),
- sort_column_id,
- order);
-}
-
-void
-gnc_tree_view_common_restore_settings (GtkTreeView *view,
- const gchar *section,
- gnc_view_column *defaults)
-{
- GtkTreeViewColumn *column, *prev;
- const gchar *col_name;
- const gchar *tree_name;
- gchar *key;
- GSList *column_names, *tmp, *next;
- gboolean visible;
- gint i, width;
-
- g_return_if_fail (GTK_IS_TREE_VIEW(view));
- g_return_if_fail (section != NULL);
- g_return_if_fail (defaults != NULL);
-
- tree_name = g_object_get_data(G_OBJECT(view), TREE_NAME);
- ENTER("view %p, name %s, section %s, defaults %p",
- view, tree_name, section, defaults);
-
- /* Get the column order information first. This can be used as a
- * key to see if 1) there is any information present in the users
- * gconf files, and 2) the gconf schema have been installed. If the
- * result is a null list, neither of the two is present and this
- * routine should bail now. We'll actually swap the columns around
- * after setting up all the other information. */
- column_names = gnc_gconf_get_list(section, "column_order",
- GCONF_VALUE_STRING, NULL);
- if (column_names == NULL)
- return;
-
- /* Restore the sort information, if any */
- gnc_tree_view_common_restore_sort_info (view, section, defaults);
-
- /* Restore any per-column information */
- for (i = 0; defaults[i].pref_name != NULL; i++) {
- column = gtk_tree_view_get_column (view, i);
- col_name = defaults[i].pref_name;
- DEBUG("Processing column %s", col_name);
-
- /* visible */
- key = g_strdup_printf("%s_visible", col_name);
- visible = gnc_gconf_get_bool(section, key, NULL);
- DEBUG(" Setting %s column visibility to %d", col_name, visible);
- gtk_tree_view_column_set_visible (column, visible);
- g_free(key);
-
- /* column width */
- key = g_strdup_printf("%s_width", col_name);
- width = gnc_gconf_get_int(section, key, NULL);
- if (width != 0) {
- DEBUG(" Would set %s column width to %d", col_name, width);
- // gtk_tree_view_column_set_width (column, width);
- }
- g_free(key);
- }
-
- /* Now swap the columns around the way the user had them. */
- DEBUG("Processing column order");
-
- /* First, convert from names to pointers */
- for (tmp = column_names; tmp; tmp = next) {
- next = g_slist_next(tmp);
- i = view_column_find_by_name(defaults, tmp->data);
- DEBUG("Processing %s column for order", (gchar *)tmp->data);
- g_free(tmp->data);
- if (i != -1) {
- column = gtk_tree_view_get_column (view, i);
- tmp->data = column;
- } else {
- column_names = g_slist_delete_link(column_names, tmp);
- }
- }
-
- /* Then reorder the columns */
- prev = NULL;
- for (tmp = column_names; tmp; tmp = g_slist_next(tmp)) {
- column = tmp->data;
- gtk_tree_view_move_column_after (view, column, prev);
- prev = column;
- }
-
- g_slist_free(column_names);
- LEAVE(" ");
-}
--- /dev/null
+++ src/gnome-utils/gnc-tree-view.c
@@ -0,0 +1,1923 @@
+/*
+ * gnc-tree-view.c -- new GtkTreeView with extra features used by
+ * all the tree views in gnucash
+ *
+ * Copyright (C) 2003,2005 David Hampton <hampton at 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
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652
+ * Boston, MA 02111-1307, USA gnu at gnu.org
+ */
+
+/** @addtogroup GUI
+ @{ */
+/** @addtogroup GncTreeView
+ * @{ */
+/** @file gnc-tree-view.c
+ @brief Base GncTreeView implementation for gnucash trees.
+ @author David Hampton <hampton at employees.org>
+*/
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <libgnome/libgnome.h>
+#include <string.h>
+
+#include "gnc-tree-view.h"
+#include "gnc-engine-util.h"
+#include "gnc-gconf-utils.h"
+#include "gnc-gnome-utils.h"
+
+/* The column id refers to a specific column in the tree model. It is
+ * also attached to the side of the tree column to allow lookup of a
+ * GtkTreeViewColumn when passed a column id from the underlying
+ * model. By convention, negative column numbers are used when the
+ * visible column has no association with the underlying model.*/
+#define MODEL_COLUMN "model_column"
+
+/* A column with this attribute cannot be hidden from view. */
+#define ALWAYS_VISIBLE "always-visible"
+
+/* For checkbox columns, this contains the real title for the column. */
+#define REAL_TITLE "real_title"
+
+/* The name of this column as it should appear in gconf. This is
+ * attached to the column when it is created, and used to map back and
+ * forth to gconf keys. The actual gconf keys are built from these
+ * strings. */
+#define PREF_NAME "pref-name"
+
+/* The actual gconf key for a particular column visibility. This is
+ * attached to the menu items that are in the column selection menu.
+ * Makes it very easy to update gconf when a menu item is toggled. */
+#define GCONF_KEY "gconf-key"
+
+/* Gconf keys within this particular section of gconf. */
+#define GCONF_KEY_SORT_COLUMN "sort_column"
+#define GCONF_KEY_SORT_ORDER "sort_order"
+#define GCONF_KEY_COLUMN_ORDER "column_order"
+
+/* Partial gconf keys within this particular section of gconf. These
+ are appended to the various column names to create the actual
+ keys. */
+#define GCONF_KEY_VISIBLE "visible"
+#define GCONF_KEY_WIDTH "width"
+
+enum {
+ PROP_0,
+ PROP_GCONF_SECTION,
+ PROP_SHOW_COLUMN_MENU,
+};
+
+/** Static Globals *******************************************************/
+
+/* This static indicates the debugging module that this .o belongs to. */
+static short module = MOD_GUI;
+static GList *active_views = NULL;
+
+/** Declarations *********************************************************/
+static void gnc_tree_view_class_init (GncTreeViewClass *klass);
+static void gnc_tree_view_init (GncTreeView *view);
+static void gnc_tree_view_finalize (GObject *object);
+static void gnc_tree_view_destroy (GtkObject *object);
+static void gnc_tree_view_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gnc_tree_view_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gnc_tree_view_remove_gconf(GncTreeView *view);
+static gboolean gnc_tree_view_drop_ok_cb (GtkTreeView *view,
+ GtkTreeViewColumn *column,
+ GtkTreeViewColumn *prev_column,
+ GtkTreeViewColumn *next_column,
+ gpointer data);
+static void gtk_tree_view_sort_column_changed_cb (GtkTreeSortable *treesortable,
+ GncTreeView *view);
+static void gnc_tree_view_build_column_menu (GncTreeView *view);
+static void gnc_tree_view_select_column_cb (GtkTreeViewColumn *column,
+ GncTreeView *view);
+
+/** Private Data Structure ***********************************************/
+
+struct GncTreeViewPrivate
+{
+ GtkTooltips *title_tips;
+ GSList *default_visible;
+
+ /* Column selection menu related values */
+ GtkTreeViewColumn *column_menu_column;
+ GtkWidget *column_menu;
+ gboolean show_column_menu;
+
+ /* Gconf related values */
+ gchar *gconf_section;
+ gboolean seen_gconf_visibility;
+ gulong columns_changed_cb_id;
+ gulong sort_column_changed_cb_id;
+ gulong size_allocate_cb_id;
+};
+
+
+/************************************************************/
+/* g_object required functions */
+/************************************************************/
+
+/** @name Gnc Tree View Object Implementation
+ @{ */
+
+static GObjectClass *parent_class = NULL;
+
+/** Create a new glib type for the base gnucash tree view.
+ *
+ * @internal
+ *
+ * @return The new type value.
+ */
+GType
+gnc_tree_view_get_type (void)
+{
+ static GType gnc_tree_view_type = 0;
+
+ if (gnc_tree_view_type == 0) {
+ static const GTypeInfo our_info = {
+ sizeof (GncTreeViewClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gnc_tree_view_class_init,
+ NULL,
+ NULL,
+ sizeof (GncTreeView),
+ 0,
+ (GInstanceInitFunc) gnc_tree_view_init
+ };
+
+ gnc_tree_view_type = g_type_register_static (GTK_TYPE_TREE_VIEW,
+ "GncTreeView",
+ &our_info, 0);
+ }
+
+ return gnc_tree_view_type;
+}
+
+#if DEBUG_REFERENCE_COUNTING
+static void
+dump_view (GncTreeView *view, gpointer dummy)
+{
+ g_warning("GncTreeView %p still exists.", view);
+}
+
+static gint
+gnc_tree_view_report_references (void)
+{
+ g_list_foreach(active_views, (GFunc)dump_view, NULL);
+ return 0;
+}
+#endif
+
+/** Initialize the class for the new base gnucash tree view. This
+ * will set up any function pointers that override functions in the
+ * parent class, and also installs the proprieties that are unique to
+ * this class.
+ *
+ * @param klass The new class structure created by the object system.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_class_init (GncTreeViewClass *klass)
+{
+ GObjectClass *gobject_class;
+ GtkObjectClass *gtkobject_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gtkobject_class = GTK_OBJECT_CLASS (klass);
+
+ gobject_class->set_property = gnc_tree_view_set_property;
+ gobject_class->get_property = gnc_tree_view_get_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_GCONF_SECTION,
+ g_param_spec_string ("gconf-section",
+ "Gconf Section",
+ "The Gconf section to use for storing settings",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_SHOW_COLUMN_MENU,
+ g_param_spec_boolean ("show-column-menu",
+ "Show Column Menu",
+ "Show the column menu so user can change what columns are visible.",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /* GObject signals */
+ gobject_class->finalize = gnc_tree_view_finalize;
+
+ /* GtkObject signals */
+ gtkobject_class->destroy = gnc_tree_view_destroy;
+
+#if DEBUG_REFERENCE_COUNTING
+ gtk_quit_add (0,
+ (GtkFunction)gnc_tree_view_report_references,
+ NULL);
+#endif
+}
+
+/** Initialize a new instance of a base gnucash tree view. This
+ * function allocates and initializes the object private storage
+ * space. It also adds the new object to a list (for memory tracking
+ * purposes), and sets up a callback for the column drag function.
+ *
+ * @param view The new object instance created by the object system.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_init (GncTreeView *view)
+{
+ GtkTreeViewColumn *column;
+ GtkWidget *icon;
+ GtkRequisition requisition;
+
+
+ view->priv = g_new0 (GncTreeViewPrivate, 1);
+
+ view->priv->default_visible = NULL;
+ view->priv->column_menu = NULL;
+ view->priv->show_column_menu = FALSE;
+ view->priv->gconf_section = NULL;
+ view->priv->seen_gconf_visibility = FALSE;
+ view->priv->columns_changed_cb_id = 0;
+ view->priv->sort_column_changed_cb_id = 0;
+ view->priv->size_allocate_cb_id = 0;
+
+ active_views = g_list_append (active_views, view);
+
+ /* Ask gtk to help the user keep track of rows. */
+ g_object_set(view, "rules-hint", TRUE, NULL);
+
+ /* Handle column drag and drop */
+ gtk_tree_view_set_column_drag_function(GTK_TREE_VIEW(view),
+ gnc_tree_view_drop_ok_cb, NULL, NULL);
+
+ /* Create the next to last column which is always present, visible,
+ * and empty. Override the defaults and make this a one pixel wide
+ * column, but have it take up any extra space in the window. */
+ column = gnc_tree_view_add_text_column (view, NULL, NULL, NULL, NULL,
+ -1, -1, NULL);
+ gtk_object_set(GTK_OBJECT(column),
+ "fixed-width", 1,
+ "expand", TRUE, NULL);
+
+ /* Create the last column which contains the column selection
+ * widget. gnc_tree_view_add_text_column will do most of the
+ * work. */
+ icon = gtk_image_new_from_stock(GTK_STOCK_GO_DOWN,
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_widget_show(icon);
+ gtk_widget_size_request(icon, &requisition);
+ column = gnc_tree_view_add_text_column (view, NULL, NULL, NULL, NULL,
+ -1, -1, NULL);
+ gtk_object_set(GTK_OBJECT(column),
+ "clickable", TRUE,
+ "widget", icon,
+ "fixed-width", requisition.width + 10,
+ NULL);
+ g_signal_connect(G_OBJECT(column), "clicked",
+ G_CALLBACK (gnc_tree_view_select_column_cb),
+ view);
+ view->priv->column_menu_column = column;
+}
+
+/** Finalize the GncTreeView object. This function is called from the
+ * G_Object level to complete the destruction of the object. It
+ * should release any memory not previously released by the destroy
+ * function (i.e. the private data structure), then chain up to the
+ * parent's destroy function.
+ *
+ * @param object The object being destroyed.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_finalize (GObject *object)
+{
+ GncTreeView *view;
+
+ ENTER("view %p", object);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNC_IS_TREE_VIEW (object));
+
+ view = GNC_TREE_VIEW (object);
+ active_views = g_list_remove (active_views, view);
+
+ g_free (view->priv);
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+ LEAVE(" ");
+}
+
+/** Destroy the GncTreeView object. This function is called (possibly
+ * multiple times) from the Gtk_Object level to destroy the object.
+ * It should release any memory owned by the object that isn't
+ * fundamental to the implementation. In this function any active
+ * callbacks are disconnected, all memory other than the private data
+ * structure are freed.
+ *
+ * @param object The object being destroyed.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_destroy (GtkObject *object)
+{
+ GncTreeView *view;
+ GSList *slist;
+
+ ENTER("view %p", object);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNC_IS_TREE_VIEW (object));
+
+ view = GNC_TREE_VIEW (object);
+
+ gnc_tree_view_remove_gconf(view);
+
+ if (view->priv->default_visible) {
+ slist = view->priv->default_visible;
+ view->priv->default_visible = NULL;
+ g_slist_foreach(slist, (GFunc)g_free, NULL);
+ g_slist_free(slist);
+ }
+
+ if (view->priv->column_menu) {
+ DEBUG("removing column selection menu");
+ gtk_widget_unref(view->priv->column_menu);
+ view->priv->column_menu = NULL;
+ }
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ LEAVE(" ");
+}
+
+/** @} */
+
+/************************************************************/
+/* g_object other functions */
+/************************************************************/
+
+/** @name Gnc Tree View Object Implementation
+ @{ */
+
+/** Retrieve a property specific to this GncTreeView object. This is
+ * nothing more than a dispatch function for routines that can be
+ * called directly. It has the nice feature of allowing a single
+ * function call to retrieve multiple properties.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GncTreeView *view = GNC_TREE_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_GCONF_SECTION:
+ g_value_set_string (value, view->priv->gconf_section);
+ break;
+ case PROP_SHOW_COLUMN_MENU:
+ g_value_set_boolean (value, view->priv->show_column_menu);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+/** Set a property specific to this GncTreeView object. This is
+ * nothing more than a dispatch function for routines that can be
+ * called directly. It has the nice feature of allowing a new view
+ * to be created with a varargs list specifying the properties,
+ * instead of having to explicitly call each property function.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GncTreeView *view = GNC_TREE_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_GCONF_SECTION:
+ gnc_tree_view_set_gconf_section (view, g_value_get_string (value));
+ break;
+ case PROP_SHOW_COLUMN_MENU:
+ gnc_tree_view_set_show_column_menu (view, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/** @} */
+
+/************************************************************/
+/* Auxiliary Functions */
+/************************************************************/
+
+/** @name Gnc Tree View Auxiliary Functions
+ @{ */
+
+/** Find a tree column given a column id number from the underlying
+ * data model. This function should only be called by code that has
+ * visibility into the data model. The column id numbers shouldn't
+ * be used for any other purpose.
+ *
+ * This function simply runs the list of all (visible and invisible)
+ * columns looking for a match. Column id numbers were attached to
+ * each column at the time the column was created.
+ *
+ * @param view The visible tree widget.
+ *
+ * @param wanted The column id number to find.
+ *
+ * @internal
+ */
+static GtkTreeViewColumn *
+view_column_find_by_model_id (GncTreeView *view,
+ const gint wanted)
+{
+ GtkTreeViewColumn *column, *found = NULL;
+ GList *column_list, *tmp;
+ gint id;
+
+ // ENTER("view %p, name %s", view, name);
+ column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
+ for (tmp = column_list; tmp; tmp = g_list_next(tmp)) {
+ column = tmp->data;
+ id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), MODEL_COLUMN));
+ if (id != wanted)
+ continue;
+ found = column;
+ break;
+ }
+ g_list_free(column_list);
+
+ // LEAVE("column %p", found);
+ return found;
+}
+
+/** Find a tree column given the "pref name" used with gconf. This
+ * function simply runs the list of all (visible and invisible)
+ * columns looking for a match. Column names were attached to each
+ * column at the time the column was created.
+ *
+ * @param view The visible tree widget.
+ *
+ * @param id The "pref name" to find.
+ *
+ * @internal
+ */
+static GtkTreeViewColumn *
+view_column_find_by_name (GncTreeView *view,
+ const gchar *wanted)
+{
+ GtkTreeViewColumn *column, *found = NULL;
+ GList *column_list, *tmp;
+ const gchar *name;
+
+ // ENTER("view %p, wanted %s", view, wanted);
+ column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
+ for (tmp = column_list; tmp; tmp = g_list_next(tmp)) {
+ column = tmp->data;
+ name = g_object_get_data(G_OBJECT(column), PREF_NAME);
+ if (!name || (strcmp(name, wanted) != 0))
+ continue;
+ found = column;
+ break;
+ }
+ g_list_free(column_list);
+
+ // LEAVE("column %p", found);
+ return found;
+}
+
+/** @} */
+
+/************************************************************/
+/* Tree Callbacks */
+/************************************************************/
+
+/** @name Gnc Tree View Callback Functions
+ @{ */
+
+/** This function is called to determine whether it is acceptable to
+ * drop a dragged tree column at a given location. This function
+ * will be called multiple times by the GtkTreeView code while the
+ * user is dragging a column. Each call is a check to see if the
+ * proposed location is an acceptable place to drop the column. In
+ * the case of a GncTreeView, the only drop locations that are
+ * prohibited are on the right side of the visible tree.
+ *
+ * @param view The visible tree widget.
+ *
+ * @param column The column being dragged.
+ *
+ * @param prev_column The column before (left) of the proposed drop
+ * location.
+ *
+ * @param next_column The column after (right) of the proposed drop
+ * location.
+ *
+ * @param data Unused.
+ *
+ * @return TRUE if this drop location is acceptable. FALSE if not
+ * acceptable.
+ *
+ * @internal
+ */
+static gboolean
+gnc_tree_view_drop_ok_cb (GtkTreeView *view,
+ GtkTreeViewColumn *column,
+ GtkTreeViewColumn *prev_column,
+ GtkTreeViewColumn *next_column,
+ gpointer data)
+{
+ const gchar *pref_name;
+
+ /* Should we allow a drop at the left side of the tree view before
+ * the widget to open a new display level? I can think of cases
+ * where the user might want to do this with a checkbox column. */
+ if (prev_column == NULL)
+ return TRUE;
+
+ /* Do not allow a drop at the right side of the tree view after the
+ * column selection widget. */
+ if (next_column == NULL)
+ return FALSE;
+
+ /* Columns without pref names are considered fixed at the right hand
+ * side of the view. At the time of this writing, the only two are
+ * the column where the "column selection widget" is stored, and the
+ * "padding" column to the left of that where extra view space ends
+ * up. */
+ pref_name = g_object_get_data(G_OBJECT(prev_column), PREF_NAME);
+ if (!pref_name)
+ return FALSE;
+
+ /* Everything else is allowed. */
+ return TRUE;
+}
+
+/** This function is called when the sort order has changed on the
+ * underlying GtkTreeModel. It propagates these changes to gconf to
+ * keep it in sync with the user's view of the tree.
+ *
+ * @param sortable The underlying sortable model.
+ *
+ * @param view A pointer to the GncTreeView that displays the model
+ * data.
+ *
+ * @internal
+ */
+static void
+gtk_tree_view_sort_column_changed_cb (GtkTreeSortable *treesortable,
+ GncTreeView *view)
+{
+ GtkTreeViewColumn *column;
+ const gchar *gconf_section;
+ gchar *column_pref_name;
+ GtkSortType order;
+ gint id;
+
+ g_return_if_fail(GTK_IS_TREE_SORTABLE(treesortable));
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ ENTER(" ");
+ if (!view->priv->gconf_section) {
+ LEAVE("no gconf section");
+ return;
+ }
+
+ /* Set defaults, then extract data from the model */
+ if (!gtk_tree_sortable_get_sort_column_id(treesortable, &id, &order)) {
+ order = GTK_SORT_ASCENDING;
+ id = 0;
+ }
+ column = view_column_find_by_model_id (view, id);
+ column_pref_name = g_object_get_data(G_OBJECT(column), PREF_NAME);
+
+ /* Store the values in gconf */
+ gconf_section = view->priv->gconf_section;
+ gnc_gconf_set_string(gconf_section, "sort_column", column_pref_name, NULL);
+ gnc_gconf_set_string(gconf_section, "sort_order",
+ gnc_enum_to_nick(GTK_TYPE_SORT_TYPE, order), NULL);
+ LEAVE(" ");
+}
+
+/** This function is called when the column order has changed in the
+ * gtk tree view. It propagates these changes to gconf to keep it in
+ * sync with the user's view of the tree. This function runs the
+ * list of all tree column data structures, building a second list of
+ * column names. This second list is passed to gconf for storing.
+ * Only columns that have names can be saved in this fashion.
+ *
+ * @param view The tree view.
+ *
+ * @param data Unused.
+ *
+ * @internal
+ */
+static void
+gtk_tree_view_columns_changed_cb (GncTreeView *view,
+ gpointer data)
+{
+ GList *column_list, *tmp;
+ GSList *column_names = NULL;
+ gchar *name;
+
+ //ENTER("view %p, data %p", view, data);
+ column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
+ for (tmp = column_list; tmp; tmp = g_list_next(tmp)) {
+ name = g_object_get_data(tmp->data, PREF_NAME);
+ if (!name)
+ continue;
+ column_names = g_slist_append(column_names, name);
+ //DEBUG("%s", name);
+ }
+ g_list_free(column_list);
+
+ gnc_gconf_set_list(view->priv->gconf_section, GCONF_KEY_COLUMN_ORDER,
+ GCONF_VALUE_STRING, column_names, NULL);
+ g_slist_free(column_names);
+ //LEAVE(" ");
+}
+
+/** This is the helper function for gtk_tree_view_size_allocate_cb().
+ * It compares the actual column width to the width as stored in
+ * gconf. If the two are different, it the updates gconf with the
+ * actual width. This will trigger a notification from gconf that
+ * the size has changes, and that code must be smart enough to
+ * prevent an infinite loop. Not storing unchanged values prevents
+ * spurious callbacks from gconf and just saves processing time.
+ *
+ * @param column The column whose size should be updated in gconf..
+ *
+ * @param view The tree view.
+ *
+ * @internal
+ */
+static void
+gtk_tree_view_size_allocate_helper (GtkTreeViewColumn *column,
+ GncTreeView *view)
+{
+ const gchar *column_pref_name;
+ gint new_width, current_width;
+ gchar *key;
+
+ g_return_if_fail(GTK_IS_TREE_VIEW_COLUMN(column));
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ /* Any updates to be made? */
+ column_pref_name = g_object_get_data(G_OBJECT(column), PREF_NAME);
+ if (!column_pref_name)
+ return;
+ new_width = gtk_tree_view_column_get_width (column);
+ if (!new_width)
+ return;
+
+ /* Do it */
+ key = g_strdup_printf("%s_%s", column_pref_name, GCONF_KEY_WIDTH);
+ current_width = gnc_gconf_get_int(view->priv->gconf_section, key, NULL);
+ if (new_width != current_width) {
+ gnc_gconf_set_int(view->priv->gconf_section, key, new_width, NULL);
+ DEBUG("set %s width to %d", column_pref_name, new_width);
+ }
+ g_free(key);
+}
+
+/** This function is called when the tree size has been reallocated.
+ * When called, one of two events has occurred. 1) The column sizes
+ * within the tree have changed. 2) The window containing the tree
+ * has been resized. This code is concerned with case one. Case two
+ * is a don't care, unless the window resizing has caused a column
+ * resizing.
+ *
+ * This function simply runs the list of all tree columns, calling the
+ * gtk_tree_view_size_allocate_helper() function on each column.
+ * There is no callback that can be used for notification of an
+ * individual column change. Its this or nothing.
+ *
+ * @param widget The tree view.
+ *
+ * @param allocation Unused.
+ *
+ * @param data Unused.
+ *
+ * @internal
+ */
+static void
+gtk_tree_view_size_allocate_cb (GtkWidget *widget,
+ GtkAllocation *allocation,
+ gpointer data)
+{
+ GncTreeView *view;
+ GList *column_list;
+
+ g_return_if_fail(GNC_IS_TREE_VIEW(widget));
+
+ view = GNC_TREE_VIEW(widget);
+ column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
+ g_list_foreach(column_list, (GFunc)gtk_tree_view_size_allocate_helper, view);
+ g_list_free(column_list);
+}
+
+/** @} */
+
+/************************************************************/
+/* Gconf Setup / Callbacks */
+/************************************************************/
+
+/** @name Gnc Tree View Gconf Callback / Related Functions
+ @{ */
+
+/** Determine the visibility of a column. This function first looks
+ * for columns specially marked to be always visible, or columns
+ * without a preference name. These are always show. Next this
+ * function checks to see if gconf is responsible for this view *and*
+ * that gconf visibility keys have been seen. (This handles the
+ * 'first run' case where gconf should manage a view but no keys yet
+ * exist in gconf.) If so, the gconf visibility key is returned.
+ * Otherwise the "'default visible column' list is checked and a
+ * value of TRUE returned if the pref name is found.
+ *
+ * @param view A GncTreeView.
+ *
+ * @param column The GtkTreeViewColumn in question. Either this
+ * value or the pref_name parameter must be non-NULL.
+ *
+ * @param pref_name The name of the column in question. Either this
+ * value or the column parameter must be non-NULL.
+ *
+ * @returns TRUE if the column should be visible. FALSE otherwise.
+ *
+ * @internal
+ */
+static gboolean
+gnc_tree_view_column_visible (GncTreeView *view,
+ GtkTreeViewColumn *column,
+ const gchar *pref_name)
+{
+ gboolean visible;
+ gchar *key;
+
+ ENTER("column %p, name %s", column, pref_name);
+ if (column) {
+ if (g_object_get_data(G_OBJECT(column), ALWAYS_VISIBLE)) {
+ LEAVE("1, first column");
+ return TRUE;
+ }
+ pref_name = (gchar *)g_object_get_data(G_OBJECT(column), PREF_NAME);
+ DEBUG("pref_name is %s", pref_name);
+ }
+
+ if (!pref_name) {
+ LEAVE("1, no pref name");
+ return TRUE;
+ }
+
+ /* Using gconf? */
+ if (view->priv->gconf_section) {
+ if (view->priv->seen_gconf_visibility) {
+ key = g_strdup_printf("%s_%s", pref_name, GCONF_KEY_VISIBLE);
+ visible = gnc_gconf_get_bool(view->priv->gconf_section, key, NULL);
+ g_free(key);
+ LEAVE("%d, gconf visibility", visible);
+ return visible;
+ }
+
+ visible = (g_slist_find_custom(view->priv->default_visible, pref_name,
+ (GCompareFunc)strcmp) != NULL);
+ LEAVE("%d, gconf but using defaults", visible);
+ return visible;
+ }
+
+ /* Check the default columns list */
+ visible = (g_slist_find_custom(view->priv->default_visible, pref_name,
+ (GCompareFunc)strcmp) != NULL);
+ LEAVE("defaults says %d", visible);
+ return visible;
+}
+
+/** This function updates the visibility of a single column. It
+ * checks if the column should be visible, and if so tells the view
+ * to show the column and (f needed) updates the gconf database.
+ *
+ * @param column The column whose visibility should be updated.
+ *
+ * @param view The GncTreeView containing the column.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_update_visibility (GtkTreeViewColumn *column,
+ GncTreeView *view)
+{
+ gchar *name, *key;
+ gboolean visible;
+
+ g_return_if_fail(GTK_IS_TREE_VIEW_COLUMN(column));
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ ENTER(" ");
+ visible = gnc_tree_view_column_visible(view, column, NULL);
+ gtk_tree_view_column_set_visible(column, visible);
+ if (view->priv->gconf_section) {
+ name = (gchar *)g_object_get_data(G_OBJECT(column), PREF_NAME);
+ if (!name) {
+ LEAVE("no pref name");
+ return;
+ }
+ key = g_strdup_printf("%s_%s", name, GCONF_KEY_VISIBLE);
+ gnc_gconf_set_bool(view->priv->gconf_section, key, visible, NULL);
+ g_free(key);
+ LEAVE("made visible, set gconf key");
+ return;
+ }
+ LEAVE("made visible");
+}
+
+/** This function is called via the gconf notification callback when
+ * the sort order has changed in gconf. It must update the model
+ * sort order to match what is specified in gconf. The sort column
+ * used will be whatever is the current sort column. This function
+ * is careful to prevent an infinite loop by blocking the
+ * "sort-column-changed" callback that is attached to the model.
+ *
+ * @param widget The tree view.
+ *
+ * @param name The sort order enum (in string form). Either
+ * "ascending" or "descending".
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_set_sort_order (GncTreeView *view,
+ const gchar *name)
+{
+ GtkTreeModel *s_model;
+ GtkSortType order;
+ gint current;
+
+ s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+ if (!s_model)
+ return;
+ order = gnc_enum_from_nick(GTK_TYPE_SORT_TYPE, name, GTK_SORT_ASCENDING);
+ if (!gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(s_model),
+ ¤t, &order))
+ current = 0;
+ g_signal_handler_block(s_model, view->priv->sort_column_changed_cb_id);
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
+ current, order);
+ g_signal_handler_unblock(s_model, view->priv->sort_column_changed_cb_id);
+ DEBUG("sort_order set to %s", gnc_enum_to_nick(GTK_TYPE_SORT_TYPE, order));
+}
+
+/** This function is called via the gconf notification callback when
+ * the sort column has changed in gconf. It must update the model
+ * sort column to match what is specified in gconf. The sort order
+ * used for this column will be whatever sort order is in use on the
+ * current sort column. This function is careful to prevent an
+ * infinite loop by blocking the "sort-column-changed" callback that
+ * is attached to the model.
+ *
+ * @param widget The tree view.
+ *
+ * @param name The name of the column that should be made the sort column.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_set_sort_column (GncTreeView *view,
+ const gchar *name)
+{
+ GtkTreeModel *s_model;
+ GtkTreeViewColumn *column;
+ GtkSortType order;
+ gint model_column, current;
+
+ column = view_column_find_by_name(view, name);
+ if (!column)
+ return;
+
+ model_column =
+ GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), MODEL_COLUMN));
+ if (model_column == GNC_TREE_VIEW_COLUMN_DATA_NONE)
+ return;
+
+ s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+ if (!gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(s_model),
+ ¤t, &order))
+ order = GTK_SORT_ASCENDING;
+ g_signal_handler_block(s_model, view->priv->sort_column_changed_cb_id);
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
+ model_column, order);
+ g_signal_handler_unblock(s_model, view->priv->sort_column_changed_cb_id);
+ DEBUG("sort column set to %s", name);
+}
+
+/** This function is called via the gconf notification callback when
+ * the column order has changed in gconf. It must update the order
+ * of the columns in the model to match what is specified in gconf.
+ * This function is careful to prevent an infinite loop by blocking
+ * the "columns-changed" callback that is attached to the view.
+ *
+ * @param widget The tree view.
+ *
+ * @param name A list of pointers to strings. These strings are the
+ * names of the columns in the order they should appear.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_set_column_order (GncTreeView *view,
+ const GSList *column_names)
+{
+ GtkTreeViewColumn *column, *prev;
+ const gchar *name;
+ const GSList *tmp;
+ GSList *columns;
+
+ /* First, convert from names to pointers */
+ ENTER(" ");
+ columns = NULL;
+ for (tmp = column_names; tmp; tmp = g_slist_next(tmp)) {
+ name = gconf_value_get_string(tmp->data);
+ column = view_column_find_by_name(view, name);
+ if (!column)
+ continue;
+ columns = g_slist_append(columns, column);
+ }
+
+ /* Then reorder the columns */
+ g_signal_handler_block(view, view->priv->columns_changed_cb_id);
+ for (prev = NULL, tmp = columns; tmp; tmp = g_slist_next(tmp)) {
+ column = tmp->data;
+ gtk_tree_view_move_column_after(GTK_TREE_VIEW(view), column, prev);
+ prev = column;
+ }
+ g_signal_handler_unblock(view, view->priv->columns_changed_cb_id);
+
+ /* Clean up */
+ g_slist_free(columns);
+ LEAVE("column order set");
+}
+
+/** This function is called via the gconf notification callback when
+ * any change has occurred. It must update the appropriate aspect of
+ * the model/view to match what is specified in gconf. Some of the
+ * updates are handled in this function, while others are handled by
+ * other helper functions.
+ *
+ * @param client A pointer to the gconf client object from which
+ * detected a change in gconf. Unused by this function.
+ *
+ * @cnxn_id The identifier for the notification that this callback
+ * represents. Unused since this code only has a single notification
+ * request.
+ *
+ * @entry A pointer to the key/value pair in gconf that changed.
+ *
+ * @param data The tree view.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_gconf_changed (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
+{
+ GncTreeView *view;
+ GtkTreeViewColumn *column;
+ GConfValue *value;
+ const gchar *key, *local;
+ gchar *column_name, *type_name;
+ gboolean known;
+ gint width;
+
+ g_return_if_fail(GNC_IS_TREE_VIEW(data));
+
+ ENTER(" ");
+ view = GNC_TREE_VIEW(data);
+ key = gconf_entry_get_key(entry);
+ value = gconf_entry_get_value(entry);
+ if (!value) {
+ /* Values can be unset */
+ LEAVE("Unset valued for %s", key);
+ return;
+ }
+
+ DEBUG("Key %s, value %p", key, value);
+ local = rindex(key, '/')+1;
+ if (strcmp(local, GCONF_KEY_SORT_COLUMN) == 0) {
+ gnc_tree_view_set_sort_column(view, gconf_value_get_string(value));
+ } else if (strcmp(local, GCONF_KEY_SORT_ORDER) == 0) {
+ gnc_tree_view_set_sort_order(view, gconf_value_get_string(value));
+ } else if (strcmp(local, GCONF_KEY_COLUMN_ORDER) == 0) {
+ gnc_tree_view_set_column_order(view, gconf_value_get_list(value));
+ } else {
+ /* Make a copy of the local part of the key so it can be split
+ * into column name and key type */
+ known = FALSE;
+ column_name = strdup(local);
+ type_name = rindex(column_name, '_');
+ *type_name++ = '\0';
+
+ if (strcmp(type_name, GCONF_KEY_VISIBLE) == 0) {
+ view->priv->seen_gconf_visibility = TRUE;
+ column = view_column_find_by_name(view, column_name);
+ if (column) {
+ known = TRUE;
+ if (!g_object_get_data(G_OBJECT(column), ALWAYS_VISIBLE)) {
+ gtk_tree_view_column_set_visible(column, gconf_value_get_bool(value));
+ }
+ }
+ } else if (strcmp(type_name, GCONF_KEY_WIDTH) == 0) {
+ width = gconf_value_get_int(value);
+ column = view_column_find_by_name(view, column_name);
+ if (column) {
+ known = TRUE;
+ if (width && (width != gtk_tree_view_column_get_width(column))) {
+ gtk_tree_view_column_set_fixed_width(column, width);
+ }
+ }
+ }
+ if (!known) {
+ DEBUG("Ignored key %s", key);
+ }
+ g_free(column_name);
+ }
+ LEAVE(" ");
+}
+
+/** This function is called force synchronization between the gconf
+ * database and a tree view. It will be called for major events like
+ * assigning a gconf section to a tree view. All values in gconf
+ * will be propagated into the view. This function simply requests a
+ * list of all key in the section from gconf, then feeds them one at
+ * a time to gnc_tree_view_gconf_changed().
+ *
+ * @param view The tree view.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_gconf_force_update (GncTreeView *view)
+{
+ GSList *all_entries, *etmp;
+ GList *columns;
+
+ ENTER("view %p", view);
+ all_entries = gnc_gconf_client_all_entries(G_OBJECT(view),
+ view->priv->gconf_section);
+
+ /* Set a flag indicating that the gconf data section may be empty.
+ * It will be checked later on and appropriate action taken if its
+ * still set. */
+ view->priv->seen_gconf_visibility = FALSE;
+
+ /* Pull all the entries from gconf */
+ for (etmp = all_entries; etmp; etmp = g_slist_next(etmp)) {
+ gnc_tree_view_gconf_changed(NULL, 0, etmp->data, view);
+ gconf_entry_free(etmp->data);
+ }
+ g_slist_free(all_entries);
+
+ /* No visibilities seen yet. Write out any columns we may have */
+ if (!view->priv->seen_gconf_visibility) {
+ columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
+ g_list_foreach(columns, (GFunc)gnc_tree_view_update_visibility, view);
+ g_list_free(columns);
+ }
+
+ LEAVE(" ");
+}
+
+/** This internal function is called to disconnect a tree view from a
+ * gconf section. It first disconnects any signals that are in
+ * effect on the model/view, then removes the gconf notification
+ * callback, then clears the gconf section string. This function may
+ * be called at any time; either when the user wants to disconnect or
+ * when the view object is being destroyed.
+ *
+ * @param view The tree view.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_remove_gconf(GncTreeView *view)
+{
+ GtkTreeModel *model;
+
+ ENTER(" ");
+ if (!view->priv->gconf_section) {
+ LEAVE("no gconf section");
+ return;
+ }
+
+ if (view->priv->sort_column_changed_cb_id) {
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW(view));
+ if (model) {
+ DEBUG("removing sort_column_changed callback (# %ld)",
+ view->priv->sort_column_changed_cb_id);
+ g_signal_handler_disconnect(GTK_TREE_SORTABLE(model),
+ view->priv->sort_column_changed_cb_id);
+ view->priv->sort_column_changed_cb_id = 0;
+ }
+ }
+
+ if (view->priv->columns_changed_cb_id) {
+ DEBUG("removing columns_changed callback (# %ld)",
+ view->priv->columns_changed_cb_id);
+ g_signal_handler_disconnect(view, view->priv->columns_changed_cb_id);
+ view->priv->columns_changed_cb_id = 0;
+ }
+
+ if (view->priv->size_allocate_cb_id) {
+ DEBUG("removing size_allocate callback (# %ld)",
+ view->priv->size_allocate_cb_id);
+ g_signal_handler_disconnect(view, view->priv->size_allocate_cb_id);
+ view->priv->size_allocate_cb_id = 0;
+ }
+
+ DEBUG("removing gconf notification");
+ gnc_gconf_remove_notification(G_OBJECT(view), view->priv->gconf_section);
+ g_free(view->priv->gconf_section);
+ view->priv->gconf_section = NULL;
+ LEAVE(" ");
+}
+
+/** This function is called to set up or remove an association between
+ * a gconf section and the display of a view. It will first remove
+ * any existing association, and then install the new one. This
+ * involves storing the gconf section value, requesting notification
+ * from gconf of any changes to keys in that section, then attaching
+ * several signals to catch user changes to the view.
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+void
+gnc_tree_view_set_gconf_section (GncTreeView *view,
+ const gchar *section)
+{
+ GtkTreeModel *model;
+ gulong id;
+
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ ENTER("view %p, section %s", view, section);
+ gnc_tree_view_remove_gconf(view);
+
+ if (!section) {
+ LEAVE("cleared gconf section");
+ return;
+ }
+
+ /* Catch changes in gconf. Propagate to view. */
+ view->priv->gconf_section = g_strdup(section);
+ gnc_gconf_add_notification(G_OBJECT(view), section,
+ gnc_tree_view_gconf_changed);
+
+ /* Catch changes to the sort column. Propagate to gconf. The key can
+ * be set before the model, so the code must handle that case. */
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW(view));
+ if (model)
+ view->priv->sort_column_changed_cb_id =
+ g_signal_connect(GTK_TREE_SORTABLE(model), "sort-column-changed",
+ (GCallback)gtk_tree_view_sort_column_changed_cb, view);
+
+ /* Catch changes to the column order. Propagate to gconf */
+ id = g_signal_connect(view, "columns-changed",
+ (GCallback)gtk_tree_view_columns_changed_cb, NULL);
+ view->priv->columns_changed_cb_id = id;
+
+ /* Catch changes to the column width. Propagate to gconf */
+ id = g_signal_connect(view, "size-allocate",
+ (GCallback)gtk_tree_view_size_allocate_cb, NULL);
+ view->priv->size_allocate_cb_id = id;
+
+ /* Force an update of the view with all items from gconf. */
+ gnc_tree_view_gconf_force_update(view);
+
+ /* Rebuild the column visibility menu */
+ gnc_tree_view_build_column_menu(view);
+ LEAVE("set gconf section");
+}
+
+/** This function is called to get the current association between a
+ * gconf section and the display of a view. It returns the same
+ * value passed to gnc_tree_view_set_gconf_section(); i.e. a string
+ * like "dialogs/edit_prices".
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+const gchar *
+gnc_tree_view_get_gconf_section (GncTreeView *view)
+{
+ g_return_val_if_fail(GNC_IS_TREE_VIEW(view), NULL);
+
+ return(view->priv->gconf_section);
+}
+
+
+/** @} */
+
+/************************************************************/
+/* Column Selection Menu */
+/************************************************************/
+
+/** @name Gnc Tree View Column Selection Menu Related Functions
+ @{ */
+
+/** This function is called when an entry in the column selection menu
+ * is toggled. It must update gconf with the current value of the
+ * checkbox. This will trigger a callback to other functions which
+ * will then change the actual state of the view.
+ *
+ * @param checkmenuitem A checkbox visible in the menu.
+ *
+ * @param view The tree view.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_menu_item_toggled (GtkCheckMenuItem *checkmenuitem,
+ GncTreeView *view)
+{
+ gboolean value;
+ gchar *key;
+
+ g_return_if_fail(GTK_IS_CHECK_MENU_ITEM(checkmenuitem));
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ ENTER("checkmenuitem %p, view %p", checkmenuitem, view);
+ if (!view->priv->gconf_section) {
+ LEAVE("no gconf section");
+ return;
+ }
+
+ key = g_object_get_data(G_OBJECT(checkmenuitem), GCONF_KEY);
+ value = gtk_check_menu_item_get_active(checkmenuitem);
+ gnc_gconf_set_bool(view->priv->gconf_section, key, value, NULL);
+ LEAVE("set gconf section %s, key %s, visible %d",
+ view->priv->gconf_section, key, value);
+}
+
+/** This function is called to create a single checkmenuitem in the
+ * column selection menu. It is called once for each column in the
+ * view. It creates a menu item for the corresponding column, and
+ * attaches to it a copy of the gconf key for this column's
+ * visibility. This makes the toggle callback function trivial.
+ *
+ * This function will create the column selection menu if one doesn't
+ * already exist.
+ *
+ * @param column Create a menu item for this column.
+ *
+ * @param view The tree view.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_create_menu_item (GtkTreeViewColumn *column,
+ GncTreeView *view)
+{
+ GncTreeViewPrivate *priv;
+ GtkWidget *widget;
+ const gchar *column_name, *pref_name;
+ gulong id;
+ gchar *key;
+
+ // ENTER("view %p, column %p", view, column);
+ priv = view->priv;
+ if (!priv->gconf_section) {
+ // LEAVE("no gconf section");
+ return;
+ }
+
+ pref_name = g_object_get_data(G_OBJECT(column), PREF_NAME);
+ if (!pref_name) {
+ // LEAVE("column has no pref_name");
+ return;
+ }
+
+ /* Create the menu if we don't have one already */
+ if (!priv->column_menu) {
+ priv->column_menu = gtk_menu_new();
+ g_object_ref(priv->column_menu);
+ gtk_object_sink(GTK_OBJECT(priv->column_menu));
+ }
+
+ /* Create the check menu item */
+ column_name = g_object_get_data(G_OBJECT(column), REAL_TITLE);
+ if (!column_name)
+ column_name = gtk_tree_view_column_get_title(column);
+ widget = gtk_check_menu_item_new_with_label(column_name);
+ gtk_menu_shell_append(GTK_MENU_SHELL(priv->column_menu), widget);
+
+ /* Should never be able to hide the first column */
+ if (g_object_get_data(G_OBJECT(column), ALWAYS_VISIBLE)) {
+ g_object_set_data(G_OBJECT(widget), ALWAYS_VISIBLE, GINT_TO_POINTER(1));
+ gtk_widget_set_sensitive(widget, FALSE);
+ }
+
+ /* Set up the callback */
+ id = g_signal_connect(widget, "toggled",
+ (GCallback)gnc_tree_view_menu_item_toggled, view);
+
+ /* Store data on the widget for callbacks */
+ key = g_strdup_printf("%s_%s", pref_name, GCONF_KEY_VISIBLE);
+ g_object_set_data_full(G_OBJECT(widget), GCONF_KEY, key, g_free);
+ // LEAVE(" ");
+}
+
+/** This function is called to build the column selection menu. It
+ * first destroys any old column selection menu, then checks to see
+ * if a new menu should be built. If so, it calls the
+ * gnc_tree_view_create_menu_item() for each column in the view.
+ * This function is invoked then either the "gconf-section" or the
+ * "show-column-menu" property is changed on the view.
+ *
+ * @param view Build a selection menu for this tree view.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_build_column_menu (GncTreeView *view)
+{
+ GncTreeViewPrivate *priv;
+ GList *column_list;
+
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ ENTER("view %p", view);
+ priv = GNC_TREE_VIEW(view)->priv;
+
+ /* Destroy any old menu */
+ if (priv->column_menu) {
+ gtk_widget_unref(priv->column_menu);
+ priv->column_menu = NULL;
+ }
+
+ if (priv->show_column_menu && priv->gconf_section) {
+ /* Show the menu popup button */
+ if (view->priv->column_menu_column)
+ g_object_set(G_OBJECT(view->priv->column_menu_column),
+ "visible", TRUE, NULL);
+
+ /* Now build a new menu */
+ column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
+ g_list_foreach(column_list, (GFunc)gnc_tree_view_create_menu_item, view);
+ g_list_free(column_list);
+ } else {
+ /* Hide the menu popup button */
+ if (view->priv->column_menu_column)
+ g_object_set(G_OBJECT(view->priv->column_menu_column),
+ "visible", FALSE, NULL);
+ }
+ LEAVE("menu: show %d, section %s", priv->show_column_menu,
+ priv->gconf_section);
+}
+
+/** This function is called to synchronize the checkbox on a menu item
+ * with the current gconf visibility value for the corresponding
+ * column (which will be the visibility of the column if the rest of
+ * the code in this file is working correctly). It simply takes the
+ * gconf key attached to the menu item, reads it, and sets the menu
+ * item to the retrieved value. It does take care to block signals
+ * from the menu item to prevent updating gconf (since the value was
+ * just read from gconf).
+ *
+ * @param checkmenuitem The menu item to update.
+ *
+ * @param view The tree view.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_update_column_menu_item (GtkCheckMenuItem *checkmenuitem,
+ GncTreeView *view)
+{
+ gchar *key;
+ gboolean visible;
+
+ g_return_if_fail(GTK_IS_CHECK_MENU_ITEM(checkmenuitem));
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ key = g_object_get_data(G_OBJECT(checkmenuitem), GCONF_KEY);
+ if (g_object_get_data(G_OBJECT(checkmenuitem), ALWAYS_VISIBLE)) {
+ visible = TRUE;
+ } else {
+ visible = gnc_gconf_get_bool(view->priv->gconf_section, key, NULL);
+ }
+
+ g_signal_handlers_block_by_func(checkmenuitem,
+ gnc_tree_view_menu_item_toggled, view);
+ gtk_check_menu_item_set_active(checkmenuitem, visible);
+ g_signal_handlers_unblock_by_func(checkmenuitem,
+ gnc_tree_view_menu_item_toggled, view);
+}
+
+/** This function when the user clicks on the button to show the
+ * column selection menu. It first synchronize the checkboxes on all
+ * menu item with the gconf visibility values. It then pops up the
+ * menu for the user to choose from.
+ *
+ * @param column The tree column containing the column selection
+ * button.
+ *
+ * @param view The tree view.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_select_column_cb (GtkTreeViewColumn *column,
+ GncTreeView *view)
+{
+ GtkWidget *widget, *menu;
+
+ g_return_if_fail(GTK_IS_TREE_VIEW_COLUMN(column));
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ menu = view->priv->column_menu;
+ if (!menu)
+ return;
+
+ /* Synchronize the menu before display */
+ gtk_container_foreach(GTK_CONTAINER(menu),
+ (GtkCallback)gnc_tree_view_update_column_menu_item,
+ view);
+
+ /* Ensure all components are visible */
+ gtk_widget_show_all(menu);
+
+ /* Pop the menu up at the button */
+ widget = gtk_tree_view_column_get_widget(column);
+ gtk_menu_popup(GTK_MENU(view->priv->column_menu), NULL, GTK_WIDGET(menu),
+ NULL, NULL, 0, gtk_get_current_event_time());
+}
+
+/** This function is called to set the "show-column-menu" property on
+ * this view. This function has no visible effect if the
+ * "gconf-section" property has not been set.
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+void
+gnc_tree_view_set_show_column_menu (GncTreeView *view,
+ gboolean visible)
+{
+ GncTreeViewPrivate *priv;
+
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ ENTER("view %p, show menu %d", view, visible);
+ priv = GNC_TREE_VIEW(view)->priv;
+ priv->show_column_menu = visible;
+ gnc_tree_view_build_column_menu(view);
+ LEAVE(" ");
+}
+
+/** This function is called to get the current value of the
+ * "show-column-menu" property. It returns the same value passed to
+ * gnc_tree_view_set_show_menu_column().
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+gboolean
+gnc_tree_view_get_show_column_menu (GncTreeView *view)
+{
+ g_return_val_if_fail(GNC_IS_TREE_VIEW(view), FALSE);
+
+ return(view->priv->show_column_menu);
+}
+
+/** @} */
+
+/************************************************************/
+/* Tree View Creation */
+/************************************************************/
+
+/** Attach a data model to a visible GncTreeView widget. Users of
+ * this view object must use this function instead of directly
+ * calling the gtk_tree_view_set_model function. This function takes
+ * the additional step of attaching a callback function to the model
+ * to catch any changes to the sorting of the model. These changes
+ * are propagated into gconf by the callback function.
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+void
+gnc_tree_view_set_model(GncTreeView *view, GtkTreeModel *model)
+{
+ GtkTreeModel *old_model;
+
+ /* Remove existing callback */
+ if (view->priv->sort_column_changed_cb_id) {
+ old_model = gtk_tree_view_get_model (GTK_TREE_VIEW(view));
+ g_signal_handler_disconnect (old_model,
+ view->priv->sort_column_changed_cb_id);
+ view->priv->sort_column_changed_cb_id = 0;
+ }
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW(view), model);
+
+ /* Maybe add a new callback */
+ if (model && view->priv->gconf_section) {
+ view->priv->sort_column_changed_cb_id =
+ g_signal_connect(GTK_TREE_SORTABLE(model), "sort-column-changed",
+ (GCallback)gtk_tree_view_sort_column_changed_cb, view);
+ }
+}
+
+/** Configure (by name) the default set of visible columns in an gnc
+ * tree view. This is the list of columns that will be shown if the
+ * view isn't using gconf to manage column visibility. If gconf is
+ * used, this list will be used the very first time the view is
+ * presented to the user, then gconf will be used after that. The
+ * available list of columns can be found in the file
+ * gnc-tree-view-xxx.c.
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+void
+gnc_tree_view_configure_columns (GncTreeView *view,
+ gchar *first_column_name,
+ ...)
+{
+ GSList *slist;
+ GList *columns;
+ gchar *name;
+ va_list args;
+
+ g_return_if_fail(GNC_IS_TREE_VIEW(view));
+
+ ENTER(" ");
+ /* Delete any old list of column names */
+ if (view->priv->default_visible) {
+ slist = view->priv->default_visible;
+ view->priv->default_visible = NULL;
+ g_slist_foreach(slist, (GFunc)g_free, NULL);
+ g_slist_free(slist);
+ }
+
+ /* Build a new list */
+ va_start (args, first_column_name);
+ name = first_column_name;
+ while (name != NULL) {
+ view->priv->default_visible =
+ g_slist_append(view->priv->default_visible, g_strdup(name));
+ name = va_arg(args, gchar*);
+ }
+ va_end (args);
+
+ /* Update the view and gconf */
+ columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
+ g_list_foreach(columns, (GFunc)gnc_tree_view_update_visibility, view);
+ g_list_free(columns);
+
+ if (view->priv->gconf_section)
+ view->priv->seen_gconf_visibility = TRUE;
+ LEAVE(" ");
+}
+
+
+/** This internal function sets a variety of common properties on a
+ * newly created GtkTreeViewColumn and its renderer.
+ *
+ * @param view A pointer to a generic GncTreeView.
+ *
+ * @param column The newly created tree view column.
+ *
+ * @param pref_name The internal name of this column. This name is
+ * used in several functions to look up the column, and it is also
+ * used to create the keys used to record the column width and
+ * visibility in gconf.
+ *
+ * @param data_column The index of the GtkTreeModel data column used
+ * to determine the data that will be displayed in this column for
+ * each row in the view. Use GNC_TREE_VIEW_COLUMN_DATA_NONE if you
+ * plan on using an non-model data source for this column.
+ *
+ * @param default_width The width this column should be if not
+ * specified by gconf. If the this value is zero, the column will
+ * be marked as automatically sized.
+ *
+ * @param resizable Whether to mark the column as user resizable.
+ * This marking is only relevant for fixed width columns.
+ *
+ * @param column_sort_function The function that GtkTreeModelSort
+ * will call to compare two rows to determine their displayed order.
+ *
+ * @internal
+ */
+static void
+gnc_tree_view_column_properties (GncTreeView *view,
+ GtkTreeViewColumn *column,
+ const gchar *pref_name,
+ gint data_column,
+ gint default_width,
+ gboolean resizable,
+ GtkTreeIterCompareFunc column_sort_fn)
+{
+ GtkTreeModel *s_model;
+ gboolean visible;
+ int width = 0;
+ gchar *key;
+
+ /* Set data used by other functions */
+ if (pref_name)
+ g_object_set_data(G_OBJECT(column), PREF_NAME, (gpointer)pref_name);
+ if (data_column == 0)
+ g_object_set_data(G_OBJECT(column), ALWAYS_VISIBLE, GINT_TO_POINTER(1));
+ if (data_column != GNC_TREE_VIEW_COLUMN_DATA_NONE)
+ g_object_set_data(G_OBJECT(column), MODEL_COLUMN,
+ GINT_TO_POINTER(data_column));
+
+ /* Get visibility */
+ visible = gnc_tree_view_column_visible(view, NULL, pref_name);
+
+ /* Get width */
+ if (view->priv->gconf_section) {
+ key = g_strdup_printf("%s_%s", pref_name, GCONF_KEY_WIDTH);
+ width = gnc_gconf_get_int(view->priv->gconf_section, key, NULL);
+ g_free(key);
+ }
+
+ /* If gconf comes back with a width of zero (or there is no gconf
+ * width) the use the default width for the column. Allow for
+ * padding L and R of the displayed data. */
+ if (width == 0)
+ width = default_width + 10;
+ if (width == 0)
+ width = 10;
+
+ /* Set column attributes */
+ g_object_set(G_OBJECT(column),
+ "visible", visible,
+ "sizing", GTK_TREE_VIEW_COLUMN_FIXED,
+ "fixed-width", width,
+ "resizable", resizable && pref_name != NULL,
+ "reorderable", pref_name != NULL,
+ NULL);
+
+ s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+ if (GTK_IS_TREE_MODEL_SORT(s_model)) {
+ gtk_tree_view_column_set_sort_column_id (column, data_column);
+ if (column_sort_fn) {
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(s_model),
+ data_column, column_sort_fn,
+ NULL /* user_data */,
+ NULL /* destroy fn */);
+ }
+ }
+
+ /* Add to the column selection menu */
+ if (pref_name) {
+ gnc_tree_view_create_menu_item(column, view);
+ }
+}
+
+/** This function adds a new toggle column to a GncTreeView base view.
+ * It takes all the parameters necessary to hook a GtkTreeModel
+ * column to a GtkTreeViewColumn. It handles creating a tooltip to
+ * show the full title name, and setting the sort and edit callback
+ * functions. If the tree has a gconf section associated with it,
+ * this function also wires up the column so that its visibility and
+ * width are remembered.
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+GtkTreeViewColumn *
+gnc_tree_view_add_toggle_column (GncTreeView *view,
+ const gchar *column_title,
+ const gchar *column_short_title,
+ const gchar *pref_name,
+ gint model_data_column,
+ gint model_visibility_column,
+ GtkTreeIterCompareFunc column_sort_fn,
+ renderer_toggled toggle_edited_cb)
+{
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ PangoLayout* layout;
+ int title_width;
+
+ g_return_val_if_fail (GNC_IS_TREE_VIEW(view), NULL);
+
+ renderer = gtk_cell_renderer_toggle_new ();
+ column =
+ gtk_tree_view_column_new_with_attributes (gettext(column_short_title),
+ renderer,
+ "active", model_data_column,
+ NULL);
+
+ /* Add the full title to the object for menu creation */
+ g_object_set_data_full(G_OBJECT(column), REAL_TITLE,
+ g_strdup(column_title), g_free);
+ if (toggle_edited_cb)
+ g_signal_connect(G_OBJECT(renderer), "toggled",
+ G_CALLBACK(toggle_edited_cb), view);
+
+ if (model_visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "visible", model_visibility_column);
+
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET(view),
+ column_short_title);
+ pango_layout_get_pixel_size(layout, &title_width, NULL);
+ g_object_unref(layout);
+
+ gnc_tree_view_column_properties (view, column, pref_name, model_data_column,
+ title_width, FALSE, column_sort_fn);
+
+ gnc_tree_view_append_column (view, column);
+
+ /* Also add the full title to the object as a tooltip */
+ if (!view->priv->title_tips)
+ view->priv->title_tips = gtk_tooltips_new();
+ gtk_tooltips_set_tip(view->priv->title_tips,
+ column->button,
+ column_title, NULL);
+
+ return column;
+}
+
+/** This function adds a new text column to a GncTreeView base view.
+ * It takes all the parameters necessary to hook a GtkTreeModel
+ * column to a GtkTreeViewColumn. If the tree has a gconf section
+ * associated with it, this function also wires up the column so that
+ * its visibility and width are remembered.
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+GtkTreeViewColumn *
+gnc_tree_view_add_text_column (GncTreeView *view,
+ const gchar *column_title,
+ const gchar *pref_name,
+ const gchar *stock_icon_name,
+ const gchar *sizing_text,
+ gint model_data_column,
+ gint model_visibility_column,
+ GtkTreeIterCompareFunc column_sort_fn)
+{
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ PangoLayout* layout;
+ int default_width, title_width;
+
+ g_return_val_if_fail (GNC_IS_TREE_VIEW(view), NULL);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, gettext(column_title));
+
+ /* Set up an icon renderer if requested */
+ if (stock_icon_name) {
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "stock-id", stock_icon_name, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ }
+
+ /* Set up a text renderer and attributes */
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+
+ /* Set renderer attributes controlled by the model */
+ if (model_data_column != GNC_TREE_VIEW_COLUMN_DATA_NONE)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "text", model_data_column);
+ if (model_visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "visible", model_visibility_column);
+
+ /* Default size is the larger of the column title and the sizing text */
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), column_title);
+ pango_layout_get_pixel_size(layout, &title_width, NULL);
+ g_object_unref(layout);
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), sizing_text);
+ pango_layout_get_pixel_size(layout, &default_width, NULL);
+ g_object_unref(layout);
+ default_width = MAX(default_width, title_width);
+ if (default_width)
+ default_width += 10; /* padding on either side */
+ gnc_tree_view_column_properties (view, column, pref_name, model_data_column,
+ default_width, TRUE, column_sort_fn);
+
+ gnc_tree_view_append_column (view, column);
+ return column;
+}
+
+/** This function adds a new numeric column to a GncTreeView base
+ * view. It takes all the parameters necessary to hook a
+ * GtkTreeModel column to a GtkTreeViewColumn. If the tree has a
+ * gconf section associated with it, this function also wires up the
+ * column so that its visibility and width are remembered. A numeric
+ * column is nothing more then a text column with a few extra
+ * attributes.
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+GtkTreeViewColumn *
+gnc_tree_view_add_numeric_column (GncTreeView *view,
+ const gchar *column_title,
+ const gchar *pref_name,
+ const gchar *sizing_text,
+ gint model_data_column,
+ gint model_color_column,
+ gint model_visibility_column,
+ GtkTreeIterCompareFunc column_sort_fn)
+{
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GList *renderers;
+
+ column = gnc_tree_view_add_text_column (view, column_title, pref_name,
+ NULL, sizing_text, model_data_column,
+ model_visibility_column,
+ column_sort_fn);
+
+ /* Get the list of one renderer */
+ renderers = gtk_tree_view_column_get_cell_renderers(column);
+ renderer = renderers->data;
+ g_list_free(renderers);
+
+ /* Right align the column title and data */
+ g_object_set(G_OBJECT(column), "alignment", 1.0, NULL);
+ g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
+
+ /* Change the text color */
+ if (model_color_column != GNC_TREE_VIEW_COLUMN_COLOR_NONE)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "foreground", model_color_column);
+
+ return column;
+}
+
+/** Add a column to a view based upon a GncTreeView. This function
+ * knows about the two special columns on the right side of this type
+ * of view, and adds the new column before these two columns. You
+ * could say that it appends to the data columns and ignores the
+ * infrastructure columns.
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+gint
+gnc_tree_view_append_column (GncTreeView *view,
+ GtkTreeViewColumn *column)
+{
+ GList *columns;
+ int n;
+
+ /* There's no easy way to get this number. */
+ columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
+ n = g_list_length(columns);
+ g_list_free(columns);
+
+ /* Ignore the initial two columns (the spacer and the selection menu) */
+ if (n >= 2)
+ n -= 2;
+ return gtk_tree_view_insert_column (GTK_TREE_VIEW(view), column, n);
+}
+
+/** @} */
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/Makefile.am,v
retrieving revision 1.48.2.28
retrieving revision 1.48.2.29
diff -Lsrc/gnome-utils/Makefile.am -Lsrc/gnome-utils/Makefile.am -u -r1.48.2.28 -r1.48.2.29
--- src/gnome-utils/Makefile.am
+++ src/gnome-utils/Makefile.am
@@ -74,9 +74,9 @@
gnc-tree-model-example-account.c \
gnc-tree-model-price.c \
gnc-tree-model-selection.c \
+ gnc-tree-view.c \
gnc-tree-view-account.c \
gnc-tree-view-commodity.c \
- gnc-tree-view-common.c \
gnc-tree-view-price.c \
gncmod-gnome-utils.c \
misc-gnome-utils.c \
@@ -124,9 +124,9 @@
gnc-tree-model-example-account.h \
gnc-tree-model-price.h \
gnc-tree-model-selection.h \
+ gnc-tree-view.h \
gnc-tree-view-account.h \
gnc-tree-view-commodity.h \
- gnc-tree-view-common.h \
gnc-tree-view-price.h \
misc-gnome-utils.h \
print-session.h
--- /dev/null
+++ src/gnome-utils/gnc-tree-view.h
@@ -0,0 +1,350 @@
+/********************************************************************\
+ * gnc-tree-view.h -- new GtkTreeView with extra features used by *
+ * all the tree views in gnucash *
+ * Copyright (C) 2003 David Hampton <hampton at 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 *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup GUI
+ @{ */
+/** @file gnc-tree-view.h
+ @brief common utilities for manipulating a GtkTreeView within gnucash
+ @author David Hampton <hampton at employees.org>
+*/
+
+#ifndef __GNC_TREE_VIEW_H
+#define __GNC_TREE_VIEW_H
+
+#include <gtk/gtktreemodel.h>
+#include <gtk/gtktreeview.h>
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_TREE_VIEW (gnc_tree_view_get_type ())
+#define GNC_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_TREE_VIEW, GncTreeView))
+#define GNC_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_TREE_VIEW, GncTreeViewClass))
+#define GNC_IS_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_TREE_VIEW))
+#define GNC_IS_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_TREE_VIEW))
+#define GNC_TREE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_TREE_VIEW, GncTreeViewClass))
+
+/* typedefs & structures */
+typedef struct GncTreeViewPrivate GncTreeViewPrivate;
+
+typedef struct {
+ GtkTreeView parent;
+
+ GncTreeViewPrivate *priv;
+} GncTreeView;
+
+typedef struct {
+ GtkTreeViewClass parent;
+} GncTreeViewClass;
+
+/* Standard g_object type */
+GType gnc_tree_view_get_type (void);
+
+
+
+
+
+#define GNC_TREE_VIEW_COLUMN_DATA_NONE -1
+#define GNC_TREE_VIEW_COLUMN_COLOR_NONE -1
+#define GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS -1
+
+
+typedef void (* renderer_toggled) (GtkCellRendererToggle *cell_renderer_toggle,
+ const gchar *path,
+ gpointer user_data);
+
+
+/** @name Tree View Creation */
+/** @{ */
+
+/** This function adds a new toggle column to a GncTreeView base view.
+ * It takes all the parameters necessary to hook a GtkTreeModel
+ * column to a GtkTreeViewColumn. It handles creating a tooltip to
+ * show the full title name, and setting the sort and edit callback
+ * functions. If the tree has a gconf section associated with it,
+ * this function also wires up the column so that its visibility and
+ * width are remembered.
+ *
+ * @param view A pointer to a generic GncTreeView.
+ *
+ * @param column_title The full title for this column. This will be
+ * added as a tooltip what will be displayed when the mouse is
+ * hovered over the column title button.
+ *
+ * @param column_short_title This is what will actually be displayed
+ * as the title of the column. This should be a single character, as
+ * anything more will unnecessarily expand the width of the column.
+ *
+ * @param pref_name The internal name of this column. This name is
+ * used in several functions to look up the column, and it is also
+ * used to create the keys used to record the column width and
+ * visibility in gconf.
+ *
+ * @param model_data_column The index of the GtkTreeModel data column
+ * used to determine whether the displayed checkbox for each row will
+ * be show as checked or empty. Use GNC_TREE_VIEW_COLUMN_DATA_NONE
+ * if you plan on using an non-model data source for this column.
+ *
+ * @param model_visibility_column The index of the GtkTreeModel data
+ * column used to determine whether or not a checkbox for each row
+ * will be displayed at all. Use GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS
+ * if the checkbox should be displayed in all rows.
+ *
+ * @param column_sort_function The function that GtkTreeModelSort
+ * will call to compare two rows to determine their displayed order.
+ *
+ * @param toggle_edited_cb The function to call when the user toggles
+ * the state of a checkbox.
+ *
+ * @return The newly created GtkTreeViewColumn.
+ */
+GtkTreeViewColumn *
+gnc_tree_view_add_toggle_column (GncTreeView *view,
+ const gchar *column_title,
+ const gchar *column_short_title,
+ const gchar *pref_name,
+ gint model_data_column,
+ gint model_visibility_column,
+ GtkTreeIterCompareFunc column_sort_fn,
+ renderer_toggled toggle_edited_cb);
+
+/** This function adds a new text column to a GncTreeView base view.
+ * It takes all the parameters necessary to hook a GtkTreeModel
+ * column to a GtkTreeViewColumn. If the tree has a gconf section
+ * associated with it, this function also wires up the column so that
+ * its visibility and width are remembered.
+ *
+ * @param view A pointer to a generic GncTreeView.
+ *
+ * @param column_title The title for this column. This will be
+ * added as a tooltip what will be displayed when the mouse is
+ * hovered over the column title button.
+ *
+ * @param pref_name The internal name of this column. This name is
+ * used in several functions to look up the column, and it is also
+ * used to create the keys used to record the column width and
+ * visibility in gconf.
+ *
+ * @param stock_icon_name The name of the stock icon to display to
+ * the left of the text in this column. Used for adding icons like
+ * the "account" icon to a view. This must be a registered stock
+ * icon, not a filename.
+ *
+ * @param sizing_text A string used to compute the default width of
+ * the column. This text is never displayed.
+ *
+ * @param model_data_column The index of the GtkTreeModel data column
+ * used to determine the data that will be displayed in this column
+ * for each row in the view. Use GNC_TREE_VIEW_COLUMN_DATA_NONE if
+ * you plan on using an non-model data source for this column.
+ *
+ * @param model_visibility_column The index of the GtkTreeModel data
+ * column used to determine whether or not a checkbox for each row
+ * will be displayed at all. Use GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS
+ * if the checkbox should be displayed in all rows.
+ *
+ * @param column_sort_function The function that GtkTreeModelSort
+ * will call to compare two rows to determine their displayed
+ * order.
+ *
+ * @return The newly created GtkTreeViewColumn.
+ */
+GtkTreeViewColumn *
+gnc_tree_view_add_text_column (GncTreeView *view,
+ const gchar *column_title,
+ const gchar *pref_name,
+ const gchar *stock_icon_name,
+ const gchar *sizing_text,
+ gint model_data_column,
+ gint model_visibility_column,
+ GtkTreeIterCompareFunc column_sort_fn);
+
+/** This function adds a new numeric column to a GncTreeView base
+ * view. It takes all the parameters necessary to hook a
+ * GtkTreeModel column to a GtkTreeViewColumn. If the tree has a
+ * gconf section associated with it, this function also wires up the
+ * column so that its visibility and width are remembered. A numeric
+ * column is nothing more then a text column with a few extra
+ * attributes.
+ *
+ * @param view A pointer to a generic GncTreeView.
+ *
+ * @param column_title The title for this column. This will be
+ * added as a tooltip what will be displayed when the mouse is
+ * hovered over the column title button.
+ *
+ * @param pref_name The internal name of this column. This name is
+ * used in several functions to look up the column, and it is also
+ * used to create the keys used to record the column width and
+ * visibility in gconf.
+ *
+ * @param sizing_text A string used to compute the default width of
+ * the column. This text is never displayed.
+ *
+ * @param model_data_column The index of the GtkTreeModel data column
+ * used to determine the data that will be displayed in this column
+ * for each row in the view. Use GNC_TREE_VIEW_COLUMN_DATA_NONE if
+ * you plan on using an non-model data source for this column.
+ *
+ * @param model_color_column The index of the GtkTreeModel data
+ * column used to determine the foreground color of any text in this
+ * column. It should be used to display negative numbers in red.
+ * Use GNC_TREE_VIEW_COLUMN_COLOR_NONE if the text in this column
+ * should always be displayed in black.
+ *
+ * @param model_visibility_column The index of the GtkTreeModel data
+ * column used to determine whether or not a checkbox for each row
+ * will be displayed at all. Use GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS
+ * if the checkbox should be displayed in all rows.
+ *
+ * @param column_sort_function The function that GtkTreeModelSort
+ * will call to compare two rows to determine their displayed
+ * order.
+ *
+ * @return The newly created GtkTreeViewColumn.
+ */
+GtkTreeViewColumn *
+gnc_tree_view_add_numeric_column (GncTreeView *view,
+ const gchar *column_title,
+ const gchar *pref_name,
+ const gchar *sizing_text,
+ gint model_data_column,
+ gint model_color_column,
+ gint model_visibility_column,
+ GtkTreeIterCompareFunc column_sort_fn);
+
+/** Add a column to a view based upon a GncTreeView. This function
+ * knows about the two special columns on the right side of this type
+ * of view, and adds the new column before these two columns. You
+ * could say that it appends to the data columns and ignores the
+ * infrastructure columns.
+ *
+ * @param view A pointer to a generic GncTreeView.
+ *
+ * @param column The column to append.
+ *
+ * @return The index of the newly added column.
+ */
+gint gnc_tree_view_append_column (GncTreeView *view,
+ GtkTreeViewColumn *column);
+
+/** @} */
+
+
+/** @name Tree View Properties */
+/** @{ */
+
+/** Attach a data model to a visible GncTreeView widget. Users of
+ * this view object must use this function instead of directly
+ * calling the gtk_tree_view_set_model function. This function takes
+ * the additional step of attaching a callback function to the model
+ * to catch any changes to the sorting of the model. These changes
+ * are propagated into gconf by the callback function.
+ *
+ * @param view The visible tree widget.
+ *
+ * @param model The data model to attach.
+ */
+void gnc_tree_view_set_model(GncTreeView *view, GtkTreeModel *model);
+
+/** Configure (by name) the default set of visible columns in an gnc
+ * tree view. This is the list of columns that will be shown if the
+ * view isn't using gconf to manage column visibility. If gconf is
+ * used, this list will be used the very first time the view is
+ * presented to the user, then gconf will be used after that. The
+ * available list of columns can be found in the file
+ * gnc-tree-view-xxx.c.
+ *
+ * @param view A pointer to an gnc tree view.
+ *
+ * @param column_names A list of column names to make visible.
+ */
+void gnc_tree_view_configure_columns (GncTreeView *view,
+ gchar *first_column_name,
+ ...);
+
+/** This function is called to set up or remove an association between
+ * a gconf section and the display of a view. It will first remove
+ * any existing association, and then install the new one. This
+ * involves storing the gconf section value, requesting notification
+ * from gconf of any changes to keys in that section, then attaching
+ * several signals to catch user changes to the view.
+ *
+ * @note This function currently marks the first column as autosized
+ * and all other columns as fixed size (with the size tracked by
+ * gconf). This may change in the future. It must change if we want
+ * to take advantage of the "fixed row height" performance
+ * enhancements added to GtkTreeView in gtk-2.4
+ *
+ * @param view The tree view.
+ *
+ * @param section Link the view to this gconf section. This is
+ * everything after "/apps/gnucash". I.E. "dialogs/edit_prices".
+ * Use NULL to disconnect a gconf association.
+ */
+void gnc_tree_view_set_gconf_section (GncTreeView *view,
+ const gchar *section);
+
+/** This function is called to get the current association between a
+ * gconf section and the display of a view. It returns the same
+ * value passed to gnc_tree_view_set_gconf_section(); i.e. a string
+ * like "dialogs/edit_prices".
+ *
+ * @param view The tree view.
+ *
+ * @return The current gconf section. This is everything after
+ * "/apps/gnucash". I.E "dialogs/edit_prices".
+ */
+const gchar *gnc_tree_view_get_gconf_section (GncTreeView *view);
+
+/** This function is called to set the "show-column-menu" property on
+ * this view. This function has no visible effect if the
+ * "gconf-section" property has not been set.
+ *
+ * @param view The tree view.
+ *
+ * @param visible Create the column selection menu if TRUE.
+ */
+void
+gnc_tree_view_set_show_column_menu (GncTreeView *view,
+ gboolean visible);
+
+/** This function is called to get the current value of the
+ * "show-column-menu" property. It returns the same value passed to
+ * gnc_tree_view_set_show_menu_column().
+ *
+ * @param view The tree view.
+ *
+ * @return Whether or not the column selection menu should be shown.
+ */
+gboolean
+gnc_tree_view_get_show_column_menu (GncTreeView *view);
+
+/** @} */
+
+/** @} */
+
+G_END_DECLS
+
+#endif /* __GNC_TREE_VIEW_H */
--- src/gnome-utils/gnc-tree-view-common.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/********************************************************************\
- * gnc-tree-view-common.h -- common utilities for manipulating a *
- * GtkTreeView within gnucash *
- * Copyright (C) 2003 David Hampton <hampton at 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 *
- * published by the Free Software Foundation; either version 2 of *
- * the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact: *
- * *
- * Free Software Foundation Voice: +1-617-542-5942 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-/** @addtogroup GUI
- @{ */
-/** @addtogroup GuiTreeModel
- * @{ */
-/** @file gnc-tree-view-common.h
- @brief common utilities for manipulating a GtkTreeView within gnucash
- @author David Hampton <hampton at employees.org>
-*/
-
-#ifndef __GNC_TREE_VIEW_COMMON_H
-#define __GNC_TREE_VIEW_COMMON_H
-
-#include <gtk/gtktreemodel.h>
-#include <gtk/gtktreeview.h>
-
-#define GNC_TREE_VIEW_COLUMN_COLOR_NONE -1
-#define GNC_TREE_VIEW_COLUMN_ALIGN_NONE -1
-#define GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS -1
-
-typedef void (* renderer_toggled) (GtkCellRendererToggle *cell_renderer_toggle,
- const gchar *path,
- gpointer user_data);
-
-typedef struct {
- gint column;
- gint visibility_column;
- gint color_column;
- gfloat label_align;
- gint align_column;
- GtkTreeIterCompareFunc sort_fn;
- GtkTreeViewColumnSizing sizing;
- gboolean is_toggle;
- renderer_toggled toggle_edited;
- const char *pref_name;
- const char *field_name;
-} gnc_view_column;
-
-/** @name Tree View Creation State
- @{ */
-
-/** This function creates all the columns in a GtkTreeView. It is
- * passed a data structure that specifies all the details for each
- * column
- *
- * @param view A pointer to a generic GtkTreeView.
- *
- * @param name The name of this view. This string is used for
- * debugging messages only.
- *
- * @param stock_icon The name of the stock icon to use in the first
- * column of the tree. If null, no icon will be included.
- *
- * @param defaults A pointer to the data structure describing the
- * tree view. */
-void gnc_tree_view_common_create_columns (GtkTreeView *view,
- const gchar *tree_name,
- const gchar *stock_icon,
- gnc_view_column *defaults);
-/** @} */
-
-
-/** @name Tree View Save/Restore State
- @{ */
-
-/** This function saves all settings common to a GtkTreeView as used
- * in gnucash. This function currently saves the order in which the
- * column appear in the view, and the visibility and width of each
- * column. If the view is sortable, it also remembers the selected
- * sort column and sort order. A future enhancement will be to make
- * it remember which rows in the tree are expanded.
- *
- * @param view A pointer to a generic GtkTreeView.
- *
- * @param section The name of a gconf section where the tree
- * information should be saved.
- *
- * @param defaults A pointer to the data structure describing the
- * tree view. */
-void gnc_tree_view_common_save_settings (GtkTreeView *view,
- const gchar *section,
- gnc_view_column *defaults);
-
-/** This function restores all the settings common to a GtkTreeView as
- * used in gnucash. This function currently restores the order in
- * which the column appear in the view, and the visibility (but not
- * the width) of each column. If the view is sortable, it also
- * restores the selected sort column and sort order. A future
- * enhancement will be to make it restore which rows in the tree are
- * expanded.
- *
- * @param view A pointer to a generic GtkTreeView.
- *
- * @param section The name of a gconf section where the tree
- * information should be restored from.
- *
- * @param defaults A pointer to the data structure describing the
- * tree view. */
-void gnc_tree_view_common_restore_settings (GtkTreeView *view,
- const gchar *section,
- gnc_view_column *defaults);
-/** @} */
-
-
-/** @} */
-/** @} */
-
-G_END_DECLS
-
-#endif /* __GNC_TREE_VIEW_COMMON_H */
More information about the gnucash-changes
mailing list