GnuCash  5.6-150-g038405b370+
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_finalize (GObject *object);
57 static void gnc_tree_model_commodity_dispose (GObject *object);
58 
59 static void gnc_tree_model_commodity_tree_model_init (GtkTreeModelIface *iface);
60 static GtkTreeModelFlags gnc_tree_model_commodity_get_flags (GtkTreeModel *tree_model);
61 static int gnc_tree_model_commodity_get_n_columns (GtkTreeModel *tree_model);
62 static GType gnc_tree_model_commodity_get_column_type (GtkTreeModel *tree_model,
63  int index);
64 static gboolean gnc_tree_model_commodity_get_iter (GtkTreeModel *tree_model,
65  GtkTreeIter *iter,
66  GtkTreePath *path);
67 static GtkTreePath *gnc_tree_model_commodity_get_path (GtkTreeModel *tree_model,
68  GtkTreeIter *iter);
69 static void gnc_tree_model_commodity_get_value (GtkTreeModel *tree_model,
70  GtkTreeIter *iter,
71  int column,
72  GValue *value);
73 static gboolean gnc_tree_model_commodity_iter_next (GtkTreeModel *tree_model,
74  GtkTreeIter *iter);
75 static gboolean gnc_tree_model_commodity_iter_children (GtkTreeModel *tree_model,
76  GtkTreeIter *iter,
77  GtkTreeIter *parent);
78 static gboolean gnc_tree_model_commodity_iter_has_child (GtkTreeModel *tree_model,
79  GtkTreeIter *iter);
80 static int gnc_tree_model_commodity_iter_n_children (GtkTreeModel *tree_model,
81  GtkTreeIter *iter);
82 static gboolean gnc_tree_model_commodity_iter_nth_child (GtkTreeModel *tree_model,
83  GtkTreeIter *iter,
84  GtkTreeIter *parent,
85  int n);
86 static gboolean gnc_tree_model_commodity_iter_parent (GtkTreeModel *tree_model,
87  GtkTreeIter *iter,
88  GtkTreeIter *child);
89 static void gnc_tree_model_commodity_event_handler (QofInstance *entity,
90  QofEventId event_type,
91  gpointer user_data,
92  gpointer event_data);
93 
96 {
97  GncTreeModel gnc_tree_model;
98  int stamp;
101  QofBook *book;
102  gnc_commodity_table *commodity_table;
103  gint event_handler_id;
104 };
105 
106 G_DEFINE_TYPE_WITH_CODE(GncTreeModelCommodity, gnc_tree_model_commodity, GNC_TYPE_TREE_MODEL,
107  G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL,
108  gnc_tree_model_commodity_tree_model_init))
109 
110 static void
111 gnc_tree_model_commodity_class_init (GncTreeModelCommodityClass *klass)
112 {
113  GObjectClass *o_class = G_OBJECT_CLASS (klass);
114 
115  o_class->finalize = gnc_tree_model_commodity_finalize;
116  o_class->dispose = gnc_tree_model_commodity_dispose;
117 }
118 
119 static void
120 gnc_tree_model_commodity_init (GncTreeModelCommodity *model)
121 {
122  while (model->stamp == 0)
123  {
124  model->stamp = g_random_int ();
125  }
126 }
127 
128 static void
129 gnc_tree_model_commodity_finalize (GObject *object)
130 {
131  GncTreeModelCommodity *model;
132 
133  g_return_if_fail (object != NULL);
134  g_return_if_fail (GNC_IS_TREE_MODEL_COMMODITY (object));
135 
136  ENTER("model %p", object);
137 
138  model = GNC_TREE_MODEL_COMMODITY (object);
139  model->book = NULL;
140  model->commodity_table = NULL;
141 
142  G_OBJECT_CLASS (gnc_tree_model_commodity_parent_class)->finalize (object);
143  LEAVE(" ");
144 }
145 
146 static void
147 gnc_tree_model_commodity_dispose (GObject *object)
148 {
149  GncTreeModelCommodity *model;
150 
151  g_return_if_fail (object != NULL);
152  g_return_if_fail (GNC_IS_TREE_MODEL_COMMODITY (object));
153 
154  ENTER("model %p", object);
155  model = GNC_TREE_MODEL_COMMODITY (object);
156 
157  if (model->event_handler_id)
158  {
159  qof_event_unregister_handler (model->event_handler_id);
160  model->event_handler_id = 0;
161  }
162 
163  G_OBJECT_CLASS (gnc_tree_model_commodity_parent_class)->dispose (object);
164  LEAVE(" ");
165 }
166 
167 GtkTreeModel *
168 gnc_tree_model_commodity_new (QofBook *book, gnc_commodity_table *ct)
169 {
170  GncTreeModelCommodity *model;
171  const GList *item;
172 
173  ENTER("");
174 
175  item = gnc_gobject_tracking_get_list(GNC_TREE_MODEL_COMMODITY_NAME);
176  for ( ; item; item = g_list_next(item))
177  {
178  model = (GncTreeModelCommodity *)item->data;
179  if (model->commodity_table == ct)
180  {
181  g_object_ref(G_OBJECT(model));
182  LEAVE("returning existing model %p", model);
183  return GTK_TREE_MODEL(model);
184  }
185  }
186 
187  model = g_object_new (GNC_TYPE_TREE_MODEL_COMMODITY, NULL);
188  model->book = book;
189  model->commodity_table = ct;
190 
191  model->event_handler_id =
192  qof_event_register_handler (gnc_tree_model_commodity_event_handler, model);
193 
194  LEAVE("");
195  return GTK_TREE_MODEL (model);
196 }
197 
198 gboolean
199 gnc_tree_model_commodity_iter_is_namespace (GncTreeModelCommodity *model,
200  GtkTreeIter *iter)
201 {
202  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE);
203  g_return_val_if_fail (iter != NULL, FALSE);
204  g_return_val_if_fail (iter->user_data != NULL, FALSE);
205  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
206 
207  return (iter->user_data == ITER_IS_NAMESPACE);
208 }
209 
210 gboolean
211 gnc_tree_model_commodity_iter_is_commodity (GncTreeModelCommodity *model,
212  GtkTreeIter *iter)
213 {
214  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE);
215  g_return_val_if_fail (iter != NULL, FALSE);
216  g_return_val_if_fail (iter->user_data != NULL, FALSE);
217  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
218 
219  return (iter->user_data == ITER_IS_COMMODITY);
220 }
221 
222 gnc_commodity_namespace *
223 gnc_tree_model_commodity_get_namespace (GncTreeModelCommodity *model,
224  GtkTreeIter *iter)
225 {
226  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), NULL);
227  g_return_val_if_fail (iter != NULL, NULL);
228  g_return_val_if_fail (iter->user_data != NULL, NULL);
229  g_return_val_if_fail (iter->stamp == model->stamp, NULL);
230 
231  if (iter->user_data != ITER_IS_NAMESPACE)
232  return NULL;
233  return (gnc_commodity_namespace *)iter->user_data2;
234 }
235 
236 gnc_commodity *
237 gnc_tree_model_commodity_get_commodity (GncTreeModelCommodity *model,
238  GtkTreeIter *iter)
239 {
240  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), NULL);
241  g_return_val_if_fail (iter != NULL, NULL);
242  g_return_val_if_fail (iter->user_data != NULL, NULL);
243  g_return_val_if_fail (iter->stamp == model->stamp, NULL);
244 
245  if (iter->user_data != ITER_IS_COMMODITY)
246  return NULL;
247  return (gnc_commodity *)iter->user_data2;
248 }
249 
250 /************************************************************/
251 /* Gnc Tree Model Debugging Utility Function */
252 /************************************************************/
253 
254 #define debug_path(fn, path) { \
255  gchar *path_string = gtk_tree_path_to_string(path); \
256  fn("tree path %s", path_string? path_string : "NULL"); \
257  g_free(path_string); \
258  }
259 
260 #define ITER_STRING_LEN 128
261 
262 static const gchar *
263 iter_to_string (GtkTreeIter *iter)
264 {
265  gnc_commodity_namespace *name_space;
266  gnc_commodity *commodity = NULL;
267 #ifdef G_THREADS_ENABLED
268  static GPrivate gtmits_buffer_key = G_PRIVATE_INIT(g_free);
269  gchar *string;
270 
271  string = g_private_get (&gtmits_buffer_key);
272  if (string == NULL)
273  {
274  string = g_malloc(ITER_STRING_LEN + 1);
275  g_private_set (&gtmits_buffer_key, string);
276  }
277 #else
278  static char string[ITER_STRING_LEN + 1];
279 #endif
280  if (iter)
281  {
282  switch (GPOINTER_TO_INT(iter->user_data))
283  {
284  case GPOINTER_TO_INT(ITER_IS_NAMESPACE):
285  name_space = (gnc_commodity_namespace *) iter->user_data2;
286  snprintf(string, ITER_STRING_LEN,
287  "[stamp:%x data:%d (NAMESPACE), %p (%s), %d]",
288  iter->stamp, GPOINTER_TO_INT(iter->user_data),
289  iter->user_data2, gnc_commodity_namespace_get_name (name_space),
290  GPOINTER_TO_INT(iter->user_data3));
291  break;
292 
293  case GPOINTER_TO_INT(ITER_IS_COMMODITY):
294  commodity = (gnc_commodity *) iter->user_data2;
295  snprintf(string, ITER_STRING_LEN,
296  "[stamp:%x data:%d (COMMODITY), %p (%s), %d]",
297  iter->stamp, GPOINTER_TO_INT(iter->user_data),
298  iter->user_data2, gnc_commodity_get_mnemonic (commodity),
299  GPOINTER_TO_INT(iter->user_data3));
300  break;
301 
302  default:
303  snprintf(string, ITER_STRING_LEN,
304  "[stamp:%x data:%d (UNKNOWN), %p, %d]",
305  iter->stamp,
306  GPOINTER_TO_INT(iter->user_data),
307  iter->user_data2,
308  GPOINTER_TO_INT(iter->user_data3));
309  break;
310  }
311  }
312  return string;
313 }
314 
315 
316 /************************************************************/
317 /* Gtk Tree Model Required Interface Functions */
318 /************************************************************/
319 
320 static void
321 gnc_tree_model_commodity_tree_model_init (GtkTreeModelIface *iface)
322 {
323  iface->get_flags = gnc_tree_model_commodity_get_flags;
324  iface->get_n_columns = gnc_tree_model_commodity_get_n_columns;
325  iface->get_column_type = gnc_tree_model_commodity_get_column_type;
326  iface->get_iter = gnc_tree_model_commodity_get_iter;
327  iface->get_path = gnc_tree_model_commodity_get_path;
328  iface->get_value = gnc_tree_model_commodity_get_value;
329  iface->iter_next = gnc_tree_model_commodity_iter_next;
330  iface->iter_children = gnc_tree_model_commodity_iter_children;
331  iface->iter_has_child = gnc_tree_model_commodity_iter_has_child;
332  iface->iter_n_children = gnc_tree_model_commodity_iter_n_children;
333  iface->iter_nth_child = gnc_tree_model_commodity_iter_nth_child;
334  iface->iter_parent = gnc_tree_model_commodity_iter_parent;
335 }
336 
337 static GtkTreeModelFlags
338 gnc_tree_model_commodity_get_flags (GtkTreeModel *tree_model)
339 {
340  return 0;
341 }
342 
343 static int
344 gnc_tree_model_commodity_get_n_columns (GtkTreeModel *tree_model)
345 {
346  return GNC_TREE_MODEL_COMMODITY_NUM_COLUMNS;
347 }
348 
349 static GType
350 gnc_tree_model_commodity_get_column_type (GtkTreeModel *tree_model,
351  int index)
352 {
353  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), G_TYPE_INVALID);
354  g_return_val_if_fail ((index < GNC_TREE_MODEL_COMMODITY_NUM_COLUMNS) && (index >= 0), G_TYPE_INVALID);
355 
356  switch (index)
357  {
358  case GNC_TREE_MODEL_COMMODITY_COL_MNEMONIC:
359  case GNC_TREE_MODEL_COMMODITY_COL_NAMESPACE:
360  case GNC_TREE_MODEL_COMMODITY_COL_FULLNAME:
361  case GNC_TREE_MODEL_COMMODITY_COL_PRINTNAME:
362  case GNC_TREE_MODEL_COMMODITY_COL_CUSIP:
363  case GNC_TREE_MODEL_COMMODITY_COL_UNIQUE_NAME:
364  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_SOURCE:
365  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_TZ:
366  case GNC_TREE_MODEL_COMMODITY_COL_USER_SYMBOL:
367  return G_TYPE_STRING;
368  case GNC_TREE_MODEL_COMMODITY_COL_FRACTION:
369  return G_TYPE_INT;
370  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_FLAG:
371  case GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY:
372  return G_TYPE_BOOLEAN;
373  default:
374  g_assert_not_reached ();
375  return G_TYPE_INVALID;
376  }
377 }
378 
379 static gboolean
380 gnc_tree_model_commodity_get_iter (GtkTreeModel *tree_model,
381  GtkTreeIter *iter,
382  GtkTreePath *path)
383 {
384  GncTreeModelCommodity *model;
385  gnc_commodity_table *ct;
386  gnc_commodity_namespace *name_space;
387  gnc_commodity *commodity = NULL;
388  GList *list;
389  guint i, depth;
390 
391  iter->stamp = 0;
392  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
393  g_return_val_if_fail (iter != NULL, FALSE);
394  g_return_val_if_fail (path != NULL, FALSE);
395 
396  depth = gtk_tree_path_get_depth (path);
397  ENTER("model %p, iter %p, path %p (depth %d)", tree_model, iter, path, depth);
398  debug_path(DEBUG, path);
399 
400  /* Check the path depth. */
401  if (depth == 0)
402  {
403  LEAVE("depth too small");
404  return FALSE;
405  }
406  if (depth > 2)
407  {
408  LEAVE("depth too big");
409  return FALSE;
410  }
411 
412  /* Make sure the model has a commodity db. */
413  model = GNC_TREE_MODEL_COMMODITY (tree_model);
414  ct = model->commodity_table;
415  if (ct == NULL)
416  {
417  LEAVE("no commodity table");
418  return FALSE;
419  }
420 
421  /* Verify the first part of the path: the namespace. */
423  i = gtk_tree_path_get_indices (path)[0];
424  name_space = g_list_nth_data (list, i);
425  g_list_free (list);
426  if (!name_space)
427  {
428  LEAVE("invalid path at namespace");
429  return FALSE;
430  }
431 
432  if (depth == 1)
433  {
434  /* Return an iterator for the namespace. */
435  iter->stamp = model->stamp;
436  iter->user_data = ITER_IS_NAMESPACE;
437  iter->user_data2 = name_space;
438  iter->user_data3 = GINT_TO_POINTER(i);
439  LEAVE("iter (ns) %s", iter_to_string(iter));
440  return TRUE;
441  }
442 
443  /* Verify the second part of the path: the commodity. */
445  i = gtk_tree_path_get_indices (path)[1];
446  commodity = g_list_nth_data (list, i);
447  g_list_free (list);
448  if (!commodity)
449  {
450  LEAVE("invalid path at commodity");
451  return FALSE;
452  }
453 
454  /* Return an iterator for the commodity. */
455  iter->stamp = model->stamp;
456  iter->user_data = ITER_IS_COMMODITY;
457  iter->user_data2 = commodity;
458  iter->user_data3 = GINT_TO_POINTER(i);
459  LEAVE("iter (cm) %s", iter_to_string(iter));
460  return TRUE;
461 }
462 
463 static GtkTreePath *
464 gnc_tree_model_commodity_get_path (GtkTreeModel *tree_model,
465  GtkTreeIter *iter)
466 {
467  GncTreeModelCommodity *model;
468  GtkTreePath *path;
469  gnc_commodity_table *ct;
470  gnc_commodity_namespace *name_space;
471  GList *ns_list;
472 
473  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), NULL);
474  model = GNC_TREE_MODEL_COMMODITY (tree_model);
475  g_return_val_if_fail (iter != NULL, NULL);
476  g_return_val_if_fail (iter->user_data != NULL, NULL);
477  g_return_val_if_fail (iter->user_data2 != NULL, NULL);
478  g_return_val_if_fail (iter->stamp == model->stamp, NULL);
479  ENTER("model %p, iter %p (%s)", tree_model, iter, iter_to_string(iter));
480 
481  /* Make sure this model has a commodity db. */
482  ct = model->commodity_table;
483  if (ct == NULL)
484  {
485  LEAVE("no commodity table");
486  return FALSE;
487  }
488 
489  if (iter->user_data == ITER_IS_NAMESPACE)
490  {
491  /* Create a path to the namespace. This is just the index into
492  * the namespace list, which we already stored in user_data3. */
493  path = gtk_tree_path_new ();
494  gtk_tree_path_append_index (path, GPOINTER_TO_INT(iter->user_data3));
495  debug_path(LEAVE, path);
496  return path;
497  }
498 
499  /* Get the namespaces list. */
501  name_space = gnc_commodity_get_namespace_ds((gnc_commodity*)iter->user_data2);
502 
503  /* Create a path to the commodity. */
504  path = gtk_tree_path_new ();
505  gtk_tree_path_append_index (path, g_list_index (ns_list, name_space));
506  gtk_tree_path_append_index (path, GPOINTER_TO_INT(iter->user_data3));
507  debug_path(LEAVE, path);
508  g_list_free (ns_list);
509  return path;
510 }
511 
512 static void
513 gnc_tree_model_commodity_get_value (GtkTreeModel *tree_model,
514  GtkTreeIter *iter,
515  int column,
516  GValue *value)
517 {
518  GncTreeModelCommodity *model = GNC_TREE_MODEL_COMMODITY (tree_model);
519  gnc_commodity_namespace *name_space;
520  gnc_commodity *commodity;
521  gnc_quote_source *source;
522 
523  g_return_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model));
524  g_return_if_fail (iter != NULL);
525  g_return_if_fail (iter->user_data != NULL);
526  g_return_if_fail (iter->user_data2 != NULL);
527  g_return_if_fail (iter->stamp == model->stamp);
528 
529  if (iter->user_data == ITER_IS_NAMESPACE)
530  {
531  name_space = (gnc_commodity_namespace *)iter->user_data2;
532  switch (column)
533  {
534  case GNC_TREE_MODEL_COMMODITY_COL_NAMESPACE:
535  g_value_init (value, G_TYPE_STRING);
536  g_value_set_string (value, _(gnc_commodity_namespace_get_gui_name (name_space)));
537  break;
538  default:
539  g_value_init (value, G_TYPE_STRING);
540  g_value_set_string (value, "");
541  break;
542  case GNC_TREE_MODEL_COMMODITY_COL_FRACTION:
543  g_value_init (value, G_TYPE_INT);
544  g_value_set_int (value, 0);
545  break;
546  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_FLAG:
547  g_value_init (value, G_TYPE_BOOLEAN);
548  g_value_set_boolean (value, FALSE);
549  break;
550  case GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY:
551  g_value_init (value, G_TYPE_BOOLEAN);
552  g_value_set_boolean (value, FALSE);
553  break;
554  }
555  return;
556  }
557 
558  commodity = (gnc_commodity *)iter->user_data2;
559  switch (column)
560  {
561  case GNC_TREE_MODEL_COMMODITY_COL_MNEMONIC:
562  g_value_init (value, G_TYPE_STRING);
563 
564  g_value_set_string (value, gnc_commodity_get_mnemonic (commodity));
565  break;
566  case GNC_TREE_MODEL_COMMODITY_COL_NAMESPACE:
567  g_value_init (value, G_TYPE_STRING);
568 
569 // g_value_set_string (value, gnc_commodity_get_namespace (commodity));
570  g_value_set_string (value, NULL);
571  break;
572  case GNC_TREE_MODEL_COMMODITY_COL_FULLNAME:
573  g_value_init (value, G_TYPE_STRING);
574 
575  g_value_set_string (value, gnc_commodity_get_fullname (commodity));
576  break;
577  case GNC_TREE_MODEL_COMMODITY_COL_PRINTNAME:
578  g_value_init (value, G_TYPE_STRING);
579 
580  g_value_set_string (value, gnc_commodity_get_printname (commodity));
581  break;
582  case GNC_TREE_MODEL_COMMODITY_COL_CUSIP:
583  g_value_init (value, G_TYPE_STRING);
584 
585  g_value_set_string (value, gnc_commodity_get_cusip (commodity));
586  break;
587  case GNC_TREE_MODEL_COMMODITY_COL_UNIQUE_NAME:
588  g_value_init (value, G_TYPE_STRING);
589 
590  g_value_set_string (value, gnc_commodity_get_unique_name (commodity));
591  break;
592  case GNC_TREE_MODEL_COMMODITY_COL_FRACTION:
593  g_value_init (value, G_TYPE_INT);
594 
595  g_value_set_int (value, gnc_commodity_get_fraction (commodity));
596  break;
597  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_FLAG:
598  g_value_init (value, G_TYPE_BOOLEAN);
599 
600  g_value_set_boolean (value, gnc_commodity_get_quote_flag (commodity));
601  break;
602  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_SOURCE:
603  g_value_init (value, G_TYPE_STRING);
604 
605  if (gnc_commodity_get_quote_flag (commodity))
606  {
607  source = gnc_commodity_get_quote_source (commodity);
608  g_value_set_string (value, gnc_quote_source_get_internal_name(source));
609  }
610  else
611  {
612  g_value_set_static_string (value, "");
613  }
614  break;
615  case GNC_TREE_MODEL_COMMODITY_COL_QUOTE_TZ:
616  g_value_init (value, G_TYPE_STRING);
617 
618  if (gnc_commodity_get_quote_flag (commodity))
619  {
620  g_value_set_string (value, gnc_commodity_get_quote_tz (commodity));
621  }
622  else
623  {
624  g_value_set_static_string (value, "");
625  }
626  break;
627  case GNC_TREE_MODEL_COMMODITY_COL_USER_SYMBOL:
628  g_value_init (value, G_TYPE_STRING);
629 
630  g_value_set_string (value, gnc_commodity_get_nice_symbol (commodity));
631  break;
632  case GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY:
633  g_value_init (value, G_TYPE_BOOLEAN);
634  g_value_set_boolean (value, TRUE);
635  break;
636  default:
637  g_assert_not_reached ();
638  }
639 }
640 
641 static gboolean
642 gnc_tree_model_commodity_iter_next (GtkTreeModel *tree_model,
643  GtkTreeIter *iter)
644 {
645  GncTreeModelCommodity *model;
646  gnc_commodity_table *ct;
647  gnc_commodity_namespace *name_space;
648  GList *list;
649  int n;
650 
651  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
652  model = GNC_TREE_MODEL_COMMODITY (tree_model);
653  g_return_val_if_fail (iter != NULL, FALSE);
654  g_return_val_if_fail (iter->user_data != NULL, FALSE);
655  g_return_val_if_fail (iter->user_data2 != NULL, FALSE);
656  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
657 
658  ENTER("model %p, iter %p(%s)", tree_model, iter, iter_to_string(iter));
659  if (iter->user_data == ITER_IS_NAMESPACE)
660  {
661  ct = model->commodity_table;
663  }
664  else if (iter->user_data == ITER_IS_COMMODITY)
665  {
666  name_space = gnc_commodity_get_namespace_ds((gnc_commodity *)iter->user_data2);
668  }
669  else
670  {
671  LEAVE("unknown iter type");
672  return FALSE;
673  }
674 
675  n = GPOINTER_TO_INT(iter->user_data3) + 1;
676  iter->user_data2 = g_list_nth_data(list, n);
677  g_list_free (list);
678  if (iter->user_data2 == NULL)
679  {
680  LEAVE("no next iter");
681  return FALSE;
682  }
683  iter->user_data3 = GINT_TO_POINTER(n);
684  LEAVE("iter %p(%s)", iter, iter_to_string(iter));
685  return TRUE;
686 }
687 
688 
689 static gboolean
690 gnc_tree_model_commodity_iter_children (GtkTreeModel *tree_model,
691  GtkTreeIter *iter,
692  GtkTreeIter *parent)
693 {
694  GncTreeModelCommodity *model;
695  gnc_commodity_table *ct;
696  gnc_commodity_namespace *name_space;
697  GList *list;
698 
699  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
700 
701  ENTER("model %p, iter %p, parent %p (%s)",
702  tree_model, iter, parent, iter_to_string(parent));
703  model = GNC_TREE_MODEL_COMMODITY (tree_model);
704 
705  if (parent == NULL)
706  {
707  ct = model->commodity_table;
709  if (list == NULL)
710  {
711  LEAVE("no namespaces");
712  return FALSE;
713  }
714 
715  iter->stamp = model->stamp;
716  iter->user_data = ITER_IS_NAMESPACE;
717  iter->user_data2 = g_list_nth_data(list, 0);
718  iter->user_data3 = GINT_TO_POINTER(0);
719  LEAVE("ns iter %p (%s)", iter, iter_to_string(iter));
720  g_list_free (list);
721  return TRUE;
722  }
723 
724  if (parent->user_data == ITER_IS_NAMESPACE)
725  {
726  name_space = (gnc_commodity_namespace *)parent->user_data2;
728  if (list == NULL)
729  {
730  LEAVE("no commodities");
731  return FALSE;
732  }
733 
734  iter->stamp = model->stamp;
735  iter->user_data = ITER_IS_COMMODITY;
736  iter->user_data2 = g_list_nth_data(list, 0);
737  iter->user_data3 = GINT_TO_POINTER(0);
738  LEAVE("cm iter %p (%s)", iter, iter_to_string(iter));
739  g_list_free (list);
740  return TRUE;
741  }
742 
743  LEAVE("FALSE");
744  return FALSE;
745 }
746 
747 static gboolean
748 gnc_tree_model_commodity_iter_has_child (GtkTreeModel *tree_model,
749  GtkTreeIter *iter)
750 {
751  gnc_commodity_namespace *name_space;
752  GList *list;
753 
754  g_return_val_if_fail (iter != NULL, FALSE);
755  ENTER("model %p, iter %p (%s)", tree_model,
756  iter, iter_to_string(iter));
757 
758  if (iter->user_data != ITER_IS_NAMESPACE)
759  {
760  LEAVE("no children (not ns)");
761  return FALSE;
762  }
763 
764  name_space = (gnc_commodity_namespace *)iter->user_data2;
766  LEAVE("%s children", list ? "has" : "no");
767  gboolean rv = (list != NULL);
768  g_list_free (list);
769  return rv;
770 }
771 
772 static int
773 gnc_tree_model_commodity_iter_n_children (GtkTreeModel *tree_model,
774  GtkTreeIter *iter)
775 {
776  GncTreeModelCommodity *model;
777  gnc_commodity_table *ct;
778  gnc_commodity_namespace *name_space;
779  GList *list;
780 
781  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), -1);
782 
783  ENTER("model %p, iter %p (%s)", tree_model, iter, iter_to_string(iter));
784  model = GNC_TREE_MODEL_COMMODITY (tree_model);
785 
786  if (iter == NULL)
787  {
788  ct = model->commodity_table;
790  LEAVE("ns list length %d", g_list_length(list));
791  guint rv = g_list_length (list);
792  g_list_free (list);
793  return rv;
794  }
795 
796  if (iter->user_data == ITER_IS_NAMESPACE)
797  {
798  name_space = (gnc_commodity_namespace *)iter->user_data2;
800  LEAVE("cm list length %d", g_list_length(list));
801  guint rv = g_list_length (list);
802  g_list_free (list);
803  return rv;
804  }
805 
806  LEAVE("0");
807  return 0;
808 }
809 
810 static gboolean
811 gnc_tree_model_commodity_iter_nth_child (GtkTreeModel *tree_model,
812  GtkTreeIter *iter,
813  GtkTreeIter *parent,
814  int n)
815 {
816  GncTreeModelCommodity *model;
817  gnc_commodity_table *ct;
818  gnc_commodity_namespace *name_space;
819  GList *list;
820 
821  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
822  g_return_val_if_fail (iter != NULL, FALSE);
823 
824  ENTER("model %p, iter %p, parent %p (%s)",
825  tree_model, iter, parent, iter_to_string(parent));
826  model = GNC_TREE_MODEL_COMMODITY (tree_model);
827 
828  if (parent == NULL)
829  {
830  ct = model->commodity_table;
832 
833  iter->stamp = model->stamp;
834  iter->user_data = ITER_IS_NAMESPACE;
835  iter->user_data2 = g_list_nth_data(list, n);
836  iter->user_data3 = GINT_TO_POINTER(n);
837  LEAVE("ns iter %p (%s)", iter, iter_to_string(iter));
838  g_list_free (list);
839  return iter->user_data2 != NULL;
840  }
841 
842  if (parent->user_data == ITER_IS_NAMESPACE)
843  {
844  name_space = (gnc_commodity_namespace *)parent->user_data2;
846 
847  iter->stamp = model->stamp;
848  iter->user_data = ITER_IS_COMMODITY;
849  iter->user_data2 = g_list_nth_data(list, n);
850  iter->user_data3 = GINT_TO_POINTER(n);
851  LEAVE("cm iter %p (%s)", iter, iter_to_string(iter));
852  g_list_free (list);
853  return iter->user_data2 != NULL;
854  }
855 
856  iter->stamp = 0;
857  LEAVE("FALSE");
858  return FALSE;
859 }
860 
861 static gboolean
862 gnc_tree_model_commodity_iter_parent (GtkTreeModel *tree_model,
863  GtkTreeIter *iter,
864  GtkTreeIter *child)
865 {
866  GncTreeModelCommodity *model;
867  gnc_commodity_table *ct;
868  gnc_commodity_namespace *name_space;
869  GList *list;
870 
871  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (tree_model), FALSE);
872  g_return_val_if_fail (iter != NULL, FALSE);
873  g_return_val_if_fail (child != NULL, FALSE);
874 
875  ENTER("model %p, iter %p, child %p (%s)",
876  tree_model, iter, child, iter_to_string(child));
877  model = GNC_TREE_MODEL_COMMODITY (tree_model);
878 
879  if (child->user_data == ITER_IS_NAMESPACE)
880  {
881  LEAVE("ns has no parent");
882  return FALSE;
883  }
884 
885  ct = model->commodity_table;
887  name_space = gnc_commodity_get_namespace_ds((gnc_commodity*)child->user_data2);
888 
889  iter->stamp = model->stamp;
890  iter->user_data = ITER_IS_NAMESPACE;
891  iter->user_data2 = name_space;
892  iter->user_data3 = GINT_TO_POINTER(g_list_index(list, name_space));
893  LEAVE("ns iter %p (%s)", iter, iter_to_string(iter));
894  g_list_free (list);
895  return TRUE;
896 }
897 
898 /************************************************************/
899 /* Commodity Tree View Functions */
900 /************************************************************/
901 
902 /*
903  * Convert a model/commodity pair into a gtk_tree_model_iter. This
904  * routine should only be called from the file
905  * gnc-tree-view-commodity.c.
906  */
907 gboolean
909  gnc_commodity *commodity,
910  GtkTreeIter *iter)
911 {
912  gnc_commodity_namespace *name_space;
913  GList *list;
914  gint n;
915 
916  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE);
917  g_return_val_if_fail ((commodity != NULL), FALSE);
918  g_return_val_if_fail ((iter != NULL), FALSE);
919 
920  ENTER("model %p, commodity %p, iter %p", model, commodity, iter);
921 
922  name_space = gnc_commodity_get_namespace_ds(commodity);
923  if (name_space == NULL)
924  {
925  LEAVE("no namespace");
926  return FALSE;
927  }
928 
930  if (list == NULL)
931  {
932  LEAVE("empty list");
933  return FALSE;
934  }
935 
936  n = g_list_index(list, commodity);
937  g_list_free (list);
938  if (n == -1)
939  {
940  LEAVE("not in list");
941  return FALSE;
942  }
943 
944  iter->stamp = model->stamp;
945  iter->user_data = ITER_IS_COMMODITY;
946  iter->user_data2 = commodity;
947  iter->user_data3 = GINT_TO_POINTER(n);
948  LEAVE("iter %s", iter_to_string(iter));
949  return TRUE;
950 }
951 
952 /*
953  * Convert a model/commodity pair into a gtk_tree_model_path. This
954  * routine should only be called from the file
955  * gnc-tree-view-commodity.c.
956  */
957 GtkTreePath *
959  gnc_commodity *commodity)
960 {
961  GtkTreeIter tree_iter;
962  GtkTreePath *tree_path;
963 
964  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), NULL);
965  g_return_val_if_fail (commodity != NULL, NULL);
966  ENTER("model %p, commodity %p", model, commodity);
967 
968  if (!gnc_tree_model_commodity_get_iter_from_commodity (model, commodity, &tree_iter))
969  {
970  LEAVE("no iter");
971  return NULL;
972  }
973 
974  tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &tree_iter);
975  if (tree_path)
976  {
977  gchar *path_string = gtk_tree_path_to_string(tree_path);
978  LEAVE("path (2) %s", path_string);
979  g_free(path_string);
980  }
981  else
982  {
983  LEAVE("no path");
984  }
985  return tree_path;
986 }
987 
988 /*
989  * Convert a model/namespace pair into a gtk_tree_model_iter. This
990  * routine should only be called from the file
991  * gnc-tree-view-commodity.c.
992  */
993 gboolean
995  gnc_commodity_namespace *name_space,
996  GtkTreeIter *iter)
997 {
998  GList *list;
999  gint n;
1000 
1001  g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE);
1002  g_return_val_if_fail ((name_space != NULL), FALSE);
1003  g_return_val_if_fail ((iter != NULL), FALSE);
1004 
1005  ENTER("model %p, namespace %p, iter %p", model, name_space, iter);
1006 
1007  list = gnc_commodity_table_get_namespaces_list(model->commodity_table);
1008  if (list == NULL)
1009  {
1010  LEAVE("");
1011  return FALSE;
1012  }
1013 
1014  n = g_list_index(list, name_space);
1015  g_list_free (list);
1016  if (n == -1)
1017  {
1018  LEAVE("");
1019  return FALSE;
1020  }
1021 
1022  iter->stamp = model->stamp;
1023  iter->user_data = ITER_IS_NAMESPACE;
1024  iter->user_data2 = name_space;
1025  iter->user_data3 = GINT_TO_POINTER(n);
1026  LEAVE("iter %s", iter_to_string(iter));
1027  return TRUE;
1028 }
1029 
1030 
1031 /************************************************************/
1032 /* Commodity Tree Model - Engine Event Handling Functions */
1033 /************************************************************/
1034 
1035 typedef struct _remove_data
1036 {
1037  GncTreeModelCommodity *model;
1038  GtkTreePath *path;
1039 } remove_data;
1040 
1041 static GSList *pending_removals = NULL;
1042 
1054 static void
1055 gnc_tree_model_commodity_row_add (GncTreeModelCommodity *model,
1056  GtkTreeIter *iter)
1057 {
1058  GtkTreePath *path;
1059  GtkTreeModel *tree_model;
1060  GtkTreeIter tmp_iter;
1061 
1062  ENTER("model %p, iter (%p)%s", model, iter, iter_to_string(iter));
1063 
1064  /* We're adding a row, so the lists on which this model is based have
1065  * changed. Since existing iterators (except the one just passed in)
1066  * are all based on old indexes into those lists, we need to invalidate
1067  * them, which we can do by changing the model's stamp. */
1068  do
1069  {
1070  model->stamp++;
1071  }
1072  while (model->stamp == 0);
1073  iter->stamp = model->stamp;
1074 
1075  /* Tag the new row as inserted. */
1076  tree_model = GTK_TREE_MODEL(model);
1077  path = gnc_tree_model_commodity_get_path(tree_model, iter);
1078  gtk_tree_model_row_inserted(tree_model, path, iter);
1079 
1080  /* Inform all ancestors. */
1081  /*
1082  * Charles Day: I don't think calls to gtk_tree_model_row_changed() should
1083  * be necessary. It is just a workaround for bug #540201.
1084  */
1085  if (gtk_tree_path_up(path) &&
1086  gtk_tree_path_get_depth(path) > 0 &&
1087  gtk_tree_model_get_iter(tree_model, &tmp_iter, path))
1088  {
1089  /* Signal the change to the parent. */
1090  gtk_tree_model_row_changed(tree_model, path, &tmp_iter);
1091 
1092  /* Is this the parent's first child? */
1093  if (gtk_tree_model_iter_n_children(tree_model, &tmp_iter) == 1)
1094  gtk_tree_model_row_has_child_toggled(tree_model, path, &tmp_iter);
1095 
1096  /* Signal any other ancestors. */
1097  while (gtk_tree_path_up(path) &&
1098  gtk_tree_path_get_depth(path) > 0 &&
1099  gtk_tree_model_get_iter(tree_model, &tmp_iter, path))
1100  {
1101  gtk_tree_model_row_changed(tree_model, path, &tmp_iter);
1102  }
1103  }
1104  gtk_tree_path_free(path);
1105 
1106  /* If the new row already has children, signal that so the expander
1107  * can be shown. This can happen, for example, if a namespace is
1108  * changed in another place and gets removed and then re-added to
1109  * the commodity db. */
1110  if (gnc_tree_model_commodity_iter_has_child(tree_model, iter))
1111  {
1112  path = gnc_tree_model_commodity_get_path(tree_model, iter);
1113  gtk_tree_model_row_has_child_toggled(tree_model, path, iter);
1114  gtk_tree_path_free(path);
1115  }
1116 
1117  LEAVE(" ");
1118 }
1119 
1131 static void
1132 gnc_tree_model_commodity_row_delete (GncTreeModelCommodity *model,
1133  GtkTreePath *path)
1134 {
1135  GtkTreeModel *tree_model;
1136  GtkTreeIter iter;
1137 
1138  g_return_if_fail(GNC_IS_TREE_MODEL_COMMODITY(model));
1139  g_return_if_fail(path);
1140 
1141  debug_path(ENTER, path);
1142 
1143  tree_model = GTK_TREE_MODEL(model);
1144 
1145  /* We're removing a row, so the lists on which this model is based have
1146  * changed. Since existing iterators are all based on old indexes into
1147  * those lists, we need to invalidate them, which we can do by changing
1148  * the model's stamp. */
1149  do
1150  {
1151  model->stamp++;
1152  }
1153  while (model->stamp == 0);
1154 
1155  /* Signal that the path has been deleted. */
1156  gtk_tree_model_row_deleted(tree_model, path);
1157 
1158  /* Issue any appropriate signals to ancestors. */
1159  if (gtk_tree_path_up(path) &&
1160  gtk_tree_path_get_depth(path) > 0 &&
1161  gtk_tree_model_get_iter(tree_model, &iter, path) &&
1162  !gtk_tree_model_iter_has_child(tree_model, &iter))
1163  {
1164  DEBUG("parent toggled, iter %s", iter_to_string(&iter));
1165  gtk_tree_model_row_has_child_toggled(tree_model, path, &iter);
1166  }
1167 
1168  LEAVE(" ");
1169 }
1170 
1171 
1188 static gboolean
1189 gnc_tree_model_commodity_do_deletions (gpointer unused)
1190 {
1191  ENTER(" ");
1192 
1193  /* Go through the list of paths needing removal. */
1194  while (pending_removals)
1195  {
1196  remove_data *data = pending_removals->data;
1197  pending_removals = g_slist_delete_link(pending_removals, pending_removals);
1198 
1199  if (data)
1200  {
1201  debug_path(DEBUG, data->path);
1202 
1203  /* Remove the path. */
1204  gnc_tree_model_commodity_row_delete(data->model, data->path);
1205 
1206  gtk_tree_path_free(data->path);
1207  g_free(data);
1208  }
1209  }
1210 
1211  LEAVE(" ");
1212  /* Don't call me again. */
1213  return FALSE;
1214 }
1215 
1216 
1248 static void
1249 gnc_tree_model_commodity_event_handler (QofInstance *entity,
1250  QofEventId event_type,
1251  gpointer user_data,
1252  gpointer event_data)
1253 {
1254  GncTreeModelCommodity *model;
1255  GtkTreePath *path;
1256  GtkTreeIter iter;
1257  remove_data *data;
1258  const gchar *name;
1259 
1260  model = (GncTreeModelCommodity *)user_data;
1261 
1262  /* hard failures */
1263  g_return_if_fail(GNC_IS_TREE_MODEL_COMMODITY(model));
1264 
1265  ENTER("entity %p, event %d, model %p, event data %p",
1266  entity, event_type, user_data, event_data);
1267 
1268  /* Do deletions if any are pending. */
1269  if (pending_removals)
1270  gnc_tree_model_commodity_do_deletions(NULL);
1271 
1272  /* get type specific data */
1273  if (GNC_IS_COMMODITY(entity))
1274  {
1275  gnc_commodity *commodity;
1276 
1277  commodity = GNC_COMMODITY(entity);
1278  name = gnc_commodity_get_mnemonic(commodity);
1279  if (event_type != QOF_EVENT_DESTROY)
1280  {
1281  if (!gnc_tree_model_commodity_get_iter_from_commodity (model, commodity, &iter))
1282  {
1283  LEAVE("no iter");
1284  return;
1285  }
1286  }
1287  }
1288  else if (GNC_IS_COMMODITY_NAMESPACE(entity))
1289  {
1290  gnc_commodity_namespace *name_space;
1291 
1292  name_space = GNC_COMMODITY_NAMESPACE(entity);
1293  name = gnc_commodity_namespace_get_name(name_space);
1294  if (event_type != QOF_EVENT_DESTROY)
1295  {
1296  if (!gnc_tree_model_commodity_get_iter_from_namespace (model, name_space, &iter))
1297  {
1298  LEAVE("no iter");
1299  return;
1300  }
1301  }
1302  }
1303  else
1304  {
1305  LEAVE("");
1306  return;
1307  }
1308 
1309  switch (event_type)
1310  {
1311  case QOF_EVENT_ADD:
1312  /* Tell the filters/views where the new account was added. */
1313  DEBUG("add %s", name);
1314  gnc_tree_model_commodity_row_add (model, &iter);
1315  break;
1316 
1317  case QOF_EVENT_REMOVE:
1318  /* Record the path of this account for later use in destruction */
1319  DEBUG("remove %s", name);
1320  path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter);
1321  if (path == NULL)
1322  {
1323  LEAVE("not in model");
1324  return;
1325  }
1326 
1327  data = g_new0 (remove_data, 1);
1328  data->model = model;
1329  data->path = path;
1330  pending_removals = g_slist_append (pending_removals, data);
1331  g_idle_add_full(G_PRIORITY_HIGH_IDLE,
1332  gnc_tree_model_commodity_do_deletions, NULL, NULL);
1333 
1334  LEAVE(" ");
1335  return;
1336 
1337  case QOF_EVENT_MODIFY:
1338  DEBUG("change %s", name);
1339  path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter);
1340  if (path == NULL)
1341  {
1342  LEAVE("not in model");
1343  return;
1344  }
1345  gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, &iter);
1346  gtk_tree_path_free(path);
1347  LEAVE(" ");
1348  return;
1349 
1350  default:
1351  LEAVE("ignored event for %s", name);
1352  return;
1353  }
1354  LEAVE(" new stamp %u", model->stamp);
1355 }
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.
GncTreeModel gnc_tree_model
The parent object data.
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.
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.
G_DEFINE_TYPE_WITH_CODE(GncMainWindow, gnc_main_window, GTK_TYPE_APPLICATION_WINDOW, G_IMPLEMENT_INTERFACE(GNC_TYPE_WINDOW, gnc_window_main_window_init)) static guint main_window_signals[LAST_SIGNAL]
A holding place for all the signals generated by the main window code.
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
The instance data structure for a commodity tree model.
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.
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.