* modest-widget-memory.[ch]:
[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 <glib/gi18n.h>
31 #include <gdk/gdkkeysyms.h>
32 #include "modest-widget-factory.h"
33 #include <modest-protocol-mgr.h>
34 #include <tny-gtk-account-list-model.h>
35 #include <tny-gtk-folder-store-tree-model.h>
36 #include <tny-account-store.h>
37 #include <tny-device.h>
38 #include <tny-folder-store-query.h>
39
40 #include "modest-tny-platform-factory.h"
41 #include "modest-account-mgr.h"
42 #include "modest-mail-operation.h"
43
44
45 /* 'private'/'protected' functions */
46 static void modest_widget_factory_class_init    (ModestWidgetFactoryClass *klass);
47 static void modest_widget_factory_init          (ModestWidgetFactory *obj);
48 static void modest_widget_factory_finalize      (GObject *obj);
49
50
51 /* callbacks */
52 static void on_folder_selected         (ModestFolderView *folder_view,
53                                         TnyFolder *folder,
54                                         ModestWidgetFactory *self);
55 static void on_folder_key_press_event  (ModestFolderView *header_view, 
56                                         GdkEventKey *event, 
57                                         gpointer user_data);
58 static void on_message_selected        (ModestHeaderView *header_view, TnyMsg *msg,
59                                         ModestWidgetFactory *self);
60 static void on_header_status_update    (ModestHeaderView *header_view, const gchar *msg,
61                                         gint status_id, ModestWidgetFactory *self);
62 static void on_msg_link_hover          (ModestMsgView *msgview, const gchar* link,
63                                         ModestWidgetFactory *self);
64 static void on_msg_link_clicked        (ModestMsgView *msgview, const gchar* link,
65                                         ModestWidgetFactory *self);
66 static void on_msg_attachment_clicked  (ModestMsgView *msgview, int index,
67                                         ModestWidgetFactory *self);
68
69 static void on_connection_changed (TnyDevice *device, gboolean online,
70                                    ModestWidgetFactory *self);
71 static void on_online_toggle_toggled (GtkToggleButton *toggle, ModestWidgetFactory *factory);
72
73 static void on_password_requested (ModestTnyAccountStore *account_store, const gchar* account_name,
74                                    gchar **password, gboolean *cancel, ModestWidgetFactory *self);
75
76 static void on_item_not_found     (ModestHeaderView* header_view, ModestItemType type,
77                                    ModestWidgetFactory *self);
78
79
80 /* list my signals */
81 enum {
82         /* MY_SIGNAL_1, */
83         /* MY_SIGNAL_2, */
84         LAST_SIGNAL
85 };
86
87 typedef struct _ModestWidgetFactoryPrivate ModestWidgetFactoryPrivate;
88 struct _ModestWidgetFactoryPrivate {
89         
90         TnyPlatformFactory    *fact;
91         TnyAccountStore       *account_store;
92         ModestProtocolMgr     *proto_mgr;
93         
94         ModestHeaderView      *header_view;
95         ModestFolderView      *folder_view;
96         ModestMsgView         *msg_preview;
97         ModestToolbar         *main_toolbar, *edit_toolbar;
98
99         GtkWidget             *progress_bar;
100         GtkWidget             *status_bar;
101         GtkWidget             *folder_info_label;
102
103         GtkWidget             *online_toggle;
104 };
105 #define MODEST_WIDGET_FACTORY_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
106                                                    MODEST_TYPE_WIDGET_FACTORY, \
107                                                    ModestWidgetFactoryPrivate))
108 /* globals */
109 static GObjectClass *parent_class = NULL;
110
111 /* uncomment the following if you have defined any signals */
112 /* static guint signals[LAST_SIGNAL] = {0}; */
113
114 GType
115 modest_widget_factory_get_type (void)
116 {
117         static GType my_type = 0;
118         if (!my_type) {
119                 static const GTypeInfo my_info = {
120                         sizeof(ModestWidgetFactoryClass),
121                         NULL,           /* base init */
122                         NULL,           /* base finalize */
123                         (GClassInitFunc) modest_widget_factory_class_init,
124                         NULL,           /* class finalize */
125                         NULL,           /* class data */
126                         sizeof(ModestWidgetFactory),
127                         1,              /* n_preallocs */
128                         (GInstanceInitFunc) modest_widget_factory_init,
129                         NULL
130                 };
131                 my_type = g_type_register_static (G_TYPE_OBJECT,
132                                                   "ModestWidgetFactory",
133                                                   &my_info, 0);
134         }
135         return my_type;
136 }
137
138 static void
139 modest_widget_factory_class_init (ModestWidgetFactoryClass *klass)
140 {
141         GObjectClass *gobject_class;
142         gobject_class = (GObjectClass*) klass;
143
144         parent_class            = g_type_class_peek_parent (klass);
145         gobject_class->finalize = modest_widget_factory_finalize;
146
147         g_type_class_add_private (gobject_class, sizeof(ModestWidgetFactoryPrivate));
148 }
149
150 static void
151 modest_widget_factory_init (ModestWidgetFactory *obj)
152 {
153         ModestWidgetFactoryPrivate *priv;
154         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(obj);
155
156         priv->fact = modest_tny_platform_factory_get_instance ();
157         priv->account_store = tny_platform_factory_new_account_store (priv->fact);
158         priv->proto_mgr     = modest_protocol_mgr_new ();
159         
160         priv->progress_bar = gtk_progress_bar_new ();
161         gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(priv->progress_bar),
162                                        1.0);
163         priv->status_bar   = gtk_statusbar_new ();
164         gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR(priv->status_bar),
165                                            FALSE);
166 }
167
168 static void
169 modest_widget_factory_finalize (GObject *obj)
170 {
171         ModestWidgetFactoryPrivate *priv;
172         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(obj);
173
174         if (priv->proto_mgr) {
175                 g_object_unref (G_OBJECT(priv->proto_mgr));
176                 priv->proto_mgr = NULL;
177         }
178 }
179
180
181
182 static void
183 init_signals (ModestWidgetFactory *self)
184 {
185         
186         TnyDevice *device;
187         ModestWidgetFactoryPrivate *priv;
188         
189         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
190
191         /* folder view */
192         g_signal_connect (G_OBJECT(priv->folder_view), "folder_selected",
193                           G_CALLBACK(on_folder_selected), self);
194         g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
195                           G_CALLBACK(on_folder_key_press_event), self);
196
197         /* header view */
198         g_signal_connect (G_OBJECT(priv->header_view), "status_update",
199                           G_CALLBACK(on_header_status_update), self);
200         g_signal_connect (G_OBJECT(priv->header_view), "message_selected",
201                           G_CALLBACK(on_message_selected), self);
202         g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
203                           G_CALLBACK(on_item_not_found), self);
204
205         
206         /* msg preview */
207         g_signal_connect (G_OBJECT(priv->msg_preview), "link_clicked",
208                           G_CALLBACK(on_msg_link_clicked), self);
209         g_signal_connect (G_OBJECT(priv->msg_preview), "link_hover",
210                           G_CALLBACK(on_msg_link_hover), self);
211         g_signal_connect (G_OBJECT(priv->msg_preview), "attachment_clicked",
212                           G_CALLBACK(on_msg_attachment_clicked), self);
213
214         /* account store */     
215         g_signal_connect (G_OBJECT (priv->account_store), "password_requested",
216                           G_CALLBACK(on_password_requested), self);     
217
218         /* FIXME: const casting is evil ==> tinymail */
219         device = (TnyDevice*) tny_account_store_get_device (priv->account_store);
220         if (device) {
221                 g_signal_connect (G_OBJECT(device), "connection_changed",
222                                   G_CALLBACK(on_connection_changed), self);
223                 g_signal_connect (G_OBJECT(priv->online_toggle), "toggled",
224                                   G_CALLBACK(on_online_toggle_toggled), self);
225                 
226                 /* init toggle in correct state */
227                 on_connection_changed (device,
228                                        tny_device_is_online (device),
229                                        self);
230         }
231 }
232
233 static gboolean
234 init_widgets (ModestWidgetFactory *self)
235 {
236         ModestWidgetFactoryPrivate *priv;
237         TnyFolderStoreQuery *query;
238
239         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
240
241         /* folder view */
242         query = tny_folder_store_query_new ();
243         tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
244         if (!(priv->folder_view =
245               MODEST_FOLDER_VIEW(modest_folder_view_new (MODEST_TNY_ACCOUNT_STORE (priv->account_store),
246                                                          query)))) {
247                 g_printerr ("modest: cannot instantiate folder view\n");
248                 return FALSE;
249         }
250         g_object_unref (G_OBJECT (query));
251
252         /* header view */
253         if (!(priv->header_view =
254               MODEST_HEADER_VIEW(modest_header_view_new
255                                  (NULL, NULL,MODEST_HEADER_VIEW_STYLE_NORMAL)))) {
256                 g_printerr ("modest: cannot instantiate header view\n");
257                 return FALSE;
258         }
259         
260         
261         /* msg preview */
262         if (!(priv->msg_preview = MODEST_MSG_VIEW(modest_msg_view_new (NULL)))) {
263                 g_printerr ("modest: cannot instantiate header view\n");
264                 return FALSE;
265         }
266
267
268
269         /* online/offline combo */
270         priv->online_toggle = gtk_toggle_button_new ();
271
272         /* label with number of items, unread items for 
273            the current folder */
274         priv->folder_info_label = gtk_label_new (NULL);
275         
276         init_signals (self);
277         
278         return TRUE;
279 }
280
281
282 ModestWidgetFactory*
283 modest_widget_factory_new (void)
284 {
285         GObject *obj;
286         ModestWidgetFactoryPrivate *priv;
287
288         obj  = g_object_new (MODEST_TYPE_WIDGET_FACTORY, NULL); 
289         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(obj);
290
291         if (!init_widgets (MODEST_WIDGET_FACTORY(obj))) {
292                 g_printerr ("modest: widget factory failed to init widgets\n");
293                 g_object_unref (obj);
294                 return NULL;
295         }
296         
297         return MODEST_WIDGET_FACTORY(obj);
298 }
299
300
301
302
303 ModestFolderView*
304 modest_widget_factory_get_folder_view (ModestWidgetFactory *self)
305 {
306         g_return_val_if_fail (self, NULL);
307         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->folder_view;
308 }
309
310
311 ModestHeaderView*
312 modest_widget_factory_get_header_view (ModestWidgetFactory *self)
313 {
314         g_return_val_if_fail (self, NULL);
315         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->header_view;
316 }
317
318
319 ModestMsgView*
320 modest_widget_factory_get_msg_preview (ModestWidgetFactory *self)
321 {
322         g_return_val_if_fail (self, NULL);
323         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->msg_preview;
324 }
325
326
327 ModestAccountView*
328 modest_widget_factory_get_account_view (ModestWidgetFactory *self)
329 {
330         ModestWidgetFactoryPrivate *priv;
331         ModestAccountMgr *account_mgr;
332         
333         g_return_val_if_fail (self, NULL);
334         priv =  MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
335
336         account_mgr = 
337                 modest_tny_platform_factory_get_modest_account_mgr_instance (priv->fact);
338         
339         return modest_account_view_new (account_mgr);
340 }
341
342
343
344 GtkWidget*
345 modest_widget_factory_get_progress_bar (ModestWidgetFactory *self)
346 {
347         g_return_val_if_fail (self, NULL);
348         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->progress_bar;
349 }
350
351
352 GtkWidget*
353 modest_widget_factory_get_status_bar (ModestWidgetFactory *self)
354 {
355         g_return_val_if_fail (self, NULL);
356         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->status_bar;
357 }
358
359
360
361 static const GSList*
362 get_transports (ModestWidgetFactory *self)
363 {
364         ModestWidgetFactoryPrivate *priv;
365         ModestAccountMgr *account_mgr;
366         GSList *transports = NULL;
367         GSList *cursor, *accounts;
368         
369         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
370
371         account_mgr = 
372                 modest_tny_platform_factory_get_modest_account_mgr_instance (priv->fact);
373         cursor = accounts = modest_account_mgr_account_names (account_mgr, NULL);
374         while (cursor) {
375                 ModestAccountData *data;
376                 gchar *account_name = (gchar*)cursor->data;
377
378                 data = modest_account_mgr_get_account_data (account_mgr, account_name);
379                 if (data && data->transport_account) {
380                         gchar *display_name = g_strdup_printf ("%s (%s)", data->email, account_name);
381                         ModestPair *pair = modest_pair_new ((gpointer) data,
382                                                             (gpointer) display_name , TRUE);
383                         transports = g_slist_append (transports, pair);
384                 }
385                 /* don't free account name; it's freed when the transports list is freed */
386                 cursor = cursor->next;
387         }
388         g_slist_free (accounts);
389         
390         return transports;
391 }
392
393
394 GtkWidget*
395 modest_widget_factory_get_combo_box (ModestWidgetFactory *self, ModestComboBoxType type)
396 {
397         ModestWidgetFactoryPrivate *priv;
398         const GSList *list = NULL;
399         GtkWidget* combo_box;
400         
401         g_return_val_if_fail (self, NULL);
402
403         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
404         
405         switch (type) {
406         case MODEST_COMBO_BOX_TYPE_STORE_PROTOS:
407                 list = modest_protocol_mgr_get_store_protocols (priv->proto_mgr);
408                 break;
409         case MODEST_COMBO_BOX_TYPE_TRANSPORT_PROTOS:
410                 list = modest_protocol_mgr_get_transport_protocols (priv->proto_mgr);
411                 break;
412         case MODEST_COMBO_BOX_TYPE_SECURITY_PROTOS:
413                 list = modest_protocol_mgr_get_security_protocols (priv->proto_mgr);
414                 break;
415         case MODEST_COMBO_BOX_TYPE_AUTH_PROTOS:
416                 list = modest_protocol_mgr_get_auth_protocols (priv->proto_mgr);
417                 break;
418         case MODEST_COMBO_BOX_TYPE_TRANSPORTS:
419                 list = get_transports (self);
420                 break;
421         default:
422                 g_warning ("invalid combo box type: %d", type);
423                 return NULL;
424         }
425
426         combo_box = modest_combo_box_new (list);
427         gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box), 0);
428         
429         return combo_box;
430 }
431
432
433
434 GtkWidget*
435 modest_widget_factory_get_online_toggle (ModestWidgetFactory *self)
436 {
437         g_return_val_if_fail (self, NULL);
438         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->online_toggle;
439 }
440
441
442
443 GtkWidget*
444 modest_widget_factory_get_folder_info_label (ModestWidgetFactory *self)
445 {
446         g_return_val_if_fail (self, NULL);
447         return MODEST_WIDGET_FACTORY_GET_PRIVATE(self)->folder_info_label;
448 }
449
450 ModestToolbar*
451 modest_widget_factory_get_main_toolbar (ModestWidgetFactory *self, 
452                                         GSList *items)
453 {
454         ModestWidgetFactoryPrivate *priv;
455         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
456
457         if (priv->main_toolbar)
458                 return priv->main_toolbar;
459
460         priv->main_toolbar = modest_toolbar_new (items);
461         if (!priv->main_toolbar) {
462                 g_printerr ("modest: failed to create main toolbar\n");
463                 return NULL;
464         }
465         
466         return priv->main_toolbar;
467 }
468
469
470 ModestToolbar*
471 modest_widget_factory_get_edit_toolbar (ModestWidgetFactory *self, 
472                                         GSList *items)
473 {
474         return modest_toolbar_new (items);
475 }
476
477
478
479 static void
480 on_folder_selected (ModestFolderView *folder_view, TnyFolder *folder,
481                     ModestWidgetFactory *self)
482 {
483         ModestWidgetFactoryPrivate *priv;
484         gchar *txt;
485
486         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
487         
488         modest_header_view_set_folder (priv->header_view, folder);
489         
490         if (folder) {
491                 guint num, unread;
492                 
493                 num    = tny_folder_get_all_count    (folder);
494                 unread = tny_folder_get_unread_count (folder);
495
496                 txt = g_strdup_printf (_("%d %s, %d unread"),
497                                        num, num==1 ? _("item") : _("items"), unread);
498                 
499                 gtk_label_set_label (GTK_LABEL(priv->folder_info_label), txt);
500                 g_free (txt);
501         } else
502                 gtk_label_set_label (GTK_LABEL(priv->folder_info_label), "");
503 }
504
505 /*********************** Test code ********************/
506 static void
507 on_folder_key_press_event (ModestFolderView *folder_view, GdkEventKey *event, gpointer user_data)
508 {
509         GtkTreeSelection *selection;
510         GtkTreeModel *model;
511         GtkTreeIter iter;
512         TnyFolderStore *folder;
513         gint type;
514         ModestMailOperation *mail_op;
515
516         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
517         gtk_tree_selection_get_selected (selection, &model, &iter);
518         
519         gtk_tree_model_get (model, &iter, 
520                             TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, &type, 
521                             TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder, 
522                             -1);
523
524         mail_op = modest_mail_operation_new ();
525
526         if (event->keyval == GDK_C || event->keyval == GDK_c) {
527                 if (type != TNY_FOLDER_TYPE_ROOT)
528                         modest_mail_operation_create_folder (mail_op, folder, "New");
529         } else if (event->keyval == GDK_D || event->keyval == GDK_d) {
530                 if (type != TNY_FOLDER_TYPE_ROOT)
531                         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), FALSE);
532         } else if (event->keyval == GDK_N || event->keyval == GDK_n) {
533                 if (type != TNY_FOLDER_TYPE_ROOT)
534                         modest_mail_operation_rename_folder (mail_op, TNY_FOLDER (folder), "New Name");
535         } else if (event->keyval == GDK_T || event->keyval == GDK_t) {
536                 if (type != TNY_FOLDER_TYPE_ROOT)
537                         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), TRUE);
538         }
539
540         g_object_unref (G_OBJECT (mail_op));
541 }
542 /****************************************************/
543
544 static void
545 on_message_selected (ModestHeaderView *folder_view, TnyMsg *msg,
546                      ModestWidgetFactory *self)
547 {       
548         ModestWidgetFactoryPrivate *priv;
549         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
550         
551         modest_msg_view_set_message (priv->msg_preview, msg);
552 }
553
554
555 /*
556  * below some stuff to clearup statusbar messages after 1,5 seconds....
557  */
558 typedef struct {
559         GtkWidget *status_bar;
560         GtkWidget *progress_bar;
561         guint     msg_id;
562 } StatusRemoveData;
563
564
565 static gboolean
566 on_statusbar_remove_msg (StatusRemoveData *data)
567 {
568         /* we need to test types, as this callback maybe called after the
569          * widgets have been destroyed
570          */
571         if (GTK_IS_STATUSBAR(data->status_bar)) 
572                 gtk_statusbar_remove (GTK_STATUSBAR(data->status_bar),
573                                       0, data->msg_id);
574         if (GTK_IS_PROGRESS_BAR(data->progress_bar))
575                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(data->progress_bar),
576                                                1.0);
577         g_free (data);
578         return FALSE;
579 }
580
581
582 static void
583 statusbar_push (ModestWidgetFactory *self, guint context_id, const gchar *msg)
584 {
585         guint id;
586         StatusRemoveData *data;
587         ModestWidgetFactoryPrivate *priv;
588         
589         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
590         
591         if (!msg)
592                 return;
593         
594         id = gtk_statusbar_push (GTK_STATUSBAR(priv->status_bar), 0, msg);
595
596         data = g_new (StatusRemoveData, 1);
597         data->status_bar   = priv->status_bar;
598         data->progress_bar = priv->progress_bar;
599         data->msg_id     = id;
600
601         g_timeout_add (1500, (GSourceFunc)on_statusbar_remove_msg, data);
602 }
603 /****************************************************************************/
604
605
606 static void
607 on_header_status_update (ModestHeaderView *header_view, const gchar *msg,
608                          gint status_id, ModestWidgetFactory *self)
609 {
610         ModestWidgetFactoryPrivate *priv;
611         
612         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
613                         
614         gtk_progress_bar_pulse (GTK_PROGRESS_BAR(priv->progress_bar));
615         statusbar_push (self, 0, msg);
616 }
617
618
619 static void
620 on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
621                    ModestWidgetFactory *self)
622 {
623         ModestWidgetFactoryPrivate *priv;
624         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
625         
626         statusbar_push (self, 0, link);
627
628 }       
629
630
631 static void
632 on_msg_link_clicked  (ModestMsgView *msgview, const gchar* link,
633                       ModestWidgetFactory *self)
634 {
635         gchar *msg;
636         msg = g_strdup_printf (_("Opening %s..."), link);
637         statusbar_push (self, 0, msg);
638         g_free (msg);
639 }
640
641 static void
642 on_msg_attachment_clicked  (ModestMsgView *msgview, int index,
643                             ModestWidgetFactory *self)
644 {
645         gchar *msg;
646         
647         msg = g_strdup_printf (_("Opening attachment %d..."), index);
648         statusbar_push (self, 0, msg);
649         
650         g_free (msg);
651 }
652
653
654 static void
655 on_connection_changed (TnyDevice *device, gboolean online,
656                        ModestWidgetFactory *self)
657 {
658         ModestWidgetFactoryPrivate *priv;
659         priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
660
661         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(priv->online_toggle),
662                                       online);
663         gtk_button_set_label (GTK_BUTTON(priv->online_toggle),
664                               online ? _("Online") : _("Offline"));
665
666         statusbar_push (self, 0, online ? _("Modest went online") : _("Modest went offline"));
667 }
668
669
670 static void
671 on_online_toggle_toggled (GtkToggleButton *toggle, ModestWidgetFactory *self)
672 {
673         gboolean online;
674         const TnyDevice *device;
675         ModestWidgetFactoryPrivate *priv;
676         
677         priv    = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
678         online  = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(priv->online_toggle));
679         device  = tny_account_store_get_device (priv->account_store); 
680
681         /* FIXME: const casting should not be necessary ==> tinymail */
682         if (online)  /* we're moving to online state */
683                 tny_device_force_online ((TnyDevice*)device);
684         else  /* we're moving to offline state */
685                 tny_device_force_offline ((TnyDevice*)device);
686 }
687
688
689 static void
690 on_item_not_found (ModestHeaderView* header_view, ModestItemType type,
691                    ModestWidgetFactory *self)
692 {
693         /* FIXME ==> ask from UI... */
694         GtkWidget *dialog;
695         gchar *txt;
696         gboolean online;
697         gchar *item = type == MODEST_ITEM_TYPE_FOLDER ? "folder" : "message";
698         
699         TnyDevice *device;
700         ModestWidgetFactoryPrivate *priv;
701         
702         priv    = MODEST_WIDGET_FACTORY_GET_PRIVATE(self);
703         device  = tny_account_store_get_device (priv->account_store);
704         
705         online = tny_device_is_online (device);
706         if (online) {
707                 /* already online -- the item is simply not there... */
708                 dialog = gtk_message_dialog_new (NULL,
709                                                  GTK_DIALOG_MODAL,
710                                                  GTK_MESSAGE_WARNING,
711                                                  GTK_BUTTONS_OK,
712                                                  _("The %s you selected cannot be found"),
713                                                  item);
714                 gtk_dialog_run (GTK_DIALOG(dialog));
715         } else {
716
717                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
718                                                       NULL,
719                                                       GTK_DIALOG_MODAL,
720                                                       GTK_STOCK_CANCEL,
721                                                       GTK_RESPONSE_REJECT,
722                                                       GTK_STOCK_OK,
723                                                       GTK_RESPONSE_ACCEPT,
724                                                       NULL);
725
726                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
727                                          "Do you want to get online?"), item);
728                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
729                                     gtk_label_new (txt), FALSE, FALSE, 0);
730                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
731                 g_free (txt);
732
733                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
734                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
735                         tny_device_force_online (device);
736         }
737         gtk_widget_destroy (dialog);
738 }
739
740
741
742 static void
743 on_password_requested (ModestTnyAccountStore *account_store, const gchar* account_name,
744                        gchar **password, gboolean *cancel, ModestWidgetFactory *self)
745 {
746         gchar *txt;
747         GtkWidget *dialog, *entry, *remember_pass_check;
748         
749         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
750                                               NULL,
751                                               GTK_DIALOG_MODAL,
752                                               GTK_STOCK_CANCEL,
753                                               GTK_RESPONSE_REJECT,
754                                               GTK_STOCK_OK,
755                                               GTK_RESPONSE_ACCEPT,
756                                               NULL);
757
758         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
759         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
760                             FALSE, FALSE, 0);
761         g_free (txt);
762
763         entry = gtk_entry_new_with_max_length (40);
764         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
765         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
766         
767         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
768                             TRUE, FALSE, 0);    
769
770         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
771         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
772                             TRUE, FALSE, 0);
773
774         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
775         
776         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
777                 *password = g_strdup(gtk_entry_get_text (GTK_ENTRY(entry)));
778                 *cancel   = FALSE;
779         } else {
780                 *password = NULL;
781                 *cancel   = TRUE;
782         }
783         gtk_widget_destroy (dialog);
784 }
785