GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-component-manager.c
1 /********************************************************************\
2  * gnc-component-manager.h - GUI component manager interface *
3  * Copyright (C) 2000 Dave Peticolas <[email protected]> *
4  * *
5  * This program is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU General Public License as *
7  * published by the Free Software Foundation; either version 2 of *
8  * the License, or (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License*
16  * along with this program; if not, write to the Free Software *
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
18 \********************************************************************/
19 
20 #include "config.h"
21 
22 #include <stdio.h>
23 
24 #include "gnc-component-manager.h"
25 #include "qof.h"
26 #include "gnc-ui-util.h"
27 
28 
31 #define CM_DEBUG 0
32 
33 typedef struct
34 {
35  QofIdType entity_type;
36  QofEventId event_mask;
38 
39 typedef struct
40 {
41  GHashTable * event_masks;
42  GHashTable * entity_events;
43 
44  gboolean match;
46 
47 typedef struct
48 {
49  GNCComponentRefreshHandler refresh_handler;
50  GNCComponentCloseHandler close_handler;
51  gpointer user_data;
52 
53  ComponentEventInfo watch_info;
54 
55  char *component_class;
56  gint component_id;
57  gpointer session;
59 
60 
62 static guint suspend_counter = 0;
63 /* Some code foolishly uses 0 instead of NO_COMPONENT, so we start with 1. */
64 static gint next_component_id = 1;
65 static GList *components = NULL;
66 
67 static ComponentEventInfo changes = { NULL, NULL, FALSE };
68 static ComponentEventInfo changes_backup = { NULL, NULL, FALSE };
69 
70 
71 /* This static indicates the debugging module that this .o belongs to. */
72 static QofLogModule log_module = GNC_MOD_GUI;
73 
74 
76 static void gnc_gui_refresh_internal (gboolean force);
77 static GList * find_component_ids_by_class (const char *component_class);
78 static gboolean got_events = FALSE;
79 
80 
83 #if CM_DEBUG
84 static void
85 dump_components (void)
86 {
87  GList *node;
88 
89  fprintf (stderr, "Components:\n");
90 
91  for (node = components; node; node = node->next)
92  {
93  ComponentInfo *ci = node->data;
94 
95  fprintf (stderr, " %s:\t%d\n",
96  ci->component_class ? ci->component_class : "(null)",
97  ci->component_id);
98  }
99 
100  fprintf (stderr, "\n");
101 }
102 #endif
103 
104 static void
105 clear_mask_hash_helper (gpointer key, gpointer value, gpointer user_data)
106 {
107  QofEventId * et = value;
108 
109  *et = 0;
110 }
111 
112 /* clear a hash table of the form string --> QofEventId,
113  * where the values are g_malloced and the keys are in the engine
114  * string cache. */
115 static void
116 clear_mask_hash (GHashTable *hash)
117 {
118  if (hash == NULL)
119  return;
120 
121  g_hash_table_foreach (hash, clear_mask_hash_helper, NULL);
122 }
123 
124 static gboolean
125 destroy_mask_hash_helper (gpointer key, gpointer value, gpointer user_data)
126 {
128  g_free (value);
129 
130  return TRUE;
131 }
132 
133 static void
134 destroy_mask_hash (GHashTable *hash)
135 {
136  g_hash_table_foreach_remove (hash, destroy_mask_hash_helper, NULL);
137  g_hash_table_destroy (hash);
138 }
139 
140 static gboolean
141 destroy_event_hash_helper (gpointer key, gpointer value, gpointer user_data)
142 {
143  GncGUID *guid = key;
144  EventInfo *ei = value;
145 
146  guid_free (guid);
147  g_free (ei);
148 
149  return TRUE;
150 }
151 
152 /* clear a hash table of the form GncGUID --> EventInfo, where
153  * both keys and values are g_malloced */
154 static void
155 clear_event_hash (GHashTable *hash)
156 {
157  if (hash == NULL)
158  return;
159 
160  g_hash_table_foreach_remove (hash, destroy_event_hash_helper, NULL);
161 }
162 
163 static void
164 destroy_event_hash (GHashTable *hash)
165 {
166  clear_event_hash (hash);
167  g_hash_table_destroy (hash);
168 }
169 
170 static void
171 clear_event_info (ComponentEventInfo *cei)
172 {
173  if (!cei)
174  return;
175 
176  clear_mask_hash (cei->event_masks);
177  clear_event_hash (cei->entity_events);
178 }
179 
180 static void
181 add_event (ComponentEventInfo *cei, const GncGUID *entity,
182  QofEventId event_mask, gboolean or_in)
183 {
184  GHashTable *hash;
185 
186  if (!cei || !cei->entity_events || !entity)
187  return;
188 
189  hash = cei->entity_events;
190 
191  if (event_mask == 0)
192  {
193  gpointer key;
194  gpointer value;
195 
196  if (or_in)
197  return;
198 
199  if (g_hash_table_lookup_extended (hash, entity, &key, &value))
200  {
201  g_hash_table_remove (hash, entity);
202  guid_free (key);
203  g_free (value);
204  }
205  }
206  else
207  {
208  EventInfo *ei;
209 
210  ei = g_hash_table_lookup (hash, entity);
211  if (ei == NULL)
212  {
213  GncGUID *key;
214 
215  key = guid_malloc ();
216  *key = *entity;
217 
218  ei = g_new (EventInfo, 1);
219  ei->event_mask = 0;
220 
221  g_hash_table_insert (hash, key, ei);
222  }
223 
224  if (or_in)
225  ei->event_mask |= event_mask;
226  else
227  ei->event_mask = event_mask;
228  }
229 }
230 
231 static void
232 add_event_type (ComponentEventInfo *cei, QofIdTypeConst entity_type,
233  QofEventId event_mask, gboolean or_in)
234 {
235  QofEventId *mask;
236 
237  g_return_if_fail (cei);
238  g_return_if_fail (cei->event_masks);
239  g_return_if_fail (entity_type);
240 
241  mask = g_hash_table_lookup (cei->event_masks, entity_type);
242  if (!mask)
243  {
244  char * key = qof_string_cache_insert ((gpointer) entity_type);
245  mask = g_new0 (QofEventId, 1);
246  g_hash_table_insert (cei->event_masks, key, mask);
247  }
248 
249  if (or_in)
250  *mask |= event_mask;
251  else
252  *mask = event_mask;
253 }
254 
255 static void
256 gnc_cm_event_handler (QofInstance *entity,
257  QofEventId event_type,
258  gpointer user_data,
259  gpointer event_data)
260 {
261  const GncGUID *guid = qof_entity_get_guid(entity);
262 #if CM_DEBUG
263  gchar guidstr[GUID_ENCODING_LENGTH+1];
264  guid_to_string_buff (guid, guidstr);
265  fprintf (stderr, "event_handler: event %d, entity %p, guid %s\n", event_type,
266  entity, guidstr);
267 #endif
268  add_event (&changes, guid, event_type, TRUE);
269 
270  if (QOF_CHECK_TYPE(entity, GNC_ID_SPLIT))
271  {
272  /* split events are never generated by the engine, but might
273  * be generated by a backend (viz. the postgres backend.)
274  * Handle them like a transaction modify event. */
275  add_event_type (&changes, GNC_ID_TRANS, QOF_EVENT_MODIFY, TRUE);
276  }
277  else
278  add_event_type (&changes, entity->e_type, event_type, TRUE);
279 
280  got_events = TRUE;
281 
282  if (suspend_counter == 0)
283  gnc_gui_refresh_internal (FALSE);
284 }
285 
286 static gint handler_id;
287 
288 void
289 gnc_component_manager_init (void)
290 {
291  if (changes.entity_events)
292  {
293  PERR ("component manager already initialized");
294  return;
295  }
296 
297  changes.event_masks = g_hash_table_new (g_str_hash, g_str_equal);
298  changes.entity_events = guid_hash_table_new ();
299 
300  changes_backup.event_masks = g_hash_table_new (g_str_hash, g_str_equal);
301  changes_backup.entity_events = guid_hash_table_new ();
302 
303  handler_id = qof_event_register_handler (gnc_cm_event_handler, NULL);
304 }
305 
306 void
307 gnc_component_manager_shutdown (void)
308 {
309  if (!changes.entity_events)
310  {
311  PERR ("component manager not initialized");
312  return;
313  }
314 
315  destroy_mask_hash (changes.event_masks);
316  changes.event_masks = NULL;
317 
318  destroy_event_hash (changes.entity_events);
319  changes.entity_events = NULL;
320 
321  destroy_mask_hash (changes_backup.event_masks);
322  changes_backup.event_masks = NULL;
323 
324  destroy_event_hash (changes_backup.entity_events);
325  changes_backup.entity_events = NULL;
326 
327  qof_event_unregister_handler (handler_id);
328 }
329 
330 static ComponentInfo *
331 find_component (gint component_id)
332 {
333  GList *node;
334 
335  for (node = components; node; node = node->next)
336  {
337  ComponentInfo *ci = node->data;
338 
339  if (ci->component_id == component_id)
340  return ci;
341  }
342 
343  return NULL;
344 }
345 
346 static GList *
347 find_components_by_data (gpointer user_data)
348 {
349  GList *list = NULL;
350  GList *node;
351 
352  for (node = components; node; node = node->next)
353  {
354  ComponentInfo *ci = node->data;
355 
356  if (ci->user_data == user_data)
357  list = g_list_prepend (list, ci);
358  }
359 
360  return list;
361 }
362 
363 static GList *
364 find_components_by_session (gpointer session)
365 {
366  GList *list = NULL;
367  GList *node;
368 
369  for (node = components; node; node = node->next)
370  {
371  ComponentInfo *ci = node->data;
372 
373  if (ci->session == session)
374  list = g_list_prepend (list, ci);
375  }
376 
377  return list;
378 }
379 
380 static ComponentInfo *
381 gnc_register_gui_component_internal (const char * component_class)
382 {
383  ComponentInfo *ci;
384  gint component_id;
385 
386  g_return_val_if_fail (component_class, NULL);
387 
388  /* look for a free handler id */
389  component_id = next_component_id;
390 
391  /* design warning: if we ever get 2^32-1 components,
392  this loop is infinite. Instead of fixing it, we'll just
393  complain when (if) we get half way there (probably never).
394  */
395  while (find_component (component_id))
396  if (++component_id == NO_COMPONENT)
397  component_id++;
398 
399  if (component_id < 0)
400  PERR("Amazing! Half way to running out of component_ids.");
401 
402  /* found one, add the handler */
403  ci = g_new0 (ComponentInfo, 1);
404 
405  ci->watch_info.event_masks = g_hash_table_new (g_str_hash, g_str_equal);
406  ci->watch_info.entity_events = guid_hash_table_new ();
407 
408  ci->component_class = g_strdup (component_class);
409  ci->component_id = component_id;
410  ci->session = NULL;
411 
412  components = g_list_prepend (components, ci);
413 
414  /* update id for next registration */
415  next_component_id = component_id + 1;
416 
417 #if CM_DEBUG
418  fprintf (stderr, "Register component %d in class %s\n",
419  component_id, component_class ? component_class : "(null)");
420  dump_components ();
421 #endif
422 
423  return ci;
424 }
425 
426 gint
427 gnc_register_gui_component (const char *component_class,
428  GNCComponentRefreshHandler refresh_handler,
429  GNCComponentCloseHandler close_handler,
430  gpointer user_data)
431 {
432  ComponentInfo *ci;
433 
434  /* sanity check */
435  if (!component_class)
436  {
437  PERR ("no class specified");
438  return NO_COMPONENT;
439  }
440 
441  ci = gnc_register_gui_component_internal (component_class);
442  g_return_val_if_fail (ci, NO_COMPONENT);
443 
444  ci->refresh_handler = refresh_handler;
445  ci->close_handler = close_handler;
446  ci->user_data = user_data;
447 
448  return ci->component_id;
449 }
450 
451 void
452 gnc_gui_component_watch_entity (gint component_id,
453  const GncGUID *entity,
454  QofEventId event_mask)
455 {
456  ComponentInfo *ci;
457 
458  if (entity == NULL)
459  return;
460 
461  ci = find_component (component_id);
462  if (!ci)
463  {
464  PERR ("component not found");
465  return;
466  }
467 
468  add_event (&ci->watch_info, entity, event_mask, FALSE);
469 }
470 
471 void
472 gnc_gui_component_watch_entity_type (gint component_id,
473  QofIdTypeConst entity_type,
474  QofEventId event_mask)
475 {
476  ComponentInfo *ci;
477 
478  ci = find_component (component_id);
479  if (!ci)
480  {
481  PERR ("component not found");
482  return;
483  }
484 
485  add_event_type (&ci->watch_info, entity_type, event_mask, FALSE);
486 }
487 
488 const EventInfo *
489 gnc_gui_get_entity_events (GHashTable *changes, const GncGUID *entity)
490 {
491  if (!changes || !entity)
492  return QOF_EVENT_NONE;
493 
494  return g_hash_table_lookup (changes, entity);
495 }
496 
497 void
498 gnc_gui_component_clear_watches (gint component_id)
499 {
500  ComponentInfo *ci;
501 
502  ci = find_component (component_id);
503  if (!ci)
504  {
505  PERR ("component not found");
506  return;
507  }
508 
509  clear_event_info (&ci->watch_info);
510 }
511 
512 void
513 gnc_unregister_gui_component (gint component_id)
514 {
515  ComponentInfo *ci;
516 
517  ci = find_component (component_id);
518  if (!ci)
519  {
520  PERR ("component %d not found", component_id);
521  return;
522  }
523 
524 #if CM_DEBUG
525  fprintf (stderr, "Unregister component %d in class %s\n",
526  ci->component_id,
527  ci->component_class ? ci->component_class : "(null)");
528 #endif
529 
530  gnc_gui_component_clear_watches (component_id);
531 
532  components = g_list_remove (components, ci);
533 
534  destroy_mask_hash (ci->watch_info.event_masks);
535  ci->watch_info.event_masks = NULL;
536 
537  destroy_event_hash (ci->watch_info.entity_events);
538  ci->watch_info.entity_events = NULL;
539 
540  g_free (ci->component_class);
541  ci->component_class = NULL;
542 
543  g_free (ci);
544 
545 #if CM_DEBUG
546  dump_components ();
547 #endif
548 }
549 
550 void
551 gnc_unregister_gui_component_by_data (const char *component_class,
552  gpointer user_data)
553 {
554  GList *list;
555  GList *node;
556 
557  list = find_components_by_data (user_data);
558 
559  for (node = list; node; node = node->next)
560  {
561  ComponentInfo *ci = node->data;
562 
563  if (component_class &&
564  g_strcmp0 (component_class, ci->component_class) != 0)
565  continue;
566 
567  gnc_unregister_gui_component (ci->component_id);
568  }
569 
570  g_list_free (list);
571 }
572 
573 void
574 gnc_suspend_gui_refresh (void)
575 {
576  suspend_counter++;
577 
578  if (suspend_counter == 0)
579  {
580  PERR ("suspend counter overflow");
581  }
582 }
583 
584 void
585 gnc_resume_gui_refresh (void)
586 {
587  if (suspend_counter == 0)
588  {
589  PERR ("suspend counter underflow");
590  return;
591  }
592 
593  suspend_counter--;
594 
595  if (suspend_counter == 0)
596  gnc_gui_refresh_internal (FALSE);
597 }
598 
599 static void
600 match_type_helper (gpointer key, gpointer value, gpointer user_data)
601 {
602  ComponentEventInfo *cei = user_data;
603  QofIdType id_type = key;
604  QofEventId * et = value;
605  QofEventId * et_2;
606 
607  et_2 = g_hash_table_lookup (cei->event_masks, id_type);
608  if (!et_2)
609  return;
610 
611  if (*et & *et_2)
612  cei->match = TRUE;
613 }
614 
615 static void
616 match_helper (gpointer key, gpointer value, gpointer user_data)
617 {
618  GncGUID *guid = key;
619  EventInfo *ei_1 = value;
620  EventInfo *ei_2;
621  ComponentEventInfo *cei = user_data;
622 
623  ei_2 = g_hash_table_lookup (cei->entity_events, guid);
624  if (!ei_2)
625  return;
626 
627  if (ei_1->event_mask & ei_2->event_mask)
628  cei->match = TRUE;
629 }
630 
631 static gboolean
632 changes_match (ComponentEventInfo *cei, ComponentEventInfo *changes)
633 {
634  ComponentEventInfo *big_cei;
635  GHashTable *smalltable;
636 
637  if (cei == NULL)
638  return FALSE;
639 
640  /* check types first, for efficiency */
641  cei->match = FALSE;
642  g_hash_table_foreach (changes->event_masks, match_type_helper, cei);
643  if (cei->match)
644  return TRUE;
645 
646  if (g_hash_table_size (cei->entity_events) <=
647  g_hash_table_size (changes->entity_events))
648  {
649  smalltable = cei->entity_events;
650  big_cei = changes;
651  }
652  else
653  {
654  smalltable = changes->entity_events;
655  big_cei = cei;
656  }
657 
658  big_cei->match = FALSE;
659 
660  g_hash_table_foreach (smalltable, match_helper, big_cei);
661 
662  return big_cei->match;
663 }
664 
665 static void
666 gnc_gui_refresh_internal (gboolean force)
667 {
668  GList *list;
669  GList *node;
670 
671  if (!got_events && !force)
672  return;
673 
674  gnc_suspend_gui_refresh ();
675 
676  {
677  GHashTable *table;
678 
679  table = changes_backup.event_masks;
680  changes_backup.event_masks = changes.event_masks;
681  changes.event_masks = table;
682 
683  table = changes_backup.entity_events;
684  changes_backup.entity_events = changes.entity_events;
685  changes.entity_events = table;
686  }
687 
688 #if CM_DEBUG
689  fprintf (stderr, "%srefresh!\n", force ? "forced " : "");
690 #endif
691 
692  list = find_component_ids_by_class (NULL);
693 
694  for (node = list; node; node = node->next)
695  {
696  ComponentInfo *ci = find_component (GPOINTER_TO_INT (node->data));
697 
698  if (!ci)
699  continue;
700 
701  if (!ci->refresh_handler)
702  {
703 #if CM_DEBUG
704  fprintf (stderr, "no handlers for %s:%d\n", ci->component_class, ci->component_id);
705 #endif
706  continue;
707  }
708 
709  if (force)
710  {
711  if (ci->refresh_handler)
712  {
713 #if CM_DEBUG
714  fprintf (stderr, "calling %s:%d C handler\n", ci->component_class, ci->component_id);
715 #endif
716  ci->refresh_handler (NULL, ci->user_data);
717  }
718  }
719  else if (changes_match (&ci->watch_info, &changes_backup))
720  {
721  if (ci->refresh_handler)
722  {
723 #if CM_DEBUG
724  fprintf (stderr, "calling %s:%d C handler\n", ci->component_class, ci->component_id);
725 #endif
726  ci->refresh_handler (changes_backup.entity_events, ci->user_data);
727  }
728  }
729  else
730  {
731 #if CM_DEBUG
732  fprintf (stderr, "no match for %s:%d\n", ci->component_class, ci->component_id);
733 #endif
734  }
735  }
736 
737  clear_event_info (&changes_backup);
738  got_events = FALSE;
739 
740  g_list_free (list);
741 
742  gnc_resume_gui_refresh ();
743 }
744 
745 void
746 gnc_gui_refresh_all (void)
747 {
748  if (suspend_counter != 0)
749  {
750  PERR ("suspend counter not zero");
751  return;
752  }
753 
754  gnc_gui_refresh_internal (TRUE);
755 }
756 
757 gboolean
758 gnc_gui_refresh_suspended (void)
759 {
760  return suspend_counter != 0;
761 }
762 
763 void
764 gnc_close_gui_component (gint component_id)
765 {
766  ComponentInfo *ci;
767 
768  ci = find_component (component_id);
769  if (!ci)
770  {
771  PERR ("component not found");
772  return;
773  }
774 
775  if (!ci->close_handler)
776  return;
777 
778  if (ci->close_handler)
779  ci->close_handler (ci->user_data);
780 }
781 
782 void
783 gnc_close_gui_component_by_data (const char *component_class,
784  gpointer user_data)
785 {
786  GList *list;
787  GList *node;
788 
789  list = find_components_by_data (user_data);
790 
791  for (node = list; node; node = node->next)
792  {
793  ComponentInfo *ci = node->data;
794 
795  if (component_class &&
796  g_strcmp0 (component_class, ci->component_class) != 0)
797  continue;
798 
799  gnc_close_gui_component (ci->component_id);
800  }
801 
802  g_list_free (list);
803 }
804 
805 void
806 gnc_gui_component_set_session (gint component_id, gpointer session)
807 {
808  ComponentInfo *ci;
809 
810  ci = find_component (component_id);
811  if (!ci)
812  {
813  PERR ("component not found");
814  return;
815  }
816 
817  ci->session = session;
818 }
819 
820 void
821 gnc_close_gui_component_by_session (gpointer session)
822 {
823  GList *list;
824  GList *node;
825 
826  list = find_components_by_session (session);
827 
828  for (node = list; node; node = node->next)
829  {
830  ComponentInfo *ci = node->data;
831 
832  gnc_close_gui_component (ci->component_id);
833  }
834 
835  g_list_free (list);
836 }
837 
838 GList *
839 gnc_find_gui_components (const char *component_class,
840  GNCComponentFindHandler find_handler,
841  gpointer find_data)
842 {
843  GList *list = NULL;
844  GList *node;
845 
846  if (!component_class)
847  return NULL;
848 
849  for (node = components; node; node = node->next)
850  {
851  ComponentInfo *ci = node->data;
852 
853  if (g_strcmp0 (component_class, ci->component_class) != 0)
854  continue;
855 
856  if (find_handler && !find_handler (find_data, ci->user_data))
857  continue;
858 
859  list = g_list_prepend (list, ci->user_data);
860  }
861 
862  return list;
863 }
864 
865 gpointer
866 gnc_find_first_gui_component (const char *component_class,
867  GNCComponentFindHandler find_handler,
868  gpointer find_data)
869 {
870  GList *list;
871  gpointer user_data;
872 
873 #if CM_DEBUG
874  fprintf (stderr, "find: class %s, fn %p, data %p\n", component_class,
875  find_handler, find_data);
876 #endif
877  if (!component_class)
878  return NULL;
879 
880  list = gnc_find_gui_components (component_class, find_handler, find_data);
881  if (!list)
882  return NULL;
883 
884  user_data = list->data;
885 
886  g_list_free (list);
887 
888 #if CM_DEBUG
889  fprintf (stderr, "found: data %p\n", user_data);
890 #endif
891  return user_data;
892 }
893 
894 static GList *
895 find_component_ids_by_class (const char *component_class)
896 {
897  GList *list = NULL;
898  GList *node;
899 
900  for (node = components; node; node = node->next)
901  {
902  ComponentInfo *ci = node->data;
903 
904  if (component_class &&
905  g_strcmp0 (component_class, ci->component_class) != 0)
906  continue;
907 
908  list = g_list_prepend (list, GINT_TO_POINTER (ci->component_id));
909  }
910 
911  return list;
912 }
913 
914 gint
915 gnc_forall_gui_components (const char *component_class,
916  GNCComponentHandler handler,
917  gpointer iter_data)
918 {
919  GList *list;
920  GList *node;
921  gint count = 0;
922 
923  if (!handler)
924  return(0);
925 
926  /* so components can be destroyed during the forall */
927  list = find_component_ids_by_class (component_class);
928 
929  for (node = list; node; node = node->next)
930  {
931  ComponentInfo *ci = find_component (GPOINTER_TO_INT (node->data));
932 
933  if (!ci)
934  continue;
935 
936  if (handler (ci->component_class, ci->component_id, ci->user_data, iter_data))
937  count++;
938  }
939 
940  g_list_free (list);
941  return(count);
942 }
QofIdType e_type
Definition: qofinstance.h:69
utility functions for the GnuCash UI
const gchar * QofIdTypeConst
Definition: qofid.h:87
GHashTable * guid_hash_table_new(void)
gchar * guid_to_string_buff(const GncGUID *guid, gchar *buff)
#define PERR(format, args...)
Definition: qoflog.h:237
Definition: guid.h:65
gint qof_event_register_handler(QofEventHandler handler, gpointer handler_data)
Register a handler for events.
const gchar * QofIdType
Definition: qofid.h:85
#define QOF_CHECK_TYPE(obj, type)
Definition: qofid.h:124
gint QofEventId
Definition: qofevent.h:45
GncGUID * guid_malloc(void)
#define GUID_ENCODING_LENGTH
Definition: guid.h:74
void qof_event_unregister_handler(gint handler_id)
Unregister an event handler.
const GncGUID * qof_entity_get_guid(gconstpointer)
#define QOF_EVENT_NONE
Default events for backwards compatibility.
Definition: qofevent.h:72
void qof_string_cache_remove(gconstpointer key)
gpointer qof_string_cache_insert(gconstpointer key)
const gchar * QofLogModule
Definition: qofid.h:89