* implement status bar messages
[modest] / src / modest-widget-factory.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-widget-factory.h"
31 /* include other impl specific header files */
32
33 /* 'private'/'protected' functions */
34 static void modest_widget_factory_class_init    (ModestWidgetFactoryClass *klass);
35 static void modest_widget_factory_init          (ModestWidgetFactory *obj);
36 static void modest_widget_factory_finalize      (GObject *obj);
37
38
39 /* callbacks */
40 static void on_folder_selected         (ModestFolderView *folder_view,
41                                         TnyMsgFolderIface *folder,
42                                         ModestWidgetFactory *self);
43 static void on_message_selected        (ModestHeaderView *header_view, TnyMsgIface *msg,
44                                         ModestWidgetFactory *self);
45 static void on_header_status_update    (ModestHeaderView *header_view, const gchar *msg,
46                                         gint status_id, ModestWidgetFactory *self);
47 static void on_msg_link_hover          (ModestMsgView *msgview, const gchar* link,
48                                         ModestWidgetFactory *self);
49 static void on_msg_link_clicked        (ModestMsgView *msgview, const gchar* link,
50                                         ModestWidgetFactory *self);
51 static void on_msg_attachment_clicked  (ModestMsgView *msgview, int index,
52                                         ModestWidgetFactory *self);
53
54 /* list my signals */
55 enum {
56         /* MY_SIGNAL_1, */
57         /* MY_SIGNAL_2, */
58         LAST_SIGNAL
59 };
60
61
62 enum _StatusID {
63         STATUS_ID_HEADER,
64         STATUS_ID_FOLDER,
65         STATUS_ID_MESSAGE,
66
67         STATUS_ID_NUM
68 };
69 typedef enum _StatusID StatusID;
70
71 typedef struct _ModestWidgetFactoryPrivate ModestWidgetFactoryPrivate;
72 struct _ModestWidgetFactoryPrivate {
73         
74         ModestTnyAccountStore *account_store;
75         ModestAccountMgr      *account_mgr;
76         ModestConf            *conf;
77         
78         ModestHeaderView      *header_view;
79         ModestFolderView      *folder_view;
80         ModestMsgView         *msg_preview;
81
82         GtkWidget             *progress_bar;
83         GtkWidget             *status_bar;
84         
85         gboolean              auto_connect;
86
87         StatusID              status_bar_ctx[STATUS_ID_NUM];
88         
89 };
90 #define MODEST_WIDGET_FACTORY_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
91                                                    MODEST_TYPE_WIDGET_FACTORY, \
92                                                    ModestWidgetFactoryPrivate))
93 /* globals */
94 static GObjectClass *parent_class = NULL;
95
96 /* uncomment the following if you have defined any signals */
97 /* static guint signals[LAST_SIGNAL] = {0}; */
98
99 GType
100 modest_widget_factory_get_type (void)
101 {
102         static GType my_type = 0;
103         if (!my_type) {
104                 static const GTypeInfo my_info = {
105                         sizeof(ModestWidgetFactoryClass),
106                         NULL,           /* base init */
107                         NULL,           /* base finalize */
108                         (GClassInitFunc) modest_widget_factory_class_init,
109                         NULL,           /* class finalize */
110                         NULL,           /* class data */
111                         sizeof(ModestWidgetFactory),
112                         1,              /* n_preallocs */
113                         (GInstanceInitFunc) modest_widget_factory_init,
114                 };
115                 my_type = g_type_register_static (G_TYPE_OBJECT,
116                                                   "ModestWidgetFactory",
117                                                   &my_info, 0);
118         }
119         return my_type;
120 }
121
122 static void
123 modest_widget_factory_class_init (ModestWidgetFactoryClass *klass)
124 {
125         GObjectClass *gobject_class;
126         gobject_class = (GObjectClass*) klass;
127
128         parent_class            = g_type_class_peek_parent (klass);
129         gobject_class->finalize = modest_widget_factory_finalize;
130
131         g_type_class_add_private (gobject_class, sizeof(ModestWidgetFactoryPrivate));
132
133         /* signal definitions go here, e.g.: */
134 /*      signals[MY_SIGNAL_1] = */
135 /*              g_signal_new ("my_signal_1",....); */
136 /*      signals[MY_SIGNAL_2] = */
137 /*              g_signal_new ("my_signal_2",....); */
138 /*      etc. */
139 }
140
141 static void
142 modest_widget_factory_init (ModestWidgetFactory *obj)
143 {
144         ModestWidgetFactoryPrivate *priv;
145         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(obj);
146
147         priv->conf          = NULL;
148         priv->account_mgr   = NULL;
149         priv->account_store = NULL;
150         
151         priv->progress_bar = gtk_progress_bar_new ();
152         gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(priv->progress_bar),
153                                        1.0);
154         priv->status_bar   = gtk_statusbar_new ();
155         gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR(priv->status_bar),
156                                            FALSE);
157         
158         priv->status_bar_ctx[STATUS_ID_HEADER] =
159                 gtk_statusbar_get_context_id (GTK_STATUSBAR(priv->status_bar),
160                                               "header");
161         priv->status_bar_ctx[STATUS_ID_MESSAGE] =
162                 gtk_statusbar_get_context_id (GTK_STATUSBAR(priv->status_bar),
163                                               "message");       
164         priv->status_bar_ctx[STATUS_ID_FOLDER] =
165                 gtk_statusbar_get_context_id (GTK_STATUSBAR(priv->status_bar),
166                                               "folder");
167 }
168
169 static void
170 modest_widget_factory_finalize (GObject *obj)
171 {
172         ModestWidgetFactoryPrivate *priv;
173         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(obj);
174
175         if (priv->account_mgr) {
176                 g_object_unref (G_OBJECT(priv->account_mgr));
177                 priv->account_mgr = NULL;
178         }
179
180         if (priv->conf) {
181                 g_object_unref (G_OBJECT(priv->conf));
182                 priv->conf = NULL;
183         }
184
185         if (priv->account_store) {
186                 g_object_unref (G_OBJECT(priv->account_store));
187                 priv->account_store = NULL;
188         }
189 }
190
191
192 static gboolean
193 init_widgets (ModestWidgetFactory *self)
194 {
195         ModestWidgetFactoryPrivate *priv;
196         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
197
198         /* folder view */
199         if (!(priv->folder_view =
200               MODEST_FOLDER_VIEW(modest_folder_view_new
201                                  (TNY_ACCOUNT_STORE_IFACE(priv->account_store))))) {
202                 g_printerr ("modest: cannot instantiate folder view\n");
203                 return FALSE;
204         }
205
206         /* header view */
207         if (!(priv->header_view =
208               MODEST_HEADER_VIEW(modest_header_view_new
209                                  (NULL, NULL,MODEST_HEADER_VIEW_STYLE_NORMAL)))) {
210                 g_printerr ("modest: cannot instantiate header view\n");
211                 return FALSE;
212         }
213
214         /* msg preview */
215         if (!(priv->msg_preview = MODEST_MSG_VIEW(modest_msg_view_new (NULL)))) {
216                 g_printerr ("modest: cannot instantiate header view\n");
217                 return FALSE;
218         }
219
220         if (priv->auto_connect) {
221                 g_signal_connect (G_OBJECT(priv->header_view), "message_selected",
222                                   G_CALLBACK(on_message_selected), self);
223                 g_signal_connect (G_OBJECT(priv->folder_view), "folder_selected",
224                                   G_CALLBACK(on_folder_selected), self);
225                 g_signal_connect (G_OBJECT(priv->header_view), "status_update",
226                                   G_CALLBACK(on_header_status_update), self);
227                 g_signal_connect (G_OBJECT(priv->msg_preview), "link_clicked",
228                                   G_CALLBACK(on_msg_link_clicked), self);
229                 g_signal_connect (G_OBJECT(priv->msg_preview), "link_hover",
230                                   G_CALLBACK(on_msg_link_hover), self);
231                 g_signal_connect (G_OBJECT(priv->msg_preview), "attachment_clicked",
232                                   G_CALLBACK(on_msg_attachment_clicked), self);
233         }
234
235         return TRUE;
236 }
237
238
239 ModestWidgetFactory*
240 modest_widget_factory_new (ModestConf *conf,
241                            ModestTnyAccountStore *account_store,
242                            ModestAccountMgr *account_mgr,
243                            gboolean auto_connect)
244 {
245         GObject *obj;
246         ModestWidgetFactoryPrivate *priv;
247
248         g_return_val_if_fail (account_store, NULL);
249         g_return_val_if_fail (account_mgr, NULL);
250         g_return_val_if_fail (conf, NULL);
251         
252         obj  = g_object_new(MODEST_TYPE_WIDGET_FACTORY, NULL);  
253         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(obj);
254
255         priv->auto_connect = auto_connect;
256
257         g_object_ref (G_OBJECT(conf));
258         priv->conf = conf;
259         
260         g_object_ref (G_OBJECT(account_mgr));
261         priv->account_mgr = account_mgr;
262
263         g_object_ref (G_OBJECT(account_store));
264         priv->account_store = account_store;
265
266         if (!init_widgets (MODEST_WIDGET_FACTORY(obj))) {
267                 g_printerr ("modest: widget factory failed to init widgets\n");
268                 g_object_unref (obj);
269                 return NULL;
270         }
271         
272         return MODEST_WIDGET_FACTORY(obj);
273 }
274
275
276
277
278 ModestFolderView*
279 modest_widget_factory_get_folder_view (ModestWidgetFactory *self)
280 {
281         g_return_val_if_fail (self, NULL);
282         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->folder_view;
283 }
284
285
286 ModestHeaderView*
287 modest_widget_factory_get_header_view (ModestWidgetFactory *self)
288 {
289         g_return_val_if_fail (self, NULL);
290         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->header_view;
291 }
292
293
294 ModestMsgView*
295 modest_widget_factory_get_msg_preview (ModestWidgetFactory *self)
296 {
297         g_return_val_if_fail (self, NULL);
298         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->msg_preview;
299 }
300
301
302 ModestAccountView*
303 modest_widget_factory_get_account_view (ModestWidgetFactory *self)
304 {
305         ModestWidgetFactoryPrivate *priv;
306         
307         g_return_val_if_fail (self, NULL);
308
309         return modest_account_view_new (priv->account_mgr);
310 }
311
312
313
314 GtkWidget*
315 modest_widget_factory_get_progress_bar (ModestWidgetFactory *self)
316 {
317         g_return_val_if_fail (self, NULL);
318         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->progress_bar;
319 }
320
321
322 GtkWidget*
323 modest_widget_factory_get_status_bar (ModestWidgetFactory *self)
324 {
325         g_return_val_if_fail (self, NULL);
326         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->status_bar;
327 }
328
329
330 static void
331 on_folder_selected (ModestFolderView *folder_view, TnyMsgFolderIface *folder,
332                     ModestWidgetFactory *self)
333 {
334         ModestWidgetFactoryPrivate *priv;
335         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
336         
337         modest_header_view_set_folder (priv->header_view, folder);
338 }
339
340
341 static void
342 on_message_selected (ModestHeaderView *folder_view, TnyMsgIface *msg,
343                      ModestWidgetFactory *self)
344 {       
345         ModestWidgetFactoryPrivate *priv;
346         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
347         
348         modest_msg_view_set_message (priv->msg_preview, msg);
349 }
350
351
352 static void
353 on_header_status_update (ModestHeaderView *header_view, const gchar *msg,
354                          gint status_id, ModestWidgetFactory *self)
355 {
356         ModestWidgetFactoryPrivate *priv;
357         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
358         
359         if (msg && status_id) {
360                 gchar *msg = g_strdup_printf ("%s", msg);
361                 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(priv->progress_bar));
362                 gtk_statusbar_push (GTK_STATUSBAR(priv->status_bar),
363                                        priv->status_bar_ctx[STATUS_ID_HEADER],
364                                        msg);
365                 g_free (msg);
366         } else {
367                 gtk_statusbar_pop (GTK_STATUSBAR(priv->status_bar),
368                                    priv->status_bar_ctx[STATUS_ID_HEADER]);
369                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(priv->progress_bar),
370                                                1.0);
371         }
372 }
373
374
375 static void
376 on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
377                    ModestWidgetFactory *self)
378 {
379         ModestWidgetFactoryPrivate *priv;
380         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
381
382         if (link)
383                 gtk_statusbar_push (GTK_STATUSBAR(priv->status_bar),
384                                     priv->status_bar_ctx[STATUS_ID_MESSAGE],
385                                     link);
386         else
387                 gtk_statusbar_pop (GTK_STATUSBAR(priv->status_bar),
388                                    priv->status_bar_ctx[STATUS_ID_MESSAGE]);
389
390 }       
391
392
393 static void
394 on_msg_link_clicked  (ModestMsgView *msgview, const gchar* link,
395                       ModestWidgetFactory *self)
396 {
397         ModestWidgetFactoryPrivate *priv;
398         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
399
400         if (link) {
401                 gchar *msg = g_strdup_printf (_("Opening %s..."), link);
402                 gtk_statusbar_push (GTK_STATUSBAR(priv->status_bar),
403                                     priv->status_bar_ctx[STATUS_ID_MESSAGE],
404                                     msg);
405                 g_free (msg);
406         }       
407 }
408
409 static void
410 on_msg_attachment_clicked  (ModestMsgView *msgview, int index,
411                             ModestWidgetFactory *self)
412 {
413         ModestWidgetFactoryPrivate *priv;
414         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
415         
416         gchar *msg = g_strdup_printf (_("Opening attachment %d..."), index);
417         gtk_statusbar_push (GTK_STATUSBAR(priv->status_bar),
418                             priv->status_bar_ctx[STATUS_ID_MESSAGE],
419                             msg);
420         g_free (msg);
421 }