Migrate certificates, icons, logs to XDG dirs
[pidgin-git.git] / pidgin / plugins / markerline.c
blobdebcdc6e2f12c0124770983365560c25d7b621fc
1 /*
2 * Markerline - Draw a line to indicate new messages in a conversation.
3 * Copyright (C) 2006
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02111-1301, USA.
20 #include "internal.h"
22 #define PLUGIN_ID "gtk-plugin_pack-markerline"
23 #define PLUGIN_NAME N_("Markerline")
24 #define PLUGIN_CATEGORY N_("User interface")
25 #define PLUGIN_STATIC_NAME Markerline
26 #define PLUGIN_SUMMARY N_("Draw a line to indicate new messages in a conversation.")
27 #define PLUGIN_DESCRIPTION N_("Draw a line to indicate new messages in a conversation.")
28 #define PLUGIN_AUTHORS {"Sadrul H Chowdhury <sadrul@users.sourceforge.net>", NULL}
30 /* System headers */
31 #include <gdk/gdk.h>
32 #include <glib.h>
33 #include <gtk/gtk.h>
35 /* Purple headers */
36 #include <gtkconv.h>
37 #include <gtkplugin.h>
38 #include <gtkwebview.h>
39 #include <version.h>
41 #define PREF_PREFIX "/plugins/gtk/" PLUGIN_ID
42 #define PREF_IMS PREF_PREFIX "/ims"
43 #define PREF_CHATS PREF_PREFIX "/chats"
45 static void
46 update_marker_for_gtkconv(PidginConversation *gtkconv)
48 PurpleConversation *conv;
50 g_return_if_fail(gtkconv != NULL);
52 conv = gtkconv->active_conv;
54 if ((PURPLE_IS_CHAT_CONVERSATION(conv) && !purple_prefs_get_bool(PREF_CHATS)) ||
55 (PURPLE_IS_IM_CONVERSATION(conv) && !purple_prefs_get_bool(PREF_IMS)))
56 return;
58 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(gtkconv->webview),
59 "var mhr = document.getElementById(\"markerhr\");"
60 "if (!mhr) {"
61 "mhr = document.createElement(\"hr\");"
62 "mhr.setAttribute(\"id\", \"markerhr\");"
63 "mhr.setAttribute(\"color\", \"#ff0000\");"
64 "mhr.setAttribute(\"size\", \"1\");"
65 "}"
66 "document.getElementById(\"Chat\").appendChild(mhr);");
69 static gboolean
70 focus_removed(GtkWidget *widget, GdkEventVisibility *event, PidginConvWindow *win)
72 PurpleConversation *conv;
73 PidginConversation *gtkconv;
75 conv = pidgin_conv_window_get_active_conversation(win);
76 g_return_val_if_fail(conv != NULL, FALSE);
78 gtkconv = PIDGIN_CONVERSATION(conv);
79 update_marker_for_gtkconv(gtkconv);
81 return FALSE;
84 static void
85 page_switched(GtkWidget *widget, GtkWidget *page, gint num, PidginConvWindow *win)
87 focus_removed(NULL, NULL, win);
90 static void
91 detach_from_gtkconv(PidginConversation *gtkconv, gpointer null)
93 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(gtkconv->webview),
94 "var mhr = document.getElementById(\"markerhr\");"
95 "if (mhr) mhr.parentNode.removeChild(mhr);");
98 static void
99 detach_from_pidgin_window(PidginConvWindow *win, gpointer null)
101 g_list_foreach(pidgin_conv_window_get_gtkconvs(win), (GFunc)detach_from_gtkconv, NULL);
102 g_signal_handlers_disconnect_by_func(G_OBJECT(win->notebook), page_switched, win);
103 g_signal_handlers_disconnect_by_func(G_OBJECT(win->window), focus_removed, win);
106 static void
107 attach_to_gtkconv(PidginConversation *gtkconv, gpointer null)
109 detach_from_gtkconv(gtkconv, NULL);
110 update_marker_for_gtkconv(gtkconv);
113 static void
114 attach_to_pidgin_window(PidginConvWindow *win, gpointer null)
116 g_list_foreach(pidgin_conv_window_get_gtkconvs(win), (GFunc)attach_to_gtkconv, NULL);
118 g_signal_connect(G_OBJECT(win->window), "focus_out_event",
119 G_CALLBACK(focus_removed), win);
121 g_signal_connect(G_OBJECT(win->notebook), "switch_page",
122 G_CALLBACK(page_switched), win);
125 static void
126 detach_from_all_windows(void)
128 g_list_foreach(pidgin_conv_windows_get_list(), (GFunc)detach_from_pidgin_window, NULL);
131 static void
132 attach_to_all_windows(void)
134 g_list_foreach(pidgin_conv_windows_get_list(), (GFunc)attach_to_pidgin_window, NULL);
137 static void
138 conv_created(PidginConversation *gtkconv, gpointer null)
140 PidginConvWindow *win;
142 win = pidgin_conv_get_window(gtkconv);
143 if (!win)
144 return;
146 detach_from_pidgin_window(win, NULL);
147 attach_to_pidgin_window(win, NULL);
150 static void
151 jump_to_markerline(PurpleConversation *conv, gpointer null)
153 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
155 if (!gtkconv)
156 return;
158 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(gtkconv->webview),
159 "var mhr = document.getElementById(\"markerhr\");"
160 "if (mhr) {"
161 "window.scroll(0, mhr.offsetTop);"
162 "}");
165 static void
166 conv_menu_cb(PurpleConversation *conv, GList **list)
168 gboolean enabled = ((PURPLE_IS_IM_CONVERSATION(conv) && purple_prefs_get_bool(PREF_IMS)) ||
169 (PURPLE_IS_CHAT_CONVERSATION(conv) && purple_prefs_get_bool(PREF_CHATS)));
170 PurpleMenuAction *action = purple_menu_action_new(_("Jump to markerline"),
171 enabled ? PURPLE_CALLBACK(jump_to_markerline) : NULL, NULL, NULL);
172 *list = g_list_append(*list, action);
175 static PurplePluginPrefFrame *
176 get_plugin_pref_frame(PurplePlugin *plugin)
178 PurplePluginPrefFrame *frame;
179 PurplePluginPref *pref;
181 frame = purple_plugin_pref_frame_new();
183 pref = purple_plugin_pref_new_with_label(_("Draw Markerline in "));
184 purple_plugin_pref_frame_add(frame, pref);
186 pref = purple_plugin_pref_new_with_name_and_label(PREF_IMS,
187 _("_IM windows"));
188 purple_plugin_pref_frame_add(frame, pref);
190 pref = purple_plugin_pref_new_with_name_and_label(PREF_CHATS,
191 _("C_hat windows"));
192 purple_plugin_pref_frame_add(frame, pref);
194 return frame;
197 static PidginPluginInfo *
198 plugin_query(GError **error)
200 const gchar * const authors[] = PLUGIN_AUTHORS;
202 return pidgin_plugin_info_new(
203 "id", PLUGIN_ID,
204 "name", PLUGIN_NAME,
205 "version", DISPLAY_VERSION,
206 "category", PLUGIN_CATEGORY,
207 "summary", PLUGIN_SUMMARY,
208 "description", PLUGIN_DESCRIPTION,
209 "authors", authors,
210 "website", PURPLE_WEBSITE,
211 "abi-version", PURPLE_ABI_VERSION,
212 "pref-frame-cb", get_plugin_pref_frame,
213 NULL
217 static gboolean
218 plugin_load(PurplePlugin *plugin, GError **error)
220 purple_prefs_add_none(PREF_PREFIX);
221 purple_prefs_add_bool(PREF_IMS, FALSE);
222 purple_prefs_add_bool(PREF_CHATS, TRUE);
224 attach_to_all_windows();
226 purple_signal_connect(pidgin_conversations_get_handle(), "conversation-displayed",
227 plugin, PURPLE_CALLBACK(conv_created), NULL);
229 purple_signal_connect(purple_conversations_get_handle(), "conversation-extended-menu",
230 plugin, PURPLE_CALLBACK(conv_menu_cb), NULL);
231 return TRUE;
234 static gboolean
235 plugin_unload(PurplePlugin *plugin, GError **error)
237 detach_from_all_windows();
239 return TRUE;
242 PURPLE_PLUGIN_INIT(PLUGIN_STATIC_NAME, plugin_query, plugin_load, plugin_unload);