4 * Finch is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
27 #include <gntbutton.h>
31 #include <gntwindow.h>
37 #include "gntnotify.h"
47 notify_msg_window_destroy_cb(GntWidget
*window
, PurpleNotifyType type
)
49 purple_notify_close(type
, window
);
53 finch_notify_common(PurpleNotifyType ntype
, PurpleNotifyMessageType msgtype
,
54 const char *title
, const char *primary
, const char *secondary
,
55 PurpleRequestCommonParameters
*cpar
)
57 GntWidget
*window
, *button
;
58 GntTextFormatFlags pf
= 0, sf
= 0;
62 case PURPLE_NOTIFY_MSG_ERROR
:
63 sf
|= GNT_TEXT_FLAG_BOLD
;
65 case PURPLE_NOTIFY_MSG_WARNING
:
66 pf
|= GNT_TEXT_FLAG_UNDERLINE
;
68 case PURPLE_NOTIFY_MSG_INFO
:
69 pf
|= GNT_TEXT_FLAG_BOLD
;
73 window
= gnt_window_box_new(FALSE
, TRUE
);
74 gnt_box_set_title(GNT_BOX(window
), title
);
75 gnt_box_set_fill(GNT_BOX(window
), FALSE
);
76 gnt_box_set_alignment(GNT_BOX(window
), GNT_ALIGN_MID
);
77 gnt_box_set_pad(GNT_BOX(window
), 0);
80 gnt_box_add_widget(GNT_BOX(window
),
81 gnt_label_new_with_format(primary
, pf
));
83 button
= gnt_button_new(_("OK"));
87 if (ntype
== PURPLE_NOTIFY_FORMATTED
) {
88 int width
= -1, height
= -1;
89 char *plain
= (char*)secondary
;
90 msg
= gnt_text_view_new();
91 gnt_text_view_set_flag(GNT_TEXT_VIEW(msg
), GNT_TEXT_VIEW_TOP_ALIGN
| GNT_TEXT_VIEW_NO_SCROLL
);
93 plain
= purple_markup_strip_html(secondary
);
94 if (!gnt_util_parse_xhtml_to_textview(secondary
, GNT_TEXT_VIEW(msg
)))
95 gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(msg
), plain
, sf
);
97 gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(msg
), button
);
98 gnt_util_get_text_bound(plain
, &width
, &height
);
99 gnt_widget_set_size(msg
, width
+ 3, height
+ 1);
100 if (plain
!= secondary
)
103 msg
= gnt_label_new_with_format(secondary
, sf
);
105 gnt_box_add_widget(GNT_BOX(window
), msg
);
106 g_object_set_data(G_OBJECT(window
), "info-widget", msg
);
109 gnt_box_add_widget(GNT_BOX(window
), button
);
110 g_signal_connect_swapped(G_OBJECT(button
), "activate",
111 G_CALLBACK(gnt_widget_destroy
), window
);
112 g_signal_connect(G_OBJECT(window
), "destroy",
113 G_CALLBACK(notify_msg_window_destroy_cb
), GINT_TO_POINTER(ntype
));
115 gnt_widget_show(window
);
119 /* handle is, in all/most occasions, a GntWidget * */
120 static void finch_close_notify(PurpleNotifyType type
, void *handle
)
122 GntWidget
*widget
= handle
;
127 widget
= gnt_widget_get_toplevel(widget
);
129 if (type
== PURPLE_NOTIFY_SEARCHRESULTS
)
130 purple_notify_searchresults_free(g_object_get_data(handle
, "notify-results"));
132 /* This did not seem to be necessary */
133 g_signal_handlers_disconnect_by_func(G_OBJECT(widget
),
134 G_CALLBACK(notify_msg_window_destroy_cb
), GINT_TO_POINTER(type
));
136 gnt_widget_destroy(widget
);
140 finch_notify_message(PurpleNotifyMessageType type
, const char *title
,
141 const char *primary
, const char *secondary
,
142 PurpleRequestCommonParameters
*cpar
)
144 return finch_notify_common(PURPLE_NOTIFY_MESSAGE
, type
, title
, primary
,
148 static void *finch_notify_formatted(const char *title
, const char *primary
,
149 const char *secondary
, const char *text
)
152 char *t
= g_strdup_printf("<span>%s%s%s</span>",
153 secondary
? secondary
: "",
154 secondary
? "\n" : "",
158 purple_markup_html_to_xhtml(t
, &xhtml
, NULL
);
159 ret
= finch_notify_common(PURPLE_NOTIFY_FORMATTED
,
160 PURPLE_NOTIFY_MSG_INFO
, title
, primary
, xhtml
, NULL
);
169 reset_email_dialog(void)
171 emaildialog
.window
= NULL
;
172 emaildialog
.tree
= NULL
;
176 setup_email_dialog(void)
178 GntWidget
*box
, *tree
, *button
;
179 if (emaildialog
.window
)
182 emaildialog
.window
= box
= gnt_vbox_new(FALSE
);
183 gnt_box_set_toplevel(GNT_BOX(box
), TRUE
);
184 gnt_box_set_title(GNT_BOX(box
), _("Emails"));
185 gnt_box_set_fill(GNT_BOX(box
), FALSE
);
186 gnt_box_set_alignment(GNT_BOX(box
), GNT_ALIGN_MID
);
187 gnt_box_set_pad(GNT_BOX(box
), 0);
189 gnt_box_add_widget(GNT_BOX(box
),
190 gnt_label_new_with_format(_("You have mail!"), GNT_TEXT_FLAG_BOLD
));
192 emaildialog
.tree
= tree
= gnt_tree_new_with_columns(3);
193 gnt_tree_set_column_titles(GNT_TREE(tree
), _("Account"), _("Sender"), _("Subject"));
194 gnt_tree_set_show_title(GNT_TREE(tree
), TRUE
);
195 gnt_tree_set_col_width(GNT_TREE(tree
), 0, 15);
196 gnt_tree_set_col_width(GNT_TREE(tree
), 1, 25);
197 gnt_tree_set_col_width(GNT_TREE(tree
), 2, 25);
199 gnt_box_add_widget(GNT_BOX(box
), tree
);
201 button
= gnt_button_new(_("Close"));
202 gnt_box_add_widget(GNT_BOX(box
), button
);
204 g_signal_connect_swapped(G_OBJECT(button
), "activate", G_CALLBACK(gnt_widget_destroy
), box
);
205 g_signal_connect(G_OBJECT(box
), "destroy", G_CALLBACK(reset_email_dialog
), NULL
);
209 finch_notify_emails(PurpleConnection
*gc
, size_t count
, gboolean detailed
,
210 const char **subjects
, const char **froms
, const char **tos
,
213 PurpleAccount
*account
= purple_connection_get_account(gc
);
222 message
= g_strdup_printf(
223 ngettext("%s (%s) has %d new message.",
224 "%s (%s) has %d new messages.", (int)count
),
225 tos
? *tos
: purple_account_get_username(account
),
226 purple_account_get_protocol_name(account
), (int)count
);
227 ret
= finch_notify_common(PURPLE_NOTIFY_EMAIL
, PURPLE_NOTIFY_MSG_INFO
,
228 _("New Mail"), _("You have mail!"), message
,
233 gboolean newwin
= (emaildialog
.window
== NULL
);
236 setup_email_dialog();
238 to
= g_strdup_printf("%s (%s)", tos
? *tos
: purple_account_get_username(account
),
239 purple_account_get_protocol_name(account
));
240 gnt_tree_add_row_after(GNT_TREE(emaildialog
.tree
), GINT_TO_POINTER(++key
),
241 gnt_tree_create_row(GNT_TREE(emaildialog
.tree
), to
,
242 froms
? *froms
: "[Unknown sender]",
247 gnt_widget_show(emaildialog
.window
);
249 gnt_window_present(emaildialog
.window
);
257 finch_notify_email(PurpleConnection
*gc
, const char *subject
, const char *from
,
258 const char *to
, const char *url
)
260 return finch_notify_emails(gc
, 1, subject
!= NULL
,
261 subject
? &subject
: NULL
,
267 /** User information. **/
268 static GHashTable
*userinfo
;
271 userinfo_hash(PurpleAccount
*account
, const char *who
)
274 g_snprintf(key
, sizeof(key
), "%s - %s", purple_account_get_username(account
), purple_normalize(account
, who
));
275 return g_utf8_strup(key
, -1);
279 remove_userinfo(GntWidget
*widget
, gpointer key
)
281 g_hash_table_remove(userinfo
, key
);
285 purple_notify_user_info_get_xhtml(PurpleNotifyUserInfo
*user_info
)
290 text
= g_string_new("<span>");
292 for (l
= purple_notify_user_info_get_entries(user_info
)->head
; l
!= NULL
;
294 PurpleNotifyUserInfoEntry
*user_info_entry
= l
->data
;
295 PurpleNotifyUserInfoEntryType type
= purple_notify_user_info_entry_get_entry_type(user_info_entry
);
296 const char *label
= purple_notify_user_info_entry_get_label(user_info_entry
);
297 const char *value
= purple_notify_user_info_entry_get_value(user_info_entry
);
299 /* Handle the label/value pair itself */
300 if (type
== PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER
)
301 g_string_append(text
, "<u>");
303 g_string_append_printf(text
, "<b>%s</b>", label
);
304 g_string_append(text
, "<span>");
306 g_string_append(text
, ": ");
308 char *strip
= purple_markup_strip_html(value
);
309 g_string_append(text
, strip
);
312 g_string_append(text
, "</span>");
313 if (type
== PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER
)
314 g_string_append(text
, "</u>");
315 else if (type
== PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK
)
316 g_string_append(text
, "<HR/>");
317 g_string_append(text
, "<BR/>");
319 g_string_append(text
, "</span>");
321 return g_string_free(text
, FALSE
);
325 finch_notify_userinfo(PurpleConnection
*gc
, const char *who
, PurpleNotifyUserInfo
*user_info
)
330 char *key
= userinfo_hash(purple_connection_get_account(gc
), who
);
332 info
= purple_notify_user_info_get_xhtml(user_info
);
334 ui_handle
= g_hash_table_lookup(userinfo
, key
);
335 if (ui_handle
!= NULL
) {
336 GntTextView
*msg
= GNT_TEXT_VIEW(g_object_get_data(G_OBJECT(ui_handle
), "info-widget"));
337 char *strip
= purple_markup_strip_html(info
);
338 int tvw
, tvh
, width
, height
, ntvw
, ntvh
;
341 ui_handle
= window
= gnt_widget_get_toplevel(GNT_WIDGET(ui_handle
));
342 gnt_widget_get_size(window
, &width
, &height
);
343 gnt_widget_get_size(GNT_WIDGET(msg
), &tvw
, &tvh
);
345 gnt_text_view_clear(msg
);
346 if (!gnt_util_parse_xhtml_to_textview(info
, msg
))
347 gnt_text_view_append_text_with_flags(msg
, strip
, GNT_TEXT_FLAG_NORMAL
);
348 gnt_text_view_scroll(msg
, 0);
349 gnt_util_get_text_bound(strip
, &ntvw
, &ntvh
);
353 gnt_screen_resize_widget(window
, width
+ MAX(0, ntvw
- tvw
), height
+ MAX(0, ntvh
- tvh
));
357 primary
= g_strdup_printf(_("Info for %s"), who
);
358 ui_handle
= finch_notify_formatted(_("Buddy Information"), primary
, NULL
, info
);
359 g_hash_table_insert(userinfo
, key
, ui_handle
);
361 g_signal_connect(G_OBJECT(ui_handle
), "destroy", G_CALLBACK(remove_userinfo
), key
);
369 notify_button_activated(GntWidget
*widget
, PurpleNotifySearchButton
*b
)
372 PurpleAccount
*account
= g_object_get_data(G_OBJECT(widget
), "notify-account");
373 gpointer data
= g_object_get_data(G_OBJECT(widget
), "notify-data");
375 list
= gnt_tree_get_selection_text_list(GNT_TREE(g_object_get_data(G_OBJECT(widget
), "notify-tree")));
377 b
->callback(purple_account_get_connection(account
), list
, data
);
378 g_list_free_full(list
, g_free
);
382 finch_notify_sr_new_rows(PurpleConnection
*gc
,
383 PurpleNotifySearchResults
*results
, void *data
)
385 GntWindow
*window
= GNT_WINDOW(data
);
386 GntTree
*tree
= GNT_TREE(g_object_get_data(G_OBJECT(window
), "tree-widget"));
388 GntTreeRow
*prev
= NULL
;
390 gnt_tree_remove_all(GNT_TREE(tree
));
392 for (o
= results
->rows
; o
; o
= o
->next
)
394 gnt_tree_add_row_after(GNT_TREE(tree
), o
->data
,
395 gnt_tree_create_row_from_list(GNT_TREE(tree
), o
->data
),
402 notify_sr_destroy_cb(GntWidget
*window
, void *data
)
404 purple_notify_close(PURPLE_NOTIFY_SEARCHRESULTS
, window
);
408 finch_notify_searchresults(PurpleConnection
*gc
, const char *title
,
409 const char *primary
, const char *secondary
,
410 PurpleNotifySearchResults
*results
, gpointer data
)
412 GntWidget
*window
, *tree
, *box
, *button
;
416 window
= gnt_vbox_new(FALSE
);
417 gnt_box_set_toplevel(GNT_BOX(window
), TRUE
);
418 gnt_box_set_title(GNT_BOX(window
), title
);
419 gnt_box_set_fill(GNT_BOX(window
), TRUE
);
420 gnt_box_set_pad(GNT_BOX(window
), 0);
421 gnt_box_set_alignment(GNT_BOX(window
), GNT_ALIGN_MID
);
424 gnt_box_add_widget(GNT_BOX(window
),
425 gnt_label_new_with_format(primary
, GNT_TEXT_FLAG_BOLD
));
427 gnt_box_add_widget(GNT_BOX(window
),
428 gnt_label_new_with_format(secondary
, GNT_TEXT_FLAG_NORMAL
));
430 columns
= g_list_length(results
->columns
);
431 tree
= gnt_tree_new_with_columns(columns
);
432 gnt_tree_set_show_title(GNT_TREE(tree
), TRUE
);
433 gnt_box_add_widget(GNT_BOX(window
), tree
);
436 for (iter
= results
->columns
; iter
; iter
= iter
->next
)
438 PurpleNotifySearchColumn
*column
= iter
->data
;
439 gnt_tree_set_column_title(GNT_TREE(tree
), i
, purple_notify_searchresult_column_get_title(column
));
441 if (!purple_notify_searchresult_column_is_visible(column
))
442 gnt_tree_set_column_visible(GNT_TREE(tree
), i
, FALSE
);
446 box
= gnt_hbox_new(TRUE
);
448 for (iter
= results
->buttons
; iter
; iter
= iter
->next
)
450 PurpleNotifySearchButton
*b
= iter
->data
;
455 case PURPLE_NOTIFY_BUTTON_LABELED
:
458 case PURPLE_NOTIFY_BUTTON_CONTINUE
:
459 text
= _("Continue");
461 case PURPLE_NOTIFY_BUTTON_ADD
:
464 case PURPLE_NOTIFY_BUTTON_INFO
:
467 case PURPLE_NOTIFY_BUTTON_IM
:
470 case PURPLE_NOTIFY_BUTTON_JOIN
:
473 case PURPLE_NOTIFY_BUTTON_INVITE
:
480 button
= gnt_button_new(text
);
481 g_object_set_data(G_OBJECT(button
), "notify-account", purple_connection_get_account(gc
));
482 g_object_set_data(G_OBJECT(button
), "notify-data", data
);
483 g_object_set_data(G_OBJECT(button
), "notify-tree", tree
);
484 g_signal_connect(G_OBJECT(button
), "activate",
485 G_CALLBACK(notify_button_activated
), b
);
487 gnt_box_add_widget(GNT_BOX(box
), button
);
490 gnt_box_add_widget(GNT_BOX(window
), box
);
491 g_signal_connect(G_OBJECT(tree
), "destroy",
492 G_CALLBACK(notify_sr_destroy_cb
), NULL
);
494 g_object_set_data(G_OBJECT(window
), "tree-widget", tree
);
495 finch_notify_sr_new_rows(gc
, results
, window
);
497 g_signal_connect(G_OBJECT(window
), "destroy",
498 G_CALLBACK(notify_msg_window_destroy_cb
), GINT_TO_POINTER(PURPLE_NOTIFY_SEARCHRESULTS
));
500 gnt_widget_show(window
);
501 g_object_set_data(G_OBJECT(window
), "notify-results", results
);
507 finch_notify_uri(const char *url
)
509 return finch_notify_common(PURPLE_NOTIFY_URI
, PURPLE_NOTIFY_MSG_INFO
,
510 _("URI"), url
, NULL
, NULL
);
513 static PurpleNotifyUiOps ops
=
515 finch_notify_message
,
518 finch_notify_formatted
,
519 finch_notify_searchresults
,
520 finch_notify_sr_new_rows
,
521 finch_notify_userinfo
,
523 finch_close_notify
, /* The rest of the notify-uiops return a GntWidget.
524 These widgets should be destroyed from here. */
532 PurpleNotifyUiOps
*finch_notify_get_ui_ops()
537 void finch_notify_init()
539 userinfo
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
, NULL
);
542 void finch_notify_uninit()
544 g_hash_table_destroy(userinfo
);