Remove inclusion of sys/socket.h from nntp-thread.c
[claws.git] / src / plugins / notification / notification_plugin.c
blobd946a2eca51f4d172af9a79e413de47b40d799a3
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_banner.h"
41 #include "notification_lcdproc.h"
42 #include "notification_trayicon.h"
43 #include "notification_indicator.h"
44 #include "notification_hotkeys.h"
45 #include "notification_foldercheck.h"
46 #include "notification_pixbuf.h"
47 #include "plugin.h"
49 #if HAVE_LIBNOTIFY
50 # include <libnotify/notify.h>
51 #endif
53 /* delay in ms until the tray icon shall be embedded in the
54 system tray before it is assumed that the tray doesn't
55 work and the main window is shown again */
56 #define CM_NOTIFICATION_TRAYICON_SAFETY_NET_DELAY_MS 5000
58 static gboolean my_folder_item_update_hook(gpointer, gpointer);
59 static gboolean my_folder_update_hook(gpointer, gpointer);
60 static gboolean my_msginfo_update_hook(gpointer, gpointer);
61 static gboolean my_offline_switch_hook(gpointer, gpointer);
62 static gboolean my_main_window_close_hook(gpointer, gpointer);
63 static gboolean my_main_window_got_iconified_hook(gpointer, gpointer);
64 static gboolean my_account_list_changed_hook(gpointer, gpointer);
65 static gboolean my_update_theme_hook(gpointer, gpointer);
67 #ifdef NOTIFICATION_TRAYICON
68 static gboolean trayicon_startup_idle(gpointer);
69 #endif
71 static gulong hook_f_item;
72 static gulong hook_f;
73 static gulong hook_m_info;
74 static gulong hook_offline;
75 static gulong hook_mw_close;
76 static gulong hook_got_iconified;
77 static gulong hook_account;
78 static gulong hook_theme_changed;
80 #ifdef NOTIFICATION_BANNER
81 static GSList* banner_collected_msgs;
82 #endif
84 void notification_update_urgency_hint(void)
86 MainWindow *mainwin;
87 mainwin = mainwindow_get_mainwindow();
88 if(mainwin) {
89 NotificationMsgCount count;
90 gboolean active;
91 active = FALSE;
92 if(notify_config.urgency_hint_new || notify_config.urgency_hint_unread) {
93 notification_core_get_msg_count(NULL, &count);
94 if(notify_config.urgency_hint_new)
95 active = (active || (count.new_msgs > 0));
96 if(notify_config.urgency_hint_unread)
97 active = (active || (count.unread_msgs > 0));
99 gtk_window_set_urgency_hint(GTK_WINDOW(mainwin->window), active);
103 static gboolean my_account_list_changed_hook(gpointer source,
104 gpointer data)
106 gboolean retVal = FALSE;
108 #ifdef NOTIFICATION_TRAYICON
109 notification_update_msg_counts(NULL);
110 retVal = notification_trayicon_account_list_changed(source, data);
112 #endif
113 return retVal;
116 static gboolean my_update_theme_hook(gpointer source, gpointer data)
118 notification_pixbuf_free_all();
119 #ifdef NOTIFICATION_TRAYICON
120 notification_update_trayicon();
121 #endif
122 return FALSE;
125 static gboolean my_main_window_got_iconified_hook(gpointer source,
126 gpointer data)
128 gboolean retVal = FALSE;
129 #ifdef NOTIFICATION_TRAYICON
130 notification_update_msg_counts(NULL);
131 retVal = notification_trayicon_main_window_got_iconified(source, data);
132 #endif
133 return retVal;
136 static gboolean my_main_window_close_hook(gpointer source, gpointer data)
138 gboolean retVal = FALSE;
139 #ifdef NOTIFICATION_TRAYICON
140 notification_update_msg_counts(NULL);
141 retVal = notification_trayicon_main_window_close(source, data);
142 #endif
143 return retVal;
146 static gboolean my_offline_switch_hook(gpointer source, gpointer data)
148 #ifdef NOTIFICATION_TRAYICON
149 notification_update_msg_counts(NULL);
150 #endif
151 return FALSE;
154 static gboolean my_folder_item_update_hook(gpointer source, gpointer data)
156 FolderItemUpdateData *update_data = source;
157 FolderType ftype;
158 gchar *uistr;
160 g_return_val_if_fail(source != NULL, FALSE);
162 if (folder_has_parent_of_type(update_data->item, F_DRAFT))
163 return FALSE;
165 #if defined(NOTIFICATION_LCDPROC) || defined(NOTIFICATION_TRAYICON) || defined(NOTIFICATION_INDICATOR)
166 notification_update_msg_counts(NULL);
167 #else
168 if(notify_config.urgency_hint_new || notify_config.urgency_hint_unread)
169 notification_update_msg_counts(NULL);
170 #endif
172 /* Check if the folder types is to be notified about */
173 ftype = update_data->item->folder->klass->type;
174 uistr = update_data->item->folder->klass->uistr;
175 if(!notify_include_folder_type(ftype, uistr))
176 return FALSE;
178 if(update_data->update_flags & F_ITEM_UPDATE_MSGCNT) {
179 #ifdef NOTIFICATION_BANNER
180 notification_update_banner();
181 #endif
182 #if defined(NOTIFICATION_POPUP) || defined(NOTIFICATION_COMMAND)
183 notification_new_unnotified_msgs(update_data);
184 #endif
186 return FALSE;
189 static gboolean my_folder_update_hook(gpointer source, gpointer data)
191 FolderUpdateData *hookdata;
193 g_return_val_if_fail(source != NULL, FALSE);
194 hookdata = source;
196 #if defined(NOTIFICATION_LCDPROC) || defined(NOTIFICATION_TRAYICON)
197 if(hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM)
198 notification_update_msg_counts(hookdata->item);
199 else
200 notification_update_msg_counts(NULL);
201 #endif
203 return FALSE;
208 static gboolean my_msginfo_update_hook(gpointer source, gpointer data)
210 return notification_notified_hash_msginfo_update((MsgInfoUpdate*)source);
213 gint plugin_init(gchar **error)
215 gchar *rcpath;
217 /* Version check */
218 /* No be able to test against new-contacts */
219 if(!check_plugin_version(MAKE_NUMERIC_VERSION(3,8,1,46),
220 VERSION_NUMERIC, _("Notification"), error))
221 return -1;
223 hook_f_item = hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST,
224 my_folder_item_update_hook, NULL);
225 if(hook_f_item == 0) {
226 *error = g_strdup(_("Failed to register folder item update hook in the "
227 "Notification plugin"));
228 return -1;
231 hook_f = hooks_register_hook(FOLDER_UPDATE_HOOKLIST,
232 my_folder_update_hook, NULL);
233 if(hook_f == 0) {
234 *error = g_strdup(_("Failed to register folder update hook in the "
235 "Notification plugin"));
236 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
237 return -1;
241 hook_m_info = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST,
242 my_msginfo_update_hook, NULL);
243 if(hook_m_info == 0) {
244 *error = g_strdup(_("Failed to register msginfo update hook in the "
245 "Notification plugin"));
246 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
247 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
248 return -1;
251 hook_offline = hooks_register_hook(OFFLINE_SWITCH_HOOKLIST,
252 my_offline_switch_hook, NULL);
253 if(hook_offline == 0) {
254 *error = g_strdup(_("Failed to register offline switch hook in the "
255 "Notification plugin"));
256 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
257 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
258 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
259 return -1;
262 hook_mw_close = hooks_register_hook(MAIN_WINDOW_CLOSE,
263 my_main_window_close_hook, NULL);
264 if(hook_mw_close == 0) {
265 *error = g_strdup(_("Failed to register main window close hook in the "
266 "Notification plugin"));
267 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
268 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
269 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
270 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
271 return -1;
274 hook_got_iconified = hooks_register_hook(MAIN_WINDOW_GOT_ICONIFIED,
275 my_main_window_got_iconified_hook,
276 NULL);
277 if(hook_got_iconified == 0) {
278 *error = g_strdup(_("Failed to register got iconified hook in the "
279 "Notification plugin"));
280 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
281 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
282 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
283 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
284 hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
285 return -1;
288 hook_account = hooks_register_hook(ACCOUNT_LIST_CHANGED_HOOKLIST,
289 my_account_list_changed_hook, NULL);
290 if (hook_account == 0) {
291 *error = g_strdup(_("Failed to register account list changed hook in the "
292 "Notification plugin"));
293 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
294 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
295 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
296 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
297 hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
298 hooks_unregister_hook(MAIN_WINDOW_GOT_ICONIFIED, hook_got_iconified);
299 return -1;
302 hook_theme_changed = hooks_register_hook(THEME_CHANGED_HOOKLIST, my_update_theme_hook, NULL);
303 if(hook_theme_changed == 0) {
304 *error = g_strdup(_("Failed to register theme change hook in the "
305 "Notification plugin"));
306 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
307 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
308 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
309 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
310 hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
311 hooks_unregister_hook(MAIN_WINDOW_GOT_ICONIFIED, hook_got_iconified);
312 hooks_unregister_hook(ACCOUNT_LIST_CHANGED_HOOKLIST, hook_account);
313 return -1;
316 /* Configuration */
317 prefs_set_default(notify_param);
318 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
319 prefs_read_config(notify_param, "NotificationPlugin", rcpath, NULL);
320 g_free(rcpath);
322 /* Folder specific stuff */
323 notification_foldercheck_read_array();
325 notification_notified_hash_startup_init();
327 notify_gtk_init();
329 #ifdef NOTIFICATION_INDICATOR
330 notification_indicator_setup();
331 #endif
332 #ifdef NOTIFICATION_BANNER
333 notification_update_banner();
334 #endif
335 #ifdef NOTIFICATION_LCDPROC
336 notification_lcdproc_connect();
337 #endif
338 #ifdef NOTIFICATION_TRAYICON
339 if(notify_config.trayicon_enabled &&
340 notify_config.trayicon_hide_at_startup && claws_is_starting()) {
341 MainWindow *mainwin = mainwindow_get_mainwindow();
343 g_timeout_add(CM_NOTIFICATION_TRAYICON_SAFETY_NET_DELAY_MS, trayicon_startup_idle,NULL);
344 if(mainwin && gtk_widget_get_visible(GTK_WIDGET(mainwin->window)))
345 main_window_hide(mainwin);
346 main_set_show_at_startup(FALSE);
348 #endif
349 my_account_list_changed_hook(NULL,NULL);
351 if(notify_config.urgency_hint_new || notify_config.urgency_hint_unread)
352 notification_update_msg_counts(NULL);
354 #ifdef NOTIFICATION_HOTKEYS
355 notification_hotkeys_update_bindings();
356 #endif
358 debug_print("Notification plugin loaded\n");
360 return 0;
363 gboolean plugin_done(void)
365 hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
366 hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
367 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
368 hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
369 hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
370 hooks_unregister_hook(MAIN_WINDOW_GOT_ICONIFIED, hook_got_iconified);
371 hooks_unregister_hook(ACCOUNT_LIST_CHANGED_HOOKLIST, hook_account);
372 hooks_unregister_hook(THEME_CHANGED_HOOKLIST, hook_theme_changed);
374 notify_save_config();
376 notify_gtk_done();
378 /* foldercheck cleanup */
379 notification_foldercheck_write_array();
380 notification_free_folder_specific_array();
382 #ifdef NOTIFICATION_BANNER
383 notification_collected_msgs_free(banner_collected_msgs);
384 banner_collected_msgs = NULL;
385 notification_banner_destroy();
386 #endif
387 #ifdef NOTIFICATION_LCDPROC
388 notification_lcdproc_disconnect();
389 #endif
390 #ifdef NOTIFICATION_TRAYICON
391 notification_trayicon_destroy();
392 #endif
393 #ifdef NOTIFICATION_INDICATOR
394 notification_indicator_destroy();
395 #endif
396 notification_core_free();
398 #ifdef HAVE_LIBNOTIFY
399 if(notify_is_initted())
400 notify_uninit();
401 #endif
403 #ifdef NOTIFICATION_HOTKEYS
404 notification_hotkeys_unbind_all();
405 #endif
407 notification_pixbuf_free_all();
409 debug_print("Notification plugin unloaded\n");
411 /* Returning FALSE here means that g_module_close() will not be called on the plugin.
412 * This is necessary, as needed libraries are not designed to be unloaded. */
413 return FALSE;
416 const gchar *plugin_name(void)
418 return _("Notification");
421 const gchar *plugin_desc(void)
423 return _("This plugin provides various ways "
424 "to notify the user of new and unread email.\n"
425 "The plugin is extensively configurable in the "
426 "plugins section of the preferences dialog.\n\n"
427 "Feedback to <berndth@gmx.de> is welcome.");
430 const gchar *plugin_type(void)
432 return "GTK3";
435 const gchar *plugin_licence(void)
437 return "GPL3+";
440 const gchar *plugin_version(void)
442 return VERSION;
445 struct PluginFeature *plugin_provides(void)
447 static struct PluginFeature features[] =
448 { {PLUGIN_NOTIFIER, N_("Various tools")},
449 {PLUGIN_NOTHING, NULL}};
450 return features;
453 #ifdef NOTIFICATION_BANNER
454 void notification_update_banner(void)
456 notification_collected_msgs_free(banner_collected_msgs);
457 banner_collected_msgs = NULL;
459 if(notify_config.banner_show != NOTIFY_BANNER_SHOW_NEVER) {
460 guint id;
461 GSList *folder_list = NULL;
463 if(notify_config.banner_folder_specific) {
464 id = notification_register_folder_specific_list
465 (BANNER_SPECIFIC_FOLDER_ID_STR);
466 folder_list = notification_foldercheck_get_list(id);
469 if(!(notify_config.banner_folder_specific && (folder_list == NULL)))
470 banner_collected_msgs =
471 notification_collect_msgs(notify_config.banner_include_unread,
472 notify_config.banner_folder_specific ?
473 folder_list : NULL, notify_config.banner_max_msgs);
476 notification_banner_show(banner_collected_msgs);
478 #endif
480 #ifdef NOTIFICATION_TRAYICON
481 static gboolean trayicon_startup_idle(gpointer data)
483 /* if the trayicon is not available,
484 simulate click on it to show mainwindow */
485 if(!notification_trayicon_is_available())
486 notification_trayicon_on_activate(NULL,data);
487 return FALSE;
489 #endif