1 /********************************************************************\
2  * gnc-component-manager.h - GUI component manager interface        *
3  * Copyright (C) 2000 Dave Peticolas <dave@krondo.com>              *
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 #ifndef GNC_COMPONENT_MANAGER_H
21 #define GNC_COMPONENT_MANAGER_H
22 
23 #include <glib.h>
24 
25 #include "qof.h"
26 
27 
28 #define NO_COMPONENT (-1)
29 
30 typedef struct
31 {
32     QofEventId event_mask;
33 } EventInfo;
34 
35 
36 /* GNCComponentRefreshHandler
37  *   Handler invoked to inform the component that a refresh
38  *   may be needed.
39  *
40  * changes: if NULL, the component should perform a refresh.
41  *
42  *          if non-NULL, changes is a GncGUID hash that maps
43  *          GUIDs to EventInfo structs describing which
44  *          events have been received. Entities not in
45  *          the hash have not generated any events.
46  *          Entities which have been destroyed will be in
47  *          the hash, but may not exist anymore.
48  *
49  *          Note since refreshes may not occur with every change,
50  *          an entity may have all three change values.
51  *
52  *          The component should use 'changes' to determine whether
53  *          or not a refresh is needed. The hash table must not be
54  *          changed.
55  *
56  * Notes on refreshing: when the handler is invoked any engine
57  *                      entities used by the component may have
58  *                      already been deleted. 'Refreshing' the
59  *                      component may require closing the component.
60  *
61  * Notes on dealing with destroyed entities: As stated above, entities
62  * in the changes GHashTable may no longer exist.  So how can you
63  * determine if this has happened?  Well, it's a good idea to check
64  * for the QOF_EVENT_DESTROY bit in the EventInfo structure.  Of
65  * course, that means you need the hash key (GncGUID) for the destroyed
66  * entity.  How are you going to get the GncGUID from the entity if the
67  * entity has already been destroyed?  You're not.  So, you have to
68  * save a COPY of the key (GncGUID) away beforehand.
69  *
70  * user_data: user_data supplied when component was registered.
71  */
72 typedef void (*GNCComponentRefreshHandler) (GHashTable *changes,
73         gpointer user_data);
74 
75 /* GNCComponentCloseHandler
76  *   Handler invoked to close the component.
77  *
78  * user_data: user_data supplied when component was registered.
79  *
80  * Notes on closing: components are not automatically unregistered
81  *                   when the close handler is invoked. Components
82  *                   may not ignore the handler.
83  */
84 typedef void (*GNCComponentCloseHandler) (gpointer user_data);
85 
86 
87 /* GNCComponentFindHandler
88  *   Handler invoked when searching for a component.
89  *
90  * find_data: find_data supplied when search was started.
91  * user_data: user_data supplied when component was registered.
92  *
93  * Return: TRUE if the component matches the search criteria.
94  */
95 typedef gboolean (*GNCComponentFindHandler) (gpointer find_data,
96         gpointer user_data);
97 
98 /* GNCComponentHandler
99  *   Generic handler used in iterating over components.
100  *
101  * component_class: class of component
102  * component_id:    id of component
103  * iter_data:       user_data supplied by caller
104  *
105  * Return: TRUE if the callback did something
106  */
107 typedef gboolean (*GNCComponentHandler) (const char *component_class,
108         gint component_id,
109         gpointer user_data,
110         gpointer iter_data);
111 
112 /* gnc_component_manager_init
113  *   Initialize the component manager.
114  */
115 void gnc_component_manager_init (void);
116 
117 /* gnc_component_manager_shutdown
118  *   Shutdown the component manager.
119  */
120 void gnc_component_manager_shutdown (void);
121 
122 /* gnc_register_gui_component
123  *   Register a GUI component with the manager.
124  *
125  * component_class: a string defining a class of components
126  *                  certain component functions can be performed
127  *                  on all components in a class. For that reason,
128  *                  components in the same class should all use
129  *                  the same type for user_data.
130  *
131  * refresh_cb:      refresh handler, may be NULL
132  * close_cb:        close handler, may be NULL
133  * user_data:       user_data argument for handlers
134  *
135  *
136  * Notes:           After a refresh handler is registered, the
137  *                  component must use the API calls below to
138  *                  inform the component manager which engine
139  *                  entities are being 'watched', i.e., which
140  *                  engine entities may cause the component
141  *                  to need refreshing.
142  *
143  *                  When a component is first registered, it
144  *                  is not watching anything, and thus will
145  *                  not receive refresh events.
146  *
147  * Return:          id of component, or NO_COMPONENT, if error
148  */
149 gint gnc_register_gui_component (const char *component_class,
150                                  GNCComponentRefreshHandler refresh_handler,
151                                  GNCComponentCloseHandler close_handler,
152                                  gpointer user_data);
153 
154 /* gnc_gui_component_set_session
155  *   Set the associated session of this component
156  *
157  * component_id: id of component which is watching the entity
158  * session:      the session this component is associated with
159  */
160 void gnc_gui_component_set_session (gint component_id, gpointer session);
161 
162 /* gnc_gui_component_watch_entity
163  *   Add an entity to the list of those being watched by the component.
164  *   Only entities with refresh handlers should add watches.
165  *
166  * component_id: id of component which is watching the entity
167  * entity:       id of entity to watch
168  * event_mask:   mask which determines which kinds of events are watched
169  *               setting the mask to 0 turns off watching for the entity.
170  */
171 void gnc_gui_component_watch_entity (gint component_id,
172                                      const GncGUID *entity,
173                                      QofEventId event_mask);
174 
175 /* gnc_gui_component_watch_entity_type
176  *   Watch all entities of a particular type.
177  *
178  * component_id: id of component which is watching the entity type
179  * entity_type:  type of entity to watch, either GNC_ID_TRANS or
180  *               GNC_ID_ACCOUNT
181  * event_mask:   mask which determines which kinds of events are watched
182  *               setting the mask to 0 turns off watching for the entity type
183  */
184 void gnc_gui_component_watch_entity_type (gint component_id,
185         QofIdTypeConst entity_type,
186         QofEventId event_mask);
187 
188 /* gnc_gui_get_entity_events
189  *   Return the event info of the events which have been generated by
190  *   the given entity.
191  *
192  * changes: a hash of changes as in the refresh handler
193  * entity:  the GncGUID of the entity to get the event mask for
194  *
195  * Returns: the event info of the entity, or NULL
196  *          if it is not found.
197  */
198 const EventInfo * gnc_gui_get_entity_events (GHashTable *changes,
199         const GncGUID *entity);
200 
201 /* gnc_gui_component_clear_watches
202  *   Clear all watches for the component.
203  *
204  * component_id: id of component to clear watches for.
205  */
206 void gnc_gui_component_clear_watches (gint component_id);
207 
208 /* gnc_unregister_gui_component
209  *   Unregister a gui component from the manager.
210  *
211  * component_id: id of component to unregister
212  */
213 void gnc_unregister_gui_component (gint component_id);
214 
215 /* gnc_unregister_gui_component_by_data
216  *   Unregister a gui component using the user_data pointer.
217  *
218  * component_class: class component is in
219  * user_data:       user_data pointer of component to unregister
220  *                  all components with that user_data in the
221  *                  class are unregistered.
222  */
223 void gnc_unregister_gui_component_by_data (const char *component_class,
224         gpointer user_data);
225 
226 /* gnc_suspend_gui_refresh
227  *   Suspend refresh handlers by the component manager.
228  *   This routine may be called multiple times. Each call
229  *   increases the suspend counter (starts at zero).
230  */
231 void gnc_suspend_gui_refresh (void);
232 
233 /* gnc_resume_gui_refresh
234  *   Resume refresh handlers by the component manager.
235  *   Each call reduces the suspend counter by one. When
236  *   the counter reaches zero, all changes which have
237  *   occurred since the last refresh are collected and
238  *   passed to the components in refresh handlers.
239  */
240 void gnc_resume_gui_refresh (void);
241 
242 /* gnc_gui_refresh_all
243  *   Force all components to refresh.
244  *
245  *   This routine may only be invoked when the suspend counter
246  *   is zero. It should never be mixed with the suspend/resume
247  *   refresh routines.
248  */
249 void gnc_gui_refresh_all (void);
250 
251 /* gnc_gui_refresh_suspended
252  *   Return TRUE if gui refreshes are suspended.
253  */
254 gboolean gnc_gui_refresh_suspended (void);
255 
256 /* gnc_close_gui_component
257  *   Invoke the close handler for the indicated component.
258  *
259  * component_id: id of component to close
260  */
261 void gnc_close_gui_component (gint component_id);
262 
263 /* gnc_close_gui_component_by_data
264  *   Invoke the close handler for components in the given
265  *   class with the given user_data.
266  *
267  * component_class: class to close components in
268  * user_data:       user_data of component to close
269  *                  all components with that user_data
270  *                  are closed.
271  */
272 void gnc_close_gui_component_by_data (const char *component_class,
273                                       gpointer user_data);
274 
275 /* gnc_close_gui_component_by_session
276  *   Invoke the close handler for components with the given session
277  *
278  * session:         session to close
279  *                  all components with that session
280  *                  are closed.
281  */
282 void gnc_close_gui_component_by_session (gpointer session);
283 
284 /* gnc_find_gui_components
285  *   Search for components in the specified class.
286  *
287  * component_class:     the class to search for components in
288  *                      must be non-NULL
289  * find_cb:             the handler used to search for the component
290  *                      if NULL, all components in class are returned
291  * find_data:           find_data passed to find_cb
292  *
293  * Returns: GList of user_data of found components, or NULL if none found
294  *          The list should be freed with g_list_free().
295  *
296  * Notes on finding: components should not be registered or unregistered
297  *                   by the find callback.
298  */
299 GList * gnc_find_gui_components (const char *component_class,
300                                  GNCComponentFindHandler find_handler,
301                                  gpointer find_data);
302 
303 /* gnc_find_first_gui_component
304  *   Search for the first matching component in the specified class.
305  *
306  * component_class:     the class to search for components in
307  *                      must be non-NULL
308  * find_cb:             the handler used to search for the component
309  *                      must be non-null
310  * find_data:           find_data passed to find_cb
311  *
312  * Returns: user_data of first found component, or NULL if none found
313  *
314  * Notes on finding: components should not be registered or unregistered
315  *                   by the find callback.
316  */
317 gpointer gnc_find_first_gui_component (const char *component_class,
318                                        GNCComponentFindHandler find_handler,
319                                        gpointer find_data);
320 
321 /* gnc_forall_gui_components
322  *   Invoke 'handler' for components in the database.
323  *
324  * component_class: class to iterate over, if NULL then
325  *                  all classes are iterated over
326  * handler:         handler to invoke
327  * iter_data:       data passed to handler
328  *
329  * Notes on forall: components may be unregistered by the handler,
330  *                  but no components should be registered.
331  */
332 gint gnc_forall_gui_components (const char *component_class,
333                                 GNCComponentHandler handler,
334                                 gpointer iter_data);
335 
336 #endif
337