support image/x-eps format via pdf_viewer
[claws.git] / src / plugins / notification / notification_plugin.c
blob9b883cce96602a57be3d2f39a0c70d857e920d4d
1 /* Notification plugin for Claws Mail
2 * Copyright (C) 2005-2007 Holger Berndt
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
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
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 # include "claws-features.h"
21 #endif
23 #include <glib.h>
24 #include <glib/gi18n.h>
26 #include "common/claws.h"
27 #include "common/version.h"
28 #include "common/utils.h"
29 #include "common/defs.h"
30 #include "folder.h"
31 #include "common/hooks.h"
32 #include "procmsg.h"
33 #include "mainwindow.h"
34 #include "main.h"
35 #include "gtk/gtkutils.h"
37 #include "notification_plugin.h"
38 #include "notification_core.h"
39 #include "notification_prefs.h"
40 #include "notification_ayatana_indicator.h"
41 #include "notification_banner.h"
42 #include "notification_lcdproc.h"
43 #include "notification_trayicon.h"
44 #include "notification_indicator.h"
45 #include "notification_hotkeys.h"
46 #include "notification_foldercheck.h"
47 #include "notification_pixbuf.h"
48 #include "plugin.h"
50 #if HAVE_LIBNOTIFY
51 # include <libnotify/notify.h>
52 #endif
54 /* delay in ms until the tray icon shall be embedded in the
55 system tray before it is assumed that the tray doesn't
56 work and the main window is shown again */
57 #define CM_NOTIFICATION_TRAYICON_SAFETY_NET_DELAY_MS 5000
59 static gboolean my_folder_item_update_hook(gpointer, gpointer);
60 static gboolean my_folder_update_hook(gpointer, gpointer);
61 static gboolean my_msginfo_update_hook(gpointer, gpointer);
62 static gboolean my_offline_switch_hook(gpointer, gpointer);
63 static gboolean my_main_window_close_hook(gpointer, gpointer);
64 static gboolean my_main_window_got_iconified_hook(gpointer, gpointer);
65 static gboolean my_account_list_changed_hook(gpointer, gpointer);
66 static gboolean my_update_theme_hook(gpointer, gpointer);
68 #ifdef NOTIFICATION_TRAYICON
69 static gboolean trayicon_startup_idle(gpointer);
70 #endif
72 static gulong hook_f_item;
73 static gulong hook_f;
74 static gulong hook_m_info;
75 static gulong hook_offline;
76 static gulong hook_mw_close;
77 static gulong hook_got_iconified;
78 static gulong hook_account;
79 static gulong hook_theme_changed;
81 #ifdef NOTIFICATION_BANNER
82 static GSList* banner_collected_msgs;
83 #endif
85 void notification_update_urgency_hint(void)
87 MainWindow *mainwin;
88 mainwin = mainwindow_get_mainwindow();
89 if(mainwin) {
90 NotificationMsgCount count;
91 gboolean active;
92 active = FALSE;
93 if(notify_config.urgency_hint_new || notify_config.urgency_hint_unread) {
94 notification_core_get_msg_count(NULL, &count);
95 if(notify_config.urgency_hint_new)
96 active = (active || (count.new_msgs > 0));
97 if(notify_config.urgency_hint_unread)
98 active = (active || (count.unread_msgs > 0));
100 gtk_window_set_urgency_hint(GTK_WINDOW(mainwin->window), active);
104 static gboolean my_account_list_changed_hook(gpointer source,
105 gpointer data)
107 gboolean retVal = FALSE;
109 #ifdef NOTIFICATION_TRAYICON
110 notification_update_msg_counts(NULL);
111 retVal = notification_trayicon_account_list_changed(source, data);
113 #endif
114 return retVal;
117 static gboolean my_update_theme_hook(gpointer source, gpointer data)
119 notification_pixbuf_free_all();
120 #ifdef NOTIFICATION_TRAYICON
121 notification_update_trayicon();
122 #endif
123 return FALSE;
126 static gboolean my_main_window_got_iconified_hook(gpointer source,
127 gpointer data)
129 gboolean retVal = FALSE;
130 #ifdef NOTIFICATION_TRAYICON
131 notification_update_msg_counts(NULL);
132 retVal = notification_trayicon_main_window_got_iconified(source, data);
133 #endif
134 return retVal;
137 static gboolean my_main_window_close_hook(gpointer source, gpointer data)
139 gboolean retVal = FALSE;
140 #ifdef NOTIFICATION_TRAYICON
141 notification_update_msg_counts(NULL);
142 retVal = notification_trayicon_main_window_close(source, data);
143 #endif
144 return retVal;
147 static gboolean my_offline_switch_hook(gpointer source, gpointer data)
149 #ifdef NOTIFICATION_TRAYICON
150 notification_update_msg_counts(NULL);
151 #endif
152 return FALSE;
155 static gboolean my_folder_item_update_hook(gpointer source, gpointer data)
157 FolderItemUpdateData *update_data = source;
158 FolderType ftype;
159 gchar *uistr;
161 g_return_val_if_fail(source != NULL, FALSE);
163 if (folder_has_parent_of_type(update_data->item, F_DRAFT))
164 return FALSE;
166 #if defined(NOTIFICATION_LCDPROC) || defined(NOTIFICATION_TRAYICON) || defined(NOTIFICATION_AYATANA_INDICATOR) || defined(NOTIFICATION_INDICATOR)
167 notification_update_msg_counts(NULL);
168 #else
169 if(notify_config.urgency_hint_new || notify_config.urgency_hint_unread)
170 notification_update_msg_counts(NULL);
171 #endif
173 /* Check if the folder types is to be notified about */
174 ftype = update_data->item->folder->klass->type;
175 uistr = update_data->item->folder->klass->uistr;
176 if(!notify_include_folder_type(ftype, uistr))
177 return FALSE;
179 if(update_data->update_flags & F_ITEM_UPDATE_MSGCNT) {
180 #ifdef NOTIFICATION_BANNER
181 notification_update_banner();
182 #endif
183 #if defined(NOTIFICATION_POPUP) || defined(NOTIFICATION_COMMAND)
184 notification_new_unnotified_msgs(update_data);
185 #endif
187 return FALSE;
190 static gboolean my_folder_update_hook(gpointer source, gpointer data)
192 FolderUpdateData *hookdata;
194 g_return_val_if_fail(source != NULL, FALSE);
195 hookdata = source;
197 #if defined(NOTIFICATION_LCDPROC) || defined(NOTIFICATION_TRAYICON)
198 if(hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM)
199 notification_update_msg_counts(hookdata->item);
200 else
201 notification_update_msg_counts(NULL);
202 #endif
204 return FALSE;
209 static gboolean my_msginfo_update_hook(gpointer source, gpointer data)
211 return notification_notified_hash_msginfo_update((MsgInfoUpdate*)source);
214 gint plugin_init(gchar **error)
216 gchar *rcpath;
218 /* Version check */
219 /* No be able to test against new-contacts */
220 if(!check_plugin_version(MAKE_NUMERIC_VERSION(3,8,1,46),
221 VERSION_NUMERIC, _("Notification"), error))
222 return -1;
224 hook_f_item = hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST,
225 my_folder_item_update_hook, NULL);
226 if(hook_f_item == 0) {
227 *error = g_strdup(_("Failed to register folder item update hook in the "
228 "Notification plugin"));
229 return -1;
232 hook_f = hooks_register_hook(FOLDER_UPDATE_HOOKLIST,
233 my_folder_update_hook, NULL);
234 if(hook_f == 0) {
235 *error = g_strdup(_("Failed to register folder update hook in the "
236 "Notification plugin"));
237 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
238 return -1;
242 hook_m_info = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST,
243 my_msginfo_update_hook, NULL);
244 if(hook_m_info == 0) {
245 *error = g_strdup(_("Failed to register msginfo update hook in the "
246 "Notification plugin"));
247 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
248 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
249 return -1;
252 hook_offline = hooks_register_hook(OFFLINE_SWITCH_HOOKLIST,
253 my_offline_switch_hook, NULL);
254 if(hook_offline == 0) {
255 *error = g_strdup(_("Failed to register offline switch hook in the "
256 "Notification plugin"));
257 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
258 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
259 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
260 return -1;
263 hook_mw_close = hooks_register_hook(MAIN_WINDOW_CLOSE,
264 my_main_window_close_hook, NULL);
265 if(hook_mw_close == 0) {
266 *error = g_strdup(_("Failed to register main window close hook in the "
267 "Notification plugin"));
268 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
269 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
270 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
271 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
272 return -1;
275 hook_got_iconified = hooks_register_hook(MAIN_WINDOW_GOT_ICONIFIED,
276 my_main_window_got_iconified_hook,
277 NULL);
278 if(hook_got_iconified == 0) {
279 *error = g_strdup(_("Failed to register got iconified hook in the "
280 "Notification plugin"));
281 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
282 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
283 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
284 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
285 hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
286 return -1;
289 hook_account = hooks_register_hook(ACCOUNT_LIST_CHANGED_HOOKLIST,
290 my_account_list_changed_hook, NULL);
291 if (hook_account == 0) {
292 *error = g_strdup(_("Failed to register account list changed hook in the "
293 "Notification plugin"));
294 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
295 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
296 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
297 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
298 hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
299 hooks_unregister_hook(MAIN_WINDOW_GOT_ICONIFIED, hook_got_iconified);
300 return -1;
303 hook_theme_changed = hooks_register_hook(THEME_CHANGED_HOOKLIST, my_update_theme_hook, NULL);
304 if(hook_theme_changed == 0) {
305 *error = g_strdup(_("Failed to register theme change hook in the "
306 "Notification plugin"));
307 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
308 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
309 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
310 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
311 hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
312 hooks_unregister_hook(MAIN_WINDOW_GOT_ICONIFIED, hook_got_iconified);
313 hooks_unregister_hook(ACCOUNT_LIST_CHANGED_HOOKLIST, hook_account);
314 return -1;
317 /* Configuration */
318 prefs_set_default(notify_param);
319 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
320 prefs_read_config(notify_param, "NotificationPlugin", rcpath, NULL);
321 g_free(rcpath);
323 /* Folder specific stuff */
324 notification_foldercheck_read_array();
326 notification_notified_hash_startup_init();
328 notify_gtk_init();
330 #ifdef NOTIFICATION_AYATANA_INDICATOR
331 notification_ayatana_indicator_enable();
332 #endif
333 #ifdef NOTIFICATION_INDICATOR
334 notification_indicator_setup();
335 #endif
336 #ifdef NOTIFICATION_BANNER
337 notification_update_banner();
338 #endif
339 #ifdef NOTIFICATION_LCDPROC
340 notification_lcdproc_connect();
341 #endif
342 #ifdef NOTIFICATION_TRAYICON
343 if(notify_config.trayicon_enabled &&
344 notify_config.trayicon_hide_at_startup && claws_is_starting()) {
345 MainWindow *mainwin = mainwindow_get_mainwindow();
347 g_timeout_add(CM_NOTIFICATION_TRAYICON_SAFETY_NET_DELAY_MS, trayicon_startup_idle,NULL);
348 if(mainwin && gtk_widget_get_visible(GTK_WIDGET(mainwin->window)))
349 main_window_hide(mainwin);
350 main_set_show_at_startup(FALSE);
352 #endif
353 my_account_list_changed_hook(NULL,NULL);
355 if(notify_config.urgency_hint_new || notify_config.urgency_hint_unread)
356 notification_update_msg_counts(NULL);
358 #ifdef NOTIFICATION_HOTKEYS
359 notification_hotkeys_update_bindings();
360 #endif
362 debug_print("Notification plugin loaded\n");
364 return 0;
367 gboolean plugin_done(void)
369 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
370 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
371 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
372 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
373 hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
374 hooks_unregister_hook(MAIN_WINDOW_GOT_ICONIFIED, hook_got_iconified);
375 hooks_unregister_hook(ACCOUNT_LIST_CHANGED_HOOKLIST, hook_account);
376 hooks_unregister_hook(THEME_CHANGED_HOOKLIST, hook_theme_changed);
378 notify_save_config();
380 notify_gtk_done();
382 /* foldercheck cleanup */
383 notification_foldercheck_write_array();
384 notification_free_folder_specific_array();
386 #ifdef NOTIFICATION_AYATANA_INDICATOR
387 notification_ayatana_indicator_disable();
388 #endif
389 #ifdef NOTIFICATION_BANNER
390 notification_collected_msgs_free(banner_collected_msgs);
391 banner_collected_msgs = NULL;
392 notification_banner_destroy();
393 #endif
394 #ifdef NOTIFICATION_LCDPROC
395 notification_lcdproc_disconnect();
396 #endif
397 #ifdef NOTIFICATION_TRAYICON
398 notification_trayicon_destroy();
399 #endif
400 #ifdef NOTIFICATION_INDICATOR
401 notification_indicator_destroy();
402 #endif
403 notification_core_free();
405 #ifdef HAVE_LIBNOTIFY
406 if(notify_is_initted())
407 notify_uninit();
408 #endif
410 #ifdef NOTIFICATION_HOTKEYS
411 notification_hotkeys_unbind_all();
412 #endif
414 notification_pixbuf_free_all();
416 debug_print("Notification plugin unloaded\n");
418 /* Returning FALSE here means that g_module_close() will not be called on the plugin.
419 * This is necessary, as needed libraries are not designed to be unloaded. */
420 return FALSE;
423 const gchar *plugin_name(void)
425 return _("Notification");
428 const gchar *plugin_desc(void)
430 return _("This plugin provides various ways "
431 "to notify the user of new and unread email.\n"
432 "The plugin is extensively configurable in the "
433 "plugins section of the preferences dialog.\n\n"
434 "Feedback to <berndth@gmx.de> is welcome.");
437 const gchar *plugin_type(void)
439 return "GTK3";
442 const gchar *plugin_licence(void)
444 return "GPL3+";
447 const gchar *plugin_version(void)
449 return VERSION;
452 struct PluginFeature *plugin_provides(void)
454 static struct PluginFeature features[] =
455 { {PLUGIN_NOTIFIER, N_("Various tools")},
456 {PLUGIN_NOTHING, NULL}};
457 return features;
460 #ifdef NOTIFICATION_BANNER
461 void notification_update_banner(void)
463 notification_collected_msgs_free(banner_collected_msgs);
464 banner_collected_msgs = NULL;
466 if(notify_config.banner_show != NOTIFY_BANNER_SHOW_NEVER) {
467 guint id;
468 GSList *folder_list = NULL;
470 if(notify_config.banner_folder_specific) {
471 id = notification_register_folder_specific_list
472 (BANNER_SPECIFIC_FOLDER_ID_STR);
473 folder_list = notification_foldercheck_get_list(id);
476 if(!(notify_config.banner_folder_specific && (folder_list == NULL)))
477 banner_collected_msgs =
478 notification_collect_msgs(notify_config.banner_include_unread,
479 notify_config.banner_folder_specific ?
480 folder_list : NULL, notify_config.banner_max_msgs);
483 notification_banner_show(banner_collected_msgs);
485 #endif
487 #ifdef NOTIFICATION_TRAYICON
488 static gboolean trayicon_startup_idle(gpointer data)
490 /* if the trayicon is not available,
491 simulate click on it to show mainwindow */
492 if(!notification_trayicon_is_available())
493 notification_trayicon_on_activate(NULL,data);
494 return FALSE;
496 #endif