evolution-3.6.4/plugins/mail-notification/mail-notification.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Miguel Angel Lopez Hernandez <miguel@gulev.org.mx>
 18  *
 19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 20  *
 21  */
 22 
 23 #ifdef HAVE_CONFIG_H
 24 #include <config.h>
 25 #endif
 26 
 27 #include <string.h>
 28 #include <glib/gi18n.h>
 29 #include <gtk/gtk.h>
 30 #include <gio/gio.h>
 31 
 32 #ifdef HAVE_CANBERRA
 33 #include <canberra-gtk.h>
 34 #endif
 35 
 36 #include <time.h>
 37 
 38 #include <e-util/e-config.h>
 39 #include <libemail-engine/e-mail-folder-utils.h>
 40 #include <mail/em-utils.h>
 41 #include <mail/em-event.h>
 42 #include <mail/em-folder-tree.h>
 43 #include <shell/e-shell-view.h>
 44 
 45 #ifdef HAVE_LIBNOTIFY
 46 #include <libnotify/notify.h>
 47 #endif
 48 
 49 #define CONF_KEY_NOTIFY_ONLY_INBOX	"notify-only-inbox"
 50 #define CONF_KEY_ENABLED_STATUS	        "notify-status-enabled"
 51 #define CONF_KEY_STATUS_NOTIFICATION	"notify-status-notification"
 52 #define CONF_KEY_ENABLED_SOUND		"notify-sound-enabled"
 53 
 54 static gboolean enabled = FALSE;
 55 static GtkWidget *get_cfg_widget (void);
 56 static GStaticMutex mlock = G_STATIC_MUTEX_INIT;
 57 
 58 /**
 59  * each part should "implement" its own "public" functions:
 60  * a) void new_notify_... (EMEventTargetFolder *t)
 61  *    when new_notify message is sent by Evolution
 62  *
 63  * b) void read_notify_... (EMEventTargetMessage *t)
 64  *    it is called when read_notify message is sent by Evolution
 65  *
 66  * c) void enable_... (gint enable)
 67  *    when plugin itself or the part is enabled/disabled
 68  *
 69  * d) GtkWidget *get_config_widget_...(void)
 70  *    to obtain config widget for the particular part
 71  *
 72  * It also should have its own GSettings key for enabled state. In each particular
 73  * function it should do its work as expected. enable_... will be called always
 74  * when disabling plugin, but only when enabling/disabling part itself.
 75  **/
 76 
 77 /* -------------------------------------------------------------------  */
 78 /*                       Helper functions                               */
 79 /* -------------------------------------------------------------------  */
 80 
 81 static gboolean
 82 is_part_enabled (const gchar *key)
 83 {
 84 	/* the part is enabled by default */
 85 	gboolean res = TRUE;
 86 	GSettings *settings;
 87 
 88 	settings = g_settings_new ("org.gnome.evolution.plugin.mail-notification");
 89 
 90 	res = g_settings_get_boolean (settings, key);
 91 
 92 	g_object_unref (settings);
 93 
 94 	return res;
 95 }
 96 
 97 /* -------------------------------------------------------------------  */
 98 /*                           DBUS part                                  */
 99 /* -------------------------------------------------------------------  */
100 
101 #define DBUS_PATH		"/org/gnome/evolution/mail/newmail"
102 #define DBUS_INTERFACE		"org.gnome.evolution.mail.dbus.Signal"
103 
104 static GDBusConnection *connection = NULL;
105 
106 static gboolean init_gdbus (void);
107 
108 static void
109 send_dbus_message (const gchar *name,
110                    const gchar *display_name,
111                    guint new_count,
112                    const gchar *msg_uid,
113                    const gchar *msg_sender,
114                    const gchar *msg_subject)
115 {
116 	GDBusMessage *message;
117 	GVariantBuilder *builder;
118 	GError *error = NULL;
119 
120 	g_return_if_fail (name != NULL);
121 	g_return_if_fail (display_name != NULL);
122 	g_return_if_fail (g_utf8_validate (name, -1, NULL));
123 	g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
124 	g_return_if_fail (msg_uid == NULL || g_utf8_validate (msg_uid, -1, NULL));
125 	g_return_if_fail (msg_sender == NULL || g_utf8_validate (msg_sender, -1, NULL));
126 	g_return_if_fail (msg_subject == NULL || g_utf8_validate (msg_subject, -1, NULL));
127 
128 	/* Create a new message on the DBUS_INTERFACE */
129 	if (!(message = g_dbus_message_new_signal (DBUS_PATH, DBUS_INTERFACE, name)))
130 		return;
131 
132 	builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
133 
134 	/* Appends the data as an argument to the message */
135 	g_variant_builder_add (builder, "(s)", display_name);
136 
137 	if (new_count) {
138 		g_variant_builder_add (builder, "(s)", display_name);
139 		g_variant_builder_add (builder, "(u)", new_count);
140 	}
141 
142 	#define add_named_param(name, value)				\
143 		if (value) {						\
144 			gchar *val;					\
145 			val = g_strconcat (name, ":", value, NULL);	\
146 			g_variant_builder_add (builder, "(s)", val);	\
147 			g_free (val);					\
148 		}
149 
150 	add_named_param ("msg_uid", msg_uid);
151 	add_named_param ("msg_sender", msg_sender);
152 	add_named_param ("msg_subject", msg_subject);
153 
154 	#undef add_named_param
155 
156 	g_dbus_message_set_body (message, g_variant_builder_end (builder));
157 	g_variant_builder_unref (builder);
158 
159 	/* Sends the message */
160 	g_dbus_connection_send_message (
161 		connection, message,
162 		G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error);
163 
164 	/* Frees the message */
165 	g_object_unref (message);
166 
167 	if (error) {
168 		g_warning ("%s: %s", G_STRFUNC, error->message);
169 		g_error_free (error);
170 	}
171 }
172 
173 static gboolean
174 reinit_gdbus (gpointer user_data)
175 {
176 	if (!enabled || init_gdbus ())
177 		return FALSE;
178 
179 	/* keep trying to re-establish dbus connection */
180 	return TRUE;
181 }
182 
183 static void
184 connection_closed_cb (GDBusConnection *pconnection,
185                       gboolean remote_peer_vanished,
186                       GError *error,
187                       gpointer user_data)
188 {
189 	g_return_if_fail (connection != pconnection);
190 
191 	g_object_unref (connection);
192 	connection = NULL;
193 
194 	g_timeout_add (3000, reinit_gdbus, NULL);
195 }
196 
197 static gboolean
198 init_gdbus (void)
199 {
200 	GError *error = NULL;
201 
202 	if (connection != NULL)
203 		return TRUE;
204 
205 	connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
206 	if (error) {
207 		g_warning ("could not get system bus: %s\n", error->message);
208 		g_error_free (error);
209 
210 		return FALSE;
211 	}
212 
213 	g_dbus_connection_set_exit_on_close (connection, FALSE);
214 
215 	g_signal_connect (
216 		connection, "closed",
217 		G_CALLBACK (connection_closed_cb), NULL);
218 
219 	return TRUE;
220 }
221 
222 /* -------------------------------------------------------------------  */
223 
224 static void
225 new_notify_dbus (EMEventTargetFolder *t)
226 {
227 	if (connection != NULL)
228 		send_dbus_message (
229 			"Newmail", t->display_name, t->new,
230 			t->msg_uid, t->msg_sender, t->msg_subject);
231 }
232 
233 static void
234 read_notify_dbus (EMEventTargetMessage *t)
235 {
236 	if (connection != NULL)
237 		send_dbus_message (
238 			"MessageReading",
239 			camel_folder_get_display_name (t->folder),
240 			0, NULL, NULL, NULL);
241 }
242 
243 static void
244 enable_dbus (gint enable)
245 {
246 	if (enable) {
247 		/* we ignore errors here */
248 		init_gdbus ();
249 	} else if (connection != NULL) {
250 		g_object_unref (connection);
251 		connection = NULL;
252 	}
253 }
254 
255 /* -------------------------------------------------------------------  */
256 /*                     Notification area part                           */
257 /* -------------------------------------------------------------------  */
258 
259 #ifdef HAVE_LIBNOTIFY
260 
261 static guint status_count = 0;
262 
263 static NotifyNotification *notify = NULL;
264 
265 static void
266 remove_notification (void)
267 {
268 	if (notify)
269 		notify_notification_close (notify, NULL);
270 
271 	notify = NULL;
272 
273 	status_count = 0;
274 }
275 
276 static gboolean
277 notification_callback (NotifyNotification *notification)
278 {
279 	GError *error = NULL;
280 
281 	notify_notification_show (notification, &error);
282 
283 	if (error != NULL) {
284 		g_warning ("%s", error->message);
285 		g_error_free (error);
286 	}
287 
288 	return FALSE;
289 }
290 
291 /* -------------------------------------------------------------------  */
292 
293 static void
294 notify_default_action_cb (NotifyNotification *notification,
295                           const gchar *label,
296                           const gchar *folder_uri)
297 {
298 	EShell *shell;
299 	EShellView *shell_view;
300 	EShellWindow *shell_window;
301 	EShellSidebar *shell_sidebar;
302 	EMFolderTree *folder_tree;
303 	GtkApplication *application;
304 	GtkAction *action;
305 	GList *list;
306 
307 	shell = e_shell_get_default ();
308 	application = GTK_APPLICATION (shell);
309 	list = gtk_application_get_windows (application);
310 
311 	/* Find the first EShellWindow in the list. */
312 	while (list != NULL && !E_IS_SHELL_WINDOW (list->data))
313 		list = g_list_next (list);
314 
315 	g_return_if_fail (list != NULL);
316 
317 	/* Present the shell window. */
318 	shell_window = E_SHELL_WINDOW (list->data);
319 	gtk_window_present (GTK_WINDOW (shell_window));
320 
321 	/* Switch to the mail view. */
322 	shell_view = e_shell_window_get_shell_view (shell_window, "mail");
323 	action = e_shell_view_get_action (shell_view);
324 	gtk_action_activate (action);
325 
326 	/* Select the latest folder with new mail. */
327 	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
328 	g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
329 	em_folder_tree_set_selected (folder_tree, folder_uri, FALSE);
330 
331 	remove_notification ();
332 }
333 
334 /* Check if actions are supported by the notification daemon.
335  * This is really only for Ubuntu's Notify OSD, which does not
336  * support actions.  Pretty much all other implementations do. */
337 static gboolean
338 can_support_actions (void)
339 {
340 	static gboolean supports_actions = FALSE;
341 	static gboolean have_checked = FALSE;
342 
343 	if (!have_checked) {
344 		GList *caps = NULL;
345 		GList *match;
346 
347 		have_checked = TRUE;
348 
349 		caps = notify_get_server_caps ();
350 
351 		match = g_list_find_custom (
352 			caps, "actions", (GCompareFunc) strcmp);
353 		supports_actions = (match != NULL);
354 
355 		g_list_foreach (caps, (GFunc) g_free, NULL);
356 		g_list_free (caps);
357 	}
358 
359 	return supports_actions;
360 }
361 
362 static void
363 new_notify_status (EMEventTargetFolder *t)
364 {
365 	gchar *escaped_text;
366 	gchar *text;
367 	const gchar *summary;
368 	const gchar *icon_name;
369 
370 	if (!status_count) {
371 		CamelService *service;
372 		const gchar *store_name;
373 		gchar *folder_name;
374 
375 		service = CAMEL_SERVICE (t->store);
376 		store_name = camel_service_get_display_name (service);
377 
378 		folder_name = g_strdup_printf (
379 			"%s/%s", store_name, t->folder_name);
380 
381 		status_count = t->new;
382 
383 		/* Translators: '%d' is the count of mails received. */
384 		text = g_strdup_printf (ngettext (
385 			"You have received %d new message.",
386 			"You have received %d new messages.",
387 			status_count), status_count);
388 
389 		g_free (folder_name);
390 
391 		if (t->msg_sender) {
392 			gchar *tmp, *str;
393 
394 			/* Translators: "From:" is preceding a new mail
395 			 * sender address, like "From: user@example.com" */
396 			str = g_strdup_printf (_("From: %s"), t->msg_sender);
397 			tmp = g_strconcat (text, "\n", str, NULL);
398 
399 			g_free (text);
400 			g_free (str);
401 
402 			text = tmp;
403 		}
404 
405 		if (t->msg_subject) {
406 			gchar *tmp, *str;
407 
408 			/* Translators: "Subject:" is preceding a new mail
409 			 * subject, like "Subject: It happened again" */
410 			str = g_strdup_printf (_("Subject: %s"), t->msg_subject);
411 			tmp = g_strconcat (text, "\n", str, NULL);
412 
413 			g_free (text);
414 			g_free (str);
415 
416 			text = tmp;
417 		}
418 	} else {
419 		status_count += t->new;
420 		text = g_strdup_printf (ngettext (
421 			"You have received %d new message.",
422 			"You have received %d new messages.",
423 			status_count), status_count);
424 	}
425 
426 	icon_name = "evolution";
427 	summary = _("New email in Evolution");
428 	escaped_text = g_markup_escape_text (text, strlen (text));
429 
430 	if (notify) {
431 		notify_notification_update (
432 			notify, summary, escaped_text, icon_name);
433 	} else {
434 		if (!notify_init ("evolution-mail-notification"))
435 			fprintf (stderr,"notify init error");
436 
437 		notify  = notify_notification_new (
438 			summary, escaped_text, icon_name);
439 
440 		notify_notification_set_urgency (
441 			notify, NOTIFY_URGENCY_NORMAL);
442 
443 		notify_notification_set_timeout (
444 			notify, NOTIFY_EXPIRES_DEFAULT);
445 
446 		/* Check if actions are supported */
447 		if (can_support_actions ()) {
448 			gchar *label;
449 			gchar *folder_uri;
450 
451 			/* NotifyAction takes ownership. */
452 			folder_uri = e_mail_folder_uri_build (
453 				t->store, t->folder_name);
454 
455 			label = g_strdup_printf (
456 				/* Translators: The '%s' is a mail
457 				 * folder name.  (e.g. "Show Inbox") */
458 				_("Show %s"), t->display_name);
459 
460 			notify_notification_add_action (
461 				notify, "default", label,
462 				(NotifyActionCallback)
463 				notify_default_action_cb,
464 				folder_uri,
465 				(GFreeFunc) g_free);
466 
467 			g_free (label);
468 		}
469 	}
470 
471 	g_idle_add_full (
472 		G_PRIORITY_DEFAULT_IDLE,
473 		(GSourceFunc) notification_callback,
474 		g_object_ref (notify),
475 		(GDestroyNotify) g_object_unref);
476 
477 	g_free (escaped_text);
478 	g_free (text);
479 }
480 
481 static void
482 read_notify_status (EMEventTargetMessage *t)
483 {
484 	remove_notification ();
485 }
486 #endif
487 
488 /* -------------------------------------------------------------------  */
489 /*                         Sound part                                   */
490 /* -------------------------------------------------------------------  */
491 
492 /* min no. seconds between newmail notifications */
493 #define NOTIFY_THROTTLE 30
494 
495 #define CONF_KEY_SOUND_BEEP		"notify-sound-beep"
496 #define CONF_KEY_SOUND_FILE		"notify-sound-file"
497 #define CONF_KEY_SOUND_PLAY_FILE	"notify-sound-play-file"
498 #define CONF_KEY_SOUND_USE_THEME        "notify-sound-use-theme"
499 
500 #ifdef HAVE_CANBERRA
501 static ca_context *mailnotification = NULL;
502 #endif
503 
504 static void
505 do_play_sound (gboolean beep,
506                gboolean use_theme,
507                const gchar *file)
508 {
509 	if (!beep) {
510 #ifdef HAVE_CANBERRA
511 		if (!use_theme && file && *file)
512 			ca_context_play (
513 				mailnotification, 0,
514 				CA_PROP_MEDIA_FILENAME, file,
515 				NULL);
516 		else
517 			ca_context_play (
518 				mailnotification, 0,
519 				CA_PROP_EVENT_ID,"message-new-email",
520 				NULL);
521 #endif
522 	} else
523 		gdk_beep ();
524 }
525 
526 struct _SoundConfigureWidgets {
527 	GtkToggleButton *enable;
528 	GtkToggleButton *beep;
529 	GtkToggleButton *use_theme;
530 	GtkFileChooser *filechooser;
531 };
532 
533 static void
534 sound_file_set_cb (GtkFileChooser *file_chooser,
535                    gpointer data)
536 {
537 	gchar *file;
538 	GSettings *settings;
539 
540 	settings = g_settings_new ("org.gnome.evolution.plugin.mail-notification");
541 	file = gtk_file_chooser_get_filename (file_chooser);
542 
543 	g_settings_set_string (settings, CONF_KEY_SOUND_FILE, (file != NULL) ? file : "");
544 
545 	g_object_unref (settings);
546 	g_free (file);
547 }
548 
549 static void
550 sound_play_cb (GtkWidget *widget,
551                struct _SoundConfigureWidgets *scw)
552 {
553 	gchar *file;
554 
555 	if (!gtk_toggle_button_get_active (scw->enable))
556 		return;
557 
558 	file = gtk_file_chooser_get_filename (scw->filechooser);
559 
560 	do_play_sound (
561 		gtk_toggle_button_get_active (scw->beep),
562 		gtk_toggle_button_get_active (scw->use_theme),
563 		file);
564 
565 	g_free (file);
566 }
567 
568 struct _SoundNotifyData {
569 	time_t last_notify;
570 	guint notify_idle_id;
571 };
572 
573 static gboolean
574 sound_notify_idle_cb (gpointer user_data)
575 {
576 	gchar *file;
577 	GSettings *settings;
578 	struct _SoundNotifyData *data = (struct _SoundNotifyData *) user_data;
579 
580 	g_return_val_if_fail (data != NULL, FALSE);
581 
582 	settings = g_settings_new ("org.gnome.evolution.plugin.mail-notification");
583 	file = g_settings_get_string (settings, CONF_KEY_SOUND_FILE);
584 
585 	do_play_sound (
586 		is_part_enabled (CONF_KEY_SOUND_BEEP),
587 		is_part_enabled (CONF_KEY_SOUND_USE_THEME),
588 		file);
589 
590 	g_object_unref (settings);
591 	g_free (file);
592 
593 	time (&data->last_notify);
594 
595 	data->notify_idle_id = 0;
596 
597 	return FALSE;
598 }
599 
600 /* -------------------------------------------------------------------  */
601 
602 static void
603 new_notify_sound (EMEventTargetFolder *t)
604 {
605 	time_t last_newmail;
606 	static struct _SoundNotifyData data = {0, 0};
607 
608 	time (&last_newmail);
609 
610 	/* just put it to the idle queue */
611 	if (data.notify_idle_id == 0 &&
612 		(last_newmail - data.last_notify >= NOTIFY_THROTTLE))
613 		data.notify_idle_id = g_idle_add_full (
614 			G_PRIORITY_LOW, sound_notify_idle_cb, &data, NULL);
615 }
616 
617 static void
618 read_notify_sound (EMEventTargetMessage *t)
619 {
620 	/* we do nothing here */
621 }
622 
623 static void
624 enable_sound (gint enable)
625 {
626 #ifdef HAVE_CANBERRA
627 	if (enable) {
628 		ca_context_create (&mailnotification);
629 		ca_context_change_props (
630 			mailnotification,
631 			CA_PROP_APPLICATION_NAME,
632 			"mailnotification Plugin",
633 			NULL);
634 	}
635 	else
636 		ca_context_destroy (mailnotification);
637 #endif
638 }
639 
640 static GtkWidget *
641 get_config_widget_sound (void)
642 {
643 	GtkWidget *vbox;
644 	GtkWidget *container;
645 	GtkWidget *master;
646 	GtkWidget *widget;
647 	gchar *file;
648 	GSettings *settings;
649 	GSList *group = NULL;
650 	struct _SoundConfigureWidgets *scw;
651 	const gchar *text;
652 
653 	scw = g_malloc0 (sizeof (struct _SoundConfigureWidgets));
654 
655 	vbox = gtk_vbox_new (FALSE, 6);
656 	gtk_widget_show (vbox);
657 
658 	container = vbox;
659 
660 	text = _("_Play sound when a new message arrives");
661 	widget = gtk_check_button_new_with_mnemonic (text);
662 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
663 	gtk_widget_show (widget);
664 
665 	settings = g_settings_new ("org.gnome.evolution.plugin.mail-notification");
666 
667 	g_settings_bind (
668 		settings, CONF_KEY_ENABLED_SOUND,
669 		widget, "active", G_SETTINGS_BIND_DEFAULT);
670 
671 	master = widget;
672 	scw->enable = GTK_TOGGLE_BUTTON (widget);
673 
674 	widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
675 	gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0);
676 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
677 	gtk_widget_show (widget);
678 
679 	g_object_bind_property (
680 		master, "active",
681 		widget, "sensitive",
682 		G_BINDING_SYNC_CREATE);
683 
684 	container = widget;
685 
686 	widget = gtk_vbox_new (FALSE, 6);
687 	gtk_container_add (GTK_CONTAINER (container), widget);
688 	gtk_widget_show (widget);
689 
690 	container = widget;
691 
692 	text = _("_Beep");
693 	widget = gtk_radio_button_new_with_mnemonic (group, text);
694 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
695 	gtk_widget_show (widget);
696 
697 	g_settings_bind (
698 		settings, CONF_KEY_SOUND_BEEP,
699 		widget, "active", G_SETTINGS_BIND_DEFAULT);
700 
701 	scw->beep = GTK_TOGGLE_BUTTON (widget);
702 
703 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
704 
705 	text = _("Use sound _theme");
706 	widget = gtk_radio_button_new_with_mnemonic (group, text);
707 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
708 	gtk_widget_show (widget);
709 
710 	g_settings_bind (
711 		settings, CONF_KEY_SOUND_USE_THEME,
712 		widget, "active", G_SETTINGS_BIND_DEFAULT);
713 
714 	scw->use_theme = GTK_TOGGLE_BUTTON (widget);
715 
716 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
717 
718 	widget = gtk_hbox_new (FALSE, 6);
719 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
720 	gtk_widget_show (widget);
721 
722 	container = widget;
723 
724 	text = _("Play _file:");
725 	widget = gtk_radio_button_new_with_mnemonic (group, text);
726 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
727 	gtk_widget_show (widget);
728 
729 	g_settings_bind (
730 		settings, CONF_KEY_SOUND_PLAY_FILE,
731 		widget, "active", G_SETTINGS_BIND_DEFAULT);
732 
733 	text = _("Select sound file");
734 	widget = gtk_file_chooser_button_new (
735 		text, GTK_FILE_CHOOSER_ACTION_OPEN);
736 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
737 	gtk_widget_show (widget);
738 
739 	scw->filechooser = GTK_FILE_CHOOSER (widget);
740 
741 	widget = gtk_button_new ();
742 	gtk_button_set_image (
743 		GTK_BUTTON (widget), gtk_image_new_from_icon_name (
744 		"media-playback-start", GTK_ICON_SIZE_BUTTON));
745 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
746 	gtk_widget_show (widget);
747 
748 	g_signal_connect (
749 		widget, "clicked",
750 		G_CALLBACK (sound_play_cb), scw);
751 
752 	file = g_settings_get_string (settings, CONF_KEY_SOUND_FILE);
753 
754 	if (file && *file)
755 		gtk_file_chooser_set_filename (scw->filechooser, file);
756 
757 	g_object_unref (settings);
758 	g_free (file);
759 
760 	g_signal_connect (
761 		scw->filechooser, "file-set",
762 		G_CALLBACK (sound_file_set_cb), scw);
763 
764 	/* to let structure free properly */
765 	g_object_set_data_full (G_OBJECT (vbox), "scw-data", scw, g_free);
766 
767 	return vbox;
768 }
769 
770 /* -------------------------------------------------------------------  */
771 /*                     Plugin itself part                               */
772 /* -------------------------------------------------------------------  */
773 
774 static GtkWidget *
775 get_cfg_widget (void)
776 {
777 	GtkWidget *container;
778 	GtkWidget *widget;
779 	GSettings *settings;
780 	const gchar *text;
781 
782 	settings = g_settings_new ("org.gnome.evolution.plugin.mail-notification");
783 
784 	widget = gtk_vbox_new (FALSE, 12);
785 	gtk_widget_show (widget);
786 
787 	container = widget;
788 
789 	text = _("Notify new messages for _Inbox only");
790 	widget = gtk_check_button_new_with_mnemonic (text);
791 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
792 	gtk_widget_show (widget);
793 
794 	g_settings_bind (
795 		settings, CONF_KEY_NOTIFY_ONLY_INBOX,
796 		widget, "active", G_SETTINGS_BIND_DEFAULT);
797 
798 #ifdef HAVE_LIBNOTIFY
799 	text = _("Show _notification when a new message arrives");
800 	widget = gtk_check_button_new_with_mnemonic (text);
801 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
802 	gtk_widget_show (widget);
803 
804 	g_settings_bind (
805 		settings, CONF_KEY_ENABLED_STATUS,
806 		widget, "active", G_SETTINGS_BIND_DEFAULT);
807 #endif
808 
809 	widget = get_config_widget_sound ();
810 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
811 
812 	g_object_unref (settings);
813 
814 	return container;
815 }
816 
817 void org_gnome_mail_new_notify (EPlugin *ep, EMEventTargetFolder *t);
818 void org_gnome_mail_read_notify (EPlugin *ep, EMEventTargetMessage *t);
819 
820 gint e_plugin_lib_enable (EPlugin *ep, gint enable);
821 GtkWidget *e_plugin_lib_get_configure_widget (EPlugin *epl);
822 
823 void
824 org_gnome_mail_new_notify (EPlugin *ep,
825                            EMEventTargetFolder *t)
826 {
827 	g_return_if_fail (t != NULL);
828 
829 	if (!enabled || !t->new || (!t->is_inbox &&
830 		is_part_enabled (CONF_KEY_NOTIFY_ONLY_INBOX)))
831 		return;
832 
833 	g_static_mutex_lock (&mlock);
834 
835 	new_notify_dbus (t);
836 
837 #ifdef HAVE_LIBNOTIFY
838 	if (is_part_enabled (CONF_KEY_ENABLED_STATUS))
839 		new_notify_status (t);
840 #endif
841 
842 	if (is_part_enabled (CONF_KEY_ENABLED_SOUND))
843 		new_notify_sound (t);
844 
845 	g_static_mutex_unlock (&mlock);
846 }
847 
848 void
849 org_gnome_mail_read_notify (EPlugin *ep,
850                             EMEventTargetMessage *t)
851 {
852 	g_return_if_fail (t != NULL);
853 
854 	if (!enabled)
855 		return;
856 
857 	g_static_mutex_lock (&mlock);
858 
859 	read_notify_dbus (t);
860 
861 #ifdef HAVE_LIBNOTIFY
862 	if (is_part_enabled (CONF_KEY_ENABLED_STATUS))
863 		read_notify_status (t);
864 #endif
865 
866 	if (is_part_enabled (CONF_KEY_ENABLED_SOUND))
867 		read_notify_sound (t);
868 
869 	g_static_mutex_unlock (&mlock);
870 }
871 
872 gint
873 e_plugin_lib_enable (EPlugin *ep,
874                      gint enable)
875 {
876 	if (enable) {
877 		enable_dbus (enable);
878 
879 		if (is_part_enabled (CONF_KEY_ENABLED_SOUND))
880 			enable_sound (enable);
881 
882 		enabled = TRUE;
883 	} else {
884 		enable_dbus (enable);
885 		enable_sound (enable);
886 
887 		enabled = FALSE;
888 	}
889 
890 	return 0;
891 }
892 
893 GtkWidget *
894 e_plugin_lib_get_configure_widget (EPlugin *epl)
895 {
896 	return get_cfg_widget ();
897 }