* Fixes NB#98417, fixes a crash when trying to move the outbox folder
[modest] / src / gnome / modest-platform.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 <libgnomevfs/gnome-vfs-mime.h>
31 #include <libgnomeui/gnome-icon-lookup.h>
32 #include <tny-gnome-device.h>
33 #include <tny-camel-imap-store-account.h>
34 #include <tny-camel-pop-store-account.h>
35 #include <tny-simple-list.h>
36 #include "modest-platform.h"
37 #include "modest-mail-operation-queue.h"
38 #include "modest-runtime.h"
39 #include "gnome/modest-gnome-global-settings-dialog.h"
40 #include "widgets/modest-default-account-settings-dialog.h"
41 #include "gnome/modest-account-assistant.h"
42 #include "gnome/modest-gnome-sort-dialog.h"
43 #include "widgets/modest-details-dialog.h"
44 #include "widgets/modest-main-window.h"
45
46 gboolean
47 modest_platform_init (int argc, char *argv[])
48 {       
49         return TRUE; /* nothing to do */
50 }
51
52
53 gboolean modest_platform_uninit (void)
54 {
55         return TRUE; /*nothing to do */
56 }
57
58
59 TnyDevice*
60 modest_platform_get_new_device (void)
61 {
62         return TNY_DEVICE (tny_gnome_device_new ());
63 }
64
65
66 gchar*
67 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
68                                           gchar **effective_mime_type)
69 {
70         GString *mime_str = NULL;
71         gchar *icon_name  = NULL;
72         gchar *uri;
73         const static gchar* octet_stream = "application/octet-stream";
74         
75         g_return_val_if_fail (name || mime_type, NULL);
76
77         if (!mime_type || g_ascii_strcasecmp (mime_type, octet_stream)) 
78                 mime_str = g_string_new(gnome_vfs_mime_type_from_name_or_default
79                                         (name, "application/octet-stream"));
80         else {
81                 mime_str = g_string_new (mime_type);
82                 g_string_ascii_down (mime_str);
83         }
84
85         uri = g_strconcat ("file:///", name ? name : "dummy", NULL);
86         icon_name  = gnome_icon_lookup (gtk_icon_theme_get_default(), NULL,
87                                         uri, NULL, NULL, mime_str->str, 0, 0);
88         g_free (uri);
89
90         if (effective_mime_type)
91                 *effective_mime_type = g_string_free (mime_str, FALSE);
92         else
93                 g_string_free (mime_str, TRUE);
94
95         return icon_name;
96 }
97
98 gboolean 
99 modest_platform_activate_uri (const gchar *uri)
100 {
101         g_message ("NOT IMPLEMENTED");;
102         return FALSE;
103 }
104
105 gboolean 
106 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
107 {
108         g_message ("NOT IMPLEMENTED");;
109         return FALSE;
110 }
111
112 gboolean 
113 modest_platform_show_uri_popup (const gchar *uri)
114 {
115         g_message ("NOT IMPLEMENTED");;
116         return FALSE;
117 }
118
119 GdkPixbuf*
120 modest_platform_get_icon (const gchar *name, guint icon_size)
121 {
122         GError *err = NULL;
123         GdkPixbuf* pixbuf;
124
125         g_return_val_if_fail (name, NULL);
126
127         pixbuf = gdk_pixbuf_new_from_file (name, &err);
128
129         if (!pixbuf) {
130 /*              g_printerr ("modest: error while loading icon '%s': %s\n", */
131 /*                          name, err->message); */
132                 g_error_free (err);
133                 err = NULL;
134
135                 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), name, icon_size, 0, &err);
136                 if (!pixbuf) {
137                         g_error_free (err);
138                 }
139         }
140         
141         return pixbuf;
142 }
143
144
145 const gchar*
146 modest_platform_get_app_name (void)
147 {
148         return ("Modest");
149 }
150
151 gint 
152 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
153                                        TnyFolderStore *suggested_parent,
154                                        gchar *suggested_name,
155                                        gchar **folder_name,
156                                        TnyFolderStore **parent_folder)
157 {
158         GtkWidget *dialog, *entry;
159         gint result;
160
161         /* Ask the user for the folder name */
162         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
163                                               parent_window,
164                                               GTK_DIALOG_MODAL,
165                                               GTK_STOCK_CANCEL,
166                                               GTK_RESPONSE_REJECT,
167                                               GTK_STOCK_OK,
168                                               GTK_RESPONSE_ACCEPT,
169                                               NULL);
170         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
171                             gtk_label_new (_("Please enter a name for the new folder")),
172                             FALSE, FALSE, 0);
173                 
174         entry = gtk_entry_new_with_max_length (40);
175         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
176                             entry,
177                             TRUE, FALSE, 0);
178         
179         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
180
181         result = gtk_dialog_run (GTK_DIALOG(dialog));
182         if (result == GTK_RESPONSE_ACCEPT)
183                 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
184
185         gtk_widget_destroy (dialog);
186
187         if (parent_folder != NULL) {
188                 parent_folder = suggested_parent?g_object_ref (suggested_parent): NULL;
189         }
190
191         return result;
192 }
193
194
195 gint
196 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
197                                          const gchar *msg)
198 {
199         gint response;
200         GtkWidget *dialog;
201
202         dialog = gtk_message_dialog_new (parent_window,
203                                          GTK_DIALOG_MODAL,
204                                          GTK_MESSAGE_QUESTION,
205                                          GTK_BUTTONS_OK_CANCEL,
206                                          msg);
207
208         response = gtk_dialog_run (GTK_DIALOG(dialog));
209         gtk_widget_destroy (dialog);
210         
211         return response;
212 }
213
214 gint
215 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
216                                                       const gchar *message,
217                                                       const gchar *button_accept,
218                                                       const gchar *button_cancel)
219 {
220         gint response;
221         GtkWidget *dialog;
222
223         dialog = gtk_dialog_new_with_buttons (message,
224                                               parent_window,
225                                               GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
226                                               button_accept,
227                                               GTK_RESPONSE_ACCEPT,
228                                               button_cancel,
229                                               GTK_RESPONSE_CANCEL,
230                                               NULL);
231
232         response = gtk_dialog_run (GTK_DIALOG(dialog));
233         gtk_widget_destroy (dialog);
234         
235         return response;
236 }
237
238 void
239 modest_platform_run_information_dialog (GtkWindow *parent_window,
240                                         const gchar *message,
241                                         gboolean block)
242 {
243         GtkWidget *dialog;
244
245         dialog = gtk_message_dialog_new (parent_window,
246                                          GTK_DIALOG_MODAL,
247                                          GTK_MESSAGE_INFO,
248                                          GTK_BUTTONS_OK,
249                                          message);
250
251         gtk_dialog_run (GTK_DIALOG (dialog));
252         gtk_widget_destroy (dialog);
253         
254 }
255
256 gboolean modest_platform_connect_and_wait (GtkWindow *parent_window, TnyAccount *account)
257 {
258         /* TODO: Do something with network-manager? 
259            Otherwise, maybe it is safe to assume that we would already be online if we could be. */
260         return TRUE;
261 }
262
263 gboolean modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
264 {
265         /* TODO: Do something with network-manager? 
266            Otherwise, maybe it is safe to assume that we would already be online if we could be. */
267         return TRUE;
268 }
269
270
271 void
272 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window, 
273                                                gboolean force,
274                                                TnyFolderStore *folder_store, 
275                                                ModestConnectedPerformer callback, 
276                                                gpointer user_data)
277 {
278         TnyAccount *account = NULL;
279
280         if (!folder_store ||
281             (TNY_IS_MERGE_FOLDER (folder_store) &&
282              (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
283
284                 /* We promise to instantly perform the callback, so ... */
285                 if (callback) {
286                         GError *error = NULL;
287                         g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
288                                      "Unable to move or not found folder");
289                         callback (FALSE, error, parent_window, NULL, user_data);
290                         g_error_free (error);
291                 }
292                 return;
293
294         } else if (TNY_IS_FOLDER (folder_store)) {
295                 /* Get the folder's parent account: */
296                 account = tny_folder_get_account(TNY_FOLDER (folder_store));
297         } else if (TNY_IS_ACCOUNT (folder_store)) {
298                 /* Use the folder store as an account: */
299                 account = TNY_ACCOUNT (folder_store);
300         }
301  
302         if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
303                 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
304                     !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
305
306                         /* This IS a local account like a maildir account, which does not require 
307                          * a connection. (original comment had a vague assumption in its language
308                          * usage. There's no assuming needed, this IS what it IS: a local account), */
309  
310                         /* We promise to instantly perform the callback, so ... */
311                         if (callback) {
312                                 callback (FALSE, NULL, parent_window, account, user_data);
313                         }
314                         
315                         return;
316                 }
317         }
318  
319         modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
320  
321         return;
322 }
323
324
325 gboolean modest_platform_set_update_interval (guint minutes)
326 {
327         /* TODO. */
328         return FALSE;
329 }
330
331 GtkWidget *
332 modest_platform_create_sort_dialog (GtkWindow *parent_window)
333 {
334         return modest_gnome_sort_dialog_new (parent_window);
335 }
336
337 GtkWidget *
338 modest_platform_get_global_settings_dialog ()
339 {
340         return modest_gnome_global_settings_dialog_new ();
341 }
342
343 void
344 modest_platform_push_email_notification(void)
345 {
346         /* TODO: implement this */
347         g_print ("--------------- NEW MESSAGE ARRIVED ---------------\n");
348 }
349
350 void 
351 modest_platform_on_new_headers_received (TnyList *header_list,
352                                          gboolean show_visual)
353 {
354         /* TODO: implement this */
355         g_print ("--------------- NEW MESSAGE ARRIVED ---------------\n");
356 }
357
358
359
360 void
361 modest_platform_show_help (GtkWindow *parent_window, const gchar *help_id)
362 {
363         return; /* TODO */
364 }
365
366 void 
367 modest_platform_information_banner (GtkWidget *widget,
368                                     const gchar *icon_name,
369                                     const gchar *text)
370 {
371         g_message ("NOT IMPLEMENTED");;
372 }
373
374 void
375 modest_platform_information_banner_with_timeout (GtkWidget *widget,
376                                                  const gchar *icon_name,
377                                                  const gchar *text,
378                                                  gint timeout)
379 {
380         g_message ("NOT IMPLEMENTED");;
381 }
382
383 GtkWidget *
384 modest_platform_animation_banner (GtkWidget *widget,
385                                   const gchar *icon_name,
386                                   const gchar *text)
387 {
388         g_message ("NOT IMPLEMENTED");
389         return NULL;
390 }
391
392
393 void
394 modest_platform_show_search_messages (GtkWindow *parent_window)
395 {
396         g_message ("NOT IMPLEMENTED");;
397 }
398
399 GtkWidget *
400 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
401 {
402         GtkWidget *widget = modest_folder_view_new (query);
403
404         gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget), FALSE);
405         /* Show all accounts by default */
406         modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
407                                       MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
408
409         return widget;
410 }
411
412 gboolean
413 modest_platform_run_alert_dialog (const gchar* prompt, 
414                                   gboolean is_question)
415 {
416         /* TODO */
417         return TRUE;
418 }
419
420 void 
421 modest_platform_connect_and_perform (GtkWindow *parent_window, 
422                                      gboolean force,
423                                      TnyAccount *account, 
424                                      ModestConnectedPerformer callback, 
425                                      gpointer user_data)
426 {
427         if (callback)
428                 callback (FALSE, NULL, parent_window, account, user_data);
429 }
430
431 void 
432 modest_platform_double_connect_and_perform (GtkWindow *parent_window, 
433                                             gboolean force,
434                                             TnyFolderStore *folder_store,
435                                             DoubleConnectionInfo *connect_info)
436 {
437         if (connect_info->callback)
438                 connect_info->callback (FALSE, NULL, parent_window, TNY_ACCOUNT (folder_store), connect_info->data);
439 }
440
441 void 
442 modest_platform_connect_and_perform_if_network_account (GtkWindow *parent_window, 
443                                                         gboolean force,
444                                                         TnyAccount *account,
445                                                         ModestConnectedPerformer callback, 
446                                                         gpointer user_data)
447 {
448         if (callback)
449                 callback (FALSE, NULL, parent_window, account, user_data);
450 }
451
452 void
453 modest_platform_connect_and_perform_if_network_folderstore (GtkWindow *parent_window, 
454                                                             TnyFolderStore *folder_store, 
455                                                             ModestConnectedPerformer callback, 
456                                                             gpointer user_data)
457 {
458         if (callback)
459                 callback (FALSE, NULL, parent_window, NULL, user_data);
460 }
461
462
463 void 
464 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
465 {
466         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
467 }
468
469 gboolean 
470 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
471 {
472         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
473         return TRUE;
474 }
475
476 gboolean 
477 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
478                                                      const gchar *certificate)
479 {
480         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
481         return TRUE;
482 }
483
484 gint
485 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
486                                           TnyFolderStore *parent_folder,
487                                           const gchar *suggested_name,
488                                           gchar **folder_name)
489 {
490         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
491         return GTK_RESPONSE_CANCEL;
492 }
493
494 void 
495 modest_platform_show_addressbook (GtkWindow *parent_window)
496 {
497         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
498 }
499
500 GtkWidget *
501 modest_platform_get_account_settings_dialog (ModestAccountSettings *settings)
502 {
503         ModestAccountSettingsDialog *dialog = modest_default_account_settings_dialog_new ();
504
505         modest_account_settings_dialog_load_settings (dialog, settings);
506         return GTK_WIDGET (dialog);
507 }
508
509 GtkWidget *
510 modest_platform_get_account_settings_wizard (void)
511 {
512         GtkWidget *widget = modest_account_assistant_new (modest_runtime_get_account_mgr ());
513         return widget;
514 }
515
516
517
518 gboolean modest_platform_check_memory_low (ModestWindow *win,
519                                            gboolean visuals)
520 {
521         g_debug ("%s not implemented", __FUNCTION__);
522         return FALSE;
523 }
524
525 void 
526 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
527                                            TnyFolder *folder)
528 {
529         GtkWidget *dialog;
530         
531         /* Create dialog */
532         dialog = modest_details_dialog_new_with_folder (parent_window, folder);
533
534         /* Run dialog */
535         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), 
536                                      GTK_WINDOW (dialog), 
537                                      parent_window);
538         gtk_widget_show_all (dialog);
539
540         g_signal_connect_swapped (dialog, "response", 
541                                   G_CALLBACK (gtk_widget_destroy),
542                                   dialog);
543 }
544
545 void
546 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
547                                            TnyHeader *header)
548 {
549         GtkWidget *dialog;
550         
551         /* Create dialog */
552         dialog = modest_details_dialog_new_with_header (parent_window, header);
553
554         /* Run dialog */
555         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), 
556                                      GTK_WINDOW (dialog),
557                                      parent_window);
558         gtk_widget_show_all (dialog);
559
560         g_signal_connect_swapped (dialog, "response", 
561                                   G_CALLBACK (gtk_widget_destroy),
562                                   dialog);
563 }
564
565 GtkWidget* 
566 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
567                                        GtkWidget **folder_view)
568 {
569         GtkWidget *dialog, *folder_view_container;
570
571         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
572                                               GTK_WINDOW (parent_window),
573                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
574                                               GTK_DIALOG_DESTROY_WITH_PARENT,
575                                               _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK,
576                                               _("mcen_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
577                                               _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL,
578                                               NULL);
579
580         /* Create folder view */
581         *folder_view = modest_platform_create_folder_view (NULL);
582
583         /* Create pannable and add it to the dialog */
584         folder_view_container = gtk_scrolled_window_new (NULL, NULL);
585         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (folder_view_container),
586                                          GTK_POLICY_AUTOMATIC,
587                                          GTK_POLICY_AUTOMATIC);
588         gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), folder_view_container);
589         gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
590
591         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
592
593         return dialog;
594 }
595
596 TnyList *
597 modest_platform_get_list_to_move (ModestWindow *window)
598 {
599         TnyList *list = NULL;
600
601         /* If it's a main window then it could be that we're moving a
602            folder or a set of messages */
603         if (MODEST_IS_MAIN_WINDOW (window)) {
604                 ModestHeaderView *header_view = NULL;
605                 ModestFolderView *folder_view = NULL;
606
607                 folder_view = (ModestFolderView *)
608                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
609                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
610                 header_view = (ModestHeaderView *)
611                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
612                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
613
614                 /* Get folder or messages to transfer */
615                 if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
616                         TnyFolderStore *src_folder;
617
618                         src_folder = modest_folder_view_get_selected (folder_view);
619                         if (src_folder) {
620                                 list = tny_simple_list_new ();
621                                 tny_list_prepend (list, G_OBJECT (src_folder));
622                                 g_object_unref (src_folder);
623                         }
624                 } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
625                         list = modest_header_view_get_selected_headers(header_view);
626                 }
627         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
628                 TnyHeader *header = NULL;
629
630                 /* We simply return the currently viewed message */
631                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
632                 if (header) {
633                         list = tny_simple_list_new ();
634                         tny_list_prepend (list, G_OBJECT (header));
635                         g_object_unref (header);
636                 }
637         } else {
638                 g_return_val_if_reached (NULL);
639         }
640
641         return list;
642 }