1 /*
2 * Copyright (C) 2015 SUSE (www.suse.com)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 * Authors:
18 * David Liang <dliang@suse.com>
19 *
20 */
21
22 #include "evolution-config.h"
23
24 #include <stdio.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <dirent.h>
30 #include <string.h>
31
32 #include <gtk/gtk.h>
33 #include <glib/gi18n-lib.h>
34
35 #include "kmail-libs.h"
36 #include "mail-importer.h"
37
38 #include "libemail-engine/libemail-engine.h"
39 #include "e-util/e-util.h"
40 #include "shell/e-shell.h"
41 #include "shell/e-shell-window.h"
42 #include "shell/e-shell-view.h"
43 #include "shell/e-shell-sidebar.h"
44
45 #include "mail/e-mail-backend.h"
46 #include "mail/em-folder-selection-button.h"
47 #include "mail/em-folder-tree-model.h"
48 #include "mail/em-folder-tree.h"
49
50 #define ENABLE_SELECT 0
51 #define d(x)
52
53 typedef struct {
54 EImport *import;
55 EImportTarget *target;
56
57 GMutex status_lock;
58 gchar *status_what;
59 gint status_pc;
60 gint status_timeout_id;
61 GCancellable *cancellable; /* cancel/status port */
62
63 gchar *uri;
64 } KMailImporter;
65
66 static gboolean
kmail_supported(EImport * ei,EImportTarget * target,EImportImporter * im)67 kmail_supported (EImport *ei,
68 EImportTarget *target,
69 EImportImporter *im)
70 {
71 return kmail_is_supported ();
72 }
73
74 static void
kmail_import_done(gpointer data,GError ** error)75 kmail_import_done (gpointer data,
76 GError **error)
77 {
78 KMailImporter *importer = data;
79
80 g_source_remove (importer->status_timeout_id);
81 g_free (importer->status_what);
82
83 g_mutex_clear (&importer->status_lock);
84 g_object_unref (importer->cancellable);
85
86 e_import_complete (importer->import, importer->target, error ? *error : NULL);
87 g_free (importer);
88 }
89
90 static void
kmail_status(CamelOperation * op,const gchar * what,gint pc,gpointer data)91 kmail_status (CamelOperation *op,
92 const gchar *what,
93 gint pc,
94 gpointer data)
95 {
96 KMailImporter *importer = data;
97 g_mutex_lock (&importer->status_lock);
98 g_free (importer->status_what);
99 importer->status_what = g_strdup (what);
100 importer->status_pc = pc;
101 g_mutex_unlock (&importer->status_lock);
102 }
103
104 static gboolean
kmail_status_timeout(gpointer data)105 kmail_status_timeout (gpointer data)
106 {
107 KMailImporter *importer = data;
108 gint pc;
109 gchar *what;
110 if (importer->status_what) {
111 g_mutex_lock (&importer->status_lock);
112 what = importer->status_what;
113 importer->status_what = NULL;
114 pc = importer->status_pc;
115 g_mutex_unlock (&importer->status_lock);
116
117 e_import_status (
118 importer->import, (EImportTarget *)
119 importer->target, what, pc);
120 }
121
122 return TRUE;
123 }
124
125 static void
checkbox_toggle_cb(GtkToggleButton * tb,EImportTarget * target)126 checkbox_toggle_cb (GtkToggleButton *tb,
127 EImportTarget *target)
128 {
129 g_datalist_set_data (
130 &target->data, "kmail-do-mail",
131 GINT_TO_POINTER (gtk_toggle_button_get_active (tb)));
132 }
133
134 #if ENABLE_SELECT
135 static void
folder_selected(EMFolderSelectionButton * button,EImportTargetURI * target)136 folder_selected (EMFolderSelectionButton *button,
137 EImportTargetURI *target)
138 {
139 g_free (target->uri_dest);
140 target->uri_dest = g_strdup (em_folder_selection_button_get_folder_uri (button));
141 }
142
143 static GtkWidget *
import_folder_getwidget(EImport * ei,EImportTarget * target,EImportImporter * im)144 import_folder_getwidget (EImport *ei,
145 EImportTarget *target,
146 EImportImporter *im)
147 {
148 EShell *shell;
149 EShellBackend *shell_backend;
150 EMailBackend *backend;
151 EMailSession *session;
152 GtkWindow *window;
153 GtkWidget *hbox, *w;
154 GtkLabel *label;
155 gchar *select_uri = NULL;
156
157 /* XXX Dig up the mail backend from the default EShell.
158 * Since the EImport framework doesn't allow for user
159 * data, I don't see how else to get to it. */
160 shell = e_shell_get_default ();
161 shell_backend = e_shell_get_backend_by_name (shell, "mail");
162
163 backend = E_MAIL_BACKEND (shell_backend);
164 session = e_mail_backend_get_session (backend);
165
166 /* preselect the folder selected in a mail view */
167 window = e_shell_get_active_window (shell);
168 if (E_IS_SHELL_WINDOW (window)) {
169 EShellWindow *shell_window;
170 const gchar *view;
171
172 shell_window = E_SHELL_WINDOW (window);
173 view = e_shell_window_get_active_view (shell_window);
174
175 if (view && g_str_equal (view, "mail")) {
176 EShellView *shell_view;
177 EShellSidebar *shell_sidebar;
178 EMFolderTree *folder_tree = NULL;
179
180 shell_view = e_shell_window_get_shell_view (
181 shell_window, view);
182
183 shell_sidebar =
184 e_shell_view_get_shell_sidebar (shell_view);
185
186 g_object_get (
187 shell_sidebar, "folder-tree",
188 &folder_tree, NULL);
189
190 select_uri =
191 em_folder_tree_get_selected_uri (folder_tree);
192
193 g_object_unref (folder_tree);
194 }
195 }
196
197 if (!select_uri) {
198 const gchar *uri;
199 uri = e_mail_session_get_local_folder_uri (
200 session, E_MAIL_LOCAL_FOLDER_INBOX);
201 select_uri = g_strdup (uri);
202 }
203
204 hbox = gtk_hbox_new (FALSE, 0);
205
206 w = gtk_label_new_with_mnemonic (_("_Destination folder:"));
207 gtk_box_pack_start ((GtkBox *) hbox, w, FALSE, TRUE, 6);
208
209 label = GTK_LABEL (w);
210
211 w = em_folder_selection_button_new (
212 session, _("Select folder"),
213 _("Select folder to import into"));
214 gtk_label_set_mnemonic_widget (label, w);
215 em_folder_selection_button_set_folder_uri (
216 EM_FOLDER_SELECTION_BUTTON (w), select_uri);
217 folder_selected (
218 EM_FOLDER_SELECTION_BUTTON (w), (EImportTargetURI *) target);
219 g_signal_connect (
220 w, "selected",
221 G_CALLBACK (folder_selected), target);
222 gtk_box_pack_start ((GtkBox *) hbox, w, FALSE, TRUE, 6);
223
224 w = gtk_vbox_new (FALSE, 0);
225 gtk_box_pack_start ((GtkBox *) w, hbox, FALSE, FALSE, 0);
226 gtk_widget_show_all (w);
227
228 g_free (select_uri);
229
230 return w;
231 }
232 #endif
233
234 static GtkWidget *
kmail_getwidget(EImport * ei,EImportTarget * target,EImportImporter * im)235 kmail_getwidget (EImport *ei,
236 EImportTarget *target,
237 EImportImporter *im)
238 {
239 GtkWidget *box, *w;
240 GSList *contact_list;
241 gint count;
242 gchar *contact_str;
243
244
245 g_datalist_set_data (
246 &target->data, "kmail-do-mail", GINT_TO_POINTER (TRUE));
247
248 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
249 w = gtk_check_button_new_with_label (_("Mail"));
250 gtk_toggle_button_set_active ((GtkToggleButton *) w, TRUE);
251 g_signal_connect (
252 w, "toggled",
253 G_CALLBACK (checkbox_toggle_cb), target);
254
255 gtk_box_pack_start ((GtkBox *) box, w, FALSE, FALSE, 0);
256
257 contact_list = kcontact_get_list ();
258 count = g_slist_length (contact_list);
259 contact_str = g_strdup_printf (ngettext ("%d Address", "%d Addresses", count), count);
260 w = gtk_check_button_new_with_label (contact_str);
261 gtk_toggle_button_set_active ((GtkToggleButton *) w, TRUE);
262 g_signal_connect (
263 w, "toggled",
264 G_CALLBACK (checkbox_toggle_cb), target);
265
266 gtk_box_pack_start ((GtkBox *) box, w, FALSE, FALSE, 0);
267
268 /* for now, we don't allow to select a folder */
269 #if ENABLE_SELECT
270 w = import_folder_getwidget (ei, target, im);
271 gtk_box_pack_start ((GtkBox *) box, w, FALSE, FALSE, 0);
272 #endif
273
274 gtk_widget_show_all (box);
275 g_slist_free_full (contact_list, g_free);
276 g_free (contact_str);
277
278 return box;
279 }
280
281 static void
kmail_import(EImport * ei,EImportTarget * target,EImportImporter * im)282 kmail_import (EImport *ei,
283 EImportTarget *target,
284 EImportImporter *im)
285 {
286 EShell *shell;
287 EShellBackend *shell_backend;
288 EMailSession *session;
289 KMailImporter *importer;
290 gchar *path;
291 GSList *contact_list;
292
293 /* XXX Dig up the EMailSession from the default EShell.
294 * Since the EImport framework doesn't allow for user
295 * data, I don't see how else to get to it. */
296 shell = e_shell_get_default ();
297 shell_backend = e_shell_get_backend_by_name (shell, "mail");
298 session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));
299
300 importer = g_malloc0 (sizeof (*importer));
301 g_datalist_set_data (&target->data, "kmail-data", importer);
302 importer->status_what = NULL;
303 importer->import = ei;
304 importer->target = target;
305 importer->cancellable = camel_operation_new ();
306 g_mutex_init (&importer->status_lock);
307 importer->status_timeout_id = g_timeout_add (100, kmail_status_timeout, importer);
308
309 g_signal_connect (
310 importer->cancellable, "status",
311 G_CALLBACK (kmail_status), importer);
312
313 /* import emails */
314 path = kmail_get_base_dir ();
315 mail_importer_import_kmail (
316 session, path, NULL,
317 importer->cancellable, kmail_import_done, importer);
318 g_free (path);
319
320 /* import contacts */
321 contact_list = kcontact_get_list ();
322 kcontact_load (contact_list);
323 g_slist_free_full (contact_list, g_free);
324 }
325
326 static void
kmail_cancel(EImport * ei,EImportTarget * target,EImportImporter * im)327 kmail_cancel (EImport *ei,
328 EImportTarget *target,
329 EImportImporter *im)
330 {
331 KMailImporter *m = g_datalist_get_data (&target->data, "kmail-data");
332
333 if (m)
334 g_cancellable_cancel (m->cancellable);
335 }
336
337 static EImportImporter kmail_importer = {
338 E_IMPORT_TARGET_HOME,
339 0,
340 kmail_supported,
341 kmail_getwidget,
342 kmail_import,
343 kmail_cancel,
344 NULL, /* get_preview */
345 };
346
347 EImportImporter *
kmail_importer_peek(void)348 kmail_importer_peek (void)
349 {
350 kmail_importer.name = _("Evolution KMail importer");
351 kmail_importer.description = _("Import mail and contacts from KMail.");
352
353 return &kmail_importer;
354 }
355