GnuCash  4.11-137-g155922540d+
gnc-tree-model-commodity.c
1 /*
2  * gnc-tree-model-commodity.c -- GtkTreeModel implementation to
3  * display commodities in a GtkTreeView.
4  *
5  * Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de>
6  * Copyright (C) 2003 David Hampton <hampton@employees.org>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, contact:
20  *
21  * Free Software Foundation Voice: +1-617-542-5942
22  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
23  * Boston, MA 02110-1301, USA gnu@gnu.org
24  */
25 
26 /*
27  * In this model, valid paths take the form "X" or "X:Y", where:
28  * X is an index into the namespaces list held by the commodity db
29  * Y is an index into the commodity list for the namespace
30  *
31  * Iterators are populated with the following private data:
32  * iter->user_data Type NAMESPACE | COMMODITY
33  * iter->user_data2 A pointer to the namespace/commodity
34  * iter->user_data3 The index of the namespace/commodity within its parent list
35  */
36 
37 #include <config.h>
38 
39 #include <glib/gi18n.h>
40 #include <gtk/gtk.h>
41 #include <string.h>
42 
44 #include "gnc-component-manager.h"
45 #include "gnc-engine.h"
46 #include "gnc-gobject-utils.h"
47 #include "gnc-ui-util.h"
48 
49 #define ITER_IS_NAMESPACE GINT_TO_POINTER(1)
50 #define ITER_IS_COMMODITY GINT_TO_POINTER(2)
51 
53 static QofLogModule log_module = GNC_MOD_GUI;
54 
56 static void gnc_tree_model_commodity_class_init (GncTreeModelCommodityClass *klass);
57 static void gnc_tree_model_commodity_init (GncTreeModelCommodity *model);
58 static void gnc_tree_model_commodity_finalize (GObject *object);
59 static void gnc_tree_model_commodity_dispose (GObject *object);
60 
61 static void gnc_tree_model_commodity_tree_model_init (GtkTreeModelIface *iface);
62 static GtkTreeModelFlags gnc_tree_model_commodity_get_flags (GtkTreeModel *tree_model);
63 static int gnc_tree_model_commodity_get_n_columns (GtkTreeModel *tree_model);
64 static GType gnc_tree_model_commodity_get_column_type (GtkTreeModel *tree_model,
65  int index);
66 static gboolean gnc_tree_model_commodity_get_iter (GtkTreeModel *tree_model,
67  GtkTreeIter *iter,
68  GtkTreePath *path);
69 static GtkTreePath *gnc_tree_model_commodity_get_path (GtkTreeModel *tree_model,
70  GtkTreeIter *iter);
71 static void gnc_tree_model_commodity_get_value (GtkTreeModel *tree_model,
72  GtkTreeIter *iter,
73  int column,
74  GValue *value);
75 static gboolean gnc_tree_model_commodity_iter_next (GtkTreeModel *tree_model,
76  GtkTreeIter *iter);
77 static gboolean gnc_tree_model_commodity_iter_children (GtkTreeModel *tree_model,
78  GtkTreeIter *iter,
79  GtkTreeIter *parent);
80 static gboolean gnc_tree_model_commodity_iter_has_child (GtkTreeModel *tree_model,
81  GtkTreeIter *iter);
82 static int gnc_tree_model_commodity_iter_n_children (GtkTreeModel *tree_model,
83  GtkTreeIter *iter);
84 static gboolean gnc_tree_model_commodity_iter_nth_child (GtkTreeModel *tree_model,
85  GtkTreeIter *iter,
86  GtkTreeIter *parent,
87  int n);
88 static gboolean gnc_tree_model_commodity_iter_parent (GtkTreeModel *tree_model,
89  GtkTreeIter *iter,
90  GtkTreeIter *child);
91 static void gnc_tree_model_commodity_event_handler (QofInstance *entity,
92  QofEventId event_type,
93  gpointer user_data,
94  gpointer event_data);
95 
98 {
99  QofBook *book;
100  gnc_commodity_table *commodity_table;
101  gint event_handler_id;
103 
104 #define GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(o) \
105  ((GncTreeModelCommodityPrivate*)gnc_tree_model_commodity_get_instance_private((GncTreeModelCommodity*)o))
106 
108 static GObjectClass *parent_class = NULL;
109 
110 G_DEFINE_TYPE_WITH_CODE(GncTreeModelCommodity, gnc_tree_model_commodity, GNC_TYPE_TREE_MODEL,
111  G_ADD_PRIVATE(GncTreeModelCommodity)
112  G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL,
113  gnc_tree_model_commodity_tree_model_init))
114 
115 static void
116 gnc_tree_model_commodity_class_init (GncTreeModelCommodityClass *klass)
117 {
118  GObjectClass *o_class = G_OBJECT_CLASS (klass);
119 
120  parent_class = g_type_class_peek_parent (klass);
121 
122  o_class->finalize = gnc_tree_model_commodity_finalize;
123  o_class->dispose = gnc_tree_model_commodity_dispose;
124 }
125 
126 static void
127 gnc_tree_model_commodity_init (GncTreeModelCommodity *model)
128 {
129  while (model->stamp == 0)
130  {
131  model->stamp = g_random_int ();
132  }
133 }
134 
135 static void
136 gnc_tree_model_commodity_finalize (GObject *object)
137 {
138  GncTreeModelCommodity *model;
140 
141  g_return_if_fail (object != NULL);
142  g_return_if_fail (GNC_IS_TREE_MODEL_COMMODITY (object));
143 
144  ENTER("model %p", object);
145 
146  model = GNC_TREE_MODEL_COMMODITY (object);
147  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
148  priv->book = NULL;
149  priv->commodity_table = NULL;
150 
151  G_OBJECT_CLASS (parent_class)->finalize (object);
152  LEAVE(" ");
153 }
154 
155 static void
156 gnc_tree_model_commodity_dispose (GObject *object)
157 {
158  GncTreeModelCommodity *model;
160 
161  g_return_if_fail (object != NULL);
162  g_return_if_fail (GNC_IS_TREE_MODEL_COMMODITY (object));
163 
164  ENTER("model %p", object);
165  model = GNC_TREE_MODEL_COMMODITY (object);
166  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
167 
168  if (priv->event_handler_id)
169  {
170  qof_event_unregister_handler (priv->event_handler_id);
171  priv->event_handler_id = 0;
172  }
173 
174  if (G_OBJECT_CLASS (parent_class)->dispose)
175  G_OBJECT_CLASS (parent_class)->dispose (object);
176  LEAVE(" ");
177 }
178 
179 GtkTreeModel *
180 gnc_tree_model_commodity_new (QofBook *book, gnc_commodity_table *ct)
181 {
182  GncTreeModelCommodity *model;
184  const GList *item;
185 
186  ENTER("");
187 
188  item = gnc_gobject_tracking_get_list(GNC_TREE_MODEL_COMMODITY_NAME);
189  for ( ; item; item = g_list_next(item))
190  {
191  model = (GncTreeModelCommodity *)item->data;
192  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
193  if (priv->commodity_table == ct)
194  {
195  g_object_ref(G_OBJECT(model));
196  LEAVE("returning existing model %p", model);
197  return GTK_TREE_MODEL(model);
198  }
199  }
200 
201  model = g_object_new (GNC_TYPE_TREE_MODEL_COMMODITY, NULL);
202  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
203  priv->book = book;
204  priv->commodity_table = ct;
205 
206  priv->event_handler_id =
207  qof_event_register_handler (gnc_tree_model_commodity_event_handler, model);
208 
209  LEAVE("");
210  return GTK_TREE_MODEL (model);
211 }
212 
213 gboolean
215  GtkTreeIter *iter)
216 {
217  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE);
218  g_return_val_if_fail (iter != NULL, FALSE);
219  g_return_val_if_fail (iter->user_data != NULL, FALSE);
220  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
221 
222  return (iter->user_data == ITER_IS_NAMESPACE);
223 }
224 
225 gboolean
227  GtkTreeIter *iter)
228 {
229  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE);
230  g_return_val_if_fail (iter != NULL, FALSE);
231  g_return_val_if_fail (iter->user_data != NULL, FALSE);
232  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
233 
234  return (iter->user_data == ITER_IS_COMMODITY);
235 }
236 
237 gnc_commodity_namespace *
239  GtkTreeIter *iter)
240 {
241  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), NULL);
242  g_return_val_if_fail (iter != NULL, NULL);
243  g_return_val_if_fail (iter->user_data != NULL, NULL);
244  g_return_val_if_fail (iter->stamp == model->stamp, NULL);
245 
246  if (iter->user_data != ITER_IS_NAMESPACE)
247  return NULL;
248  return (gnc_commodity_namespace *)iter->user_data2;
249 }
250 
251 gnc_commodity *
253  GtkTreeIter *iter)
254 {
255  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), NULL);
256  g_return_val_if_fail (iter != NULL, NULL);
257  g_return_val_if_fail (iter->user_data != NULL, NULL);
258  g_return_val_if_fail (iter->stamp == model->stamp, NULL);
259 
260  if (iter->user_data != ITER_IS_COMMODITY)
261  return NULL;
262  return (gnc_commodity *)iter->user_data2;
263 }
264 
265 /************************************************************/
266 /* Gnc Tree Model Debugging Utility Function */
267 /************************************************************/
268 
269 #define debug_path(fn, path) { \
270  gchar *path_string = gtk_tree_path_to_string(path); \
271  fn("tree path %s", path_string? path_string : "NULL"); \
272  g_free(path_string); \
273  }
274 
275 #define ITER_STRING_LEN 128
276 
277 static const gchar *
278 iter_to_string (GtkTreeIter *iter)
279 {
280  gnc_commodity_namespace *name_space;
281  gnc_commodity *commodity = NULL;
282 #ifdef G_THREADS_ENABLED
283  static GPrivate gtmits_buffer_key = G_PRIVATE_INIT(g_free);
284  gchar *string;
285 
286  string = g_private_get (&gtmits_buffer_key);
287  if (string == NULL)
288  {
289  string = g_malloc(ITER_STRING_LEN + 1);
290  g_private_set (&gtmits_buffer_key, string);
291  }
292 #else
293  static char string[ITER_STRING_LEN + 1];
294 #endif
295  if (iter)
296  {
297  switch (GPOINTER_TO_INT(iter->user_data))
298  {
299  case GPOINTER_TO_INT(ITER_IS_NAMESPACE):
300  name_space = (gnc_commodity_namespace *) iter->user_data2;
301  snprintf(string, ITER_STRING_LEN,
302  "[stamp:%x data:%d (NAMESPACE), %p (%s), %d]",
303  iter->stamp, GPOINTER_TO_INT(iter->user_data),
304  iter->user_data2, gnc_commodity_namespace_get_name (name_space),
305  GPOINTER_TO_INT(iter->user_data3));
306  break;
307 
308  case GPOINTER_TO_INT(ITER_IS_COMMODITY):
309  commodity = (gnc_commodity *) iter->user_data2;
310  snprintf(string, ITER_STRING_LEN,
311  "[stamp:%x data:%d (COMMODITY), %p (%s), %d]",
312  iter->stamp, GPOINTER_TO_INT(iter->user_data),
313  iter->user_data2, gnc_commodity_get_mnemonic (commodity),
314  GPOINTER_TO_INT(iter->user_data3));
315  break;
316 
317  default:
318  snprintf(string, ITER_STRING_LEN,
319  "[stamp:%x data:%d (UNKNOWN), %p, %d]",
320  iter->stamp,
321  GPOINTER_TO_INT(iter->user_data),
322  iter->user_data2,
323  GPOINTER_TO_INT(iter->user_data3));
324  break;
325  }
326  }
327  return string;
328 }
329 
330 
331 /************************************************************/
332 /* Gtk Tree Model Required Interface Functions */
333 /************************************************************/
334 
335 static void
336 gnc_tree_model_commodity_tree_model_init (GtkTreeModelIface *iface)
337 {
338  iface->get_flags = gnc_tree_model_commodity_get_flags;
339  iface->get_n_columns = gnc_tree_model_commodity_get_n_columns;
340  iface->get_column_type = gnc_tree_model_commodity_get_column_type;
341  iface->get_iter = gnc_tree_model_commodity_get_iter;
342  iface->get_path = gnc_tree_model_commodity_get_path;
343  iface->get_value = gnc_tree_model_commodity_get_value;
344  iface->iter_next = gnc_tree_model_commodity_iter_next;
345  iface->iter_children = gnc_tree_model_commodity_iter_children;
346  iface->iter_has_child = gnc_tree_model_commodity_iter_has_child;
347  iface->iter_n_children = gnc_tree_model_commodity_iter_n_children;
348  iface->iter_nth_child = gnc_tree_model_commodity_iter_nth_child;
349  iface->iter_parent = gnc_tree_model_commodity_iter_parent;
350 }
351 
352 static GtkTreeModelFlags
353 gnc_tree_model_commodity_get_flags (GtkTreeModel *tree_model)
354 {
355  return 0;
356 }
357 
358 static int
359 gnc_tree_model_commodity_get_n_columns (GtkTreeModel *tree_model)
360 {
361  return GNC_TREE_MODEL_COMMODITY_NUM_COLUMNS;
362 }
363 
364 static GType
365 gnc_tree_model_commodity_get_column_type (GtkTreeModel *tree_model,
366  int index)
367 {
368  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), G_TYPE_INVALID);
369  g_return_val_if_fail ((index < GNC_TREE_MODEL_COMMODITY_NUM_COLUMNS) && (index >= 0), G_TYPE_INVALID);
370 
371  switch (index)
372  {
373  case GNC_TREE_MODEL_COMMODITY_COL_MNEMONIC:
374  case GNC_TREE_MODEL_COMMODITY_COL_NAMESPACE:
375  case GNC_TREE_MODEL_COMMODITY_COL_FULLNAME:
376  case GNC_TREE_MODEL_COMMODITY_COL_PRINTNAME:
377  case GNC_TREE_MODEL_COMMODITY_COL_CUSIP:
378  case GNC_TREE_MODEL_COMMODITY_COL_UNIQUE_NAME:
379  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_SOURCE:
380  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_TZ:
381  case GNC_TREE_MODEL_COMMODITY_COL_USER_SYMBOL:
382  return G_TYPE_STRING;
383  case GNC_TREE_MODEL_COMMODITY_COL_FRACTION:
384  return G_TYPE_INT;
385  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_FLAG:
386  case GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY:
387  return G_TYPE_BOOLEAN;
388  default:
389  g_assert_not_reached ();
390  return G_TYPE_INVALID;
391  }
392 }
393 
394 static gboolean
395 gnc_tree_model_commodity_get_iter (GtkTreeModel *tree_model,
396  GtkTreeIter *iter,
397  GtkTreePath *path)
398 {
399  GncTreeModelCommodity *model;
401  gnc_commodity_table *ct;
402  gnc_commodity_namespace *name_space;
403  gnc_commodity *commodity = NULL;
404  GList *list;
405  guint i, depth;
406 
407  iter->stamp = 0;
408  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
409  g_return_val_if_fail (iter != NULL, FALSE);
410  g_return_val_if_fail (path != NULL, FALSE);
411 
412  depth = gtk_tree_path_get_depth (path);
413  ENTER("model %p, iter %p, path %p (depth %d)", tree_model, iter, path, depth);
414  debug_path(DEBUG, path);
415 
416  /* Check the path depth. */
417  if (depth == 0)
418  {
419  LEAVE("depth too small");
420  return FALSE;
421  }
422  if (depth > 2)
423  {
424  LEAVE("depth too big");
425  return FALSE;
426  }
427 
428  /* Make sure the model has a commodity db. */
429  model = GNC_TREE_MODEL_COMMODITY (tree_model);
430  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
431  ct = priv->commodity_table;
432  if (ct == NULL)
433  {
434  LEAVE("no commodity table");
435  return FALSE;
436  }
437 
438  /* Verify the first part of the path: the namespace. */
440  i = gtk_tree_path_get_indices (path)[0];
441  name_space = g_list_nth_data (list, i);
442  if (!name_space)
443  {
444  LEAVE("invalid path at namespace");
445  return FALSE;
446  }
447 
448  if (depth == 1)
449  {
450  /* Return an iterator for the namespace. */
451  iter->stamp = model->stamp;
452  iter->user_data = ITER_IS_NAMESPACE;
453  iter->user_data2 = name_space;
454  iter->user_data3 = GINT_TO_POINTER(i);
455  LEAVE("iter (ns) %s", iter_to_string(iter));
456  return TRUE;
457  }
458 
459  /* Verify the second part of the path: the commodity. */
461  i = gtk_tree_path_get_indices (path)[1];
462  commodity = g_list_nth_data (list, i);
463  if (!commodity)
464  {
465  LEAVE("invalid path at commodity");
466  return FALSE;
467  }
468 
469  /* Return an iterator for the commodity. */
470  iter->stamp = model->stamp;
471  iter->user_data = ITER_IS_COMMODITY;
472  iter->user_data2 = commodity;
473  iter->user_data3 = GINT_TO_POINTER(i);
474  LEAVE("iter (cm) %s", iter_to_string(iter));
475  return TRUE;
476 }
477 
478 static GtkTreePath *
479 gnc_tree_model_commodity_get_path (GtkTreeModel *tree_model,
480  GtkTreeIter *iter)
481 {
482  GncTreeModelCommodity *model;
484  GtkTreePath *path;
485  gnc_commodity_table *ct;
486  gnc_commodity_namespace *name_space;
487  GList *ns_list;
488 
489  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), NULL);
490  model = GNC_TREE_MODEL_COMMODITY (tree_model);
491  g_return_val_if_fail (iter != NULL, NULL);
492  g_return_val_if_fail (iter->user_data != NULL, NULL);
493  g_return_val_if_fail (iter->user_data2 != NULL, NULL);
494  g_return_val_if_fail (iter->stamp == model->stamp, NULL);
495  ENTER("model %p, iter %p (%s)", tree_model, iter, iter_to_string(iter));
496 
497  /* Make sure this model has a commodity db. */
498  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
499  ct = priv->commodity_table;
500  if (ct == NULL)
501  {
502  LEAVE("no commodity table");
503  return FALSE;
504  }
505 
506  if (iter->user_data == ITER_IS_NAMESPACE)
507  {
508  /* Create a path to the namespace. This is just the index into
509  * the namespace list, which we already stored in user_data3. */
510  path = gtk_tree_path_new ();
511  gtk_tree_path_append_index (path, GPOINTER_TO_INT(iter->user_data3));
512  debug_path(LEAVE, path);
513  return path;
514  }
515 
516  /* Get the namespaces list. */
518  name_space = gnc_commodity_get_namespace_ds((gnc_commodity*)iter->user_data2);
519 
520  /* Create a path to the commodity. */
521  path = gtk_tree_path_new ();
522  gtk_tree_path_append_index (path, g_list_index (ns_list, name_space));
523  gtk_tree_path_append_index (path, GPOINTER_TO_INT(iter->user_data3));
524  debug_path(LEAVE, path);
525  return path;
526 }
527 
528 static void
529 gnc_tree_model_commodity_get_value (GtkTreeModel *tree_model,
530  GtkTreeIter *iter,
531  int column,
532  GValue *value)
533 {
534  GncTreeModelCommodity *model = GNC_TREE_MODEL_COMMODITY (tree_model);
535  gnc_commodity_namespace *name_space;
536  gnc_commodity *commodity;
537  gnc_quote_source *source;
538 
539  g_return_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model));
540  g_return_if_fail (iter != NULL);
541  g_return_if_fail (iter->user_data != NULL);
542  g_return_if_fail (iter->user_data2 != NULL);
543  g_return_if_fail (iter->stamp == model->stamp);
544 
545  if (iter->user_data == ITER_IS_NAMESPACE)
546  {
547  name_space = (gnc_commodity_namespace *)iter->user_data2;
548  switch (column)
549  {
550  case GNC_TREE_MODEL_COMMODITY_COL_NAMESPACE:
551  g_value_init (value, G_TYPE_STRING);
552  g_value_set_string (value, _(gnc_commodity_namespace_get_gui_name (name_space)));
553  break;
554  default:
555  g_value_init (value, G_TYPE_STRING);
556  g_value_set_string (value, "");
557  break;
558  case GNC_TREE_MODEL_COMMODITY_COL_FRACTION:
559  g_value_init (value, G_TYPE_INT);
560  g_value_set_int (value, 0);
561  break;
562  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_FLAG:
563  g_value_init (value, G_TYPE_BOOLEAN);
564  g_value_set_boolean (value, FALSE);
565  break;
566  case GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY:
567  g_value_init (value, G_TYPE_BOOLEAN);
568  g_value_set_boolean (value, FALSE);
569  break;
570  }
571  return;
572  }
573 
574  commodity = (gnc_commodity *)iter->user_data2;
575  switch (column)
576  {
577  case GNC_TREE_MODEL_COMMODITY_COL_MNEMONIC:
578  g_value_init (value, G_TYPE_STRING);
579 
580  g_value_set_string (value, gnc_commodity_get_mnemonic (commodity));
581  break;
582  case GNC_TREE_MODEL_COMMODITY_COL_NAMESPACE:
583  g_value_init (value, G_TYPE_STRING);
584 
585 // g_value_set_string (value, gnc_commodity_get_namespace (commodity));
586  g_value_set_string (value, NULL);
587  break;
588  case GNC_TREE_MODEL_COMMODITY_COL_FULLNAME:
589  g_value_init (value, G_TYPE_STRING);
590 
591  g_value_set_string (value, gnc_commodity_get_fullname (commodity));
592  break;
593  case GNC_TREE_MODEL_COMMODITY_COL_PRINTNAME:
594  g_value_init (value, G_TYPE_STRING);
595 
596  g_value_set_string (value, gnc_commodity_get_printname (commodity));
597  break;
598  case GNC_TREE_MODEL_COMMODITY_COL_CUSIP:
599  g_value_init (value, G_TYPE_STRING);
600 
601  g_value_set_string (value, gnc_commodity_get_cusip (commodity));
602  break;
603  case GNC_TREE_MODEL_COMMODITY_COL_UNIQUE_NAME:
604  g_value_init (value, G_TYPE_STRING);
605 
606  g_value_set_string (value, gnc_commodity_get_unique_name (commodity));
607  break;
608  case GNC_TREE_MODEL_COMMODITY_COL_FRACTION:
609  g_value_init (value, G_TYPE_INT);
610 
611  g_value_set_int (value, gnc_commodity_get_fraction (commodity));
612  break;
613  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_FLAG:
614  g_value_init (value, G_TYPE_BOOLEAN);
615 
616  g_value_set_boolean (value, gnc_commodity_get_quote_flag (commodity));
617  break;
618  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_SOURCE:
619  g_value_init (value, G_TYPE_STRING);
620 
621  if (gnc_commodity_get_quote_flag (commodity))
622  {
623  source = gnc_commodity_get_quote_source (commodity);
624  g_value_set_string (value, gnc_quote_source_get_internal_name(source));
625  }
626  else
627  {
628  g_value_set_static_string (value, "");
629  }
630  break;
631  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_TZ:
632  g_value_init (value, G_TYPE_STRING);
633 
634  if (gnc_commodity_get_quote_flag (commodity))
635  {
636  g_value_set_string (value, gnc_commodity_get_quote_tz (commodity));
637  }
638  else
639  {
640  g_value_set_static_string (value, "");
641  }
642  break;
643  case GNC_TREE_MODEL_COMMODITY_COL_USER_SYMBOL:
644  g_value_init (value, G_TYPE_STRING);
645 
646  g_value_set_string (value, gnc_commodity_get_nice_symbol (commodity));
647  break;
648  case GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY:
649  g_value_init (value, G_TYPE_BOOLEAN);
650  g_value_set_boolean (value, TRUE);
651  break;
652  default:
653  g_assert_not_reached ();
654  }
655 }
656 
657 static gboolean
658 gnc_tree_model_commodity_iter_next (GtkTreeModel *tree_model,
659  GtkTreeIter *iter)
660 {
661  GncTreeModelCommodity *model;
663  gnc_commodity_table *ct;
664  gnc_commodity_namespace *name_space;
665  GList *list;
666  int n;
667 
668  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
669  model = GNC_TREE_MODEL_COMMODITY (tree_model);
670  g_return_val_if_fail (iter != NULL, FALSE);
671  g_return_val_if_fail (iter->user_data != NULL, FALSE);
672  g_return_val_if_fail (iter->user_data2 != NULL, FALSE);
673  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
674 
675  ENTER("model %p, iter %p(%s)", tree_model, iter, iter_to_string(iter));
676  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
677  if (iter->user_data == ITER_IS_NAMESPACE)
678  {
679  ct = priv->commodity_table;
681  }
682  else if (iter->user_data == ITER_IS_COMMODITY)
683  {
684  name_space = gnc_commodity_get_namespace_ds((gnc_commodity *)iter->user_data2);
686  }
687  else
688  {
689  LEAVE("unknown iter type");
690  return FALSE;
691  }
692 
693  n = GPOINTER_TO_INT(iter->user_data3) + 1;
694  iter->user_data2 = g_list_nth_data(list, n);
695  if (iter->user_data2 == NULL)
696  {
697  LEAVE("no next iter");
698  return FALSE;
699  }
700  iter->user_data3 = GINT_TO_POINTER(n);
701  LEAVE("iter %p(%s)", iter, iter_to_string(iter));
702  return TRUE;
703 }
704 
705 
706 static gboolean
707 gnc_tree_model_commodity_iter_children (GtkTreeModel *tree_model,
708  GtkTreeIter *iter,
709  GtkTreeIter *parent)
710 {
711  GncTreeModelCommodity *model;
713  gnc_commodity_table *ct;
714  gnc_commodity_namespace *name_space;
715  GList *list;
716 
717  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
718 
719  ENTER("model %p, iter %p, parent %p (%s)",
720  tree_model, iter, parent, iter_to_string(parent));
721  model = GNC_TREE_MODEL_COMMODITY (tree_model);
722  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
723 
724  if (parent == NULL)
725  {
726  ct = priv->commodity_table;
728  if (list == NULL)
729  {
730  LEAVE("no namespaces");
731  return FALSE;
732  }
733 
734  iter->stamp = model->stamp;
735  iter->user_data = ITER_IS_NAMESPACE;
736  iter->user_data2 = g_list_nth_data(list, 0);
737  iter->user_data3 = GINT_TO_POINTER(0);
738  LEAVE("ns iter %p (%s)", iter, iter_to_string(iter));
739  return TRUE;
740  }
741 
742  if (parent->user_data == ITER_IS_NAMESPACE)
743  {
744  name_space = (gnc_commodity_namespace *)parent->user_data2;
746  if (list == NULL)
747  {
748  LEAVE("no commodities");
749  return FALSE;
750  }
751 
752  iter->stamp = model->stamp;
753  iter->user_data = ITER_IS_COMMODITY;
754  iter->user_data2 = g_list_nth_data(list, 0);
755  iter->user_data3 = GINT_TO_POINTER(0);
756  LEAVE("cm iter %p (%s)", iter, iter_to_string(iter));
757  return TRUE;
758  }
759 
760  LEAVE("FALSE");
761  return FALSE;
762 }
763 
764 static gboolean
765 gnc_tree_model_commodity_iter_has_child (GtkTreeModel *tree_model,
766  GtkTreeIter *iter)
767 {
768  gnc_commodity_namespace *name_space;
769  GList *list;
770 
771  g_return_val_if_fail (iter != NULL, FALSE);
772  ENTER("model %p, iter %p (%s)", tree_model,
773  iter, iter_to_string(iter));
774 
775  if (iter->user_data != ITER_IS_NAMESPACE)
776  {
777  LEAVE("no children (not ns)");
778  return FALSE;
779  }
780 
781  name_space = (gnc_commodity_namespace *)iter->user_data2;
783  LEAVE("%s children", list ? "has" : "no");
784  return list != NULL;
785 }
786 
787 static int
788 gnc_tree_model_commodity_iter_n_children (GtkTreeModel *tree_model,
789  GtkTreeIter *iter)
790 {
791  GncTreeModelCommodity *model;
793  gnc_commodity_table *ct;
794  gnc_commodity_namespace *name_space;
795  GList *list;
796 
797  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), -1);
798 
799  ENTER("model %p, iter %p (%s)", tree_model, iter, iter_to_string(iter));
800  model = GNC_TREE_MODEL_COMMODITY (tree_model);
801  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
802 
803  if (iter == NULL)
804  {
805  ct = priv->commodity_table;
807  LEAVE("ns list length %d", g_list_length(list));
808  return g_list_length (list);
809  }
810 
811  if (iter->user_data == ITER_IS_NAMESPACE)
812  {
813  name_space = (gnc_commodity_namespace *)iter->user_data2;
815  LEAVE("cm list length %d", g_list_length(list));
816  return g_list_length (list);
817  }
818 
819  LEAVE("0");
820  return 0;
821 }
822 
823 static gboolean
824 gnc_tree_model_commodity_iter_nth_child (GtkTreeModel *tree_model,
825  GtkTreeIter *iter,
826  GtkTreeIter *parent,
827  int n)
828 {
829  GncTreeModelCommodity *model;
831  gnc_commodity_table *ct;
832  gnc_commodity_namespace *name_space;
833  GList *list;
834 
835  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
836  g_return_val_if_fail (iter != NULL, FALSE);
837 
838  ENTER("model %p, iter %p, parent %p (%s)",
839  tree_model, iter, parent, iter_to_string(parent));
840  model = GNC_TREE_MODEL_COMMODITY (tree_model);
841  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
842 
843  if (parent == NULL)
844  {
845  ct = priv->commodity_table;
847 
848  iter->stamp = model->stamp;
849  iter->user_data = ITER_IS_NAMESPACE;
850  iter->user_data2 = g_list_nth_data(list, n);
851  iter->user_data3 = GINT_TO_POINTER(n);
852  LEAVE("ns iter %p (%s)", iter, iter_to_string(iter));
853  return iter->user_data2 != NULL;
854  }
855 
856  if (parent->user_data == ITER_IS_NAMESPACE)
857  {
858  name_space = (gnc_commodity_namespace *)parent->user_data2;
860 
861  iter->stamp = model->stamp;
862  iter->user_data = ITER_IS_COMMODITY;
863  iter->user_data2 = g_list_nth_data(list, n);
864  iter->user_data3 = GINT_TO_POINTER(n);
865  LEAVE("cm iter %p (%s)", iter, iter_to_string(iter));
866  return iter->user_data2 != NULL;
867  }
868 
869  iter->stamp = 0;
870  LEAVE("FALSE");
871  return FALSE;
872 }
873 
874 static gboolean
875 gnc_tree_model_commodity_iter_parent (GtkTreeModel *tree_model,
876  GtkTreeIter *iter,
877  GtkTreeIter *child)
878 {
879  GncTreeModelCommodity *model;
881  gnc_commodity_table *ct;
882  gnc_commodity_namespace *name_space;
883  GList *list;
884 
885  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
886  g_return_val_if_fail (iter != NULL, FALSE);
887  g_return_val_if_fail (child != NULL, FALSE);
888 
889  ENTER("model %p, iter %p, child %p (%s)",
890  tree_model, iter, child, iter_to_string(child));
891  model = GNC_TREE_MODEL_COMMODITY (tree_model);
892  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
893 
894  if (child->user_data == ITER_IS_NAMESPACE)
895  {
896  LEAVE("ns has no parent");
897  return FALSE;
898  }
899 
900  ct = priv->commodity_table;
902  name_space = gnc_commodity_get_namespace_ds((gnc_commodity*)child->user_data2);
903 
904  iter->stamp = model->stamp;
905  iter->user_data = ITER_IS_NAMESPACE;
906  iter->user_data2 = name_space;
907  iter->user_data3 = GINT_TO_POINTER(g_list_index(list, name_space));
908  LEAVE("ns iter %p (%s)", iter, iter_to_string(iter));
909  return TRUE;
910 }
911 
912 /************************************************************/
913 /* Commodity Tree View Functions */
914 /************************************************************/
915 
916 /*
917  * Convert a model/commodity pair into a gtk_tree_model_iter. This
918  * routine should only be called from the file
919  * gnc-tree-view-commodity.c.
920  */
921 gboolean
923  gnc_commodity *commodity,
924  GtkTreeIter *iter)
925 {
926  gnc_commodity_namespace *name_space;
927  GList *list;
928  gint n;
929 
930  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE);
931  g_return_val_if_fail ((commodity != NULL), FALSE);
932  g_return_val_if_fail ((iter != NULL), FALSE);
933 
934  ENTER("model %p, commodity %p, iter %p", model, commodity, iter);
935 
936  name_space = gnc_commodity_get_namespace_ds(commodity);
937  if (name_space == NULL)
938  {
939  LEAVE("no namespace");
940  return FALSE;
941  }
942 
944  if (list == NULL)
945  {
946  LEAVE("empty list");
947  return FALSE;
948  }
949 
950  n = g_list_index(list, commodity);
951  if (n == -1)
952  {
953  LEAVE("not in list");
954  return FALSE;
955  }
956 
957  iter->stamp = model->stamp;
958  iter->user_data = ITER_IS_COMMODITY;
959  iter->user_data2 = commodity;
960  iter->user_data3 = GINT_TO_POINTER(n);
961  LEAVE("iter %s", iter_to_string(iter));
962  return TRUE;
963 }
964 
965 /*
966  * Convert a model/commodity pair into a gtk_tree_model_path. This
967  * routine should only be called from the file
968  * gnc-tree-view-commodity.c.
969  */
970 GtkTreePath *
972  gnc_commodity *commodity)
973 {
974  GtkTreeIter tree_iter;
975  GtkTreePath *tree_path;
976 
977  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), NULL);
978  g_return_val_if_fail (commodity != NULL, NULL);
979  ENTER("model %p, commodity %p", model, commodity);
980 
981  if (!gnc_tree_model_commodity_get_iter_from_commodity (model, commodity, &tree_iter))
982  {
983  LEAVE("no iter");
984  return NULL;
985  }
986 
987  tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &tree_iter);
988  if (tree_path)
989  {
990  gchar *path_string = gtk_tree_path_to_string(tree_path);
991  LEAVE("path (2) %s", path_string);
992  g_free(path_string);
993  }
994  else
995  {
996  LEAVE("no path");
997  }
998  return tree_path;
999 }
1000 
1001 /*
1002  * Convert a model/namespace pair into a gtk_tree_model_iter. This
1003  * routine should only be called from the file
1004  * gnc-tree-view-commodity.c.
1005  */
1006 gboolean
1008  gnc_commodity_namespace *name_space,
1009  GtkTreeIter *iter)
1010 {
1012  GList *list;
1013  gint n;
1014 
1015  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE);
1016  g_return_val_if_fail ((name_space != NULL), FALSE);
1017  g_return_val_if_fail ((iter != NULL), FALSE);
1018 
1019  ENTER("model %p, namespace %p, iter %p", model, name_space, iter);
1020 
1021  priv = GNC_TREE_MODEL_COMMODITY_GET_PRIVATE(model);
1022  list = gnc_commodity_table_get_namespaces_list(priv->commodity_table);
1023  if (list == NULL)
1024  {
1025  LEAVE("");
1026  return FALSE;
1027  }
1028 
1029  n = g_list_index(list, name_space);
1030  if (n == -1)
1031  {
1032  LEAVE("");
1033  return FALSE;
1034  }
1035 
1036  iter->stamp = model->stamp;
1037  iter->user_data = ITER_IS_NAMESPACE;
1038  iter->user_data2 = name_space;
1039  iter->user_data3 = GINT_TO_POINTER(n);
1040  LEAVE("iter %s", iter_to_string(iter));
1041  return TRUE;
1042 }
1043 
1044 
1045 /************************************************************/
1046 /* Commodity Tree Model - Engine Event Handling Functions */
1047 /************************************************************/
1048 
1049 typedef struct _remove_data
1050 {
1051  GncTreeModelCommodity *model;
1052  GtkTreePath *path;
1053 } remove_data;
1054 
1055 static GSList *pending_removals = NULL;
1056 
1068 static void
1069 gnc_tree_model_commodity_row_add (GncTreeModelCommodity *model,
1070  GtkTreeIter *iter)
1071 {
1072  GtkTreePath *path;
1073  GtkTreeModel *tree_model;
1074  GtkTreeIter tmp_iter;
1075 
1076  ENTER("model %p, iter (%p)%s", model, iter, iter_to_string(iter));
1077 
1078  /* We're adding a row, so the lists on which this model is based have
1079  * changed. Since existing iterators (except the one just passed in)
1080  * are all based on old indexes into those lists, we need to invalidate
1081  * them, which we can do by changing the model's stamp. */
1082  do
1083  {
1084  model->stamp++;
1085  }
1086  while (model->stamp == 0);
1087  iter->stamp = model->stamp;
1088 
1089  /* Tag the new row as inserted. */
1090  tree_model = GTK_TREE_MODEL(model);
1091  path = gnc_tree_model_commodity_get_path(tree_model, iter);
1092  gtk_tree_model_row_inserted(tree_model, path, iter);
1093 
1094  /* Inform all ancestors. */
1095  /*
1096  * Charles Day: I don't think calls to gtk_tree_model_row_changed() should
1097  * be necessary. It is just a workaround for bug #540201.
1098  */
1099  if (gtk_tree_path_up(path) &&
1100  gtk_tree_path_get_depth(path) > 0 &&
1101  gtk_tree_model_get_iter(tree_model, &tmp_iter, path))
1102  {
1103  /* Signal the change to the parent. */
1104  gtk_tree_model_row_changed(tree_model, path, &tmp_iter);
1105 
1106  /* Is this the parent's first child? */
1107  if (gtk_tree_model_iter_n_children(tree_model, &tmp_iter) == 1)
1108  gtk_tree_model_row_has_child_toggled(tree_model, path, &tmp_iter);
1109 
1110  /* Signal any other ancestors. */
1111  while (gtk_tree_path_up(path) &&
1112  gtk_tree_path_get_depth(path) > 0 &&
1113  gtk_tree_model_get_iter(tree_model, &tmp_iter, path))
1114  {
1115  gtk_tree_model_row_changed(tree_model, path, &tmp_iter);
1116  }
1117  }
1118  gtk_tree_path_free(path);
1119 
1120  /* If the new row already has children, signal that so the expander
1121  * can be shown. This can happen, for example, if a namespace is
1122  * changed in another place and gets removed and then re-added to
1123  * the commodity db. */
1124  if (gnc_tree_model_commodity_iter_has_child(tree_model, iter))
1125  {
1126  path = gnc_tree_model_commodity_get_path(tree_model, iter);
1127  gtk_tree_model_row_has_child_toggled(tree_model, path, iter);
1128  gtk_tree_path_free(path);
1129  }
1130 
1131  LEAVE(" ");
1132 }
1133 
1145 static void
1146 gnc_tree_model_commodity_row_delete (GncTreeModelCommodity *model,
1147  GtkTreePath *path)
1148 {
1149  GtkTreeModel *tree_model;
1150  GtkTreeIter iter;
1151 
1152  g_return_if_fail(GNC_IS_TREE_MODEL_COMMODITY(model));
1153  g_return_if_fail(path);
1154 
1155  debug_path(ENTER, path);
1156 
1157  tree_model = GTK_TREE_MODEL(model);
1158 
1159  /* We're removing a row, so the lists on which this model is based have
1160  * changed. Since existing iterators are all based on old indexes into
1161  * those lists, we need to invalidate them, which we can do by changing
1162  * the model's stamp. */
1163  do
1164  {
1165  model->stamp++;
1166  }
1167  while (model->stamp == 0);
1168 
1169  /* Signal that the path has been deleted. */
1170  gtk_tree_model_row_deleted(tree_model, path);
1171 
1172  /* Issue any appropriate signals to ancestors. */
1173  if (gtk_tree_path_up(path) &&
1174  gtk_tree_path_get_depth(path) > 0 &&
1175  gtk_tree_model_get_iter(tree_model, &iter, path) &&
1176  !gtk_tree_model_iter_has_child(tree_model, &iter))
1177  {
1178  DEBUG("parent toggled, iter %s", iter_to_string(&iter));
1179  gtk_tree_model_row_has_child_toggled(tree_model, path, &iter);
1180  }
1181 
1182  LEAVE(" ");
1183 }
1184 
1185 
1202 static gboolean
1203 gnc_tree_model_commodity_do_deletions (gpointer unused)
1204 {
1205  ENTER(" ");
1206 
1207  /* Go through the list of paths needing removal. */
1208  while (pending_removals)
1209  {
1210  remove_data *data = pending_removals->data;
1211  pending_removals = g_slist_delete_link(pending_removals, pending_removals);
1212 
1213  if (data)
1214  {
1215  debug_path(DEBUG, data->path);
1216 
1217  /* Remove the path. */
1218  gnc_tree_model_commodity_row_delete(data->model, data->path);
1219 
1220  gtk_tree_path_free(data->path);
1221  g_free(data);
1222  }
1223  }
1224 
1225  LEAVE(" ");
1226  /* Don't call me again. */
1227  return FALSE;
1228 }
1229 
1230 
1262 static void
1263 gnc_tree_model_commodity_event_handler (QofInstance *entity,
1264  QofEventId event_type,
1265  gpointer user_data,
1266  gpointer event_data)
1267 {
1268  GncTreeModelCommodity *model;
1269  GtkTreePath *path;
1270  GtkTreeIter iter;
1271  remove_data *data;
1272  const gchar *name;
1273 
1274  model = (GncTreeModelCommodity *)user_data;
1275 
1276  /* hard failures */
1277  g_return_if_fail(GNC_IS_TREE_MODEL_COMMODITY(model));
1278 
1279  ENTER("entity %p, event %d, model %p, event data %p",
1280  entity, event_type, user_data, event_data);
1281 
1282  /* Do deletions if any are pending. */
1283  if (pending_removals)
1284  gnc_tree_model_commodity_do_deletions(NULL);
1285 
1286  /* get type specific data */
1287  if (GNC_IS_COMMODITY(entity))
1288  {
1289  gnc_commodity *commodity;
1290 
1291  commodity = GNC_COMMODITY(entity);
1292  name = gnc_commodity_get_mnemonic(commodity);
1293  if (event_type != QOF_EVENT_DESTROY)
1294  {
1295  if (!gnc_tree_model_commodity_get_iter_from_commodity (model, commodity, &iter))
1296  {
1297  LEAVE("no iter");
1298  return;
1299  }
1300  }
1301  }
1302  else if (GNC_IS_COMMODITY_NAMESPACE(entity))
1303  {
1304  gnc_commodity_namespace *name_space;
1305 
1306  name_space = GNC_COMMODITY_NAMESPACE(entity);
1307  name = gnc_commodity_namespace_get_name(name_space);
1308  if (event_type != QOF_EVENT_DESTROY)
1309  {
1310  if (!gnc_tree_model_commodity_get_iter_from_namespace (model, name_space, &iter))
1311  {
1312  LEAVE("no iter");
1313  return;
1314  }
1315  }
1316  }
1317  else
1318  {
1319  LEAVE("");
1320  return;
1321  }
1322 
1323  switch (event_type)
1324  {
1325  case QOF_EVENT_ADD:
1326  /* Tell the filters/views where the new account was added. */
1327  DEBUG("add %s", name);
1328  gnc_tree_model_commodity_row_add (model, &iter);
1329  break;
1330 
1331  case QOF_EVENT_REMOVE:
1332  /* Record the path of this account for later use in destruction */
1333  DEBUG("remove %s", name);
1334  path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter);
1335  if (path == NULL)
1336  {
1337  LEAVE("not in model");
1338  return;
1339  }
1340 
1341  data = g_new0 (remove_data, 1);
1342  data->model = model;
1343  data->path = path;
1344  pending_removals = g_slist_append (pending_removals, data);
1345  g_idle_add_full(G_PRIORITY_HIGH_IDLE,
1346  gnc_tree_model_commodity_do_deletions, NULL, NULL);
1347 
1348  LEAVE(" ");
1349  return;
1350 
1351  case QOF_EVENT_MODIFY:
1352  DEBUG("change %s", name);
1353  path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter);
1354  if (path == NULL)
1355  {
1356  LEAVE("not in model");
1357  return;
1358  }
1359  gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, &iter);
1360  gtk_tree_path_free(path);
1361  LEAVE(" ");
1362  return;
1363 
1364  default:
1365  LEAVE("ignored event for %s", name);
1366  return;
1367  }
1368  LEAVE(" new stamp %u", model->stamp);
1369 }
GtkTreeModel implementation for gnucash commodities.
const char * gnc_commodity_get_cusip(const gnc_commodity *cm)
Retrieve the &#39;exchange code&#39; for the specified commodity.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
gnc_commodity * gnc_tree_model_commodity_get_commodity(GncTreeModelCommodity *model, GtkTreeIter *iter)
Convert a model/iter pair to a gnucash commodity.
gboolean gnc_tree_model_commodity_get_iter_from_commodity(GncTreeModelCommodity *model, gnc_commodity *commodity, GtkTreeIter *iter)
Convert a commodity pointer into a GtkTreeIter.
const GList * gnc_gobject_tracking_get_list(const gchar *name)
Get a list of all known objects of a specified type.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
GtkTreePath * gnc_tree_model_commodity_get_path_from_commodity(GncTreeModelCommodity *model, gnc_commodity *commodity)
Convert a commodity pointer into a GtkTreePath.
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
gboolean gnc_commodity_get_quote_flag(const gnc_commodity *cm)
Retrieve the automatic price quote flag for the specified commodity.
const char * gnc_commodity_get_quote_tz(const gnc_commodity *cm)
Retrieve the automatic price quote timezone for the specified commodity.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
gnc_commodity_namespace * gnc_tree_model_commodity_get_namespace(GncTreeModelCommodity *model, GtkTreeIter *iter)
Convert a model/iter pair to a gnucash commodity namespace.
The instance private data for a commodity database tree model.
int stamp
The state of the model.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
GList * gnc_commodity_namespace_get_commodity_list(const gnc_commodity_namespace *name_space)
Return a list of all commodity data structures in the specified namespace.
const char * gnc_commodity_namespace_get_name(const gnc_commodity_namespace *ns)
Return the textual name of a namespace data structure.
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
Definition: qofevent.cpp:73
gint QofEventId
Define the type of events allowed.
Definition: qofevent.h:45
Gobject helper routines.
void qof_event_unregister_handler(gint handler_id)
Unregister an event handler.
Definition: qofevent.cpp:103
GtkTreeModel * gnc_tree_model_commodity_new(QofBook *book, gnc_commodity_table *ct)
Create a new GtkTreeModel for manipulating gnucash commodities.
gboolean gnc_tree_model_commodity_get_iter_from_namespace(GncTreeModelCommodity *model, gnc_commodity_namespace *name_space, GtkTreeIter *iter)
Convert a commodity namespace pointer into a GtkTreeIter.
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Retrieve the full name for the specified commodity.
const char * gnc_commodity_get_nice_symbol(const gnc_commodity *cm)
Retrieve a symbol for the specified commodity, suitable for display to the user.
The class data structure for a commodity tree model.
All type declarations for the whole Gnucash engine.
const char * gnc_commodity_get_printname(const gnc_commodity *cm)
Retrieve the &#39;print&#39; name for the specified commodity.
gboolean gnc_tree_model_commodity_iter_is_commodity(GncTreeModelCommodity *model, GtkTreeIter *iter)
Determine whether or not the specified GtkTreeIter points to a commodity.
gnc_quote_source * gnc_commodity_get_quote_source(const gnc_commodity *cm)
Retrieve the automatic price quote source for the specified commodity.
gboolean gnc_tree_model_commodity_iter_is_namespace(GncTreeModelCommodity *model, GtkTreeIter *iter)
Determine whether or not the specified GtkTreeIter points to a commodity namespace.
gnc_commodity_namespace * gnc_commodity_get_namespace_ds(const gnc_commodity *cm)
Retrieve the namespace data structure for the specified commodity.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
const char * gnc_commodity_get_unique_name(const gnc_commodity *cm)
Retrieve the &#39;unique&#39; name for the specified commodity.
const char * gnc_quote_source_get_internal_name(const gnc_quote_source *source)
Given a gnc_quote_source data structure, return the internal name of this quote source.
GList * gnc_commodity_table_get_namespaces_list(const gnc_commodity_table *table)
Return a list of all namespace data structures in the commodity table.
The instance data structure for a commodity tree model.