comparison gtk/gtknotify.c @ 15327:5dee50faa9ef

[gaim-migrate @ 18118] Patch #1566459: "All new mail notifications in a single window" from Chris Stafford (notak). I had to update the patch to make sure it works with the current code. It's quite possible I broke something. If things work, praise Chris. If something's broke, FIX IT! :-P committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sat, 13 Jan 2007 09:50:16 +0000
parents 1f33d20e973d
children f8c999ce917f
comparison
equal deleted inserted replaced
15326:1f33d20e973d 15327:5dee50faa9ef
65 } GaimNotifySearchResultsButtonData; 65 } GaimNotifySearchResultsButtonData;
66 66
67 enum 67 enum
68 { 68 {
69 GAIM_MAIL_ICON, 69 GAIM_MAIL_ICON,
70 GAIM_MAIL_TO, 70 GAIM_MAIL_TEXT,
71 GAIM_MAIL_FROM,
72 GAIM_MAIL_SUBJECT,
73 GAIM_MAIL_DATA, 71 GAIM_MAIL_DATA,
74 COLUMNS_GAIM_MAIL 72 COLUMNS_GAIM_MAIL
75 }; 73 };
76 74
77 typedef struct _GaimMailDialog GaimMailDialog; 75 typedef struct _GaimMailDialog GaimMailDialog;
82 GtkWidget *treeview; 80 GtkWidget *treeview;
83 GtkTreeStore *treemodel; 81 GtkTreeStore *treemodel;
84 GtkLabel *label; 82 GtkLabel *label;
85 GtkWidget *open_button; 83 GtkWidget *open_button;
86 int total_count; 84 int total_count;
85 gboolean in_use;
87 }; 86 };
88 87
89 static GaimMailDialog *mail_dialog = NULL; 88 static GaimMailDialog *mail_dialog = NULL;
90 89
91 static void *gaim_gtk_notify_emails(GaimConnection *gc, size_t count, gboolean detailed, 90 static void *gaim_gtk_notify_emails(GaimConnection *gc, size_t count, gboolean detailed,
95 94
96 static void 95 static void
97 message_response_cb(GtkDialog *dialog, gint id, GtkWidget *widget) 96 message_response_cb(GtkDialog *dialog, gint id, GtkWidget *widget)
98 { 97 {
99 gaim_notify_close(GAIM_NOTIFY_MESSAGE, widget); 98 gaim_notify_close(GAIM_NOTIFY_MESSAGE, widget);
100 }
101
102 static void
103 email_nondetailed_cb(GtkDialog *dialog, gint id, GaimNotifyMailData *data)
104 {
105 if (id == GTK_RESPONSE_OK)
106 gaim_notify_uri(NULL, data->url);
107 gaim_notify_close(GAIM_NOTIFY_EMAILS, data);
108 gtk_widget_destroy(GTK_WIDGET(dialog));
109 } 99 }
110 100
111 static void 101 static void
112 email_response_cb(GtkDialog *dlg, gint id, GaimMailDialog *dialog) 102 email_response_cb(GtkDialog *dlg, gint id, GaimMailDialog *dialog)
113 { 103 {
155 } 145 }
156 146
157 static void 147 static void
158 reset_mail_dialog(GtkDialog *dialog) 148 reset_mail_dialog(GtkDialog *dialog)
159 { 149 {
150 if (mail_dialog->in_use)
151 return;
160 gtk_widget_destroy(mail_dialog->dialog); 152 gtk_widget_destroy(mail_dialog->dialog);
161 g_free(mail_dialog); 153 g_free(mail_dialog);
162 mail_dialog = NULL; 154 mail_dialog = NULL;
163 } 155 }
164 156
312 (from == NULL ? NULL : &from), 304 (from == NULL ? NULL : &from),
313 (to == NULL ? NULL : &to), 305 (to == NULL ? NULL : &to),
314 (url == NULL ? NULL : &url)); 306 (url == NULL ? NULL : &url));
315 } 307 }
316 308
317 struct inbox_info { 309 static GtkWidget *
318 char *url; 310 gaim_gtk_get_mail_dialog()
319 void *handle; 311 {
320 }; 312 if (mail_dialog == NULL) {
321 313 GtkWidget *dialog = NULL;
322 static void 314 GtkWidget *label;
323 free_inbox(struct inbox_info *inbox) 315 GtkWidget *sw;
324 {
325 g_free(inbox->url);
326 g_free(inbox);
327 }
328
329 static void
330 open_inbox_cb(struct inbox_info *inbox)
331 {
332 if (inbox->url)
333 gaim_notify_uri(inbox->handle, inbox->url);
334 free_inbox(inbox);
335 }
336
337
338 static void *
339 gaim_gtk_notify_emails(GaimConnection *gc, size_t count, gboolean detailed,
340 const char **subjects, const char **froms,
341 const char **tos, const char **urls)
342 {
343 GaimNotifyMailData *data = NULL;
344 GtkWidget *dialog = NULL;
345 GtkWidget *vbox = NULL;
346 GtkWidget *label;
347 char *detail_text;
348 char *label_text;
349 GtkTreeIter iter;
350 GaimAccount *account;
351
352 account = gaim_connection_get_account(gc);
353
354 if (!detailed) {
355 struct inbox_info *inbox = g_new0(struct inbox_info, 1);
356 GdkPixbuf *pixbuf = gtk_widget_render_icon(gaim_gtk_blist_get_default_gtk_blist()->headline_hbox,
357 GAIM_STOCK_ICON_ONLINE_MSG, GTK_ICON_SIZE_BUTTON, NULL);
358 char *label_text = g_strdup_printf(ngettext("<b>You have %d new e-mail.</b>",
359 "<b>You have %d new e-mails.</b>",
360 count), (int)count);
361
362 inbox->handle = gc;
363 inbox->url = urls ? g_strdup(urls[0]) : NULL;
364 gaim_gtk_blist_set_headline(label_text,
365 pixbuf, G_CALLBACK(open_inbox_cb), inbox,
366 (GDestroyNotify)free_inbox);
367 g_object_unref(pixbuf);
368 return NULL;
369 }
370
371 if (mail_dialog == NULL || !detailed)
372 {
373 GtkCellRenderer *rend; 316 GtkCellRenderer *rend;
374 GtkTreeViewColumn *column; 317 GtkTreeViewColumn *column;
375 GtkWidget *button = NULL; 318 GtkWidget *button = NULL;
319 GtkWidget *vbox = NULL;
376 320
377 dialog = gtk_dialog_new_with_buttons(_("New Mail"), NULL, 0, 321 dialog = gtk_dialog_new_with_buttons(_("New Mail"), NULL, 0,
378 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, 322 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
379 NULL); 323 NULL);
380 if (detailed) 324 gtk_window_set_role(GTK_WINDOW(dialog), "new_mail_detailed");
381 gtk_window_set_role(GTK_WINDOW(dialog), "new_mail_detailed"); 325
382 else 326 gtk_dialog_add_button(GTK_DIALOG(dialog),
383 gtk_window_set_role(GTK_WINDOW(dialog), "new_mail");
384
385 if (!detailed && urls)
386 {
387 gtk_dialog_add_button(GTK_DIALOG(dialog),
388 GAIM_STOCK_OPEN_MAIL, GTK_RESPONSE_OK);
389 }
390 else if (detailed && mail_dialog == NULL)
391 {
392 gtk_dialog_add_button(GTK_DIALOG(dialog),
393 _("Open All Messages"), GTK_RESPONSE_ACCEPT); 327 _("Open All Messages"), GTK_RESPONSE_ACCEPT);
394 328
395 button = gtk_dialog_add_button(GTK_DIALOG(dialog), 329 button = gtk_dialog_add_button(GTK_DIALOG(dialog),
396 GAIM_STOCK_OPEN_MAIL, GTK_RESPONSE_YES); 330 GAIM_STOCK_OPEN_MAIL, GTK_RESPONSE_YES);
397 }
398 331
399 /* Setup the dialog */ 332 /* Setup the dialog */
400 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BOX_SPACE); 333 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BOX_SPACE);
401 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BOX_SPACE); 334 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BOX_SPACE);
402 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); 335 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
403 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); 336 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER);
404 337
405 /* Vertical box */ 338 /* Vertical box */
406 vbox = GTK_DIALOG(dialog)->vbox; 339 vbox = GTK_DIALOG(dialog)->vbox;
407 340
408 if (mail_dialog == NULL && detailed) 341 /* Golden ratio it up! */
409 { 342 gtk_widget_set_size_request(dialog, 550, 400);
410 GtkWidget *sw; 343
411 344 sw = gtk_scrolled_window_new(NULL, NULL);
412 /* Golden ratio it up! */ 345 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
413 gtk_widget_set_size_request(dialog, 550, 400); 346 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
414 347
415 sw = gtk_scrolled_window_new(NULL, NULL); 348 mail_dialog = g_new0(GaimMailDialog, 1);
416 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); 349 mail_dialog->dialog = dialog;
417 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); 350 mail_dialog->open_button = button;
418 351
419 mail_dialog = g_new0(GaimMailDialog, 1); 352 mail_dialog->treemodel = gtk_tree_store_new(COLUMNS_GAIM_MAIL,
420 mail_dialog->dialog = dialog; 353 GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
421 mail_dialog->open_button = button; 354 mail_dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(mail_dialog->treemodel));
422 355
423 mail_dialog->treemodel = gtk_tree_store_new(COLUMNS_GAIM_MAIL, 356 g_signal_connect(G_OBJECT(dialog), "response",
424 GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); 357 G_CALLBACK(email_response_cb), mail_dialog);
425 mail_dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(mail_dialog->treemodel)); 358 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(mail_dialog->treeview))),
426 359 "changed", G_CALLBACK(selection_changed_cb), mail_dialog);
427 g_signal_connect(G_OBJECT(dialog), "response", 360
428 G_CALLBACK(email_response_cb), mail_dialog); 361 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(mail_dialog->treeview), FALSE);
429 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(mail_dialog->treeview))), 362 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(mail_dialog->treeview), TRUE);
430 "changed", G_CALLBACK(selection_changed_cb), mail_dialog); 363 gtk_container_add(GTK_CONTAINER(sw), mail_dialog->treeview);
431 364
432 /* Account column */ 365 column = gtk_tree_view_column_new();
433 column = gtk_tree_view_column_new(); 366 gtk_tree_view_column_set_resizable(column, TRUE);
434 gtk_tree_view_column_set_resizable(column, TRUE); 367 rend = gtk_cell_renderer_pixbuf_new();
435 gtk_tree_view_column_set_title(column, _("Account")); 368 gtk_tree_view_column_pack_start(column, rend, FALSE);
436 rend = gtk_cell_renderer_pixbuf_new(); 369 gtk_tree_view_column_set_attributes(column, rend, "pixbuf", GAIM_MAIL_ICON, NULL);
437 gtk_tree_view_column_pack_start(column, rend, FALSE); 370 rend = gtk_cell_renderer_text_new();
438 gtk_tree_view_column_set_attributes(column, rend, "pixbuf", GAIM_MAIL_ICON, NULL); 371 gtk_tree_view_column_pack_start(column, rend, TRUE);
439 rend = gtk_cell_renderer_text_new(); 372 gtk_tree_view_column_set_attributes(column, rend, "markup", GAIM_MAIL_TEXT, NULL);
440 gtk_tree_view_column_pack_start(column, rend, TRUE); 373 gtk_tree_view_append_column(GTK_TREE_VIEW(mail_dialog->treeview), column);
441 gtk_tree_view_column_set_attributes(column, rend, "markup", GAIM_MAIL_TO, NULL); 374
442 gtk_tree_view_append_column(GTK_TREE_VIEW(mail_dialog->treeview), column); 375 label = gtk_label_new(NULL);
443 376 gtk_label_set_markup(GTK_LABEL(label), _("<span weight=\"bold\" size=\"larger\">You have mail!</span>"));
444 /* From column */ 377 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
445 column = gtk_tree_view_column_new(); 378 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
446 gtk_tree_view_column_set_resizable(column, TRUE); 379 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
447 gtk_tree_view_column_set_title(column, _("From")); 380 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
448 rend = gtk_cell_renderer_text_new(); 381 }
449 gtk_tree_view_column_pack_start(column, rend, TRUE); 382
450 gtk_tree_view_column_set_attributes(column, rend, "markup", GAIM_MAIL_FROM, NULL); 383 return mail_dialog->dialog;
451 gtk_tree_view_append_column(GTK_TREE_VIEW(mail_dialog->treeview), column); 384 }
452 385
453 /* Subject column */ 386 static void *
454 column = gtk_tree_view_column_new(); 387 gaim_gtk_notify_add_mail(GtkTreeStore *treemodel, GdkPixbuf *icon, char *notification, const char *url)
455 gtk_tree_view_column_set_resizable(column, TRUE); 388 {
456 gtk_tree_view_column_set_title(column, _("Subject")); 389 GaimNotifyMailData *data = NULL;
457 rend = gtk_cell_renderer_text_new(); 390 GtkTreeIter iter;
458 gtk_tree_view_column_pack_start(column, rend, TRUE); 391
459 gtk_tree_view_column_set_attributes(column, rend, "markup", GAIM_MAIL_SUBJECT, NULL); 392 data = g_new0(GaimNotifyMailData, 1);
460 gtk_tree_view_append_column(GTK_TREE_VIEW(mail_dialog->treeview), column); 393 if (url != NULL)
461 394 data->url = g_strdup(url);
462 gtk_container_add(GTK_CONTAINER(sw), mail_dialog->treeview); 395
463 396 gtk_tree_store_append(treemodel, &iter, NULL);
464 label = gtk_label_new(NULL); 397 gtk_tree_store_set(treemodel, &iter,
465 gtk_label_set_markup(GTK_LABEL(label), _("<span weight=\"bold\" size=\"larger\">You have mail!</span>")); 398 GAIM_MAIL_ICON, icon,
466 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); 399 GAIM_MAIL_TEXT, notification,
467 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); 400 GAIM_MAIL_DATA, data,
468 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); 401 -1);
469 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); 402 data->iter = iter;
470 } 403 gtk_tree_model_get(GTK_TREE_MODEL(treemodel), &iter,
471 } 404 GAIM_MAIL_DATA, &data, -1);
472 405 return data;
473 if (detailed) 406 }
474 { 407
475 dialog = mail_dialog->dialog; 408 static void *
476 mail_dialog->total_count += count; 409 gaim_gtk_notify_emails(GaimConnection *gc, size_t count, gboolean detailed,
477 while (count--) 410 const char **subjects, const char **froms,
478 { 411 const char **tos, const char **urls)
412 {
413 GtkWidget *dialog = NULL;
414 char *notification;
415 GaimAccount *account;
416 GdkPixbuf *pixbuf;
417 GaimNotifyMailData *data = NULL;
418
419 account = gaim_connection_get_account(gc);
420 pixbuf = gaim_gtk_create_prpl_icon(account, 1);
421 dialog = gaim_gtk_get_mail_dialog(); /* This creates mail_dialog if necessary */
422
423 mail_dialog->total_count += count;
424 if (detailed) {
425 while (count--) {
479 char *to_text = NULL; 426 char *to_text = NULL;
480 char *from_text = NULL; 427 char *from_text = NULL;
481 char *subject_text = NULL; 428 char *subject_text = NULL;
482 GdkPixbuf *pixbuf; 429 char *tmp;
483 430 gboolean first = TRUE;
484 if (tos != NULL) 431
485 to_text = g_markup_escape_text(*tos, -1); 432 if (tos != NULL) {
486 if (froms != NULL) 433 tmp = g_markup_escape_text(*tos, -1);
487 from_text = g_markup_escape_text(*froms, -1); 434 to_text = g_strdup_printf("<b>%s</b>: %s\n", _("Account"), tmp);
488 if (subjects != NULL) 435 g_free(tmp);
489 subject_text = g_markup_escape_text(*subjects, -1); 436 first = FALSE;
490 437 tos++;
491 data = g_new0(GaimNotifyMailData, 1); 438 }
492 if (urls != NULL) 439 if (froms != NULL) {
493 data->url = g_strdup(*urls); 440 tmp = g_markup_escape_text(*froms, -1);
494 441 from_text = g_strdup_printf("%s<b>%s</b>: %s\n", first ? "<br>" : "", _("Sender"), tmp);
495 pixbuf = gaim_gtk_create_prpl_icon(account, 0.5); 442 g_free(tmp);
496 443 first = FALSE;
497 gtk_tree_store_append(mail_dialog->treemodel, &iter, NULL); 444 froms++;
498 gtk_tree_store_set(mail_dialog->treemodel, &iter, 445 }
499 GAIM_MAIL_ICON, pixbuf, 446 if (subjects != NULL) {
500 GAIM_MAIL_TO, to_text, 447 tmp = g_markup_escape_text(*subjects, -1);
501 GAIM_MAIL_FROM, from_text, 448 subject_text = g_strdup_printf("%s<b>%s</b>: %s", first ? "<br>" : "", _("Subject"), tmp);
502 GAIM_MAIL_SUBJECT, subject_text, 449 g_free(tmp);
503 GAIM_MAIL_DATA, data, 450 first = FALSE;
504 -1); 451 subjects++;
505 if (pixbuf != NULL) 452 }
506 g_object_unref(pixbuf); 453 #define SAFE(x) ((x) ? (x) : "")
454 notification = g_strdup_printf("%s%s%s", SAFE(to_text), SAFE(from_text), SAFE(subject_text));
455 #undef SAFE
507 g_free(to_text); 456 g_free(to_text);
508 g_free(from_text); 457 g_free(from_text);
509 g_free(subject_text); 458 g_free(subject_text);
510 data->iter = iter; 459
460 data = gaim_gtk_notify_add_mail(mail_dialog->treemodel, pixbuf, notification, urls ? *urls : NULL);
461 g_free(notification);
511 462
512 if (urls != NULL) 463 if (urls != NULL)
513 urls++; 464 urls++;
514 if (froms != NULL) 465 }
515 froms++; 466 } else {
516 if (subjects != NULL) 467 notification = g_strdup_printf(ngettext("%s has %d new message.",
517 subjects++; 468 "%s has %d new messages.",
518 if (tos != NULL) 469 (int)count),
519 tos++; 470 *tos, (int)count);
520 } 471 data = gaim_gtk_notify_add_mail(mail_dialog->treemodel, pixbuf, notification, urls ? *urls : NULL);
521 } 472 g_free(notification);
522 else 473 }
523 { 474
524 data = g_new0(GaimNotifyMailData, 1);
525
526 if (urls != NULL)
527 data->url = g_strdup(*urls);
528
529 g_signal_connect(G_OBJECT(dialog), "response",
530 G_CALLBACK(email_nondetailed_cb), data);
531
532 detail_text = g_strdup_printf(ngettext("%s has %d new message.",
533 "%s has %d new messages.",
534 (int)count),
535 *tos, (int)count);
536 label_text = g_strdup_printf(
537 _("<span weight=\"bold\" size=\"larger\">You have mail!</span>"
538 "\n\n%s"), detail_text);
539
540 label = gtk_label_new(NULL);
541
542 gtk_label_set_markup(GTK_LABEL(label), label_text);
543 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
544 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
545 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
546
547 g_free(label_text);
548 g_free(detail_text);
549 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
550 }
551 if (!GTK_WIDGET_VISIBLE(dialog)) { 475 if (!GTK_WIDGET_VISIBLE(dialog)) {
552 GdkPixbuf *pixbuf = gtk_widget_render_icon(dialog, GAIM_STOCK_ICON_ONLINE_MSG, 476 GdkPixbuf *pixbuf = gtk_widget_render_icon(dialog, GAIM_STOCK_ICON_ONLINE_MSG,
553 GTK_ICON_SIZE_BUTTON, NULL); 477 GTK_ICON_SIZE_BUTTON, NULL);
554 char *label_text = g_strdup_printf(ngettext("<b>You have %d new e-mail.</b>", 478 char *label_text = g_strdup_printf(ngettext("<b>You have %d new e-mail.</b>",
555 "<b>You have %d new e-mails.</b>", 479 "<b>You have %d new e-mails.</b>",
556 mail_dialog->total_count), mail_dialog->total_count); 480 mail_dialog->total_count), mail_dialog->total_count);
481 mail_dialog->in_use = TRUE; /* So that _set_headline doesn't accidentally
482 remove the notifications when replacing an
483 old notification. */
557 gaim_gtk_blist_set_headline(label_text, 484 gaim_gtk_blist_set_headline(label_text,
558 pixbuf, G_CALLBACK(gtk_widget_show_all), dialog, 485 pixbuf, G_CALLBACK(gtk_widget_show_all), dialog,
559 (GDestroyNotify)reset_mail_dialog); 486 (GDestroyNotify)reset_mail_dialog);
487 mail_dialog->in_use = FALSE;
488 g_free(label_text);
489 }
490
491 if (pixbuf != NULL)
560 g_object_unref(pixbuf); 492 g_object_unref(pixbuf);
561 } 493
562 494 return NULL;
563 return data;
564 } 495 }
565 496
566 static gboolean 497 static gboolean
567 formatted_input_cb(GtkWidget *win, GdkEventKey *event, gpointer data) 498 formatted_input_cb(GtkWidget *win, GdkEventKey *event, gpointer data)
568 { 499 {