28 #include <glib/gi18n.h> 36 #include "gnc-component-manager.h" 40 #include "gnc-icons.h" 47 static QofLogModule log_module = GNC_MOD_GUI;
50 static void gnc_tree_view_price_finalize (GObject *
object);
51 static void gnc_tree_view_price_destroy (GtkWidget *widget);
55 GncTreeView gnc_tree_view;
64 G_DEFINE_TYPE(GncTreeViewPrice, gnc_tree_view_price, GNC_TYPE_TREE_VIEW)
67 gnc_tree_view_price_class_init (GncTreeViewPriceClass *klass)
69 GObjectClass *o_class;
70 GtkWidgetClass *widget_class;
72 o_class = G_OBJECT_CLASS (klass);
73 widget_class = GTK_WIDGET_CLASS (klass);
76 o_class->finalize = gnc_tree_view_price_finalize;
79 widget_class->destroy = gnc_tree_view_price_destroy;
83 gnc_tree_view_price_init (GncTreeViewPrice *view)
88 gnc_tree_view_price_finalize (GObject *
object)
90 ENTER(
"view %p",
object);
94 G_OBJECT_CLASS (gnc_tree_view_price_parent_class)->finalize (
object);
99 gnc_tree_view_price_destroy (GtkWidget *widget)
101 ENTER(
"view %p", widget);
105 GTK_WIDGET_CLASS (gnc_tree_view_price_parent_class)->destroy (widget);
115 get_prices (GtkTreeModel *f_model,
116 GtkTreeIter *f_iter_a,
117 GtkTreeIter *f_iter_b,
121 GncTreeModelPrice *model;
122 GtkTreeModel *tree_model;
123 GtkTreeIter iter_a, iter_b;
125 tree_model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
126 model = GNC_TREE_MODEL_PRICE(tree_model);
128 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
136 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
146 sort_ns_or_cm (GtkTreeModel *f_model,
147 GtkTreeIter *f_iter_a,
148 GtkTreeIter *f_iter_b)
150 GncTreeModelPrice *model;
151 GtkTreeModel *tree_model;
152 GtkTreeIter iter_a, iter_b;
153 gnc_commodity_namespace *ns_a, *ns_b;
154 gnc_commodity *comm_a, *comm_b;
156 tree_model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
157 model = GNC_TREE_MODEL_PRICE(tree_model);
159 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
162 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
181 default_sort (GNCPrice *price_a, GNCPrice *price_b)
183 gnc_commodity *curr_a, *curr_b;
190 curr_a = gnc_price_get_currency (price_a);
191 curr_b = gnc_price_get_currency (price_b);
195 if (result != 0)
return result;
199 if (result != 0)
return result;
202 time_a = gnc_price_get_time64 (price_a);
203 time_b = gnc_price_get_time64 (price_b);
204 result = time_a < time_b ? -1 : time_a > time_b ? 1 : 0;
211 gnc_price_get_value (price_b));
215 sort_by_name (GtkTreeModel *f_model,
216 GtkTreeIter *f_iter_a,
217 GtkTreeIter *f_iter_b,
220 GNCPrice *price_a, *price_b;
222 if (!get_prices (f_model, f_iter_a, f_iter_b, &price_a, &price_b))
223 return sort_ns_or_cm (f_model, f_iter_a, f_iter_b);
225 return default_sort (price_a, price_b);
229 sort_by_date (GtkTreeModel *f_model,
230 GtkTreeIter *f_iter_a,
231 GtkTreeIter *f_iter_b,
234 GNCPrice *price_a, *price_b;
238 if (!get_prices (f_model, f_iter_a, f_iter_b, &price_a, &price_b))
239 return sort_ns_or_cm (f_model, f_iter_a, f_iter_b);
242 time_a = gnc_price_get_time64 (price_a);
243 time_b = gnc_price_get_time64 (price_b);
244 result = time_a < time_b ? -1 : time_a > time_b ? 1 : 0;
249 return default_sort (price_a, price_b);
253 sort_by_source (GtkTreeModel *f_model,
254 GtkTreeIter *f_iter_a,
255 GtkTreeIter *f_iter_b,
258 GNCPrice *price_a, *price_b;
261 if (!get_prices (f_model, f_iter_a, f_iter_b, &price_a, &price_b))
262 return sort_ns_or_cm (f_model, f_iter_a, f_iter_b);
265 result = gnc_price_get_source (price_a) < gnc_price_get_source (price_b);
269 return default_sort (price_a, price_b);
273 sort_by_type (GtkTreeModel *f_model,
274 GtkTreeIter *f_iter_a,
275 GtkTreeIter *f_iter_b,
278 GNCPrice *price_a, *price_b;
281 if (!get_prices (f_model, f_iter_a, f_iter_b, &price_a, &price_b))
282 return sort_ns_or_cm (f_model, f_iter_a, f_iter_b);
286 gnc_price_get_typestr (price_b));
290 return default_sort (price_a, price_b);
294 sort_by_value (GtkTreeModel *f_model,
295 GtkTreeIter *f_iter_a,
296 GtkTreeIter *f_iter_b,
299 gnc_commodity *comm_a, *comm_b;
300 GNCPrice *price_a, *price_b;
304 if (!get_prices (f_model, f_iter_a, f_iter_b, &price_a, &price_b))
305 return sort_ns_or_cm (f_model, f_iter_a, f_iter_b);
312 comm_a = gnc_price_get_currency (price_a);
313 comm_b = gnc_price_get_currency (price_b);
314 if (comm_a && comm_b)
331 gnc_price_get_value (price_b));
335 return default_sort (price_a, price_b);
351 const gchar *first_property_name,
355 GtkTreeModel *model, *f_model, *s_model;
356 GtkTreeViewColumn *col;
357 GNCPriceDB *price_db;
359 const gchar *sample_text;
368 f_model = gtk_tree_model_filter_new (model, NULL);
369 g_object_unref(G_OBJECT(model));
370 s_model = gtk_tree_model_sort_new_with_model (f_model);
371 g_object_unref(G_OBJECT(f_model));
374 view = g_object_new (GNC_TYPE_TREE_VIEW_PRICE,
375 "name",
"gnc-id-price-tree", NULL);
376 gtk_tree_view_set_model (GTK_TREE_VIEW (view), s_model);
377 g_object_unref(G_OBJECT(s_model));
379 DEBUG(
"model ref count is %d", G_OBJECT(model)->ref_count);
380 DEBUG(
"f_model ref count is %d", G_OBJECT(f_model)->ref_count);
381 DEBUG(
"s_model ref count is %d", G_OBJECT(s_model)->ref_count);
384 sample_text2 = g_strdup_printf(
"%s%s", sample_text, sample_text);
386 view, _(
"Security"),
"security", NULL, sample_text2,
387 GNC_TREE_MODEL_PRICE_COL_COMMODITY,
388 GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
390 g_free(sample_text2);
392 view, _(
"Currency"),
"currency", NULL, sample_text,
393 GNC_TREE_MODEL_PRICE_COL_CURRENCY,
394 GNC_TREE_MODEL_PRICE_COL_VISIBILITY,
396 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
398 view, _(
"Date"),
"date", NULL,
"2005-05-20",
399 GNC_TREE_MODEL_PRICE_COL_DATE,
400 GNC_TREE_MODEL_PRICE_COL_VISIBILITY,
402 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
404 view, _(
"Source"),
"source", NULL,
"Finance::Quote",
405 GNC_TREE_MODEL_PRICE_COL_SOURCE,
406 GNC_TREE_MODEL_PRICE_COL_VISIBILITY,
408 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
410 view, _(
"Type"),
"type", NULL,
"last",
411 GNC_TREE_MODEL_PRICE_COL_TYPE,
412 GNC_TREE_MODEL_PRICE_COL_VISIBILITY,
414 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
416 view, _(
"Price"),
"price",
"100.00000",
417 GNC_TREE_MODEL_PRICE_COL_VALUE,
418 GNC_TREE_VIEW_COLUMN_COLOR_NONE,
419 GNC_TREE_MODEL_PRICE_COL_VISIBILITY,
421 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
426 va_start (var_args, first_property_name);
427 g_object_set_valist (G_OBJECT(view), first_property_name, var_args);
432 if (!gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(s_model),
435 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
436 GNC_TREE_MODEL_PRICE_COL_COMMODITY,
440 gtk_widget_show(GTK_WIDGET(view));
442 return GTK_TREE_VIEW(view);
449 #define debug_path(fn, path) { \ 450 gchar *path_string = gtk_tree_path_to_string(path); \ 451 fn("tree path %s", path_string); \ 452 g_free(path_string); \ 457 gnc_tree_view_price_get_iter_from_price (GncTreeViewPrice *view,
461 GtkTreeModel *model, *f_model, *s_model;
462 GtkTreeIter iter, f_iter;
464 g_return_val_if_fail(GNC_IS_TREE_VIEW_PRICE(view), FALSE);
465 g_return_val_if_fail(price != NULL, FALSE);
466 g_return_val_if_fail(s_iter != NULL, FALSE);
468 ENTER(
"view %p, price %p", view, price);
471 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
472 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
473 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
476 LEAVE(
"model_get_iter_from_price failed");
481 gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER(f_model),
483 gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(s_model),
501 gnc_tree_view_price_cm_filter_func user_cm_fn;
502 gnc_tree_view_price_pc_filter_func user_pc_fn;
504 GDestroyNotify user_destroy;
508 gnc_tree_view_price_filter_destroy (gpointer data)
512 if (fd->user_destroy)
513 fd->user_destroy(fd->user_data);
518 gnc_tree_view_price_filter_helper (GtkTreeModel *model,
522 gnc_commodity_namespace *name_space;
523 gnc_commodity *commodity;
527 g_return_val_if_fail (GNC_IS_TREE_MODEL_PRICE (model), FALSE);
528 g_return_val_if_fail (iter != NULL, FALSE);
535 return fd->user_ns_fn(name_space, fd->user_data);
545 return fd->user_cm_fn(commodity, fd->user_data);
555 return fd->user_pc_fn(price, fd->user_data);
569 gnc_tree_view_price_set_filter (GncTreeViewPrice *view,
571 gnc_tree_view_price_cm_filter_func cm_func,
572 gnc_tree_view_price_pc_filter_func pc_func,
574 GDestroyNotify destroy)
576 GtkTreeModel *f_model, *s_model;
579 ENTER(
"view %p, ns func %p, cm func %p, pc func %p, data %p, destroy %p",
580 view, ns_func, cm_func, pc_func, data, destroy);
582 g_return_if_fail(GNC_IS_TREE_VIEW_PRICE(view));
583 g_return_if_fail((ns_func != NULL) || (cm_func != NULL));
586 fd->user_ns_fn = ns_func;
587 fd->user_cm_fn = cm_func;
588 fd->user_pc_fn = pc_func;
589 fd->user_data = data;
590 fd->user_destroy = destroy;
592 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
593 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
596 g_object_ref (G_OBJECT(s_model));
597 gtk_tree_view_set_model (GTK_TREE_VIEW(view), NULL);
599 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (f_model),
600 gnc_tree_view_price_filter_helper,
602 gnc_tree_view_price_filter_destroy);
610 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
613 gtk_tree_view_set_model (GTK_TREE_VIEW(view), s_model);
614 g_object_unref (G_OBJECT(s_model));
630 GtkTreeSelection *selection;
631 GtkTreeModel *model, *f_model, *s_model;
632 GtkTreeIter iter, f_iter, s_iter;
635 ENTER(
"view %p", view);
636 g_return_val_if_fail (GNC_IS_TREE_VIEW_PRICE (view), NULL);
638 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
639 if (!gtk_tree_selection_get_selected (selection, &s_model, &s_iter))
641 LEAVE(
"no price, get_selected failed");
645 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
648 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
649 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model),
652 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
655 LEAVE(
"price %p", price);
667 GtkTreeModel *model, *f_model, *s_model;
668 GtkTreePath *path, *f_path, *s_path, *parent_path;
669 GtkTreeSelection *selection;
671 ENTER(
"view %p, price %p", view, price);
674 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
675 gtk_tree_selection_unselect_all (selection);
680 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
681 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
682 model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (f_model));
687 LEAVE(
"get_path_from_price failed");
690 debug_path(
DEBUG, path);
692 f_path = gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (f_model),
694 gtk_tree_path_free(path);
697 LEAVE(
"no filter path");
700 debug_path(
DEBUG, f_path);
702 s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model),
704 gtk_tree_path_free(f_path);
707 LEAVE(
"no sort path");
712 parent_path = gtk_tree_path_copy (s_path);
713 if (gtk_tree_path_up (parent_path))
718 gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), parent_path);
720 gtk_tree_path_free(parent_path);
722 gtk_tree_selection_select_path (selection, s_path);
723 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), s_path, NULL, FALSE, 0.0, 0.0);
724 debug_path(
LEAVE, s_path);
725 gtk_tree_path_free(s_path);
734 get_selected_prices_helper (GtkTreeModel *s_model,
739 GList **return_list = data;
740 GtkTreeModel *model, *f_model;
741 GtkTreeIter iter, f_iter;
744 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
747 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
748 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model),
751 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
755 *return_list = g_list_prepend (*return_list, price);
768 GtkTreeSelection *selection;
769 GList *return_list = NULL;
771 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
772 gtk_tree_selection_selected_foreach(selection, get_selected_prices_helper, &return_list);
773 return g_list_reverse (return_list);
777 get_selected_commodity_helper (GtkTreeModel *s_model,
782 GList **return_list = data;
783 GtkTreeModel *model, *f_model;
784 GtkTreeIter iter, f_iter;
785 gnc_commodity *commodity;
787 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
790 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
791 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model),
794 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
798 *return_list = g_list_prepend (*return_list, commodity);
812 GtkTreeSelection *selection;
813 GList *return_list = NULL;
815 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
816 gtk_tree_selection_selected_foreach (selection, get_selected_commodity_helper, &return_list);
817 return g_list_reverse (return_list);
gboolean gnc_tree_model_price_get_iter_from_price(GncTreeModelPrice *model, GNCPrice *price, GtkTreeIter *iter)
Convert a price pointer into a GtkTreeIter.
gnc_commodity * gnc_tree_model_price_get_commodity(GncTreeModelPrice *model, GtkTreeIter *iter)
Convert a model/iter pair to a gnucash commodity.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
a simple price database for gnucash
const char * gnc_commodity_namespace_get_gui_name(const gnc_commodity_namespace *ns)
Return the textual name of a namespace data structure in a form suitable to present to the user...
utility functions for the GnuCash UI
int safe_utf8_collate(const char *da, const char *db)
Collate two UTF-8 strings.
GtkTreeModel implementation for gnucash price database.
gboolean(* gnc_tree_view_price_ns_filter_func)(gnc_commodity_namespace *, gpointer data)
This function attaches a filter function to the given price tree.
common utilities for manipulating a GtkTreeView within gnucash
#define DEBUG(format, args...)
Print a debugging message.
GNCPrice * gnc_tree_model_price_get_price(GncTreeModelPrice *model, GtkTreeIter *iter)
Convert a model/iter pair to a gnucash price.
GNCPrice * gnc_tree_view_price_get_selected_price(GncTreeViewPrice *view)
This function returns the price associated with the selected item in the price tree view...
GList * gnc_tree_view_price_get_selected_commodities(GncTreeViewPrice *view)
This function returns a list of commodities associated with the selected rows that are not prices but...
GList * gnc_tree_view_price_get_selected_prices(GncTreeViewPrice *view)
This function returns a list of the prices associated with the selected items in the price tree view...
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
Retrieve the namespace for the specified commodity.
gnc_commodity_namespace * gnc_tree_model_price_get_namespace(GncTreeModelPrice *model, GtkTreeIter *iter)
Convert a model/iter pair to a gnucash commodity namespace.
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b.
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)
This function adds a new numeric column to a GncTreeView base view.
#define ENTER(format, args...)
Print a function entry debugging message.
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Return the pricedb associated with the book.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
gboolean gnc_tree_model_price_iter_is_namespace(GncTreeModelPrice *model, GtkTreeIter *iter)
Determine whether or not the specified GtkTreeIter points to a "commodity namespace".
GtkTreeView implementation for gnucash price tree.
gboolean gnc_tree_model_price_iter_is_commodity(GncTreeModelPrice *model, GtkTreeIter *iter)
Determine whether or not the specified GtkTreeIter points to a commodity.
void gnc_tree_view_configure_columns(GncTreeView *view)
Make all the correct columns visible, respecting their default visibility setting, their "always" visibility setting, and the last saved state if available.
Gnome specific utility functions.
gboolean gnc_tree_model_price_iter_is_price(GncTreeModelPrice *model, GtkTreeIter *iter)
Determine whether or not the specified GtkTreeIter points to a price.
All type declarations for the whole Gnucash engine.
void gnc_tree_view_price_set_selected_price(GncTreeViewPrice *view, GNCPrice *price)
This function selects an price in the price tree view.
const char * gnc_commodity_get_printname(const gnc_commodity *cm)
Retrieve the 'print' name for the specified commodity.
GtkTreeModel * gnc_tree_model_price_new(QofBook *book, GNCPriceDB *price_db)
Create a new GtkTreeModel for manipulating gnucash commodity prices.
#define gnc_leave_return_if_fail(test)
Replacement for g_return_if_fail, but calls LEAVE if the test fails.
GtkTreePath * gnc_tree_model_price_get_path_from_price(GncTreeModelPrice *model, GNCPrice *price)
Convert a price pointer into a GtkTreePath.
GtkTreeViewColumn * gnc_tree_view_add_text_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *icon_name, const gchar *sizing_text, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
This function adds a new text column to a GncTreeView base view.
#define LEAVE(format, args...)
Print a function exit debugging message.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
GtkTreeView * gnc_tree_view_price_new(QofBook *book, const gchar *first_property_name,...)
Create a new price tree view.