|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * gnc-tree-view-commodity.c -- GtkTreeView implementation to * 00003 * display commodities in a GtkTreeView. * 00004 * Copyright (C) 2003,2005 David Hampton <hampton@employees.org> * 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-commodity.h" 00033 #include "gnc-tree-view-commodity.h" 00034 00035 #include "gnc-commodity.h" 00036 #include "gnc-component-manager.h" 00037 #include "gnc-engine.h" 00038 #include "gnc-gconf-utils.h" 00039 #include "gnc-glib-utils.h" 00040 #include "gnc-gnome-utils.h" 00041 #include "gnc-icons.h" 00042 #include "gnc-ui-util.h" 00043 00044 00047 /* This static indicates the debugging module that this .o belongs to. */ 00048 static QofLogModule log_module = GNC_MOD_GUI; 00049 00051 static void gnc_tree_view_commodity_class_init (GncTreeViewCommodityClass *klass); 00052 static void gnc_tree_view_commodity_init (GncTreeViewCommodity *view); 00053 static void gnc_tree_view_commodity_finalize (GObject *object); 00054 static void gnc_tree_view_commodity_destroy (GtkObject *object); 00055 00056 typedef struct GncTreeViewCommodityPrivate 00057 { 00058 gpointer dummy; 00059 } GncTreeViewCommodityPrivate; 00060 00061 #define GNC_TREE_VIEW_COMMODITY_GET_PRIVATE(o) \ 00062 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_VIEW_COMMODITY, GncTreeViewCommodityPrivate)) 00063 00064 00065 /************************************************************/ 00066 /* g_object required functions */ 00067 /************************************************************/ 00068 00069 static GObjectClass *parent_class = NULL; 00070 00071 GType 00072 gnc_tree_view_commodity_get_type (void) 00073 { 00074 static GType gnc_tree_view_commodity_type = 0; 00075 00076 if (gnc_tree_view_commodity_type == 0) 00077 { 00078 static const GTypeInfo our_info = 00079 { 00080 sizeof (GncTreeViewCommodityClass), 00081 NULL, 00082 NULL, 00083 (GClassInitFunc) gnc_tree_view_commodity_class_init, 00084 NULL, 00085 NULL, 00086 sizeof (GncTreeViewCommodity), 00087 0, 00088 (GInstanceInitFunc) gnc_tree_view_commodity_init 00089 }; 00090 00091 gnc_tree_view_commodity_type = g_type_register_static (GNC_TYPE_TREE_VIEW, 00092 "GncTreeViewCommodity", 00093 &our_info, 0); 00094 } 00095 00096 return gnc_tree_view_commodity_type; 00097 } 00098 00099 static void 00100 gnc_tree_view_commodity_class_init (GncTreeViewCommodityClass *klass) 00101 { 00102 GObjectClass *o_class; 00103 GtkObjectClass *object_class; 00104 00105 parent_class = g_type_class_peek_parent (klass); 00106 00107 o_class = G_OBJECT_CLASS (klass); 00108 object_class = GTK_OBJECT_CLASS (klass); 00109 00110 /* GObject signals */ 00111 o_class->finalize = gnc_tree_view_commodity_finalize; 00112 00113 /* GtkObject signals */ 00114 object_class->destroy = gnc_tree_view_commodity_destroy; 00115 00116 g_type_class_add_private(klass, sizeof(GncTreeViewCommodityPrivate)); 00117 } 00118 00119 static void 00120 gnc_tree_view_commodity_init (GncTreeViewCommodity *view) 00121 { 00122 } 00123 00124 static void 00125 gnc_tree_view_commodity_finalize (GObject *object) 00126 { 00127 GncTreeViewCommodity *view; 00128 GncTreeViewCommodityPrivate *priv; 00129 00130 g_return_if_fail (object != NULL); 00131 g_return_if_fail (GNC_IS_TREE_VIEW_COMMODITY (object)); 00132 00133 ENTER("view %p", object); 00134 view = GNC_TREE_VIEW_COMMODITY (object); 00135 priv = GNC_TREE_VIEW_COMMODITY_GET_PRIVATE (view); 00136 00137 if (G_OBJECT_CLASS (parent_class)->finalize) 00138 (* G_OBJECT_CLASS (parent_class)->finalize) (object); 00139 LEAVE(" "); 00140 } 00141 00142 static void 00143 gnc_tree_view_commodity_destroy (GtkObject *object) 00144 { 00145 GncTreeViewCommodity *view; 00146 00147 g_return_if_fail (object != NULL); 00148 g_return_if_fail (GNC_IS_TREE_VIEW_COMMODITY (object)); 00149 00150 ENTER("view %p", object); 00151 view = GNC_TREE_VIEW_COMMODITY (object); 00152 00153 if (GTK_OBJECT_CLASS (parent_class)->destroy) 00154 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); 00155 LEAVE(" "); 00156 } 00157 00158 00159 /************************************************************/ 00160 /* sort functions */ 00161 /************************************************************/ 00162 00163 static gboolean 00164 get_commodities_w_iters (GtkTreeModel *f_model, 00165 GtkTreeIter *f_iter_a, 00166 GtkTreeIter *f_iter_b, 00167 GtkTreeModel **model_p, 00168 GtkTreeIter *iter_a, 00169 GtkTreeIter *iter_b, 00170 gnc_commodity **comm_a, 00171 gnc_commodity **comm_b) 00172 { 00173 GncTreeModelCommodity *model; 00174 GtkTreeModel *tree_model; 00175 00176 tree_model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model)); 00177 model = GNC_TREE_MODEL_COMMODITY(tree_model); 00178 00179 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model), 00180 iter_a, 00181 f_iter_a); 00182 00183 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model), 00184 iter_b, 00185 f_iter_b); 00186 00187 /* Both iters must point to commodities for this to be meaningful */ 00188 if (!gnc_tree_model_commodity_iter_is_commodity (model, iter_a)) 00189 return FALSE; 00190 if (!gnc_tree_model_commodity_iter_is_commodity (model, iter_b)) 00191 return FALSE; 00192 00193 *comm_a = gnc_tree_model_commodity_get_commodity (model, iter_a); 00194 *comm_b = gnc_tree_model_commodity_get_commodity (model, iter_b); 00195 if (model_p) 00196 *model_p = tree_model; 00197 return TRUE; 00198 } 00199 00200 static gboolean 00201 get_commodities (GtkTreeModel *f_model, 00202 GtkTreeIter *f_iter_a, 00203 GtkTreeIter *f_iter_b, 00204 GtkTreeModel **model_p, 00205 gnc_commodity **comm_a, 00206 gnc_commodity **comm_b) 00207 { 00208 GtkTreeIter iter_a, iter_b; 00209 00210 return get_commodities_w_iters(f_model, f_iter_a, f_iter_b, model_p, 00211 &iter_a, &iter_b, comm_a, comm_b); 00212 } 00213 00214 static gint 00215 sort_namespace (GtkTreeModel *f_model, 00216 GtkTreeIter *f_iter_a, 00217 GtkTreeIter *f_iter_b) 00218 { 00219 GncTreeModelCommodity *model; 00220 GtkTreeModel *tree_model; 00221 GtkTreeIter iter_a, iter_b; 00222 gnc_commodity_namespace *ns_a, *ns_b; 00223 00224 tree_model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model)); 00225 model = GNC_TREE_MODEL_COMMODITY(tree_model); 00226 00227 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model), 00228 &iter_a, 00229 f_iter_a); 00230 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model), 00231 &iter_b, 00232 f_iter_b); 00233 00234 ns_a = gnc_tree_model_commodity_get_namespace (model, &iter_a); 00235 ns_b = gnc_tree_model_commodity_get_namespace (model, &iter_b); 00236 return safe_utf8_collate (gnc_commodity_namespace_get_name (ns_a), 00237 gnc_commodity_namespace_get_name (ns_b)); 00238 } 00239 00240 static gint 00241 default_sort (gnc_commodity *comm_a, gnc_commodity *comm_b) 00242 { 00243 gint fraction_a, fraction_b, result; 00244 00245 result = safe_utf8_collate (gnc_commodity_get_namespace (comm_a), 00246 gnc_commodity_get_namespace (comm_b)); 00247 if (result != 0) return result; 00248 00249 result = safe_utf8_collate (gnc_commodity_get_mnemonic (comm_a), 00250 gnc_commodity_get_mnemonic (comm_b)); 00251 if (result != 0) return result; 00252 00253 result = safe_utf8_collate (gnc_commodity_get_fullname (comm_a), 00254 gnc_commodity_get_fullname (comm_b)); 00255 if (result != 0) return result; 00256 00257 result = safe_utf8_collate (gnc_commodity_get_cusip (comm_a), 00258 gnc_commodity_get_cusip (comm_b)); 00259 if (result != 0) return result; 00260 00261 fraction_a = gnc_commodity_get_fraction (comm_a); 00262 fraction_b = gnc_commodity_get_fraction (comm_b); 00263 00264 if (fraction_a < fraction_b) 00265 return -1; 00266 00267 if (fraction_b < fraction_a) 00268 return 1; 00269 00270 return 0; 00271 } 00272 00273 static gint 00274 sort_by_commodity_string (GtkTreeModel *f_model, 00275 GtkTreeIter *f_iter_a, 00276 GtkTreeIter *f_iter_b, 00277 gpointer user_data) 00278 { 00279 GtkTreeModel *model; 00280 GtkTreeIter iter_a, iter_b; 00281 gnc_commodity *comm_a, *comm_b; 00282 gchar *str1, *str2; 00283 gint column = GPOINTER_TO_INT(user_data); 00284 gint result; 00285 00286 if (!get_commodities_w_iters(f_model, f_iter_a, f_iter_b, 00287 &model, &iter_a, &iter_b, &comm_a, &comm_b)) 00288 return sort_namespace (f_model, f_iter_a, f_iter_b); 00289 00290 /* Get the strings. */ 00291 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter_a, column, &str1, -1); 00292 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter_b, column, &str2, -1); 00293 00294 result = safe_utf8_collate(str1, str2); 00295 g_free(str1); 00296 g_free(str2); 00297 if (result != 0) 00298 return result; 00299 return default_sort(comm_a, comm_b); 00300 } 00301 00302 00303 static gint 00304 sort_by_fraction (GtkTreeModel *f_model, 00305 GtkTreeIter *f_iter_a, 00306 GtkTreeIter *f_iter_b, 00307 gpointer user_data) 00308 { 00309 gnc_commodity *comm_a, *comm_b; 00310 gint fraction_a, fraction_b; 00311 00312 if (!get_commodities (f_model, f_iter_a, f_iter_b, NULL, &comm_a, &comm_b)) 00313 return sort_namespace (f_model, f_iter_a, f_iter_b); 00314 00315 fraction_a = gnc_commodity_get_fraction (comm_a); 00316 fraction_b = gnc_commodity_get_fraction (comm_b); 00317 00318 if (fraction_a < fraction_b) 00319 return -1; 00320 00321 if (fraction_b < fraction_a) 00322 return 1; 00323 00324 return default_sort(comm_a, comm_b); 00325 } 00326 00327 static gint 00328 sort_by_quote_flag (GtkTreeModel *f_model, 00329 GtkTreeIter *f_iter_a, 00330 GtkTreeIter *f_iter_b, 00331 gpointer user_data) 00332 { 00333 gnc_commodity *comm_a, *comm_b; 00334 gboolean flag_a, flag_b; 00335 00336 if (!get_commodities (f_model, f_iter_a, f_iter_b, NULL, &comm_a, &comm_b)) 00337 return sort_namespace (f_model, f_iter_a, f_iter_b); 00338 00339 flag_a = gnc_commodity_get_quote_flag(comm_a); 00340 flag_b = gnc_commodity_get_quote_flag(comm_b); 00341 00342 if (flag_a < flag_b) 00343 return -1; 00344 else if (flag_a > flag_b) 00345 return 1; 00346 return default_sort(comm_a, comm_b); 00347 } 00348 00349 /************************************************************/ 00350 /* New View Creation */ 00351 /************************************************************/ 00352 00353 /* 00354 * Create a new commodity tree view with (optional) top level root node. 00355 * This view will be based on a model that is common to all view 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_commodity_new (QofBook *book, 00361 const gchar *first_property_name, 00362 ...) 00363 { 00364 GncTreeView *view; 00365 GtkTreeModel *model, *f_model, *s_model; 00366 GtkTreeViewColumn *col; 00367 gnc_commodity_table *ct; 00368 va_list var_args; 00369 00370 ENTER(" "); 00371 /* Create/get a pointer to the existing model for this set of books. */ 00372 ct = gnc_commodity_table_get_table (book); 00373 model = gnc_tree_model_commodity_new (book, ct); 00374 00375 /* Set up the view private filter on the common model. */ 00376 f_model = gtk_tree_model_filter_new (model, NULL); 00377 g_object_unref(G_OBJECT(model)); 00378 s_model = gtk_tree_model_sort_new_with_model (f_model); 00379 g_object_unref(G_OBJECT(f_model)); 00380 00381 /* Create our view */ 00382 view = g_object_new (GNC_TYPE_TREE_VIEW_COMMODITY, 00383 "name", "commodity_tree", NULL); 00384 gnc_tree_view_set_model (view, s_model); 00385 g_object_unref(G_OBJECT(s_model)); 00386 00387 DEBUG("model ref count is %d", G_OBJECT(model)->ref_count); 00388 DEBUG("f_model ref count is %d", G_OBJECT(f_model)->ref_count); 00389 DEBUG("s_model ref count is %d", G_OBJECT(s_model)->ref_count); 00390 00391 /* Set default visibilities */ 00392 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE); 00393 00394 col = gnc_tree_view_add_text_column ( 00395 view, _("Namespace"), "namespace", NULL, "NASDAQ", 00396 GNC_TREE_MODEL_COMMODITY_COL_NAMESPACE, 00397 GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS, 00398 sort_by_commodity_string); 00399 col = gnc_tree_view_add_text_column ( 00400 view, _("Symbol"), "symbol", NULL, "ACMEACME", 00401 GNC_TREE_MODEL_COMMODITY_COL_MNEMONIC, 00402 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, 00403 sort_by_commodity_string); 00404 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1)); 00405 col = gnc_tree_view_add_text_column ( 00406 view, _("Name"), "name", NULL, "Acme Corporation, Inc.", 00407 GNC_TREE_MODEL_COMMODITY_COL_FULLNAME, 00408 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, 00409 sort_by_commodity_string); 00410 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1)); 00411 col = gnc_tree_view_add_text_column ( 00412 view, _("Print Name"), "printname", NULL, 00413 "ACMEACME (Acme Corporation, Inc.)", 00414 GNC_TREE_MODEL_COMMODITY_COL_PRINTNAME, 00415 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, 00416 sort_by_commodity_string); 00417 col = gnc_tree_view_add_text_column ( 00418 view, _("Unique Name"), "uniquename", NULL, 00419 "NASDAQ::ACMEACME", GNC_TREE_MODEL_COMMODITY_COL_UNIQUE_NAME, 00420 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, 00421 sort_by_commodity_string); 00422 col = gnc_tree_view_add_text_column ( 00423 /* Translators: Again replace CUSIP by the name of your 00424 National Securities Identifying Number. */ 00425 view, _("ISIN/CUSIP"), "cusip_code", NULL, "QWERTYUIOP", 00426 GNC_TREE_MODEL_COMMODITY_COL_CUSIP, 00427 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, 00428 sort_by_commodity_string); 00429 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1)); 00430 col = gnc_tree_view_add_numeric_column ( 00431 view, _("Fraction"), "fraction", "10000", 00432 GNC_TREE_MODEL_COMMODITY_COL_FRACTION, 00433 GNC_TREE_VIEW_COLUMN_COLOR_NONE, 00434 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, 00435 sort_by_fraction); 00436 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1)); 00437 col = gnc_tree_view_add_toggle_column( 00438 view, _("Get Quotes"), 00439 /* Translators: This string has a context prefix; the translation 00440 must only contain the part after the | character. */ 00441 Q_("Column letter for 'Get Quotes'|Q"), "quote_flag", 00442 GNC_TREE_MODEL_COMMODITY_COL_QUOTE_FLAG, 00443 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, 00444 sort_by_quote_flag, 00445 NULL); 00446 col = gnc_tree_view_add_text_column ( 00447 view, _("Source"), "quote_source", NULL, "yahoo", 00448 GNC_TREE_MODEL_COMMODITY_COL_QUOTE_SOURCE, 00449 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, 00450 sort_by_commodity_string); 00451 col = gnc_tree_view_add_text_column ( 00452 view, _("Timezone"), "quote_timezone", NULL, "America/New_York", 00453 GNC_TREE_MODEL_COMMODITY_COL_QUOTE_TZ, 00454 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, 00455 sort_by_commodity_string); 00456 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1)); 00457 00458 gnc_tree_view_configure_columns(view); 00459 00460 /* Set properties */ 00461 va_start (var_args, first_property_name); 00462 g_object_set_valist (G_OBJECT(view), first_property_name, var_args); 00463 va_end (var_args); 00464 00465 /* Sort on the name column by default. This allows for a consistent 00466 * sort if commodities are briefly removed and re-added. */ 00467 if (!gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(s_model), 00468 NULL, NULL)) 00469 { 00470 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model), 00471 GNC_TREE_MODEL_COMMODITY_COL_FULLNAME, 00472 GTK_SORT_ASCENDING); 00473 } 00474 00475 gtk_widget_show(GTK_WIDGET(view)); 00476 LEAVE(" %p", view); 00477 return GTK_TREE_VIEW(view); 00478 } 00479 00480 /************************************************************/ 00481 /* Auxiliary Functions */ 00482 /************************************************************/ 00483 00484 #define debug_path(fn, path) { \ 00485 gchar *path_string = gtk_tree_path_to_string(path); \ 00486 fn("tree path %s", path_string); \ 00487 g_free(path_string); \ 00488 } 00489 00490 static gboolean 00491 gnc_tree_view_commodity_get_iter_from_commodity (GncTreeViewCommodity *view, 00492 gnc_commodity *commodity, 00493 GtkTreeIter *s_iter) 00494 { 00495 GtkTreeModel *model, *f_model, *s_model; 00496 GtkTreeIter iter, f_iter; 00497 00498 g_return_val_if_fail(GNC_IS_TREE_VIEW_COMMODITY(view), FALSE); 00499 g_return_val_if_fail(commodity != NULL, FALSE); 00500 g_return_val_if_fail(s_iter != NULL, FALSE); 00501 00502 ENTER("view %p, commodity %p (%s)", view, commodity, gnc_commodity_get_mnemonic(commodity)); 00503 00504 /* Reach down to the real model and get an iter for this commodity */ 00505 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); 00506 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model)); 00507 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model)); 00508 if (!gnc_tree_model_commodity_get_iter_from_commodity (GNC_TREE_MODEL_COMMODITY(model), commodity, &iter)) 00509 { 00510 LEAVE("model_get_iter_from_commodity failed"); 00511 return FALSE; 00512 } 00513 00514 /* convert back to a sort iter */ 00515 gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER(f_model), 00516 &f_iter, &iter); 00517 gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(s_model), 00518 s_iter, &f_iter); 00519 LEAVE(" "); 00520 return TRUE; 00521 } 00522 00523 /************************************************************/ 00524 /* Commodity Tree View Visibility Filter */ 00525 /************************************************************/ 00526 00527 typedef struct 00528 { 00529 gnc_tree_view_commodity_ns_filter_func user_ns_fn; 00530 gnc_tree_view_commodity_cm_filter_func user_cm_fn; 00531 gpointer user_data; 00532 GtkDestroyNotify user_destroy; 00533 } filter_user_data; 00534 00535 static void 00536 gnc_tree_view_commodity_filter_destroy (gpointer data) 00537 { 00538 filter_user_data *fd = data; 00539 00540 if (fd->user_destroy) 00541 fd->user_destroy(fd->user_data); 00542 g_free(fd); 00543 } 00544 00545 static gboolean 00546 gnc_tree_view_commodity_filter_helper (GtkTreeModel *model, 00547 GtkTreeIter *iter, 00548 gpointer data) 00549 { 00550 gnc_commodity_namespace *namespace; 00551 gnc_commodity *commodity; 00552 filter_user_data *fd = data; 00553 00554 g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE); 00555 g_return_val_if_fail (iter != NULL, FALSE); 00556 00557 if (gnc_tree_model_commodity_iter_is_namespace (GNC_TREE_MODEL_COMMODITY(model), iter)) 00558 { 00559 if (fd->user_ns_fn) 00560 { 00561 namespace = gnc_tree_model_commodity_get_namespace (GNC_TREE_MODEL_COMMODITY(model), iter); 00562 return fd->user_ns_fn(namespace, fd->user_data); 00563 } 00564 return TRUE; 00565 } 00566 00567 if (gnc_tree_model_commodity_iter_is_commodity (GNC_TREE_MODEL_COMMODITY(model), iter)) 00568 { 00569 if (fd->user_cm_fn) 00570 { 00571 commodity = gnc_tree_model_commodity_get_commodity (GNC_TREE_MODEL_COMMODITY(model), iter); 00572 return fd->user_cm_fn(commodity, fd->user_data); 00573 } 00574 return TRUE; 00575 } 00576 00577 return FALSE; 00578 } 00579 00580 /* 00581 * Set an GtkTreeModel visible filter on this commodity. This filter will be 00582 * called for each commodity that the tree is about to show, and the 00583 * commodity will be passed to the callback function. 00584 */ 00585 void 00586 gnc_tree_view_commodity_set_filter (GncTreeViewCommodity *view, 00587 gnc_tree_view_commodity_ns_filter_func ns_func, 00588 gnc_tree_view_commodity_cm_filter_func cm_func, 00589 gpointer data, 00590 GtkDestroyNotify destroy) 00591 { 00592 GtkTreeModel *f_model, *s_model; 00593 filter_user_data *fd = data; 00594 00595 g_return_if_fail(GNC_IS_TREE_VIEW_COMMODITY(view)); 00596 g_return_if_fail((ns_func != NULL) || (cm_func != NULL)); 00597 00598 ENTER("view %p, ns func %p, cm func %p, data %p, destroy %p", 00599 view, ns_func, cm_func, data, destroy); 00600 00601 fd = g_malloc(sizeof(filter_user_data)); 00602 fd->user_ns_fn = ns_func; 00603 fd->user_cm_fn = cm_func; 00604 fd->user_data = data; 00605 fd->user_destroy = destroy; 00606 00607 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); 00608 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model)); 00609 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (f_model), 00610 gnc_tree_view_commodity_filter_helper, 00611 fd, 00612 gnc_tree_view_commodity_filter_destroy); 00613 00614 /* Whack any existing levels. The top two levels have been created 00615 * before this routine can be called. */ 00616 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model)); 00617 LEAVE(" "); 00618 } 00619 00620 /* 00621 * Forces the entire commodity tree to be re-evaluated for visibility. 00622 */ 00623 void 00624 gnc_tree_view_commodity_refilter (GncTreeViewCommodity *view) 00625 { 00626 GtkTreeModel *f_model, *s_model; 00627 00628 g_return_if_fail(GNC_IS_TREE_VIEW_COMMODITY(view)); 00629 00630 ENTER("view %p", view); 00631 s_model = gtk_tree_view_get_model (GTK_TREE_VIEW(view)); 00632 f_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (s_model)); 00633 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model)); 00634 LEAVE(" "); 00635 } 00636 00637 00638 /************************************************************/ 00639 /* Commodity Tree View Get/Set Functions */ 00640 /************************************************************/ 00641 00642 /* 00643 * Retrieve the selected commodity from an commodity tree view. The 00644 * commodity tree must be in single selection mode. 00645 */ 00646 gnc_commodity * 00647 gnc_tree_view_commodity_get_selected_commodity (GncTreeViewCommodity *view) 00648 { 00649 GtkTreeSelection *selection; 00650 GtkTreeModel *model, *f_model, *s_model; 00651 GtkTreeIter iter, f_iter, s_iter; 00652 gnc_commodity *commodity; 00653 00654 g_return_val_if_fail (GNC_IS_TREE_VIEW_COMMODITY (view), NULL); 00655 00656 ENTER("view %p", view); 00657 00658 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view)); 00659 if (!gtk_tree_selection_get_selected (selection, &s_model, &s_iter)) 00660 { 00661 LEAVE("no commodity, get_selected failed"); 00662 return FALSE; 00663 } 00664 00665 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model), 00666 &f_iter, &s_iter); 00667 00668 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model)); 00669 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model), 00670 &iter, &f_iter); 00671 00672 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model)); 00673 commodity = gnc_tree_model_commodity_get_commodity (GNC_TREE_MODEL_COMMODITY(model), 00674 &iter); 00675 LEAVE("commodity %p (%s)", commodity, 00676 commodity ? gnc_commodity_get_mnemonic(commodity) : ""); 00677 return commodity; 00678 } 00679 00680 00681 /* 00682 * This helper function is called once for each row in the tree view 00683 * that is currently selected. Its task is to an the corresponding 00684 * commodity to the end of a glist. 00685 */ 00686 static void 00687 get_selected_commodities_helper (GtkTreeModel *s_model, 00688 GtkTreePath *s_path, 00689 GtkTreeIter *s_iter, 00690 gpointer data) 00691 { 00692 GList **return_list = data; 00693 GtkTreeModel *model, *f_model; 00694 GtkTreeIter iter, f_iter; 00695 gnc_commodity *commodity; 00696 00697 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model), 00698 &f_iter, s_iter); 00699 00700 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model)); 00701 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model), 00702 &iter, &f_iter); 00703 00704 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model)); 00705 commodity = gnc_tree_model_commodity_get_commodity (GNC_TREE_MODEL_COMMODITY(model), 00706 &iter); 00707 *return_list = g_list_append(*return_list, commodity); 00708 }
1.7.4