GnuCash 2.4.99
gnc-tree-view-owner.c
00001 /********************************************************************\
00002  * gnc-tree-view-owner.c -- GtkTreeView implementation to display   *
00003  *                            owners in a GtkTreeView.              *
00004  * Copyright (C) 2011 Geert Janssens <geert@kobaltwit.be>           *
00005  *                                                                  *
00006  * This program is free software; you can redistribute it and/or    *
00007  * modify it under the terms of the GNU General Public License as   *
00008  * published by the Free Software Foundation; either version 2 of   *
00009  * the License, or (at your option) any later version.              *
00010  *                                                                  *
00011  * This program is distributed in the hope that it will be useful,  *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00014  * GNU General Public License for more details.                     *
00015  *                                                                  *
00016  * You should have received a copy of the GNU General Public License*
00017  * along with this program; if not, contact:                        *
00018  *                                                                  *
00019  * Free Software Foundation           Voice:  +1-617-542-5942       *
00020  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00021  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00022  *                                                                  *
00023 \********************************************************************/
00024 
00025 #include "config.h"
00026 
00027 #include <gtk/gtk.h>
00028 #include <glib/gi18n.h>
00029 #include <string.h>
00030 
00031 #include "gnc-tree-view.h"
00032 #include "gnc-tree-model-owner.h"
00033 #include "gnc-tree-view-owner.h"
00034 
00035 #include "gncOwner.h"
00036 #include "gnc-accounting-period.h"
00037 #include "gnc-commodity.h"
00038 #include "gnc-component-manager.h"
00039 #include "gnc-engine.h"
00040 #include "gnc-glib-utils.h"
00041 #include "gnc-gobject-utils.h"
00042 #include "gnc-hooks.h"
00043 #include "gnc-session.h"
00044 #include "gnc-icons.h"
00045 #include "gnc-ui-balances.h"
00046 #include "dialog-utils.h"
00047 #include "window-main-summarybar.h"
00048 #include "assistant-utils.h"
00049 
00050 #define SAMPLE_OWNER_VALUE "$1,000,000.00"
00051 
00054 /* This static indicates the debugging module that this .o belongs to.  */
00055 static QofLogModule log_module = GNC_MOD_GUI;
00056 
00058 static void gnc_tree_view_owner_class_init (GncTreeViewOwnerClass *klass);
00059 static void gnc_tree_view_owner_init (GncTreeViewOwner *view);
00060 static void gnc_tree_view_owner_finalize (GObject *object);
00061 
00062 static void gtvo_update_column_names (GncTreeView *view);
00063 static void gtvo_currency_changed_cb (void);
00064 
00065 static gboolean gnc_tree_view_owner_filter_helper (GtkTreeModel *model,
00066         GtkTreeIter *iter,
00067         gpointer data);
00068 
00069 static void gtvo_setup_column_renderer_edited_cb(GncTreeViewOwner *owner_view,
00070         GtkTreeViewColumn *column,
00071         GtkCellRenderer *renderer,
00072         GncTreeViewOwnerColumnTextEdited col_edited_cb);
00073 
00074 typedef struct GncTreeViewOwnerPrivate
00075 {
00076     OwnerViewInfo ovi;
00077 
00078     gnc_tree_view_owner_filter_func filter_fn;
00079     gpointer                          filter_data;
00080     GtkFunction                       filter_destroy;
00081 
00082     GtkTreeViewColumn *name_column;
00083     GtkTreeViewColumn *id_column;
00084     GtkTreeViewColumn *balance_report_column;
00085     GtkTreeViewColumn *notes_column;
00086 } GncTreeViewOwnerPrivate;
00087 
00088 #define GNC_TREE_VIEW_OWNER_GET_PRIVATE(o)  \
00089    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_VIEW_OWNER, GncTreeViewOwnerPrivate))
00090 
00091 
00092 /************************************************************/
00093 /*               g_object required functions                */
00094 /************************************************************/
00095 
00096 static GObjectClass *parent_class = NULL;
00097 
00098 GType
00099 gnc_tree_view_owner_get_type (void)
00100 {
00101     static GType gnc_tree_view_owner_type = 0;
00102 
00103     if (gnc_tree_view_owner_type == 0)
00104     {
00105         static const GTypeInfo our_info =
00106         {
00107             sizeof (GncTreeViewOwnerClass),
00108             NULL,
00109             NULL,
00110             (GClassInitFunc) gnc_tree_view_owner_class_init,
00111             NULL,
00112             NULL,
00113             sizeof (GncTreeViewOwner),
00114             0,
00115             (GInstanceInitFunc) gnc_tree_view_owner_init
00116         };
00117 
00118         gnc_tree_view_owner_type = g_type_register_static (
00119                                        GNC_TYPE_TREE_VIEW, GNC_TREE_VIEW_OWNER_NAME,
00120                                        &our_info, 0);
00121     }
00122 
00123     return gnc_tree_view_owner_type;
00124 }
00125 
00126 static void
00127 gnc_tree_view_owner_class_init (GncTreeViewOwnerClass *klass)
00128 {
00129     GObjectClass *o_class;
00130 
00131     parent_class = g_type_class_peek_parent (klass);
00132 
00133     /* GObject signals */
00134     o_class = G_OBJECT_CLASS (klass);
00135     o_class->finalize = gnc_tree_view_owner_finalize;
00136 
00137     g_type_class_add_private(klass, sizeof(GncTreeViewOwnerPrivate));
00138 
00139     gnc_hook_add_dangler(HOOK_CURRENCY_CHANGED,
00140                          (GFunc)gtvo_currency_changed_cb, NULL);
00141 }
00142 
00143 /********************************************************************\
00144  * gnc_init_owner_view_info                                         *
00145  *   initialize an owner view info structure with default values    *
00146  *                                                                  *
00147  * Args: ovi - structure to initialize                              *
00148  * Returns: nothing                                                 *
00149 \********************************************************************/
00150 static void
00151 gnc_init_owner_view_info(OwnerViewInfo *ovi)
00152 {
00153     ovi->show_inactive = FALSE;
00154 }
00155 
00156 static void
00157 gnc_tree_view_owner_init (GncTreeViewOwner *view)
00158 {
00159     GncTreeViewOwnerPrivate *priv;
00160 
00161     priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
00162     gnc_init_owner_view_info(&priv->ovi);
00163 }
00164 
00165 static void
00166 gnc_tree_view_owner_finalize (GObject *object)
00167 {
00168     GncTreeViewOwner *owner_view;
00169     GncTreeViewOwnerPrivate *priv;
00170 
00171     ENTER("view %p", object);
00172     g_return_if_fail (object != NULL);
00173     g_return_if_fail (GNC_IS_TREE_VIEW_OWNER (object));
00174 
00175     owner_view = GNC_TREE_VIEW_OWNER (object);
00176 
00177     priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(owner_view);
00178     if (priv->filter_destroy)
00179     {
00180         priv->filter_destroy(priv->filter_data);
00181         priv->filter_destroy = NULL;
00182     }
00183     priv->filter_fn = NULL;
00184 
00185     if (G_OBJECT_CLASS (parent_class)->finalize)
00186         (* G_OBJECT_CLASS (parent_class)->finalize) (object);
00187     LEAVE(" ");
00188 }
00189 
00190 
00191 /************************************************************
00192  *                        Callbacks                         *
00193  ************************************************************/
00194 static void
00195 gnc_tree_view_owner_active_toggled (GtkCellRendererToggle *cell,
00196                                     const gchar *s_path_str,
00197                                     gpointer user_data)
00198 {
00199     GncTreeViewOwner *tree_view;
00200     GtkTreePath *s_path;
00201     GncOwner *owner;
00202     gboolean active;
00203 
00204     /* Change the requested owner */
00205     tree_view = user_data;
00206     s_path = gtk_tree_path_new_from_string (s_path_str);
00207     owner = gnc_tree_view_owner_get_owner_from_path (tree_view, s_path);
00208     if (owner)
00209     {
00210         active = !gtk_cell_renderer_toggle_get_active (cell); // hasn't changed yet.
00211         gncOwnerSetActive (owner, active);
00212     }
00213 
00214     /* Clean up */
00215     gtk_tree_path_free (s_path);
00216 }
00217 
00218 
00219 /************************************************************/
00220 /*                      sort functions                      */
00221 /************************************************************/
00222 
00223 static GtkTreeModel *
00224 sort_cb_setup_w_iters (GtkTreeModel *f_model,
00225                        GtkTreeIter *f_iter_a,
00226                        GtkTreeIter *f_iter_b,
00227                        GtkTreeIter *iter_a,
00228                        GtkTreeIter *iter_b,
00229                        const GncOwner **owner_a,
00230                        const GncOwner **owner_b)
00231 {
00232     GtkTreeModel *model;
00233 
00234     model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
00235     gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
00236             iter_a,
00237             f_iter_a);
00238     gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
00239             iter_b,
00240             f_iter_b);
00241     *owner_a = gnc_tree_model_owner_get_owner (GNC_TREE_MODEL_OWNER(model), iter_a);
00242     *owner_b = gnc_tree_model_owner_get_owner (GNC_TREE_MODEL_OWNER(model), iter_b);
00243     return model;
00244 }
00245 
00246 static void
00247 sort_cb_setup (GtkTreeModel *f_model,
00248                GtkTreeIter *f_iter_a,
00249                GtkTreeIter *f_iter_b,
00250                const GncOwner **owner_a,
00251                const GncOwner **owner_b)
00252 {
00253     GtkTreeIter iter_a, iter_b;
00254 
00255     sort_cb_setup_w_iters (f_model, f_iter_a, f_iter_b,
00256                            &iter_a, &iter_b, owner_a, owner_b);
00257 }
00258 
00259 static gint
00260 sort_by_string (GtkTreeModel *f_model,
00261                 GtkTreeIter *f_iter1,
00262                 GtkTreeIter *f_iter2,
00263                 gpointer user_data)
00264 {
00265     GtkTreeModel *model;
00266     GtkTreeIter iter1, iter2;
00267     const GncOwner *owner1, *owner2;
00268     gchar *str1, *str2;
00269     gint column = GPOINTER_TO_INT(user_data);
00270     gint result;
00271 
00272     model = sort_cb_setup_w_iters(f_model, f_iter1, f_iter2, &iter1, &iter2, &owner1, &owner2);
00273 
00274     /* Get the strings. */
00275     gtk_tree_model_get(GTK_TREE_MODEL(model), &iter1,  column, &str1, -1);
00276     gtk_tree_model_get(GTK_TREE_MODEL(model), &iter2,  column, &str2, -1);
00277 
00278     result = safe_utf8_collate(str1, str2);
00279     g_free(str1);
00280     g_free(str2);
00281     if (result != 0)
00282         return result;
00283     return gncOwnerCompare(owner1, owner2);
00284 }
00285 
00286 static gint
00287 sort_by_boolean (GtkTreeModel *f_model,
00288                  GtkTreeIter *f_iter1,
00289                  GtkTreeIter *f_iter2,
00290                  gpointer user_data)
00291 {
00292     GtkTreeModel *model;
00293     GtkTreeIter iter1, iter2;
00294     const GncOwner *owner1, *owner2;
00295     gboolean *bool1, *bool2;
00296     gint column = GPOINTER_TO_INT(user_data);
00297 
00298     model = sort_cb_setup_w_iters(f_model, f_iter1, f_iter2, &iter1, &iter2, &owner1, &owner2);
00299 
00300     /* Get the booleans. */
00301     gtk_tree_model_get(GTK_TREE_MODEL(model), &iter1,  column, &bool1, -1);
00302     gtk_tree_model_get(GTK_TREE_MODEL(model), &iter2,  column, &bool2, -1);
00303 
00304     if (bool1)
00305     {
00306         if (!bool2)
00307             return 1; /* bool1 > bool2 */
00308     }
00309     else
00310     {
00311         if (bool2)
00312             return -1; /* bool2 > bool1 */
00313     }
00314     return gncOwnerCompare(owner1, owner2);
00315 }
00316 
00317 static gint
00318 sort_by_xxx_value (GtkTreeModel *f_model,
00319                    GtkTreeIter *f_iter_a,
00320                    GtkTreeIter *f_iter_b,
00321                    gpointer user_data)
00322 {
00323     GncOwner *owner_a, *owner_b;
00324     gnc_numeric balance_a, balance_b;
00325     gint result;
00326 
00327     /* Find the owners */
00328     sort_cb_setup (f_model, f_iter_a, f_iter_b, (const GncOwner**)&owner_a, (const GncOwner**)&owner_b);
00329 
00330     balance_a = gnc_ui_owner_get_balance_full(owner_a, NULL, NULL);
00331     balance_b = gnc_ui_owner_get_balance_full(owner_b, NULL, NULL);
00332 
00333     result = gnc_numeric_compare(balance_a, balance_b);
00334     if (result != 0)
00335         return result;
00336     return gncOwnerCompare(owner_a, owner_b);
00337 }
00338 
00339 static gint
00340 sort_by_balance_value (GtkTreeModel *f_model,
00341                        GtkTreeIter *f_iter_a,
00342                        GtkTreeIter *f_iter_b,
00343                        gpointer user_data)
00344 {
00345     return sort_by_xxx_value (f_model, f_iter_a, f_iter_b, user_data);
00346 }
00347 
00348 
00349 /************************************************************/
00350 /*                    New View Creation                     */
00351 /************************************************************/
00352 
00353 /*
00354  * Create a new owner tree view for one type of owners.
00355  * This view will be based on a model that is common to all views of
00356  * the same set of books, but will have its own private filter on that
00357  * model.
00358  */
00359 GtkTreeView *
00360 gnc_tree_view_owner_new (GncOwnerType owner_type)
00361 {
00362     GncTreeView *view;
00363     GtkTreeModel *model, *f_model, *s_model;
00364     const gchar *sample_type, *sample_currency;
00365     GncTreeViewOwnerPrivate *priv;
00366     GtkTreeViewColumn *tax_info_column;
00367     GtkCellRenderer *renderer;
00368 
00369     ENTER(" ");
00370     /* Create our view */
00371     view = g_object_new (GNC_TYPE_TREE_VIEW_OWNER,
00372                          "name", "owner_tree", NULL);
00373 
00374     priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(GNC_TREE_VIEW_OWNER (view));
00375 
00376     /* Create/get a pointer to the existing model for this set of books. */
00377     model = gnc_tree_model_owner_new (owner_type);
00378 
00379     /* Set up the view private filter layer on the common model. */
00380     f_model = gtk_tree_model_filter_new (model, NULL);
00381     /* A GncTreeModelOwner is based on a GncTreeModel, which is a
00382      * GObject that provides a GtkTreeModel interface. */
00383     g_object_unref(G_OBJECT(model));
00384 
00385     /* Set up the view private sort layer on the common model. */
00386     s_model = gtk_tree_model_sort_new_with_model(f_model);
00387     g_object_unref(G_OBJECT(f_model));
00388     gnc_tree_view_set_model (view, s_model);
00389     g_object_unref(G_OBJECT(s_model));
00390 
00391     /* Set default visibilities */
00392     gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
00393 
00394     sample_type = gncOwnerTypeToQofIdType (GNC_OWNER_CUSTOMER);
00395     sample_currency = gnc_commodity_get_fullname(gnc_default_currency());
00396 
00397     priv->name_column
00398     = gnc_tree_view_add_text_column(view, _("Owner Name"), GNC_OWNER_TREE_NAME_COL,
00399                                     NULL, "GnuCash Inc.",
00400                                     GNC_TREE_MODEL_OWNER_COL_NAME,
00401                                     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00402                                     sort_by_string);
00403     gnc_tree_view_add_text_column(view, _("Type"), GNC_OWNER_TREE_TYPE_COL,
00404                                   NULL, sample_type,
00405                                   GNC_TREE_MODEL_OWNER_COL_TYPE,
00406                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00407                                   sort_by_string);
00408     priv->id_column
00409     = gnc_tree_view_add_text_column(view, _("Owner ID"), GNC_OWNER_TREE_ID_COL,
00410                                     NULL, "1-123-1234",
00411                                     GNC_TREE_MODEL_OWNER_COL_ID,
00412                                     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00413                                     sort_by_string);
00414     gnc_tree_view_add_text_column(view, _("Currency"), GNC_OWNER_TREE_CURRENCY_COL,
00415                                   NULL, sample_currency,
00416                                   GNC_TREE_MODEL_OWNER_COL_CURRENCY,
00417                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00418                                   sort_by_string);
00419     gnc_tree_view_add_text_column(view, _("Address Name"), GNC_OWNER_TREE_ADDRESS_NAME_COL,
00420                                   NULL, "GnuCash Inc.",
00421                                   GNC_TREE_MODEL_OWNER_COL_ADDRESS_NAME,
00422                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00423                                   sort_by_string);
00424     gnc_tree_view_add_text_column(view, _("Address 1"), GNC_OWNER_TREE_ADDRESS_1_COL,
00425                                   NULL, "Free Software Foundation",
00426                                   GNC_TREE_MODEL_OWNER_COL_ADDRESS_1,
00427                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00428                                   sort_by_string);
00429     gnc_tree_view_add_text_column(view, _("Address 2"), GNC_OWNER_TREE_ADDRESS_2_COL,
00430                                   NULL, "51 Franklin Street, Fifth Floor",
00431                                   GNC_TREE_MODEL_OWNER_COL_ADDRESS_2,
00432                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00433                                   sort_by_string);
00434     gnc_tree_view_add_text_column(view, _("Address 3"), GNC_OWNER_TREE_ADDRESS_3_COL,
00435                                   NULL, "Boston, MA  02110-1301",
00436                                   GNC_TREE_MODEL_OWNER_COL_ADDRESS_3,
00437                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00438                                   sort_by_string);
00439     gnc_tree_view_add_text_column(view, _("Address 4"), GNC_OWNER_TREE_ADDRESS_4_COL,
00440                                   NULL, "USA",
00441                                   GNC_TREE_MODEL_OWNER_COL_ADDRESS_4,
00442                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00443                                   sort_by_string);
00444     gnc_tree_view_add_text_column(view, _("Phone"), GNC_OWNER_TREE_PHONE_COL,
00445                                   NULL, "+1-617-542-5942",
00446                                   GNC_TREE_MODEL_OWNER_COL_PHONE,
00447                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00448                                   sort_by_string);
00449     gnc_tree_view_add_text_column(view, _("Fax"), GNC_OWNER_TREE_FAX_COL,
00450                                   NULL, "+1-617-542-2652",
00451                                   GNC_TREE_MODEL_OWNER_COL_FAX,
00452                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00453                                   sort_by_string);
00454     gnc_tree_view_add_text_column(view, _("E-mail"), GNC_OWNER_TREE_EMAIL_COL,
00455                                   NULL, "gnu@gnu.org",
00456                                   GNC_TREE_MODEL_OWNER_COL_EMAIL,
00457                                   GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00458                                   sort_by_string);
00459     gnc_tree_view_add_numeric_column(view, _("Balance"), GNC_OWNER_TREE_BALANCE_COL,
00460                                      SAMPLE_OWNER_VALUE,
00461                                      GNC_TREE_MODEL_OWNER_COL_BALANCE,
00462                                      GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE,
00463                                      GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00464                                      sort_by_balance_value);
00465 
00466     priv->balance_report_column
00467     = gnc_tree_view_add_numeric_column(view, _("Balance"), GNC_OWNER_TREE_BALANCE_REPORT_COL,
00468                                        SAMPLE_OWNER_VALUE,
00469                                        GNC_TREE_MODEL_OWNER_COL_BALANCE_REPORT,
00470                                        GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE,
00471                                        GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00472                                        sort_by_balance_value);
00473 
00474     priv->notes_column
00475     = gnc_tree_view_add_text_column(view, _("Notes"), GNC_OWNER_TREE_NOTES_COL, NULL,
00476                                     "Sample owner notes.",
00477                                     GNC_TREE_MODEL_OWNER_COL_NOTES,
00478                                     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00479                                     sort_by_string);
00480     gnc_tree_view_add_toggle_column (view, _("Active"),
00481                                      /* Translators: This string has a context prefix; the translation
00482                                         must only contain the part after the | character. */
00483                                      Q_("Column letter for 'Active'|A"),
00484                                      GNC_OWNER_TREE_ACTIVE_COL,
00485                                      GNC_TREE_MODEL_OWNER_COL_ACTIVE,
00486                                      GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
00487                                      sort_by_boolean,
00488                                      gnc_tree_view_owner_active_toggled);
00489 
00490     /* Update column titles to use the currency name. */
00491     gtvo_update_column_names(view);
00492 
00493     /* By default only the first column is visible. */
00494     gnc_tree_view_configure_columns(view);
00495     gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (f_model),
00496                                             gnc_tree_view_owner_filter_helper,
00497                                             view,
00498                                             NULL);
00499 
00500     /* Default the sorting to owner name */
00501     gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
00502                                          GNC_TREE_MODEL_OWNER_COL_NAME,
00503                                          GTK_SORT_ASCENDING);
00504 
00505     gtk_widget_show(GTK_WIDGET(view));
00506     LEAVE("%p", view);
00507     return GTK_TREE_VIEW(view);
00508 }
00509 
00510 /************************************************************/
00511 /*                   Auxiliary Functions                    */
00512 /************************************************************/
00513 
00514 #define debug_path(fn, path) {                          \
00515     gchar *path_string = gtk_tree_path_to_string(path); \
00516     fn("tree path %s", path_string);                    \
00517     g_free(path_string);                                \
00518   }
00519 
00520 static GtkTreePath *
00521 gnc_tree_view_owner_get_path_from_owner (GncTreeViewOwner *view,
00522         GncOwner *owner)
00523 {
00524     GtkTreeModel *model, *f_model, *s_model;
00525     GtkTreePath *path, *f_path, *s_path;
00526 
00527     ENTER("view %p, owner %p (%s)", view, owner, gncOwnerGetName(owner));
00528 
00529     if (owner == NULL)
00530     {
00531         LEAVE("no owner");
00532         return NULL;
00533     }
00534 
00535     /* Reach down to the real model and get a path for this owner */
00536     s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
00537     f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
00538     model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
00539     path = gnc_tree_model_owner_get_path_from_owner (GNC_TREE_MODEL_OWNER(model), owner);
00540     if (path == NULL)
00541     {
00542         LEAVE("no path");
00543         return NULL;
00544     }
00545 
00546     /* convert back to a filtered path */
00547     f_path = gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (f_model), path);
00548     gtk_tree_path_free(path);
00549     if (!f_path)
00550     {
00551         LEAVE("no filter path");
00552         return NULL;
00553     }
00554 
00555     /* convert back to a sorted path */
00556     s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model), f_path);
00557     gtk_tree_path_free(f_path);
00558     debug_path(LEAVE, s_path);
00559     return s_path;
00560 }
00561 
00562 static gboolean
00563 gnc_tree_view_owner_get_iter_from_owner (GncTreeViewOwner *view,
00564         GncOwner *owner,
00565         GtkTreeIter *s_iter)
00566 {
00567     GtkTreeModel *model, *f_model, *s_model;
00568     GtkTreeIter iter, f_iter;
00569 
00570     g_return_val_if_fail(GNC_IS_TREE_VIEW_OWNER(view), FALSE);
00571     g_return_val_if_fail(owner != NULL, FALSE);
00572     g_return_val_if_fail(s_iter != NULL, FALSE);
00573 
00574     ENTER("view %p, owner %p (%s)", view, owner, gncOwnerGetName(owner));
00575 
00576     /* Reach down to the real model and get an iter for this owner */
00577     s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
00578     f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
00579     model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
00580     if (!gnc_tree_model_owner_get_iter_from_owner (
00581                 GNC_TREE_MODEL_OWNER(model), owner, &iter))
00582     {
00583         LEAVE("model_get_iter_from_owner failed");
00584         return FALSE;
00585     }
00586 
00587     /* convert back to a sort iter */
00588     gtk_tree_model_filter_convert_child_iter_to_iter (
00589         GTK_TREE_MODEL_FILTER(f_model), &f_iter, &iter);
00590     gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(s_model),
00591             s_iter, &f_iter);
00592     LEAVE(" ");
00593     return TRUE;
00594 }
00595 
00596 /************************************************************/
00597 /*            Owner Tree View Filter Functions            */
00598 /************************************************************/
00599 
00600 static gboolean
00601 gnc_tree_view_owner_filter_helper (GtkTreeModel *model,
00602                                    GtkTreeIter *iter,
00603                                    gpointer data)
00604 {
00605     GncOwner *owner;
00606     GncTreeViewOwner *view = data;
00607     GncTreeViewOwnerPrivate *priv;
00608 
00609     g_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (model), FALSE);
00610     g_return_val_if_fail (iter != NULL, FALSE);
00611 
00612     owner = gnc_tree_model_owner_get_owner (
00613                 GNC_TREE_MODEL_OWNER(model), iter);
00614 
00615     priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
00616     if (priv->filter_fn)
00617         return priv->filter_fn(owner, priv->filter_data);
00618     else return TRUE;
00619 }
00620 
00621 /*
00622  * Set an GtkTreeModel visible filter on this owner.  This filter will be
00623  * called for each owner that the tree is about to show, and the
00624  * owner will be passed to the callback function.
00625  *
00626  * Use NULL as func to remove filter.
00627  */
00628 void
00629 gnc_tree_view_owner_set_filter (GncTreeViewOwner *view,
00630                                 gnc_tree_view_owner_filter_func func,
00631                                 gpointer data,
00632                                 GtkFunction destroy)
00633 {
00634     GncTreeViewOwnerPrivate *priv;
00635 
00636     ENTER("view %p, filter func %p, data %p, destroy %p",
00637           view, func, data, destroy);
00638 
00639     g_return_if_fail(GNC_IS_TREE_VIEW_OWNER(view));
00640 
00641     priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
00642     if (priv->filter_destroy)
00643     {
00644         priv->filter_destroy(priv->filter_data);
00645     }
00646     priv->filter_destroy = destroy;
00647     priv->filter_data = data;
00648     priv->filter_fn = func;
00649 
00650     gnc_tree_view_owner_refilter(view);
00651     LEAVE(" ");
00652 }
00653 
00654 /*
00655  * Forces the entire owner tree to be re-evaluated for visibility.
00656  */
00657 void
00658 gnc_tree_view_owner_refilter (GncTreeViewOwner *view)
00659 {
00660     GtkTreeModel *f_model, *s_model;
00661 
00662     g_return_if_fail(GNC_IS_TREE_VIEW_OWNER(view));
00663 
00664     s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
00665     f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
00666     gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
00667 }
00668 
00669 /************************************************************/
00670 /*           Owner Tree View Get/Set Functions            */
00671 /************************************************************/
00672 
00673 /*
00674  * Retrieve the selected owner from an owner tree view.  The
00675  * owner tree must be in single selection mode.
00676  */
00677 GncOwner *
00678 gnc_tree_view_owner_get_owner_from_path (GncTreeViewOwner *view,
00679         GtkTreePath *s_path)
00680 {
00681     GtkTreeModel *model, *f_model, *s_model;
00682     GtkTreePath *path, *f_path;
00683     GtkTreeIter iter;
00684     GncOwner *owner;
00685 
00686     ENTER("view %p", view);
00687     g_return_val_if_fail (GNC_IS_TREE_VIEW_OWNER (view), NULL);
00688     g_return_val_if_fail (s_path != NULL, NULL);
00689 
00690     s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
00691     f_path = gtk_tree_model_sort_convert_path_to_child_path (
00692                  GTK_TREE_MODEL_SORT (s_model), s_path);
00693     if (!f_path)
00694     {
00695         LEAVE("no filter path");
00696         return NULL;
00697     }
00698 
00699     f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
00700     path = gtk_tree_model_filter_convert_path_to_child_path (
00701                GTK_TREE_MODEL_FILTER (f_model), f_path);
00702     gtk_tree_path_free(f_path);
00703     if (!path)
00704     {
00705         LEAVE("no path");
00706         return NULL;
00707     }
00708 
00709     model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
00710     if (!gtk_tree_model_get_iter (model, &iter, path))
00711     {
00712         LEAVE("no iter");
00713         return NULL;
00714     }
00715 
00716     owner = iter.user_data;
00717     gtk_tree_path_free(path);
00718     LEAVE("owner %p (%s)", owner, gncOwnerGetName (owner));
00719     return owner;
00720 }
00721 
00722 
00723 GncOwner *
00724 gnc_tree_view_owner_get_owner_from_iter (GtkTreeModel *s_model,
00725         GtkTreeIter  *s_iter)
00726 {
00727     GtkTreeModel *model, *f_model;
00728     GtkTreeIter iter, f_iter;
00729     GncOwner *owner;
00730 
00731     g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT(s_model), NULL);
00732     g_return_val_if_fail (s_iter != NULL, NULL);
00733 
00734     ENTER("model %p, iter %p", s_model, s_iter);
00735 
00736     gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT(s_model),
00737             &f_iter,
00738             s_iter);
00739     f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
00740     gtk_tree_model_filter_convert_iter_to_child_iter (
00741         GTK_TREE_MODEL_FILTER(f_model), &iter, &f_iter);
00742     model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
00743     owner = gnc_tree_model_owner_get_owner (
00744                 GNC_TREE_MODEL_OWNER(model), &iter);
00745     LEAVE("owner %p (%s)", owner, gncOwnerGetName (owner));
00746     return owner;
00747 }
00748 
00749 
00750 /*
00751  * Retrieve the selected owner from an owner tree view.  The
00752  * owner tree must be in single selection mode.
00753  */
00754 GncOwner *
00755 gnc_tree_view_owner_get_selected_owner (GncTreeViewOwner *view)
00756 {
00757     GtkTreeSelection *selection;
00758     GtkTreeModel *f_model, *s_model;
00759     GtkTreeIter iter, f_iter, s_iter;
00760     GncOwner *owner;
00761     GtkSelectionMode mode;
00762 
00763     ENTER("view %p", view);
00764     g_return_val_if_fail (GNC_IS_TREE_VIEW_OWNER (view), NULL);
00765 
00766     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
00767     mode = gtk_tree_selection_get_mode(selection);
00768     if ((mode != GTK_SELECTION_SINGLE) && (mode != GTK_SELECTION_BROWSE))
00769     {
00770         return NULL;
00771     }
00772     if (!gtk_tree_selection_get_selected (selection, &s_model, &s_iter))
00773     {
00774         LEAVE("no owner, get_selected failed");
00775         return FALSE;
00776     }
00777 
00778     gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
00779             &f_iter, &s_iter);
00780 
00781     f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
00782     gtk_tree_model_filter_convert_iter_to_child_iter (
00783         GTK_TREE_MODEL_FILTER (f_model), &iter, &f_iter);
00784 
00785     owner = iter.user_data;
00786     LEAVE("owner %p (%s)", owner, gncOwnerGetName (owner));
00787     return owner;
00788 }
00789 
00790 /*
00791  * Selects a single owner in the owner tree view.  The owner
00792  * tree must be in single selection mode.
00793  */
00794 void
00795 gnc_tree_view_owner_set_selected_owner (GncTreeViewOwner *view,
00796                                         GncOwner *owner)
00797 {
00798     GtkTreeModel *model, *f_model, *s_model;
00799     GtkTreePath *path, *f_path, *s_path, *parent_path;
00800     GtkTreeSelection *selection;
00801 
00802     ENTER("view %p, owner %p (%s)", view,
00803           owner, gncOwnerGetName (owner));
00804     g_return_if_fail (GNC_IS_TREE_VIEW_OWNER (view));
00805 
00806     /* Clear any existing selection. */
00807     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
00808     gtk_tree_selection_unselect_all (selection);
00809 
00810     if (owner == NULL)
00811         return;
00812 
00813     s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
00814     f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
00815     model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
00816 
00817     path = gnc_tree_model_owner_get_path_from_owner (
00818                GNC_TREE_MODEL_OWNER(model), owner);
00819     if (path == NULL)
00820     {
00821         LEAVE("no path");
00822         return;
00823     }
00824     debug_path(DEBUG, path);
00825 
00826     f_path = gtk_tree_model_filter_convert_child_path_to_path (
00827                  GTK_TREE_MODEL_FILTER (f_model), path);
00828     gtk_tree_path_free(path);
00829     if (f_path == NULL)
00830     {
00831         LEAVE("no filter path");
00832         return;
00833     }
00834     debug_path(DEBUG, f_path);
00835 
00836     s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model),
00837              f_path);
00838     gtk_tree_path_free(f_path);
00839     if (s_path == NULL)
00840     {
00841         LEAVE("no sort path");
00842         return;
00843     }
00844 
00845     gtk_tree_selection_select_path (selection, s_path);
00846 
00847     /* give gtk+ a chance to resize the tree view first by handling pending
00848      * configure events */
00849     while (gtk_events_pending ())
00850         gtk_main_iteration ();
00851     gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), s_path, NULL, FALSE, 0.0, 0.0);
00852     debug_path(LEAVE, s_path);
00853     gtk_tree_path_free(s_path);
00854 }
00855 
00856 /* Information re selection process */
00857 typedef struct
00858 {
00859     GList* return_list;
00860     GncTreeViewOwnerPrivate* priv;
00861 } GncTreeViewSelectionInfo;
00862 
00863 /*
00864  * This helper function is called once for each row in the tree view
00865  * that is currently selected.  Its task is to append the corresponding
00866  * owner to the end of a glist.
00867  */
00868 static void
00869 get_selected_owners_helper (GtkTreeModel *s_model,
00870                             GtkTreePath *s_path,
00871                             GtkTreeIter *s_iter,
00872                             gpointer data)
00873 {
00874     GncTreeViewSelectionInfo *gtvsi = data;
00875     GtkTreeModel *f_model;
00876     GtkTreeIter iter, f_iter;
00877     GncOwner *owner;
00878 
00879     gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
00880             &f_iter, s_iter);
00881 
00882     f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
00883     gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model),
00884             &iter, &f_iter);
00885     owner = iter.user_data;
00886 
00887     /* Only selected if it passes the filter */
00888     if (gtvsi->priv->filter_fn == NULL || gtvsi->priv->filter_fn(owner, gtvsi->priv->filter_data))
00889     {
00890         gtvsi->return_list = g_list_append(gtvsi->return_list, owner);
00891     }
00892 }
00893 
00894 /************************************************************/
00895 /*         Owner Tree View Add Column Functions           */
00896 /************************************************************/
00897 
00898 static void
00899 gtvo_update_column_name (GtkTreeViewColumn *column,
00900                          const gchar *fmt,
00901                          const gchar *mnemonic)
00902 {
00903     gchar *name;
00904 
00905     g_return_if_fail(column);
00906 
00907     name = g_strdup_printf(fmt, mnemonic);
00908     gtk_tree_view_column_set_title(column, name);
00909     g_free(name);
00910 }
00911 
00912 
00913 static void
00914 gtvo_update_column_names (GncTreeView *view)
00915 {
00916     GncTreeViewOwnerPrivate *priv;
00917     const gchar *mnemonic;
00918 
00919     priv = GNC_TREE_VIEW_OWNER_GET_PRIVATE(view);
00920     mnemonic = gnc_commodity_get_mnemonic(gnc_default_report_currency());
00921 
00922     gtvo_update_column_name(priv->balance_report_column,
00923                             /* Translators: %s is a currency mnemonic.*/
00924                             _("Balance (%s)"), mnemonic);
00925     gnc_tree_view_set_show_column_menu(view, FALSE);
00926     gnc_tree_view_set_show_column_menu(view, TRUE);
00927 }
00928 
00929 
00930 static void
00931 gtvo_currency_changed_cb (void)
00932 {
00933     const GList *views, *ptr;
00934 
00935     views = gnc_gobject_tracking_get_list (GNC_TREE_VIEW_OWNER_NAME);
00936     for (ptr = views; ptr; ptr = g_list_next(ptr))
00937     {
00938         gtvo_update_column_names (ptr->data);
00939     }
00940 }
00941 /* This function implements a custom mapping between an owner's KVP
00942  * and the cell renderer's 'text' property. */
00943 static void
00944 owner_cell_kvp_data_func (GtkTreeViewColumn *tree_column,
00945                           GtkCellRenderer *cell,
00946                           GtkTreeModel *s_model,
00947                           GtkTreeIter *s_iter,
00948                           gpointer key)
00949 {
00950     GncOwner *owner;
00951     kvp_frame * frame;
00952 
00953     g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
00954     owner = gnc_tree_view_owner_get_owner_from_iter(s_model, s_iter);
00955     frame = gncOwnerGetSlots(owner);
00956 
00957     g_object_set (G_OBJECT (cell),
00958                   "text", kvp_frame_get_string(frame, (gchar *)key),
00959                   "xalign", 0.0,
00960                   NULL);
00961 
00962 }
00963 
00964 static void col_edited_helper(GtkCellRendererText *cell, gchar *path_string,
00965                               gchar *new_text, gpointer _s_model)
00966 {
00967     GncOwner *owner;
00968     GtkTreeModel *s_model;
00969     GtkTreeIter s_iter;
00970     GncTreeViewOwnerColumnTextEdited col_edited_cb;
00971     GtkTreeViewColumn *col;
00972 
00973     col_edited_cb = g_object_get_data(G_OBJECT(cell),
00974                                       "column_edited_callback");
00975     col = GTK_TREE_VIEW_COLUMN(g_object_get_data(G_OBJECT(cell),
00976                                "column_view"));
00977     s_model = GTK_TREE_MODEL(_s_model);
00978 
00979     if (!gtk_tree_model_get_iter_from_string(s_model, &s_iter, path_string))
00980         return;
00981 
00982     owner = gnc_tree_view_owner_get_owner_from_iter(s_model, &s_iter);
00983     col_edited_cb(owner, col, new_text);
00984 }
00985 
00986 static void col_source_helper(GtkTreeViewColumn *col, GtkCellRenderer *cell,
00987                               GtkTreeModel *s_model, GtkTreeIter *s_iter,
00988                               gpointer _col_source_cb)
00989 {
00990     GncOwner *owner;
00991     gchar *text;
00992     GncTreeViewOwnerColumnSource col_source_cb;
00993 
00994     g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
00995     col_source_cb = (GncTreeViewOwnerColumnSource) _col_source_cb;
00996     owner = gnc_tree_view_owner_get_owner_from_iter(s_model, s_iter);
00997     text = col_source_cb(owner, col, cell);
00998     g_object_set (G_OBJECT (cell), "text", text, "xalign", 1.0, NULL);
00999     g_free(text);
01000 }
01001 
01006 void
01007 gtvo_setup_column_renderer_edited_cb(GncTreeViewOwner *owner_view,
01008                                      GtkTreeViewColumn *column,
01009                                      GtkCellRenderer *renderer,
01010                                      GncTreeViewOwnerColumnTextEdited col_edited_cb)
01011 {
01012     GtkTreeModel *s_model;
01013 
01014     if (col_edited_cb == NULL)
01015     {
01016         g_object_set(G_OBJECT(renderer), "editable", FALSE, NULL);
01017         g_object_set_data(G_OBJECT(renderer), "column_edited_callback", col_edited_cb);
01018         s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(owner_view));
01019         g_signal_handlers_disconnect_by_func(G_OBJECT(renderer), col_edited_cb, s_model);
01020         g_object_set_data(G_OBJECT(renderer), "column_view", column);
01021     }
01022     else
01023     {
01024         g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
01025         g_object_set_data(G_OBJECT(renderer), "column_edited_callback",
01026                           col_edited_cb);
01027         s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(owner_view));
01028         g_signal_connect(G_OBJECT(renderer), "edited",
01029                          (GCallback) col_edited_helper, s_model);
01030         g_object_set_data(G_OBJECT(renderer), "column_view", column);
01031     }
01032 }
01033 
01034 /* BEGIN FILTER FUNCTIONS */
01035 #define FILTER_TREE_VIEW "types_tree_view"
01036 
01048 gboolean
01049 gnc_plugin_page_owner_tree_filter_owners (GncOwner *owner,
01050         gpointer user_data)
01051 {
01052     OwnerFilterDialog *fd = user_data;
01053     gnc_numeric total;
01054 
01055     ENTER("owner %p:%s", owner, gncOwnerGetName(owner));
01056 
01057     if (!fd->show_inactive && !gncOwnerGetActive (owner))
01058     {
01059         LEAVE(" hide: inactive");
01060         return FALSE;
01061     }
01062 
01063     if (!fd->show_zero_total)
01064     {
01065         /* FIXME I'm not aware of any functions to get an owner's "balance" yet.
01066          *       This should be implemented before this function does anything useful.
01067          *       The code below is copied from the tree-view-account source to serve
01068          *       as an example.
01069         total = gncOwnerGetBalanceInCurrency (owner, NULL, TRUE);
01070         */
01071         total = gnc_numeric_zero();
01072         if (gnc_numeric_zero_p(total))
01073         {
01074             LEAVE(" hide: zero balance");
01075             return FALSE;
01076         }
01077     }
01078 
01079     return TRUE;
01080 }
01081 
01088 void
01089 gppot_filter_show_inactive_toggled_cb (GtkToggleButton *button,
01090                                        OwnerFilterDialog *fd)
01091 {
01092     g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
01093 
01094     ENTER("button %p", button);
01095     fd->show_inactive = gtk_toggle_button_get_active(button);
01096     gnc_tree_view_owner_refilter(fd->tree_view);
01097     LEAVE("show_inactive %d", fd->show_inactive);
01098 }
01099 
01106 void
01107 gppot_filter_show_zero_toggled_cb (GtkToggleButton *button,
01108                                    OwnerFilterDialog *fd)
01109 {
01110     g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
01111 
01112     ENTER("button %p", button);
01113     fd->show_zero_total = gtk_toggle_button_get_active(button);
01114     gnc_tree_view_owner_refilter(fd->tree_view);
01115     LEAVE("show_zero %d", fd->show_zero_total);
01116 }
01117 
01127 void
01128 gppot_filter_response_cb (GtkWidget *dialog,
01129                           gint       response,
01130                           OwnerFilterDialog *fd)
01131 {
01132     gpointer gptemp;
01133 
01134     g_return_if_fail(GTK_IS_DIALOG(dialog));
01135 
01136     ENTER("dialog %p, response %d", dialog, response);
01137 
01138     if (response != GTK_RESPONSE_OK)
01139     {
01140         fd->show_inactive = fd->original_show_inactive;
01141         fd->show_zero_total = fd->original_show_zero_total;
01142         gnc_tree_view_owner_refilter(fd->tree_view);
01143     }
01144 
01145     /* Clean up and delete dialog */
01146     gptemp = (gpointer *)fd->dialog;
01147     g_atomic_pointer_compare_and_exchange(&gptemp,
01148                                           dialog, NULL);
01149     fd->dialog = gptemp;
01150     gtk_widget_destroy(dialog);
01151     LEAVE("");
01152 }
01153 
01154 void
01155 owner_filter_dialog_create(OwnerFilterDialog *fd, GncPluginPage *page)
01156 {
01157     GtkWidget *dialog, *button;
01158     GtkBuilder *builder;
01159     gchar *title;
01160 
01161     ENTER("(fd %p, page %p)", fd, page);
01162 
01163     if (fd->dialog)
01164     {
01165         gtk_window_present(GTK_WINDOW(fd->dialog));
01166         LEAVE("existing dialog");
01167         return;
01168     }
01169 
01170     /* Create the dialog */
01171     builder = gtk_builder_new();
01172     gnc_builder_add_from_file (builder, "gnc-tree-view-owner.glade", "Filter By");
01173     dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Filter By"));
01174     fd->dialog = dialog;
01175     gtk_window_set_transient_for(GTK_WINDOW(dialog),
01176                                  GTK_WINDOW(GNC_PLUGIN_PAGE(page)->window));
01177     /* Translators: The %s is the name of the plugin page */
01178     title = g_strdup_printf(_("Filter %s by..."),
01179                             gnc_plugin_page_get_page_name(GNC_PLUGIN_PAGE(page)));
01180     gtk_window_set_title(GTK_WINDOW(dialog), title);
01181     g_free(title);
01182 
01183     /* Remember current state */
01184     fd->original_show_inactive = fd->show_inactive;
01185     fd->original_show_zero_total = fd->show_zero_total;
01186 
01187     /* Update the dialog widgets for the current state */
01188     button = GTK_WIDGET(gtk_builder_get_object (builder, "show_inactive"));
01189     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
01190                                   fd->show_inactive);
01191     button = GTK_WIDGET(gtk_builder_get_object (builder, "show_zero"));
01192     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
01193                                   fd->show_zero_total);
01194 
01195     /* Wire up the rest of the callbacks */
01196     gtk_builder_connect_signals (builder, fd);
01197     g_object_unref(G_OBJECT(builder));
01198 
01199     /* Show it */
01200     gtk_widget_show_all (dialog);
01201     LEAVE(" ");
01202 }
01203 
01204 #define OWNER_SELECTED_LABEL "SelectedOwner"
01205 #define SHOW_INACTIVE_LABEL  "ShowInactive"
01206 #define SHOW_ZERO_LABEL      "ShowZeroTotal"
01207 
01208 typedef struct foo
01209 {
01210     GKeyFile *key_file;
01211     const gchar *group_name;
01212 } bar_t;
01213 
01224 static void
01225 tree_save_selected_row (GncTreeViewOwner *view,
01226                         gpointer user_data)
01227 {
01228     GncOwner *owner;
01229     GncOwnerType owner_type;
01230     bar_t *bar = user_data;
01231     const gchar *owner_name;
01232 
01233     owner = gnc_tree_view_owner_get_selected_owner(view);
01234     if (owner == NULL)
01235         return;
01236 
01237     owner_name = gncOwnerGetName (owner);
01238     if (owner_name == NULL)
01239         return;
01240 
01241     g_key_file_set_string(bar->key_file, bar->group_name, OWNER_SELECTED_LABEL,
01242                           owner_name);
01243 }
01244 
01245 void
01246 gnc_tree_view_owner_save(GncTreeViewOwner *view,
01247                          OwnerFilterDialog *fd,
01248                          GKeyFile *key_file, const gchar *group_name)
01249 {
01250     bar_t bar;
01251 
01252     g_return_if_fail (key_file != NULL);
01253     g_return_if_fail (group_name != NULL);
01254 
01255     ENTER("view %p, key_file %p, group_name %s", view, key_file,
01256           group_name);
01257 
01258     g_key_file_set_boolean(key_file, group_name, SHOW_INACTIVE_LABEL,
01259                            fd->show_inactive);
01260     g_key_file_set_boolean(key_file, group_name, SHOW_ZERO_LABEL,
01261                            fd->show_zero_total);
01262 
01263     bar.key_file = key_file;
01264     bar.group_name = group_name;
01265     tree_save_selected_row(view, &bar);
01266     LEAVE(" ");
01267 
01268 }
01269 
01277 static void
01278 tree_restore_selected_row (GncTreeViewOwner *view,
01279                            GncOwnerType owner_type,
01280                            const gchar *owner_guid_str)
01281 {
01282     GncOwner *owner = gncOwnerNew();
01283     QofBook *book;
01284     GncGUID owner_guid;
01285 
01286     book = qof_session_get_book (gnc_get_current_session());
01287     if (string_to_guid (owner_guid_str, &owner_guid))
01288         if (gncOwnerGetOwnerFromTypeGuid (book, owner, gncOwnerTypeToQofIdType(owner_type), &owner_guid))
01289             gnc_tree_view_owner_set_selected_owner(view, owner);
01290 }
01291 
01292 void
01293 gnc_tree_view_owner_restore(GncTreeViewOwner *view,
01294                             OwnerFilterDialog *fd,
01295                             GKeyFile *key_file, const gchar *group_name,
01296                             GncOwnerType owner_type)
01297 {
01298     GError *error = NULL;
01299     gchar *key, *value;
01300     gint i, count;
01301     gboolean show;
01302 
01303     /* Filter information. Ignore missing keys. */
01304     show = g_key_file_get_boolean(key_file, group_name, SHOW_INACTIVE_LABEL, &error);
01305     if (error)
01306     {
01307         g_warning("error reading group %s key %s: %s",
01308                   group_name, SHOW_INACTIVE_LABEL, error->message);
01309         g_error_free(error);
01310         error = NULL;
01311         show = TRUE;
01312     }
01313     fd->show_inactive = show;
01314 
01315     show = g_key_file_get_boolean(key_file, group_name, SHOW_ZERO_LABEL, &error);
01316     if (error)
01317     {
01318         g_warning("error reading group %s key %s: %s",
01319                   group_name, SHOW_ZERO_LABEL, error->message);
01320         g_error_free(error);
01321         error = NULL;
01322         show = TRUE;
01323     }
01324     fd->show_zero_total = show;
01325 
01326     /* Selected owner (if any) */
01327     value = g_key_file_get_string(key_file, group_name, OWNER_SELECTED_LABEL, NULL);
01328     if (value)
01329     {
01330         tree_restore_selected_row(view, owner_type, value);
01331         g_free(value);
01332     }
01333 
01334     /* Update tree view for any changes */
01335     gnc_tree_view_owner_refilter(view);
01336 }
01337 
01338 static void
01339 gtvo_set_column_editor(GncTreeViewOwner *view,
01340                        GtkTreeViewColumn *column,
01341                        GncTreeViewOwnerColumnTextEdited edited_cb)
01342 {
01343     GList *renderers_orig, *renderers;
01344     GtkCellRenderer *renderer;
01345 
01346     // look for the first text-renderer; on the 0th column of the owner tree,
01347     // there are two renderers: pixbuf and text.  So find the text one.
01348     for (renderers_orig = renderers = gtk_tree_view_column_get_cell_renderers(column);
01349             renderers && !GTK_IS_CELL_RENDERER_TEXT(renderers->data);
01350             renderers = renderers->next);
01351     renderer = GTK_CELL_RENDERER(renderers->data);
01352     g_list_free(renderers_orig);
01353     g_return_if_fail(renderer != NULL);
01354     gtvo_setup_column_renderer_edited_cb(GNC_TREE_VIEW_OWNER(view), column, renderer, edited_cb);
01355 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines