* add combo box with store protocols
[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         priv =  MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
309         
310         return modest_account_view_new (priv->account_mgr);
311 }
312
313
314
315 GtkWidget*
316 modest_widget_factory_get_progress_bar (ModestWidgetFactory *self)
317 {
318         g_return_val_if_fail (self, NULL);
319         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->progress_bar;
320 }
321
322
323 GtkWidget*
324 modest_widget_factory_get_status_bar (ModestWidgetFactory *self)
325 {
326         g_return_val_if_fail (self, NULL);
327         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->status_bar;
328 }
329
330
331 GtkWidget*
332 modest_widget_factory_get_store_combo (ModestWidgetFactory *self)
333 {
334         GtkWidget *combo;
335         GtkListStore *store;
336         GtkTreeIter iter;
337         const gchar **protos, **cursor; 
338
339         g_return_val_if_fail (self, NULL);
340
341         combo = gtk_combo_box_new_text ();              
342         cursor = protos = modest_proto_store_protos ();
343         while (cursor && *cursor) {
344                 gtk_combo_box_append_text (GTK_COMBO_BOX(combo),
345                                            (const gchar*)*cursor);
346                 ++cursor;
347         }
348
349         gtk_combo_box_set_active (GTK_COMBO(combo), 0);
350         
351         return combo;
352 }
353
354
355
356 static void
357 on_folder_selected (ModestFolderView *folder_view, TnyMsgFolderIface *folder,
358                     ModestWidgetFactory *self)
359 {
360         ModestWidgetFactoryPrivate *priv;
361         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
362         
363         modest_header_view_set_folder (priv->header_view, folder);
364 }
365
366
367 static void
368 on_message_selected (ModestHeaderView *folder_view, TnyMsgIface *msg,
369                      ModestWidgetFactory *self)
370 {       
371         ModestWidgetFactoryPrivate *priv;
372         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
373         
374         modest_msg_view_set_message (priv->msg_preview, msg);
375 }
376
377
378 static void
379 on_header_status_update (ModestHeaderView *header_view, const gchar *msg,
380                          gint status_id, ModestWidgetFactory *self)
381 {
382         ModestWidgetFactoryPrivate *priv;
383         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
384         
385         if (msg && status_id) {
386                 gchar *msg = g_strdup_printf ("%s", msg);
387                 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(priv->progress_bar));
388                 gtk_statusbar_push (GTK_STATUSBAR(priv->status_bar),
389                                        priv->status_bar_ctx[STATUS_ID_HEADER],
390                                        msg);
391                 g_free (msg);
392         } else {
393                 gtk_statusbar_pop (GTK_STATUSBAR(priv->status_bar),
394                                    priv->status_bar_ctx[STATUS_ID_HEADER]);
395                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(priv->progress_bar),
396                                                1.0);
397         }
398 }
399
400
401 static void
402 on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
403                    ModestWidgetFactory *self)
404 {
405         ModestWidgetFactoryPrivate *priv;
406         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
407
408         if (link)
409                 gtk_statusbar_push (GTK_STATUSBAR(priv->status_bar),
410                                     priv->status_bar_ctx[STATUS_ID_MESSAGE],
411                                     link);
412         else
413                 gtk_statusbar_pop (GTK_STATUSBAR(priv->status_bar),
414                                    priv->status_bar_ctx[STATUS_ID_MESSAGE]);
415
416 }       
417
418
419 static void
420 on_msg_link_clicked  (ModestMsgView *msgview, const gchar* link,
421                       ModestWidgetFactory *self)
422 {
423         ModestWidgetFactoryPrivate *priv;
424         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
425
426         if (link) {
427                 gchar *msg = g_strdup_printf (_("Opening %s..."), link);
428                 gtk_statusbar_push (GTK_STATUSBAR(priv->status_bar),
429                                     priv->status_bar_ctx[STATUS_ID_MESSAGE],
430                                     msg);
431                 g_free (msg);
432         }       
433 }
434
435 static void
436 on_msg_attachment_clicked  (ModestMsgView *msgview, int index,
437                             ModestWidgetFactory *self)
438 {
439         ModestWidgetFactoryPrivate *priv;
440         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
441         
442         gchar *msg = g_strdup_printf (_("Opening attachment %d..."), index);
443         gtk_statusbar_push (GTK_STATUSBAR(priv->status_bar),
444                             priv->status_bar_ctx[STATUS_ID_MESSAGE],
445                             msg);
446         g_free (msg);
447 }