3 * Finch is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 #include <gntbutton.h>
29 #include <gntwindow.h>
35 #include "gntnotify.h"
45 notify_msg_window_destroy_cb(GntWidget
*window
, PurpleNotifyType type
)
47 purple_notify_close(type
, window
);
51 finch_notify_common(PurpleNotifyType ntype
, PurpleNotifyMessageType msgtype
,
52 const char *title
, const char *primary
, const char *secondary
,
53 PurpleRequestCommonParameters
*cpar
)
55 GntWidget
*window
, *button
;
56 GntTextFormatFlags pf
= 0, sf
= 0;
60 case PURPLE_NOTIFY_MSG_ERROR
:
61 sf
|= GNT_TEXT_FLAG_BOLD
;
63 case PURPLE_NOTIFY_MSG_WARNING
:
64 pf
|= GNT_TEXT_FLAG_UNDERLINE
;
66 case PURPLE_NOTIFY_MSG_INFO
:
67 pf
|= GNT_TEXT_FLAG_BOLD
;
71 window
= gnt_window_box_new(FALSE
, TRUE
);
72 gnt_box_set_title(GNT_BOX(window
), title
);
73 gnt_box_set_fill(GNT_BOX(window
), FALSE
);
74 gnt_box_set_alignment(GNT_BOX(window
), GNT_ALIGN_MID
);
75 gnt_box_set_pad(GNT_BOX(window
), 0);
78 gnt_box_add_widget(GNT_BOX(window
),
79 gnt_label_new_with_format(primary
, pf
));
81 button
= gnt_button_new(_("OK"));
85 if (ntype
== PURPLE_NOTIFY_FORMATTED
) {
86 int width
= -1, height
= -1;
87 char *plain
= (char*)secondary
;
88 msg
= gnt_text_view_new();
89 gnt_text_view_set_flag(GNT_TEXT_VIEW(msg
), GNT_TEXT_VIEW_TOP_ALIGN
| GNT_TEXT_VIEW_NO_SCROLL
);
91 plain
= purple_markup_strip_html(secondary
);
92 if (!gnt_util_parse_xhtml_to_textview(secondary
, GNT_TEXT_VIEW(msg
)))
93 gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(msg
), plain
, sf
);
95 gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(msg
), button
);
96 gnt_util_get_text_bound(plain
, &width
, &height
);
97 gnt_widget_set_size(msg
, width
+ 3, height
+ 1);
98 if (plain
!= secondary
)
101 msg
= gnt_label_new_with_format(secondary
, sf
);
103 gnt_box_add_widget(GNT_BOX(window
), msg
);
104 g_object_set_data(G_OBJECT(window
), "info-widget", msg
);
107 gnt_box_add_widget(GNT_BOX(window
), button
);
108 g_signal_connect_swapped(G_OBJECT(button
), "activate",
109 G_CALLBACK(gnt_widget_destroy
), window
);
110 g_signal_connect(G_OBJECT(window
), "destroy",
111 G_CALLBACK(notify_msg_window_destroy_cb
), GINT_TO_POINTER(ntype
));
113 gnt_widget_show(window
);
117 /* handle is, in all/most occasions, a GntWidget * */
118 static void finch_close_notify(PurpleNotifyType type
, void *handle
)
120 GntWidget
*widget
= handle
;
125 widget
= gnt_widget_get_toplevel(widget
);
127 if (type
== PURPLE_NOTIFY_SEARCHRESULTS
)
128 purple_notify_searchresults_free(g_object_get_data(handle
, "notify-results"));
130 /* This did not seem to be necessary */
131 g_signal_handlers_disconnect_by_func(G_OBJECT(widget
),
132 G_CALLBACK(notify_msg_window_destroy_cb
), GINT_TO_POINTER(type
));
134 gnt_widget_destroy(widget
);
138 finch_notify_message(PurpleNotifyMessageType type
, const char *title
,
139 const char *primary
, const char *secondary
,
140 PurpleRequestCommonParameters
*cpar
)
142 return finch_notify_common(PURPLE_NOTIFY_MESSAGE
, type
, title
, primary
,
146 static void *finch_notify_formatted(const char *title
, const char *primary
,
147 const char *secondary
, const char *text
)
150 char *t
= g_strdup_printf("<span>%s%s%s</span>",
151 secondary
? secondary
: "",
152 secondary
? "\n" : "",
156 purple_markup_html_to_xhtml(t
, &xhtml
, NULL
);
157 ret
= finch_notify_common(PURPLE_NOTIFY_FORMATTED
,
158 PURPLE_NOTIFY_MSG_INFO
, title
, primary
, xhtml
, NULL
);
167 reset_email_dialog(void)
169 emaildialog
.window
= NULL
;
170 emaildialog
.tree
= NULL
;
174 setup_email_dialog(void)
176 GntWidget
*box
, *tree
, *button
;
177 if (emaildialog
.window
)
180 emaildialog
.window
= box
= gnt_vbox_new(FALSE
);
181 gnt_box_set_toplevel(GNT_BOX(box
), TRUE
);
182 gnt_box_set_title(GNT_BOX(box
), _("Emails"));
183 gnt_box_set_fill(GNT_BOX(box
), FALSE
);
184 gnt_box_set_alignment(GNT_BOX(box
), GNT_ALIGN_MID
);
185 gnt_box_set_pad(GNT_BOX(box
), 0);
187 gnt_box_add_widget(GNT_BOX(box
),
188 gnt_label_new_with_format(_("You have mail!"), GNT_TEXT_FLAG_BOLD
));
190 emaildialog
.tree
= tree
= gnt_tree_new_with_columns(3);
191 gnt_tree_set_column_titles(GNT_TREE(tree
), _("Account"), _("Sender"), _("Subject"));
192 gnt_tree_set_show_title(GNT_TREE(tree
), TRUE
);
193 gnt_tree_set_col_width(GNT_TREE(tree
), 0, 15);
194 gnt_tree_set_col_width(GNT_TREE(tree
), 1, 25);
195 gnt_tree_set_col_width(GNT_TREE(tree
), 2, 25);
197 gnt_box_add_widget(GNT_BOX(box
), tree
);
199 button
= gnt_button_new(_("Close"));
200 gnt_box_add_widget(GNT_BOX(box
), button
);
202 g_signal_connect_swapped(G_OBJECT(button
), "activate", G_CALLBACK(gnt_widget_destroy
), box
);
203 g_signal_connect(G_OBJECT(box
), "destroy", G_CALLBACK(reset_email_dialog
), NULL
);
207 finch_notify_emails(PurpleConnection
*gc
, size_t count
, gboolean detailed
,
208 const char **subjects
, const char **froms
, const char **tos
,
211 PurpleAccount
*account
= purple_connection_get_account(gc
);
212 GString
*message
= g_string_new(NULL
);
221 g_string_append_printf(message
,
222 ngettext("%s (%s) has %d new message.",
223 "%s (%s) has %d new messages.",
225 tos
? *tos
: purple_account_get_username(account
),
226 purple_account_get_protocol_name(account
), (int)count
);
231 gboolean newwin
= (emaildialog
.window
== NULL
);
234 setup_email_dialog();
236 to
= g_strdup_printf("%s (%s)", tos
? *tos
: purple_account_get_username(account
),
237 purple_account_get_protocol_name(account
));
238 gnt_tree_add_row_after(GNT_TREE(emaildialog
.tree
), GINT_TO_POINTER(++key
),
239 gnt_tree_create_row(GNT_TREE(emaildialog
.tree
), to
,
240 froms
? *froms
: "[Unknown sender]",
245 gnt_widget_show(emaildialog
.window
);
247 gnt_window_present(emaildialog
.window
);
251 ret
= finch_notify_common(PURPLE_NOTIFY_EMAIL
, PURPLE_NOTIFY_MSG_INFO
,
252 _("New Mail"), _("You have mail!"), message
->str
, NULL
);
253 g_string_free(message
, TRUE
);
258 finch_notify_email(PurpleConnection
*gc
, const char *subject
, const char *from
,
259 const char *to
, const char *url
)
261 return finch_notify_emails(gc
, 1, subject
!= NULL
,
262 subject
? &subject
: NULL
,
268 /** User information. **/
269 static GHashTable
*userinfo
;
272 userinfo_hash(PurpleAccount
*account
, const char *who
)
275 g_snprintf(key
, sizeof(key
), "%s - %s", purple_account_get_username(account
), purple_normalize(account
, who
));
276 return g_utf8_strup(key
, -1);
280 remove_userinfo(GntWidget
*widget
, gpointer key
)
282 g_hash_table_remove(userinfo
, key
);
286 purple_notify_user_info_get_xhtml(PurpleNotifyUserInfo
*user_info
)
291 text
= g_string_new("<span>");
293 for (l
= purple_notify_user_info_get_entries(user_info
)->head
; l
!= NULL
;
295 PurpleNotifyUserInfoEntry
*user_info_entry
= l
->data
;
296 PurpleNotifyUserInfoEntryType type
= purple_notify_user_info_entry_get_entry_type(user_info_entry
);
297 const char *label
= purple_notify_user_info_entry_get_label(user_info_entry
);
298 const char *value
= purple_notify_user_info_entry_get_value(user_info_entry
);
300 /* Handle the label/value pair itself */
301 if (type
== PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER
)
302 g_string_append(text
, "<u>");
304 g_string_append_printf(text
, "<b>%s</b>", label
);
305 g_string_append(text
, "<span>");
307 g_string_append(text
, ": ");
309 char *strip
= purple_markup_strip_html(value
);
310 g_string_append(text
, strip
);
313 g_string_append(text
, "</span>");
314 if (type
== PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER
)
315 g_string_append(text
, "</u>");
316 else if (type
== PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK
)
317 g_string_append(text
, "<HR/>");
318 g_string_append(text
, "<BR/>");
320 g_string_append(text
, "</span>");
322 return g_string_free(text
, FALSE
);
326 finch_notify_userinfo(PurpleConnection
*gc
, const char *who
, PurpleNotifyUserInfo
*user_info
)
331 char *key
= userinfo_hash(purple_connection_get_account(gc
), who
);
333 info
= purple_notify_user_info_get_xhtml(user_info
);
335 ui_handle
= g_hash_table_lookup(userinfo
, key
);
336 if (ui_handle
!= NULL
) {
337 GntTextView
*msg
= GNT_TEXT_VIEW(g_object_get_data(G_OBJECT(ui_handle
), "info-widget"));
338 char *strip
= purple_markup_strip_html(info
);
339 int tvw
, tvh
, width
, height
, ntvw
, ntvh
;
342 ui_handle
= window
= gnt_widget_get_toplevel(GNT_WIDGET(ui_handle
));
343 gnt_widget_get_size(window
, &width
, &height
);
344 gnt_widget_get_size(GNT_WIDGET(msg
), &tvw
, &tvh
);
346 gnt_text_view_clear(msg
);
347 if (!gnt_util_parse_xhtml_to_textview(info
, msg
))
348 gnt_text_view_append_text_with_flags(msg
, strip
, GNT_TEXT_FLAG_NORMAL
);
349 gnt_text_view_scroll(msg
, 0);
350 gnt_util_get_text_bound(strip
, &ntvw
, &ntvh
);
354 gnt_screen_resize_widget(window
, width
+ MAX(0, ntvw
- tvw
), height
+ MAX(0, ntvh
- tvh
));
358 primary
= g_strdup_printf(_("Info for %s"), who
);
359 ui_handle
= finch_notify_formatted(_("Buddy Information"), primary
, NULL
, info
);
360 g_hash_table_insert(userinfo
, key
, ui_handle
);
362 g_signal_connect(G_OBJECT(ui_handle
), "destroy", G_CALLBACK(remove_userinfo
), key
);
370 notify_button_activated(GntWidget
*widget
, PurpleNotifySearchButton
*b
)
373 PurpleAccount
*account
= g_object_get_data(G_OBJECT(widget
), "notify-account");
374 gpointer data
= g_object_get_data(G_OBJECT(widget
), "notify-data");
376 list
= gnt_tree_get_selection_text_list(GNT_TREE(g_object_get_data(G_OBJECT(widget
), "notify-tree")));
378 b
->callback(purple_account_get_connection(account
), list
, data
);
379 g_list_foreach(list
, (GFunc
)g_free
, NULL
);
384 finch_notify_sr_new_rows(PurpleConnection
*gc
,
385 PurpleNotifySearchResults
*results
, void *data
)
387 GntWindow
*window
= GNT_WINDOW(data
);
388 GntTree
*tree
= GNT_TREE(g_object_get_data(G_OBJECT(window
), "tree-widget"));
390 GntTreeRow
*prev
= NULL
;
392 gnt_tree_remove_all(GNT_TREE(tree
));
394 for (o
= results
->rows
; o
; o
= o
->next
)
396 gnt_tree_add_row_after(GNT_TREE(tree
), o
->data
,
397 gnt_tree_create_row_from_list(GNT_TREE(tree
), o
->data
),
404 notify_sr_destroy_cb(GntWidget
*window
, void *data
)
406 purple_notify_close(PURPLE_NOTIFY_SEARCHRESULTS
, window
);
410 finch_notify_searchresults(PurpleConnection
*gc
, const char *title
,
411 const char *primary
, const char *secondary
,
412 PurpleNotifySearchResults
*results
, gpointer data
)
414 GntWidget
*window
, *tree
, *box
, *button
;
418 window
= gnt_vbox_new(FALSE
);
419 gnt_box_set_toplevel(GNT_BOX(window
), TRUE
);
420 gnt_box_set_title(GNT_BOX(window
), title
);
421 gnt_box_set_fill(GNT_BOX(window
), TRUE
);
422 gnt_box_set_pad(GNT_BOX(window
), 0);
423 gnt_box_set_alignment(GNT_BOX(window
), GNT_ALIGN_MID
);
426 gnt_box_add_widget(GNT_BOX(window
),
427 gnt_label_new_with_format(primary
, GNT_TEXT_FLAG_BOLD
));
429 gnt_box_add_widget(GNT_BOX(window
),
430 gnt_label_new_with_format(secondary
, GNT_TEXT_FLAG_NORMAL
));
432 columns
= g_list_length(results
->columns
);
433 tree
= gnt_tree_new_with_columns(columns
);
434 gnt_tree_set_show_title(GNT_TREE(tree
), TRUE
);
435 gnt_box_add_widget(GNT_BOX(window
), tree
);
438 for (iter
= results
->columns
; iter
; iter
= iter
->next
)
440 PurpleNotifySearchColumn
*column
= iter
->data
;
441 gnt_tree_set_column_title(GNT_TREE(tree
), i
, purple_notify_searchresult_column_get_title(column
));
443 if (!purple_notify_searchresult_column_is_visible(column
))
444 gnt_tree_set_column_visible(GNT_TREE(tree
), i
, FALSE
);
448 box
= gnt_hbox_new(TRUE
);
450 for (iter
= results
->buttons
; iter
; iter
= iter
->next
)
452 PurpleNotifySearchButton
*b
= iter
->data
;
457 case PURPLE_NOTIFY_BUTTON_LABELED
:
460 case PURPLE_NOTIFY_BUTTON_CONTINUE
:
461 text
= _("Continue");
463 case PURPLE_NOTIFY_BUTTON_ADD
:
466 case PURPLE_NOTIFY_BUTTON_INFO
:
469 case PURPLE_NOTIFY_BUTTON_IM
:
472 case PURPLE_NOTIFY_BUTTON_JOIN
:
475 case PURPLE_NOTIFY_BUTTON_INVITE
:
482 button
= gnt_button_new(text
);
483 g_object_set_data(G_OBJECT(button
), "notify-account", purple_connection_get_account(gc
));
484 g_object_set_data(G_OBJECT(button
), "notify-data", data
);
485 g_object_set_data(G_OBJECT(button
), "notify-tree", tree
);
486 g_signal_connect(G_OBJECT(button
), "activate",
487 G_CALLBACK(notify_button_activated
), b
);
489 gnt_box_add_widget(GNT_BOX(box
), button
);
492 gnt_box_add_widget(GNT_BOX(window
), box
);
493 g_signal_connect(G_OBJECT(tree
), "destroy",
494 G_CALLBACK(notify_sr_destroy_cb
), NULL
);
496 g_object_set_data(G_OBJECT(window
), "tree-widget", tree
);
497 finch_notify_sr_new_rows(gc
, results
, window
);
499 g_signal_connect(G_OBJECT(window
), "destroy",
500 G_CALLBACK(notify_msg_window_destroy_cb
), GINT_TO_POINTER(PURPLE_NOTIFY_SEARCHRESULTS
));
502 gnt_widget_show(window
);
503 g_object_set_data(G_OBJECT(window
), "notify-results", results
);
509 finch_notify_uri(const char *url
)
511 return finch_notify_common(PURPLE_NOTIFY_URI
, PURPLE_NOTIFY_MSG_INFO
,
512 _("URI"), url
, NULL
, NULL
);
515 static PurpleNotifyUiOps ops
=
517 finch_notify_message
,
520 finch_notify_formatted
,
521 finch_notify_searchresults
,
522 finch_notify_sr_new_rows
,
523 finch_notify_userinfo
,
525 finch_close_notify
, /* The rest of the notify-uiops return a GntWidget.
526 These widgets should be destroyed from here. */
534 PurpleNotifyUiOps
*finch_notify_get_ui_ops()
539 void finch_notify_init()
541 userinfo
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
, NULL
);
544 void finch_notify_uninit()
546 g_hash_table_destroy(userinfo
);