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