5ba17bcb412b09d22bd1afe11c3ba7f693baec1d
[modest] / src / widgets / modest-window-mgr.c
1 /* Copyright (c) 2006,2007 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 <string.h>
31 #include "modest-window-mgr.h"
32 #include "modest-runtime.h"
33 #include "widgets/modest-main-window.h"
34 #include "widgets/modest-msg-edit-window.h"
35 #include "widgets/modest-msg-view-window.h"
36 /* include other impl specific header files */
37
38 /* 'private'/'protected' functions */
39 static void modest_window_mgr_class_init (ModestWindowMgrClass *klass);
40 static void modest_window_mgr_init       (ModestWindowMgr *obj);
41 static void modest_window_mgr_finalize   (GObject *obj);
42
43 static void on_window_destroy            (ModestWindow *window, 
44                                           ModestWindowMgr *self);
45
46 /* list my signals  */
47 enum {
48         /* MY_SIGNAL_1, */
49         /* MY_SIGNAL_2, */
50         LAST_SIGNAL
51 };
52
53 typedef struct _ModestWindowMgrPrivate ModestWindowMgrPrivate;
54 struct _ModestWindowMgrPrivate {
55         GList *window_list;
56         gboolean fullscreen_mode;
57         gboolean show_toolbars;
58         gboolean show_toolbars_fullscreen;
59 };
60 #define MODEST_WINDOW_MGR_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
61                                                MODEST_TYPE_WINDOW_MGR, \
62                                                ModestWindowMgrPrivate))
63 /* globals */
64 static GObjectClass *parent_class = NULL;
65
66 /* uncomment the following if you have defined any signals */
67 /* static guint signals[LAST_SIGNAL] = {0}; */
68
69 GType
70 modest_window_mgr_get_type (void)
71 {
72         static GType my_type = 0;
73         if (!my_type) {
74                 static const GTypeInfo my_info = {
75                         sizeof(ModestWindowMgrClass),
76                         NULL,           /* base init */
77                         NULL,           /* base finalize */
78                         (GClassInitFunc) modest_window_mgr_class_init,
79                         NULL,           /* class finalize */
80                         NULL,           /* class data */
81                         sizeof(ModestWindowMgr),
82                         1,              /* n_preallocs */
83                         (GInstanceInitFunc) modest_window_mgr_init,
84                         NULL
85                 };
86                 my_type = g_type_register_static (G_TYPE_OBJECT,
87                                                   "ModestWindowMgr",
88                                                   &my_info, 0);
89         }
90         return my_type;
91 }
92
93 static void
94 modest_window_mgr_class_init (ModestWindowMgrClass *klass)
95 {
96         GObjectClass *gobject_class;
97         gobject_class = (GObjectClass*) klass;
98
99         parent_class            = g_type_class_peek_parent (klass);
100         gobject_class->finalize = modest_window_mgr_finalize;
101
102         g_type_class_add_private (gobject_class, sizeof(ModestWindowMgrPrivate));
103 }
104
105 static void
106 modest_window_mgr_init (ModestWindowMgr *obj)
107 {
108         ModestWindowMgrPrivate *priv;
109
110         priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
111         priv->window_list = NULL;
112         priv->fullscreen_mode = FALSE;
113
114         /* Could not initialize it from gconf, singletons are not
115            ready yet */
116         priv->show_toolbars = FALSE;
117         priv->show_toolbars_fullscreen = FALSE;
118 }
119
120 static void
121 modest_window_mgr_finalize (GObject *obj)
122 {
123         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
124
125         if (priv->window_list) {
126                 GList *iter = priv->window_list;
127                 /* unregister pending windows */
128                 while (iter) {
129                         modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), 
130                                                              MODEST_WINDOW (iter->data));
131                         iter = g_list_next (iter);
132                 }
133                 g_list_free (priv->window_list);
134                 priv->window_list = NULL;
135         }
136
137         G_OBJECT_CLASS(parent_class)->finalize (obj);
138 }
139
140 ModestWindowMgr*
141 modest_window_mgr_new (void)
142 {
143         return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_WINDOW_MGR, NULL));
144 }
145
146 void 
147 modest_window_mgr_register_window (ModestWindowMgr *self, 
148                                    ModestWindow *window)
149 {
150         static gboolean first_time = TRUE;
151         GList *win;
152         gboolean show;
153         ModestWindowMgrPrivate *priv;
154
155         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
156         g_return_if_fail (MODEST_IS_WINDOW (window));
157
158         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
159
160         win = g_list_find (priv->window_list, window);
161         if (win) {
162                 g_warning ("Trying to register an already registered window");
163                 return;
164         }
165
166         /* Add to list. Keep a reference to the window */
167         g_object_ref (window);
168         priv->window_list = g_list_prepend (priv->window_list, window);
169
170         /* Listen to object destruction */
171         g_signal_connect (window, "destroy", G_CALLBACK (on_window_destroy), self);
172
173         /* Put into fullscreen if needed */
174         if (priv->fullscreen_mode)
175                 gtk_window_fullscreen (GTK_WINDOW (window));
176
177         /* Fill caches */
178         if (first_time) {
179                 ModestConf *conf = modest_runtime_get_conf ();
180                 priv->show_toolbars = 
181                         modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL);
182                 priv->show_toolbars_fullscreen = 
183                         modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL);
184                 first_time = FALSE;
185         }
186
187         /* Show/hide toolbar */
188         if (priv->fullscreen_mode)
189                 show = priv->show_toolbars_fullscreen;
190         else
191                 show = priv->show_toolbars;
192         modest_window_show_toolbar (window, show);
193 }
194
195 static void
196 on_window_destroy (ModestWindow *window, ModestWindowMgr *self)
197 {
198         /* Specific stuff first */
199         if (MODEST_IS_MAIN_WINDOW (window)) {
200                 ModestWindowMgrPrivate *priv;
201                 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
202
203                 /* If more than one window already opened */
204                 if (g_list_length (priv->window_list) > 1) {
205
206                         /* If the user wants to close all the windows */
207                         if (modest_main_window_close_all (MODEST_MAIN_WINDOW (window))) {
208                                 GList *iter = priv->window_list;
209                                 do {
210                                         if (iter->data != window) {
211                                                 GList *tmp = iter->next;
212                                                 on_window_destroy (MODEST_WINDOW (iter->data),
213                                                                    self);
214                                                 iter = tmp;
215                                         } else {
216                                                 iter = g_list_next (iter);
217                                         }
218                                 } while (iter);
219                         }
220                 }
221         } else {
222                 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
223                         /* TODO: Save currently edited message to Drafts
224                            folder */
225                 }
226         }
227
228         /* Unregister window */
229         modest_window_mgr_unregister_window (self, window);
230 }
231
232 void 
233 modest_window_mgr_unregister_window (ModestWindowMgr *self, 
234                                      ModestWindow *window)
235 {
236         GList *win;
237         ModestWindowMgrPrivate *priv;
238
239         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
240         g_return_if_fail (MODEST_IS_WINDOW (window));
241
242         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
243
244         win = g_list_find (priv->window_list, window);
245         if (!win) {
246                 g_warning ("Trying to unregister a window that has not being registered yet");
247                 return;
248         }
249
250         /* Remove from list. Remove the reference to the window */
251         g_object_unref (win->data);
252         priv->window_list = g_list_remove_link (priv->window_list, win);
253
254         /* If there are no more windows registered then exit program */
255         if (priv->window_list == NULL) {
256                 ModestConf *conf = modest_runtime_get_conf ();
257
258                 /* Save show toolbar status */
259                 modest_conf_set_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, 
260                                       priv->show_toolbars_fullscreen, NULL);
261                 modest_conf_set_bool (conf, MODEST_CONF_SHOW_TOOLBAR, 
262                                       priv->show_toolbars, NULL);
263
264                 /* Quit main loop */
265                 gtk_main_quit ();
266         }
267 }
268
269 static gint
270 compare_msguids (ModestWindow *win,
271                  const gchar *uid)
272 {
273         const gchar *msg_uid;
274
275         if (!MODEST_IS_MSG_VIEW_WINDOW (win))
276                 return 1;
277
278         /* Get message uid from msg window */
279         msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
280         if (msg_uid && !strcmp (msg_uid, uid))
281                 return 0;
282         else
283                 return 1;
284 }
285
286 ModestWindow*  
287 modest_window_mgr_find_window_by_msguid (ModestWindowMgr *self, 
288                                          const gchar *msguid)
289 {
290         ModestWindowMgrPrivate *priv;
291         GList *win = NULL;
292
293         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL);
294         g_return_val_if_fail (msguid != NULL, NULL);
295
296         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
297
298         /* Look for the window */
299         if (priv->window_list)
300                 win = g_list_find_custom (priv->window_list, 
301                                           msguid, 
302                                           (GCompareFunc) compare_msguids);
303
304         if (win)
305                 return win->data;
306         else 
307                 return NULL;
308 }
309
310 void
311 modest_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
312                                        gboolean on)
313 {
314         ModestWindowMgrPrivate *priv;
315         GList *win = NULL;
316
317         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
318
319         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
320
321         /* If there is no change do nothing */
322         if (priv->fullscreen_mode == on)
323                 return;
324
325         priv->fullscreen_mode = on;
326
327         /* Update windows */
328         win = priv->window_list;
329         while (win) {
330                 if (on) {
331                         gtk_window_fullscreen (GTK_WINDOW (win->data));
332                         modest_window_show_toolbar (MODEST_WINDOW (win->data), 
333                                                     priv->show_toolbars_fullscreen);
334                 } else {
335                         gtk_window_unfullscreen (GTK_WINDOW (win->data));
336                         modest_window_show_toolbar (MODEST_WINDOW (win->data), 
337                                                     priv->show_toolbars);
338                 }
339                 win = g_list_next (win);
340         }
341 }
342
343 gboolean
344 modest_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
345 {
346         ModestWindowMgrPrivate *priv;
347
348         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
349
350         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
351
352         return priv->fullscreen_mode;
353 }
354
355 void 
356 modest_window_mgr_show_toolbars (ModestWindowMgr *self,
357                                  gboolean show_toolbars,
358                                  gboolean fullscreen)
359 {
360         ModestWindowMgrPrivate *priv;
361
362         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
363
364         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
365
366         /* If nothing changes then return. Otherwise cache it, do not
367            save to GConf for the moment, it will be done when all
368            windows become unregistered in order to avoid unnecessary
369            ModestConf calls */
370         if (fullscreen) {
371                 if (priv->show_toolbars_fullscreen == show_toolbars)
372                         return;
373                 else
374                         priv->show_toolbars_fullscreen = show_toolbars;
375         } else {
376                 if (priv->show_toolbars == show_toolbars)
377                         return;
378                 else
379                         priv->show_toolbars = show_toolbars;
380         }
381
382         /* Apply now if the view mode is the right one */
383         if ((fullscreen && priv->fullscreen_mode) ||
384             (!fullscreen && !priv->fullscreen_mode)) {
385
386                 GList *win = priv->window_list;
387
388                 while (win) {
389                         modest_window_show_toolbar (MODEST_WINDOW (win->data),
390                                                     show_toolbars);
391                         win = g_list_next (win);
392                 }
393         }
394 }