Fixes leak 7/26
[modest] / src / modest-ui-dimming-manager.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "modest-debug.h"
31 #include "modest-ui-dimming-manager.h"
32 #include "modest-dimming-rules-group-priv.h"
33
34 static void modest_ui_dimming_manager_class_init (ModestUIDimmingManagerClass *klass);
35 static void modest_ui_dimming_manager_init       (ModestUIDimmingManager *obj);
36 static void modest_ui_dimming_manager_finalize   (GObject *obj);
37 static void modest_ui_dimming_manager_dispose    (GObject *obj);
38
39 static void _process_all_rules (gpointer key, gpointer value, gpointer user_data);
40
41
42 typedef struct _ModestUIDimmingManagerPrivate ModestUIDimmingManagerPrivate;
43 struct _ModestUIDimmingManagerPrivate {
44         GHashTable *groups_map;
45         GHashTable *delayed_calls;
46 };
47
48 #define MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
49                                                    MODEST_TYPE_UI_DIMMING_MANAGER, \
50                                                    ModestUIDimmingManagerPrivate))
51
52 /* globals */
53 static GObjectClass *parent_class = NULL;
54
55 GType
56 modest_ui_dimming_manager_get_type (void)
57 {
58         static GType my_type = 0;
59         if (!my_type) {
60                 static const GTypeInfo my_info = {
61                         sizeof(ModestUIDimmingManagerClass),
62                         NULL,           /* base init */
63                         NULL,           /* base finalize */
64                         (GClassInitFunc) modest_ui_dimming_manager_class_init,
65                         NULL,           /* class finalize */
66                         NULL,           /* class data */
67                         sizeof(ModestUIDimmingManager),
68                         1,              /* n_preallocs */
69                         (GInstanceInitFunc) modest_ui_dimming_manager_init,
70                         NULL
71                 };
72                 my_type = g_type_register_static (G_TYPE_OBJECT,
73                                                   "ModestUIDimmingManager",
74                                                   &my_info, 0);
75         }
76         return my_type;
77 }
78
79 static void
80 modest_ui_dimming_manager_class_init (ModestUIDimmingManagerClass *klass)
81 {
82         GObjectClass *gobject_class;
83         gobject_class = (GObjectClass*) klass;
84
85         parent_class            = g_type_class_peek_parent (klass);
86         gobject_class->finalize = modest_ui_dimming_manager_finalize;
87         gobject_class->dispose  = modest_ui_dimming_manager_dispose;
88
89         g_type_class_add_private (gobject_class, sizeof(ModestUIDimmingManagerPrivate));
90 }
91
92 static void
93 modest_ui_dimming_manager_init (ModestUIDimmingManager *obj)
94 {
95         ModestUIDimmingManagerPrivate *priv;
96
97         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(obj);
98
99         priv->groups_map = g_hash_table_new_full ((GHashFunc) g_str_hash,
100                                                   (GEqualFunc) g_str_equal,
101                                                   (GDestroyNotify) g_free,
102                                                   (GDestroyNotify) g_object_unref);
103         priv->delayed_calls = g_hash_table_new_full (g_str_hash,
104                                                      g_str_equal,
105                                                      g_free,
106                                                      NULL);
107 }
108
109 static void
110 remove_all_timeouts (gpointer key, 
111                      gpointer value, 
112                      gpointer user_data)
113 {
114         if (GPOINTER_TO_INT (value) > 0)
115                 g_source_remove (GPOINTER_TO_INT (value));
116 }
117
118 static void
119 modest_ui_dimming_manager_finalize (GObject *obj)
120 {
121         ModestUIDimmingManagerPrivate *priv;
122
123         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(obj);
124
125         if (priv->groups_map != NULL)
126                 g_hash_table_unref (priv->groups_map);
127
128         if (priv->delayed_calls != NULL) {
129                 /* Remove all pending calls */
130                 g_hash_table_foreach (priv->delayed_calls,
131                                       remove_all_timeouts,
132                                       NULL);
133
134                 g_hash_table_unref (priv->delayed_calls);
135         }
136
137         G_OBJECT_CLASS(parent_class)->finalize (obj);
138 }
139
140 static void
141 modest_ui_dimming_manager_dispose (GObject *obj)
142 {
143         ModestUIDimmingManagerPrivate *priv;
144
145         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(obj);
146
147         if (priv->delayed_calls != NULL && (g_hash_table_size (priv->delayed_calls) > 0)) {
148                 /* Remove all pending calls */
149                 g_hash_table_foreach (priv->delayed_calls,
150                                       remove_all_timeouts,
151                                       NULL);
152                 g_hash_table_remove_all (priv->delayed_calls);
153         }
154
155         G_OBJECT_CLASS(parent_class)->dispose (obj);
156 }
157
158
159 ModestUIDimmingManager*
160 modest_ui_dimming_manager_new()
161 {
162         ModestUIDimmingManager *obj;
163
164         obj = MODEST_UI_DIMMING_MANAGER(g_object_new(MODEST_TYPE_UI_DIMMING_MANAGER, NULL));
165
166
167         return obj;
168 }
169
170 void
171 modest_ui_dimming_manager_insert_rules_group (ModestUIDimmingManager *self,
172                                               ModestDimmingRulesGroup *group)
173 {
174         ModestUIDimmingManagerPrivate *priv;
175         gchar *group_name = NULL;
176         gboolean unique = FALSE;
177         
178         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(self);
179         
180         /* Get group name */
181         group_name = modest_dimming_rules_group_get_name (group);
182         
183         /* Check group name is unique */
184         unique = g_hash_table_lookup (priv->groups_map, group_name) == NULL;
185         if (!unique) {
186                 g_free(group_name);
187                 g_return_if_fail (unique);
188         }
189         
190         
191         /* Insert new dimming rules group */
192         g_hash_table_insert (priv->groups_map, group_name, g_object_ref(group));
193 }
194
195 void
196 modest_ui_dimming_manager_process_dimming_rules (ModestUIDimmingManager *self)
197 {
198         ModestUIDimmingManagerPrivate *priv;
199         
200         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(self);
201
202         /* Peforms a full dimming tules checking */
203         g_hash_table_foreach (priv->groups_map, _process_all_rules, NULL);
204 }
205
206 typedef struct
207 {
208         ModestDimmingRulesGroup *group;
209         ModestUIDimmingManager *manager;
210         gchar *name;
211         gboolean delete;
212 } DelayedDimmingRules;
213
214 static gboolean
215 process_dimming_rules_delayed (gpointer data)
216 {
217         DelayedDimmingRules *helper = (DelayedDimmingRules *) data;
218         gpointer timeout_handler;
219         ModestUIDimmingManagerPrivate *priv;
220
221         /* Let the destroyer remove it from the hash table */
222         helper->delete = TRUE;
223
224         /* We remove the timeout here because the execute action could
225            take too much time, and so this will be called again */
226         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(helper->manager);
227         timeout_handler = g_hash_table_lookup (priv->delayed_calls, helper->name);
228
229         if (GPOINTER_TO_INT (timeout_handler) > 0) {
230                 g_source_remove (GPOINTER_TO_INT (timeout_handler));
231         }
232
233         gdk_threads_enter ();
234         modest_dimming_rules_group_execute (helper->group);
235         gdk_threads_leave ();
236
237         return FALSE;
238 }
239
240 static void
241 process_dimming_rules_delayed_destroyer (gpointer data)
242 {
243         DelayedDimmingRules *helper = (DelayedDimmingRules *) data;
244         ModestUIDimmingManagerPrivate *priv;
245
246         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(helper->manager);
247
248         /* We can only destroy it if we had really executed it. If the
249            source is removed because the manager is finalized then we
250            cannot remove it because it removes the sources in a
251            foreach, that does not allow you to modify the hash table
252            in the mean time */
253         if (helper->delete)
254                 g_hash_table_remove (priv->delayed_calls, helper->name);
255
256         g_free (helper->name);
257         g_object_unref (helper->manager);
258         g_slice_free (DelayedDimmingRules, helper);
259 }
260
261 void
262 modest_ui_dimming_manager_process_dimming_rules_group (ModestUIDimmingManager *self,
263                                                        const gchar *group_name)
264 {
265         ModestDimmingRulesGroup *group = NULL;
266         ModestUIDimmingManagerPrivate *priv;
267         guint *handler, new_handler;
268         DelayedDimmingRules *helper;
269
270         g_return_if_fail (group_name != NULL);
271
272         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(self);
273
274         /* Search group by name */
275         group = MODEST_DIMMING_RULES_GROUP(g_hash_table_lookup (priv->groups_map, group_name));
276         g_return_if_fail (group != NULL);
277
278         /* If there was another pending dimming operation check then ignore this */
279         handler = g_hash_table_lookup (priv->delayed_calls, group_name);
280         if (!handler) {
281                 /* Create the helper and start the timeout */
282                 helper = g_slice_new (DelayedDimmingRules);
283                 helper->group = group;
284                 helper->manager = g_object_ref (self);
285                 helper->name = g_strdup (group_name);
286                 helper->delete = FALSE;
287                 new_handler = g_timeout_add_full (G_PRIORITY_DEFAULT, 100,
288                                                   process_dimming_rules_delayed,
289                                                   helper, process_dimming_rules_delayed_destroyer);
290                 g_hash_table_insert (priv->delayed_calls, 
291                                      g_strdup (group_name), 
292                                      GINT_TO_POINTER (new_handler));
293                 MODEST_DEBUG_BLOCK(g_print ("---------------------Adding %d\n", new_handler););
294         } else {
295                 MODEST_DEBUG_BLOCK(g_print ("---------------------Ignoring\n"););
296         }
297 }
298
299
300 static void
301 _process_all_rules (gpointer key, gpointer value, gpointer user_data)
302 {
303         g_return_if_fail (MODEST_IS_DIMMING_RULES_GROUP (value));
304
305         modest_dimming_rules_group_execute (MODEST_DIMMING_RULES_GROUP (value));
306 }
307