24 #include "gnc-component-manager.h" 41 GHashTable * event_masks;
42 GHashTable * entity_events;
49 GNCComponentRefreshHandler refresh_handler;
50 GNCComponentCloseHandler close_handler;
55 char *component_class;
62 static guint suspend_counter = 0;
64 static gint next_component_id = 1;
65 static GList *components = NULL;
72 static QofLogModule log_module = GNC_MOD_GUI;
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;
85 dump_components (
void)
89 fprintf (stderr,
"Components:\n");
91 for (node = components; node; node = node->next)
95 fprintf (stderr,
" %s:\t%d\n",
96 ci->component_class ? ci->component_class :
"(null)",
100 fprintf (stderr,
"\n");
105 clear_mask_hash_helper (gpointer key, gpointer value, gpointer user_data)
116 clear_mask_hash (GHashTable *hash)
121 g_hash_table_foreach (hash, clear_mask_hash_helper, NULL);
125 destroy_mask_hash_helper (gpointer key, gpointer value, gpointer user_data)
134 destroy_mask_hash (GHashTable *hash)
136 g_hash_table_foreach_remove (hash, destroy_mask_hash_helper, NULL);
137 g_hash_table_destroy (hash);
141 destroy_event_hash_helper (gpointer key, gpointer value, gpointer user_data)
155 clear_event_hash (GHashTable *hash)
160 g_hash_table_foreach_remove (hash, destroy_event_hash_helper, NULL);
164 destroy_event_hash (GHashTable *hash)
166 clear_event_hash (hash);
167 g_hash_table_destroy (hash);
176 clear_mask_hash (cei->event_masks);
177 clear_event_hash (cei->entity_events);
186 if (!cei || !cei->entity_events || !entity)
189 hash = cei->entity_events;
199 if (g_hash_table_lookup_extended (hash, entity, &key, &value))
201 g_hash_table_remove (hash, entity);
210 ei = g_hash_table_lookup (hash, entity);
221 g_hash_table_insert (hash, key, ei);
225 ei->event_mask |= event_mask;
227 ei->event_mask = event_mask;
237 g_return_if_fail (cei);
238 g_return_if_fail (cei->event_masks);
239 g_return_if_fail (entity_type);
241 mask = g_hash_table_lookup (cei->event_masks, entity_type);
246 g_hash_table_insert (cei->event_masks, (gpointer)key, mask);
265 fprintf (stderr,
"event_handler: event %d, entity %p, guid %s\n", event_type,
268 add_event (&changes, guid, event_type, TRUE);
275 add_event_type (&changes, GNC_ID_TRANS, QOF_EVENT_MODIFY, TRUE);
278 add_event_type (&changes, entity->e_type, event_type, TRUE);
282 if (suspend_counter == 0)
283 gnc_gui_refresh_internal (FALSE);
286 static gint handler_id;
289 gnc_component_manager_init (
void)
291 if (changes.entity_events)
293 PERR (
"component manager already initialized");
297 changes.event_masks = g_hash_table_new (g_str_hash, g_str_equal);
300 changes_backup.event_masks = g_hash_table_new (g_str_hash, g_str_equal);
307 gnc_component_manager_shutdown (
void)
309 if (!changes.entity_events)
311 PERR (
"component manager not initialized");
315 destroy_mask_hash (changes.event_masks);
316 changes.event_masks = NULL;
318 destroy_event_hash (changes.entity_events);
319 changes.entity_events = NULL;
321 destroy_mask_hash (changes_backup.event_masks);
322 changes_backup.event_masks = NULL;
324 destroy_event_hash (changes_backup.entity_events);
325 changes_backup.entity_events = NULL;
331 find_component (gint component_id)
335 for (node = components; node; node = node->next)
339 if (ci->component_id == component_id)
347 find_components_by_data (gpointer user_data)
352 for (node = components; node; node = node->next)
356 if (ci->user_data == user_data)
357 list = g_list_prepend (list, ci);
364 find_components_by_session (gpointer session)
369 for (node = components; node; node = node->next)
373 if (ci->session == session)
374 list = g_list_prepend (list, ci);
381 gnc_register_gui_component_internal (
const char * component_class)
386 g_return_val_if_fail (component_class, NULL);
389 component_id = next_component_id;
395 while (find_component (component_id))
396 if (++component_id == NO_COMPONENT)
399 if (component_id < 0)
400 PERR(
"Amazing! Half way to running out of component_ids.");
405 ci->watch_info.event_masks = g_hash_table_new (g_str_hash, g_str_equal);
408 ci->component_class = g_strdup (component_class);
409 ci->component_id = component_id;
412 components = g_list_prepend (components, ci);
415 next_component_id = component_id + 1;
418 fprintf (stderr,
"Register component %d in class %s\n",
419 component_id, component_class ? component_class :
"(null)");
427 gnc_register_gui_component (
const char *component_class,
428 GNCComponentRefreshHandler refresh_handler,
429 GNCComponentCloseHandler close_handler,
435 if (!component_class)
437 PERR (
"no class specified");
441 ci = gnc_register_gui_component_internal (component_class);
442 g_return_val_if_fail (ci, NO_COMPONENT);
444 ci->refresh_handler = refresh_handler;
445 ci->close_handler = close_handler;
446 ci->user_data = user_data;
448 return ci->component_id;
452 gnc_gui_component_watch_entity (gint component_id,
461 ci = find_component (component_id);
464 PERR (
"component not found");
468 add_event (&ci->watch_info, entity, event_mask, FALSE);
472 gnc_gui_component_watch_entity_type (gint component_id,
478 ci = find_component (component_id);
481 PERR (
"component not found");
485 add_event_type (&ci->watch_info, entity_type, event_mask, FALSE);
489 gnc_gui_get_entity_events (GHashTable *changes,
const GncGUID *entity)
491 if (!changes || !entity)
494 return g_hash_table_lookup (changes, entity);
498 gnc_gui_component_clear_watches (gint component_id)
502 ci = find_component (component_id);
505 PERR (
"component not found");
509 clear_event_info (&ci->watch_info);
513 gnc_unregister_gui_component (gint component_id)
517 ci = find_component (component_id);
520 PERR (
"component %d not found", component_id);
525 fprintf (stderr,
"Unregister component %d in class %s\n",
527 ci->component_class ? ci->component_class :
"(null)");
530 gnc_gui_component_clear_watches (component_id);
532 components = g_list_remove (components, ci);
534 destroy_mask_hash (ci->watch_info.event_masks);
535 ci->watch_info.event_masks = NULL;
537 destroy_event_hash (ci->watch_info.entity_events);
538 ci->watch_info.entity_events = NULL;
540 g_free (ci->component_class);
541 ci->component_class = NULL;
551 gnc_unregister_gui_component_by_data (
const char *component_class,
557 list = find_components_by_data (user_data);
559 for (node = list; node; node = node->next)
563 if (component_class &&
564 g_strcmp0 (component_class, ci->component_class) != 0)
567 gnc_unregister_gui_component (ci->component_id);
574 gnc_suspend_gui_refresh (
void)
578 if (suspend_counter == 0)
580 PERR (
"suspend counter overflow");
585 gnc_resume_gui_refresh (
void)
587 if (suspend_counter == 0)
589 PERR (
"suspend counter underflow");
595 if (suspend_counter == 0)
596 gnc_gui_refresh_internal (FALSE);
600 match_type_helper (gpointer key, gpointer value, gpointer user_data)
607 et_2 = g_hash_table_lookup (cei->event_masks, id_type);
616 match_helper (gpointer key, gpointer value, gpointer user_data)
623 ei_2 = g_hash_table_lookup (cei->entity_events, guid);
627 if (ei_1->event_mask & ei_2->event_mask)
635 GHashTable *smalltable;
642 g_hash_table_foreach (changes->event_masks, match_type_helper, cei);
646 if (g_hash_table_size (cei->entity_events) <=
647 g_hash_table_size (changes->entity_events))
649 smalltable = cei->entity_events;
654 smalltable = changes->entity_events;
658 big_cei->match = FALSE;
660 g_hash_table_foreach (smalltable, match_helper, big_cei);
662 return big_cei->match;
666 gnc_gui_refresh_internal (gboolean force)
671 if (!got_events && !force)
674 gnc_suspend_gui_refresh ();
679 table = changes_backup.event_masks;
680 changes_backup.event_masks = changes.event_masks;
681 changes.event_masks =
table;
683 table = changes_backup.entity_events;
684 changes_backup.entity_events = changes.entity_events;
685 changes.entity_events =
table;
689 fprintf (stderr,
"%srefresh!\n", force ?
"forced " :
"");
692 list = find_component_ids_by_class (NULL);
694 list = g_list_reverse (list);
696 for (node = list; node; node = node->next)
698 ComponentInfo *ci = find_component (GPOINTER_TO_INT (node->data));
703 if (!ci->refresh_handler)
706 fprintf (stderr,
"no handlers for %s:%d\n", ci->component_class, ci->component_id);
713 if (ci->refresh_handler)
716 fprintf (stderr,
"calling %s:%d C handler\n", ci->component_class, ci->component_id);
718 ci->refresh_handler (NULL, ci->user_data);
721 else if (changes_match (&ci->watch_info, &changes_backup))
723 if (ci->refresh_handler)
726 fprintf (stderr,
"calling %s:%d C handler\n", ci->component_class, ci->component_id);
728 ci->refresh_handler (changes_backup.entity_events, ci->user_data);
734 fprintf (stderr,
"no match for %s:%d\n", ci->component_class, ci->component_id);
739 clear_event_info (&changes_backup);
744 gnc_resume_gui_refresh ();
748 gnc_gui_refresh_all (
void)
750 if (suspend_counter != 0)
752 PERR (
"suspend counter not zero");
756 gnc_gui_refresh_internal (TRUE);
760 gnc_gui_refresh_suspended (
void)
762 return suspend_counter != 0;
766 gnc_close_gui_component (gint component_id)
770 ci = find_component (component_id);
773 PERR (
"component not found");
777 if (!ci->close_handler)
780 if (ci->close_handler)
781 ci->close_handler (ci->user_data);
785 gnc_close_gui_component_by_data (
const char *component_class,
791 list = find_components_by_data (user_data);
793 for (node = list; node; node = node->next)
797 if (component_class &&
798 g_strcmp0 (component_class, ci->component_class) != 0)
801 gnc_close_gui_component (ci->component_id);
808 gnc_gui_component_set_session (gint component_id, gpointer session)
812 ci = find_component (component_id);
815 PERR (
"component not found");
819 ci->session = session;
823 gnc_close_gui_component_by_session (gpointer session)
828 list = find_components_by_session (session);
831 list = g_list_reverse (list);
833 for (node = list; node; node = node->next)
837 gnc_close_gui_component (ci->component_id);
844 gnc_find_gui_components (
const char *component_class,
845 GNCComponentFindHandler find_handler,
851 if (!component_class)
854 for (node = components; node; node = node->next)
858 if (g_strcmp0 (component_class, ci->component_class) != 0)
861 if (find_handler && !find_handler (
find_data, ci->user_data))
864 list = g_list_prepend (list, ci->user_data);
871 gnc_find_first_gui_component (
const char *component_class,
872 GNCComponentFindHandler find_handler,
879 fprintf (stderr,
"find: class %s, fn %p, data %p\n", component_class,
882 if (!component_class)
885 list = gnc_find_gui_components (component_class, find_handler,
find_data);
889 user_data = list->data;
894 fprintf (stderr,
"found: data %p\n", user_data);
900 find_component_ids_by_class (
const char *component_class)
905 for (node = components; node; node = node->next)
909 if (component_class &&
910 g_strcmp0 (component_class, ci->component_class) != 0)
913 list = g_list_prepend (list, GINT_TO_POINTER (ci->component_id));
920 gnc_forall_gui_components (
const char *component_class,
921 GNCComponentHandler handler,
932 list = find_component_ids_by_class (component_class);
934 for (node = list; node; node = node->next)
936 ComponentInfo *ci = find_component (GPOINTER_TO_INT (node->data));
941 if (handler (ci->component_class, ci->component_id, ci->user_data, iter_data))
utility functions for the GnuCash UI
const gchar * QofIdTypeConst
QofIdTypeConst declaration.
GHashTable * guid_hash_table_new(void)
Returns a GHashTable with <GUID*> as key and a <gpointer> as value and no destructor functions for ke...
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
#define PERR(format, args...)
Log a serious error.
const char * qof_string_cache_insert(const char *key)
You can use this function with g_hash_table_insert(), for the key (or value), as long as you use the ...
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
const gchar * QofIdType
QofIdType declaration.
#define QOF_CHECK_TYPE(obj, type)
return TRUE if object is of the given type
gint QofEventId
Define the type of events allowed.
GncGUID * guid_malloc(void)
Allocate memory for a GUID.
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
void qof_event_unregister_handler(gint handler_id)
Unregister an event handler.
const GncGUID * qof_entity_get_guid(gconstpointer ent)
#define QOF_EVENT_NONE
Default events for backwards compatibility.
The type used to store guids in C.
void qof_string_cache_remove(const char *key)
You can use this function as a destroy notifier for a GHashTable that uses common strings as keys (or...