Mercurial > pidgin.yaz
comparison pidgin/gtkprefs.c @ 27666:a08e84032814
merge of '2348ff22f0ff3453774b8b25b36238465580c609'
and 'e76f11543c2a4aa05bdf584f087cbe3439029661'
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sun, 12 Jul 2009 05:43:38 +0000 |
parents | 5b07c7253ba4 |
children | 85fa979b08c2 da33da2e1a1e |
comparison
equal
deleted
inserted
replaced
27186:048bcf41deef | 27666:a08e84032814 |
---|---|
26 */ | 26 */ |
27 #include "internal.h" | 27 #include "internal.h" |
28 #include "pidgin.h" | 28 #include "pidgin.h" |
29 | 29 |
30 #include "debug.h" | 30 #include "debug.h" |
31 #include "nat-pmp.h" | |
31 #include "notify.h" | 32 #include "notify.h" |
32 #include "prefs.h" | 33 #include "prefs.h" |
33 #include "proxy.h" | 34 #include "proxy.h" |
34 #include "prpl.h" | 35 #include "prpl.h" |
35 #include "request.h" | 36 #include "request.h" |
36 #include "savedstatuses.h" | 37 #include "savedstatuses.h" |
37 #include "sound.h" | 38 #include "sound.h" |
38 #include "sound-theme.h" | 39 #include "sound-theme.h" |
40 #include "stun.h" | |
39 #include "theme-manager.h" | 41 #include "theme-manager.h" |
42 #include "upnp.h" | |
40 #include "util.h" | 43 #include "util.h" |
41 #include "network.h" | 44 #include "network.h" |
42 | 45 |
43 #include "gtkblist.h" | 46 #include "gtkblist.h" |
44 #include "gtkconv.h" | 47 #include "gtkconv.h" |
59 #define PROXYUSER 2 | 62 #define PROXYUSER 2 |
60 #define PROXYPASS 3 | 63 #define PROXYPASS 3 |
61 | 64 |
62 #define PREFS_OPTIMAL_ICON_SIZE 32 | 65 #define PREFS_OPTIMAL_ICON_SIZE 32 |
63 | 66 |
67 struct theme_info { | |
68 gchar *type; | |
69 gchar *extension; | |
70 gchar *original_name; | |
71 }; | |
72 | |
64 static int sound_row_sel = 0; | 73 static int sound_row_sel = 0; |
65 static GtkWidget *prefsnotebook; | 74 static GtkWidget *prefsnotebook; |
66 | 75 |
67 static GtkWidget *sound_entry = NULL; | 76 static GtkWidget *sound_entry = NULL; |
68 static GtkListStore *smiley_theme_store = NULL; | 77 static GtkListStore *smiley_theme_store = NULL; |
72 static GtkWidget *prefs = NULL; | 81 static GtkWidget *prefs = NULL; |
73 static GtkWidget *debugbutton = NULL; | 82 static GtkWidget *debugbutton = NULL; |
74 static int notebook_page = 0; | 83 static int notebook_page = 0; |
75 static GtkTreeRowReference *previous_smiley_row = NULL; | 84 static GtkTreeRowReference *previous_smiley_row = NULL; |
76 | 85 |
77 static gboolean prefs_themes_unsorted = TRUE; | |
78 static GtkListStore *prefs_sound_themes; | 86 static GtkListStore *prefs_sound_themes; |
79 static GtkListStore *prefs_blist_themes; | 87 static GtkListStore *prefs_blist_themes; |
80 static GtkListStore *prefs_status_icon_themes; | 88 static GtkListStore *prefs_status_icon_themes; |
81 | 89 |
90 static GtkWidget *prefs_sound_themes_combo_box; | |
91 static GtkWidget *prefs_blist_themes_combo_box; | |
92 static GtkWidget *prefs_status_themes_combo_box; | |
82 | 93 |
83 /* | 94 /* |
84 * PROTOTYPES | 95 * PROTOTYPES |
85 */ | 96 */ |
86 static void delete_prefs(GtkWidget *, void *); | 97 static void delete_prefs(GtkWidget *, void *); |
104 GtkObject *adjust; | 115 GtkObject *adjust; |
105 int val; | 116 int val; |
106 | 117 |
107 val = purple_prefs_get_int(key); | 118 val = purple_prefs_get_int(key); |
108 | 119 |
109 adjust = gtk_adjustment_new(val, min, max, 1, 1, 1); | 120 adjust = gtk_adjustment_new(val, min, max, 1, 1, 0); |
110 spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); | 121 spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); |
111 g_object_set_data(G_OBJECT(spin), "val", (char *)key); | 122 g_object_set_data(G_OBJECT(spin), "val", (char *)key); |
112 if (max < 10000) | 123 if (max < 10000) |
113 gtk_widget_set_size_request(spin, 50, -1); | 124 gtk_widget_set_size_request(spin, 50, -1); |
114 else | 125 else |
119 | 130 |
120 return pidgin_add_widget_to_vbox(GTK_BOX(box), title, sg, spin, FALSE, NULL); | 131 return pidgin_add_widget_to_vbox(GTK_BOX(box), title, sg, spin, FALSE, NULL); |
121 } | 132 } |
122 | 133 |
123 static void | 134 static void |
124 entry_set(GtkEntry *entry, gpointer data) { | 135 entry_set(GtkEntry *entry, gpointer data) |
136 { | |
125 const char *key = (const char*)data; | 137 const char *key = (const char*)data; |
126 | 138 |
127 purple_prefs_set_string(key, gtk_entry_get_text(entry)); | 139 purple_prefs_set_string(key, gtk_entry_get_text(entry)); |
128 } | 140 } |
129 | 141 |
331 gtk_tree_row_reference_free(previous_smiley_row); | 343 gtk_tree_row_reference_free(previous_smiley_row); |
332 previous_smiley_row = NULL; | 344 previous_smiley_row = NULL; |
333 | 345 |
334 } | 346 } |
335 | 347 |
336 static void smiley_sel(GtkTreeSelection *sel, GtkTreeModel *model) { | 348 static void |
349 smiley_sel(GtkTreeSelection *sel, GtkTreeModel *model) | |
350 { | |
337 GtkTreeIter iter; | 351 GtkTreeIter iter; |
338 const char *themename; | 352 const char *themename; |
339 char *description; | 353 char *description; |
340 GValue val; | 354 GValue val; |
341 GtkTreePath *path, *oldpath; | 355 GtkTreePath *path, *oldpath; |
382 gtk_tree_row_reference_free(previous_smiley_row); | 396 gtk_tree_row_reference_free(previous_smiley_row); |
383 previous_smiley_row = gtk_tree_row_reference_new(model, path); | 397 previous_smiley_row = gtk_tree_row_reference_new(model, path); |
384 gtk_tree_path_free(path); | 398 gtk_tree_path_free(path); |
385 } | 399 } |
386 | 400 |
387 static GtkTreeRowReference *theme_refresh_theme_list(void) | 401 static GtkTreeRowReference * |
402 theme_refresh_theme_list(void) | |
388 { | 403 { |
389 GdkPixbuf *pixbuf; | 404 GdkPixbuf *pixbuf; |
390 GSList *themes; | 405 GSList *themes; |
391 GtkTreeIter iter; | 406 GtkTreeIter iter; |
392 GtkTreeRowReference *row_ref = NULL; | 407 GtkTreeRowReference *row_ref = NULL; |
440 } | 455 } |
441 | 456 |
442 return row_ref; | 457 return row_ref; |
443 } | 458 } |
444 | 459 |
445 static void theme_install_theme(char *path, char *extn) { | 460 /* Rebuild the markup for the sound theme selection for "(Custom)" themes */ |
461 static void | |
462 pref_sound_generate_markup(void) | |
463 { | |
464 gboolean print_custom, customized; | |
465 const gchar *name, *author, *description, *current_theme; | |
466 gchar *markup; | |
467 PurpleSoundTheme *theme; | |
468 GtkTreeIter iter; | |
469 | |
470 customized = pidgin_sound_is_customized(); | |
471 current_theme = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/theme"); | |
472 | |
473 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(prefs_sound_themes), &iter)) { | |
474 do { | |
475 gtk_tree_model_get(GTK_TREE_MODEL(prefs_sound_themes), &iter, 2, &name, -1); | |
476 | |
477 print_custom = customized && g_str_equal(current_theme, name); | |
478 | |
479 if (!name || *name == '\0') | |
480 markup = g_strdup_printf("<b>(Default)</b>%s%s - None\n<span foreground='dim grey'>The default Pidgin sound theme</span>", | |
481 print_custom ? " " : "", print_custom ? "(Custom)" : ""); | |
482 else { | |
483 theme = PURPLE_SOUND_THEME(purple_theme_manager_find_theme(name, "sound")); | |
484 author = purple_theme_get_author(PURPLE_THEME(theme)); | |
485 description = purple_theme_get_description(PURPLE_THEME(theme)); | |
486 | |
487 markup = g_strdup_printf("<b>%s</b>%s%s%s%s\n<span foreground='dim grey'>%s</span>", | |
488 name, print_custom ? " " : "", print_custom ? "(Custom)" : "", | |
489 author != NULL ? " - " : "", author != NULL ? author : "", description != NULL ? description : ""); | |
490 } | |
491 | |
492 gtk_list_store_set(prefs_sound_themes, &iter, 1, markup, -1); | |
493 | |
494 g_free(markup); | |
495 | |
496 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(prefs_sound_themes), &iter)); | |
497 } | |
498 } | |
499 | |
500 /* adds the themes to the theme list from the manager so they can be displayed in prefs */ | |
501 static void | |
502 prefs_themes_sort(PurpleTheme *theme) | |
503 { | |
504 GdkPixbuf *pixbuf = NULL; | |
505 GtkTreeIter iter; | |
506 gchar *image_full = NULL, *markup; | |
507 const gchar *name, *author, *description; | |
508 | |
509 if (PURPLE_IS_SOUND_THEME(theme)){ | |
510 | |
511 image_full = purple_theme_get_image_full(theme); | |
512 if (image_full != NULL){ | |
513 pixbuf = gdk_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL); | |
514 g_free(image_full); | |
515 } else pixbuf = NULL; | |
516 | |
517 gtk_list_store_append(prefs_sound_themes, &iter); | |
518 gtk_list_store_set(prefs_sound_themes, &iter, 0, pixbuf, 2, purple_theme_get_name(theme), -1); | |
519 | |
520 if (pixbuf != NULL) | |
521 g_object_unref(G_OBJECT(pixbuf)); | |
522 | |
523 } else if (PIDGIN_IS_BLIST_THEME(theme) || PIDGIN_IS_STATUS_ICON_THEME(theme)){ | |
524 GtkListStore *store; | |
525 | |
526 if (PIDGIN_IS_BLIST_THEME(theme)) | |
527 store = prefs_blist_themes; | |
528 else store = prefs_status_icon_themes; | |
529 | |
530 image_full = purple_theme_get_image_full(theme); | |
531 if (image_full != NULL){ | |
532 pixbuf = gdk_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL); | |
533 g_free(image_full); | |
534 } else pixbuf = NULL; | |
535 | |
536 name = purple_theme_get_name(theme); | |
537 author = purple_theme_get_author(theme); | |
538 description = purple_theme_get_description(theme); | |
539 | |
540 markup = g_strdup_printf("<b>%s</b>%s%s\n<span foreground='dim grey'>%s</span>", name, author != NULL ? " - " : "", | |
541 author != NULL ? author : "", description != NULL ? description : ""); | |
542 | |
543 gtk_list_store_append(store, &iter); | |
544 gtk_list_store_set(store, &iter, 0, pixbuf, 1, markup, 2, name, -1); | |
545 | |
546 g_free(markup); | |
547 if (pixbuf != NULL) | |
548 g_object_unref(G_OBJECT(pixbuf)); | |
549 } | |
550 } | |
551 | |
552 static void | |
553 prefs_set_active_theme_combo(GtkWidget *combo_box, GtkListStore *store, const gchar *current_theme) | |
554 { | |
555 GtkTreeIter iter; | |
556 gchar *theme = NULL; | |
557 gboolean unset = TRUE; | |
558 | |
559 if (current_theme && *current_theme && gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) { | |
560 do { | |
561 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 2, &theme, -1); | |
562 | |
563 if (g_str_equal(current_theme, theme)) { | |
564 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo_box), &iter); | |
565 unset = FALSE; | |
566 } | |
567 | |
568 g_free(theme); | |
569 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter)); | |
570 } | |
571 | |
572 if (unset) | |
573 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), 0); | |
574 } | |
575 | |
576 static void | |
577 prefs_themes_refresh(void) | |
578 { | |
579 GdkPixbuf *pixbuf = NULL; | |
580 gchar *filename; | |
581 GtkTreeIter iter; | |
582 | |
583 /* refresh the list of themes in the manager */ | |
584 purple_theme_manager_refresh(); | |
585 | |
586 filename = g_build_filename(DATADIR, "icons", "hicolor", "32x32", "apps", "pidgin.png", NULL); | |
587 pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL); | |
588 g_free(filename); | |
589 | |
590 /* sound themes */ | |
591 gtk_list_store_clear(prefs_sound_themes); | |
592 gtk_list_store_append(prefs_sound_themes, &iter); | |
593 gtk_list_store_set(prefs_sound_themes, &iter, 0, pixbuf, 2, "", -1); | |
594 | |
595 /* blist themes */ | |
596 gtk_list_store_clear(prefs_blist_themes); | |
597 gtk_list_store_append(prefs_blist_themes, &iter); | |
598 gtk_list_store_set(prefs_blist_themes, &iter, 0, pixbuf, 1, | |
599 "<b>(Default)</b> - None\n<span color='dim grey'>" | |
600 "The default Pidgin buddy list theme</span>", 2, "", -1); | |
601 | |
602 /* status icon themes */ | |
603 gtk_list_store_clear(prefs_status_icon_themes); | |
604 gtk_list_store_append(prefs_status_icon_themes, &iter); | |
605 gtk_list_store_set(prefs_status_icon_themes, &iter, 0, pixbuf, 1, | |
606 "<b>(Default)</b> - None\n<span color='dim grey'>" | |
607 "The default Pidgin status icon theme</span>", 2, "", -1); | |
608 g_object_unref(G_OBJECT(pixbuf)); | |
609 | |
610 purple_theme_manager_for_each_theme(prefs_themes_sort); | |
611 pref_sound_generate_markup(); | |
612 | |
613 /* set active */ | |
614 prefs_set_active_theme_combo(prefs_sound_themes_combo_box, prefs_sound_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/theme")); | |
615 prefs_set_active_theme_combo(prefs_blist_themes_combo_box, prefs_blist_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/theme")); | |
616 prefs_set_active_theme_combo(prefs_status_themes_combo_box, prefs_status_icon_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/status/icon-theme")); | |
617 } | |
618 | |
619 /* init all the theme variables so that the themes can be sorted later and used by pref pages */ | |
620 static void | |
621 prefs_themes_init(void) | |
622 { | |
623 prefs_sound_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); | |
624 | |
625 prefs_blist_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); | |
626 | |
627 prefs_status_icon_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); | |
628 } | |
629 | |
630 static PurpleTheme * | |
631 prefs_theme_find_theme(const gchar *path, const gchar *type) | |
632 { | |
633 PurpleTheme *theme = purple_theme_manager_load_theme(path, type); | |
634 GDir *dir = g_dir_open(path, 0, NULL); | |
635 const gchar *next; | |
636 | |
637 while (!PURPLE_IS_THEME(theme) && (next = g_dir_read_name(dir))) { | |
638 gchar *next_path = g_build_filename(path, next, NULL); | |
639 | |
640 if (g_file_test(next_path, G_FILE_TEST_IS_DIR)) | |
641 theme = prefs_theme_find_theme(next_path, type); | |
642 | |
643 g_free(next_path); | |
644 } | |
645 | |
646 g_dir_close(dir); | |
647 | |
648 return theme; | |
649 } | |
650 | |
651 /* Eww. Seriously ewww. But thanks, grim! This is taken from guifications2 */ | |
652 static gboolean | |
653 purple_theme_file_copy(const gchar *source, const gchar *destination) | |
654 { | |
655 FILE *src, *dest; | |
656 gint chr = EOF; | |
657 | |
658 if(!(src = g_fopen(source, "rb"))) | |
659 return FALSE; | |
660 if(!(dest = g_fopen(destination, "wb"))) { | |
661 fclose(src); | |
662 return FALSE; | |
663 } | |
664 | |
665 while((chr = fgetc(src)) != EOF) { | |
666 fputc(chr, dest); | |
667 } | |
668 | |
669 fclose(dest); | |
670 fclose(src); | |
671 | |
672 return TRUE; | |
673 } | |
674 | |
675 /* installs a theme, info is freed by function */ | |
676 static void | |
677 theme_install_theme(char *path, struct theme_info *info) | |
678 { | |
446 #ifndef _WIN32 | 679 #ifndef _WIN32 |
447 gchar *command; | 680 gchar *command; |
448 #endif | 681 #endif |
449 gchar *destdir; | 682 gchar *destdir, *tail, *type, *original_name; |
450 gchar *tail; | |
451 GtkTreeRowReference *theme_rowref; | 683 GtkTreeRowReference *theme_rowref; |
684 gboolean is_smiley_theme, is_archive; | |
685 PurpleTheme *theme = NULL; | |
686 | |
687 if (info == NULL) | |
688 return; | |
689 | |
690 original_name = info->original_name; | |
691 type = info->type; | |
692 | |
693 /* check the extension */ | |
694 tail = info->extension ? info->extension : g_strdup(strrchr(path, '.')); | |
695 | |
696 if (!tail) { | |
697 g_free(type); | |
698 g_free(original_name); | |
699 g_free(info); | |
700 return; | |
701 } else g_free(info); | |
702 | |
703 is_archive = !g_ascii_strcasecmp(tail, ".gz") || !g_ascii_strcasecmp(tail, ".tgz"); | |
704 | |
705 g_free(tail); | |
452 | 706 |
453 /* Just to be safe */ | 707 /* Just to be safe */ |
454 g_strchomp(path); | 708 g_strchomp(path); |
455 | 709 |
456 /* I dont know what you are, get out of here */ | 710 if ((is_smiley_theme = g_str_equal(type, "smiley"))) |
457 if (extn != NULL) | 711 destdir = g_build_filename(purple_user_dir(), "smileys", NULL); |
458 tail = extn; | 712 else destdir = g_build_filename(purple_user_dir(), "themes", "temp", NULL); |
459 else if ((tail = strrchr(path, '.')) == NULL) | |
460 return; | |
461 | |
462 destdir = g_strconcat(purple_user_dir(), G_DIR_SEPARATOR_S "smileys", NULL); | |
463 | 713 |
464 /* We'll check this just to make sure. This also lets us do something different on | 714 /* We'll check this just to make sure. This also lets us do something different on |
465 * other platforms, if need be */ | 715 * other platforms, if need be */ |
466 if (!g_ascii_strcasecmp(tail, ".gz") || !g_ascii_strcasecmp(tail, ".tgz")) { | 716 if (is_archive) { |
467 #ifndef _WIN32 | 717 #ifndef _WIN32 |
468 gchar *path_escaped = g_shell_quote(path); | 718 gchar *path_escaped = g_shell_quote(path); |
469 gchar *destdir_escaped = g_shell_quote(destdir); | 719 gchar *destdir_escaped = g_shell_quote(destdir); |
720 | |
721 if (!g_file_test(destdir, G_FILE_TEST_IS_DIR)) | |
722 purple_build_dir(destdir, S_IRUSR | S_IWUSR | S_IXUSR); | |
723 | |
470 command = g_strdup_printf("tar > /dev/null xzf %s -C %s", path_escaped, destdir_escaped); | 724 command = g_strdup_printf("tar > /dev/null xzf %s -C %s", path_escaped, destdir_escaped); |
471 g_free(path_escaped); | 725 g_free(path_escaped); |
472 g_free(destdir_escaped); | 726 g_free(destdir_escaped); |
727 | |
728 /* Fire! */ | |
729 if (system(command)) { | |
730 purple_notify_error(NULL, NULL, _("Theme failed to unpack."), NULL); | |
731 g_free(command); | |
732 g_free(destdir); | |
733 g_free(type); | |
734 g_free(original_name); | |
735 return; | |
736 } | |
473 #else | 737 #else |
474 if(!winpidgin_gz_untar(path, destdir)) { | 738 if(!winpidgin_gz_untar(path, destdir)) { |
475 g_free(destdir); | 739 g_free(destdir); |
740 g_free(type); | |
741 g_free(original_name); | |
476 return; | 742 return; |
477 } | 743 } |
478 #endif | 744 #endif |
479 } | 745 } |
480 else { | 746 |
481 g_free(destdir); | 747 if (is_smiley_theme) { |
482 return; | 748 /* just extract the folder to the smiley directory */ |
483 } | 749 theme_rowref = theme_refresh_theme_list(); |
484 | 750 |
485 #ifndef _WIN32 | 751 if (theme_rowref != NULL) { |
486 /* Fire! */ | 752 GtkTreePath *tp = gtk_tree_row_reference_get_path(theme_rowref); |
487 if (system(command)) | 753 |
488 { | 754 if (tp) |
489 purple_notify_error(NULL, NULL, _("Smiley theme failed to unpack."), NULL); | 755 gtk_tree_selection_select_path(smiley_theme_sel, tp); |
490 } | 756 |
491 | 757 gtk_tree_row_reference_free(theme_rowref); |
492 g_free(command); | 758 } |
493 #endif | 759 |
760 } else if (is_archive) { | |
761 theme = prefs_theme_find_theme(destdir, type); | |
762 | |
763 if (PURPLE_IS_THEME(theme)) { | |
764 /* create the location for the theme */ | |
765 gchar *theme_dest = g_build_filename(purple_user_dir(), "themes", | |
766 purple_theme_get_name(theme), | |
767 "purple", type, NULL); | |
768 | |
769 if (!g_file_test(theme_dest, G_FILE_TEST_IS_DIR)) | |
770 purple_build_dir(theme_dest, S_IRUSR | S_IWUSR | S_IXUSR); | |
771 | |
772 g_free(theme_dest); | |
773 theme_dest = g_build_filename(purple_user_dir(), "themes", | |
774 purple_theme_get_name(theme), | |
775 "purple", type, NULL); | |
776 | |
777 /* move the entire directory to new location */ | |
778 g_rename(purple_theme_get_dir(theme), theme_dest); | |
779 | |
780 g_free(theme_dest); | |
781 g_remove(destdir); | |
782 g_object_unref(theme); | |
783 | |
784 prefs_themes_refresh(); | |
785 | |
786 } else { | |
787 /* something was wrong with the theme archive */ | |
788 g_unlink(destdir); | |
789 purple_notify_error(NULL, NULL, _("Theme failed to load."), NULL); | |
790 } | |
791 | |
792 } else { /* just a single file so copy it to a new temp directory and attempt to load it*/ | |
793 gchar *temp_path, *temp_file; | |
794 | |
795 temp_path = g_build_filename(purple_user_dir(), "themes", "temp", "sub_folder", NULL); | |
796 | |
797 if (original_name != NULL) { | |
798 /* name was changed from the original (probably a dnd) change it back before loading */ | |
799 temp_file = g_build_filename(temp_path, original_name, NULL); | |
800 | |
801 } else { | |
802 gchar *source_name = g_path_get_basename(path); | |
803 temp_file = g_build_filename(temp_path, source_name, NULL); | |
804 g_free(source_name); | |
805 } | |
806 | |
807 if (!g_file_test(temp_path, G_FILE_TEST_IS_DIR)) | |
808 purple_build_dir(temp_path, S_IRUSR | S_IWUSR | S_IXUSR); | |
809 | |
810 if (purple_theme_file_copy(path, temp_file)) { | |
811 /* find the theme, could be in subfolder */ | |
812 theme = prefs_theme_find_theme(temp_path, type); | |
813 | |
814 if (PURPLE_IS_THEME(theme)) { | |
815 gchar *theme_dest = g_build_filename(purple_user_dir(), "themes", | |
816 purple_theme_get_name(theme), | |
817 "purple", type, NULL); | |
818 | |
819 if(!g_file_test(theme_dest, G_FILE_TEST_IS_DIR)) | |
820 purple_build_dir(theme_dest, S_IRUSR | S_IWUSR | S_IXUSR); | |
821 | |
822 g_rename(purple_theme_get_dir(theme), theme_dest); | |
823 | |
824 g_free(theme_dest); | |
825 g_object_unref(theme); | |
826 | |
827 prefs_themes_refresh(); | |
828 } else { | |
829 g_remove(temp_path); | |
830 purple_notify_error(NULL, NULL, _("Theme failed to load."), NULL); | |
831 } | |
832 } else { | |
833 purple_notify_error(NULL, NULL, _("Theme failed to copy."), NULL); | |
834 } | |
835 | |
836 g_free(temp_file); | |
837 g_free(temp_path); | |
838 } | |
839 | |
840 g_free(type); | |
841 g_free(original_name); | |
494 g_free(destdir); | 842 g_free(destdir); |
495 | |
496 theme_rowref = theme_refresh_theme_list(); | |
497 if (theme_rowref != NULL) { | |
498 GtkTreePath *tp = gtk_tree_row_reference_get_path(theme_rowref); | |
499 | |
500 if (tp) | |
501 gtk_tree_selection_select_path(smiley_theme_sel, tp); | |
502 gtk_tree_row_reference_free(theme_rowref); | |
503 } | |
504 } | 843 } |
505 | 844 |
506 static void | 845 static void |
507 theme_got_url(PurpleUtilFetchUrlData *url_data, gpointer user_data, | 846 theme_got_url(PurpleUtilFetchUrlData *url_data, gpointer user_data, |
508 const gchar *themedata, size_t len, const gchar *error_message) | 847 const gchar *themedata, size_t len, const gchar *error_message) |
531 g_free(path); | 870 g_free(path); |
532 } | 871 } |
533 | 872 |
534 static void | 873 static void |
535 theme_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | 874 theme_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, |
536 GtkSelectionData *sd, guint info, guint t, gpointer data) | 875 GtkSelectionData *sd, guint info, guint t, gpointer user_data) |
537 { | 876 { |
538 gchar *name = (gchar *)sd->data; | 877 gchar *name = g_strchomp((gchar *)sd->data); |
539 | 878 |
540 if ((sd->length >= 0) && (sd->format == 8)) { | 879 if ((sd->length >= 0) && (sd->format == 8)) { |
541 /* Well, it looks like the drag event was cool. | 880 /* Well, it looks like the drag event was cool. |
542 * Let's do something with it */ | 881 * Let's do something with it */ |
882 gchar *temp; | |
883 struct theme_info *info = g_new0(struct theme_info, 1); | |
884 info->type = g_strdup((gchar *)user_data); | |
885 info->extension = g_strdup(g_strrstr(name,".")); | |
886 temp = g_strrstr(name, "/"); | |
887 info->original_name = temp ? g_strdup(++temp) : NULL; | |
543 | 888 |
544 if (!g_ascii_strncasecmp(name, "file://", 7)) { | 889 if (!g_ascii_strncasecmp(name, "file://", 7)) { |
545 GError *converr = NULL; | 890 GError *converr = NULL; |
546 gchar *tmp; | 891 gchar *tmp; |
547 /* It looks like we're dealing with a local file. Let's | 892 /* It looks like we're dealing with a local file. Let's |
550 purple_debug(PURPLE_DEBUG_ERROR, "theme dnd", "%s\n", | 895 purple_debug(PURPLE_DEBUG_ERROR, "theme dnd", "%s\n", |
551 (converr ? converr->message : | 896 (converr ? converr->message : |
552 "g_filename_from_uri error")); | 897 "g_filename_from_uri error")); |
553 return; | 898 return; |
554 } | 899 } |
555 theme_install_theme(tmp, NULL); | 900 theme_install_theme(tmp, info); |
556 g_free(tmp); | 901 g_free(tmp); |
557 } else if (!g_ascii_strncasecmp(name, "http://", 7)) { | 902 } else if (!g_ascii_strncasecmp(name, "http://", 7)) { |
558 /* Oo, a web drag and drop. This is where things | 903 /* Oo, a web drag and drop. This is where things |
559 * will start to get interesting */ | 904 * will start to get interesting */ |
560 purple_util_fetch_url(name, TRUE, NULL, FALSE, theme_got_url, ".tgz"); | 905 purple_util_fetch_url(name, TRUE, NULL, FALSE, theme_got_url, info); |
561 } else if (!g_ascii_strncasecmp(name, "https://", 8)) { | 906 } else if (!g_ascii_strncasecmp(name, "https://", 8)) { |
562 /* purple_util_fetch_url() doesn't support HTTPS, but we want users | 907 /* purple_util_fetch_url() doesn't support HTTPS, but we want users |
563 * to be able to drag and drop links from the SF trackers, so | 908 * to be able to drag and drop links from the SF trackers, so |
564 * we'll try it as an HTTP URL. */ | 909 * we'll try it as an HTTP URL. */ |
565 char *tmp = g_strdup(name + 1); | 910 char *tmp = g_strdup(name + 1); |
566 tmp[0] = 'h'; | 911 tmp[0] = 'h'; |
567 tmp[1] = 't'; | 912 tmp[1] = 't'; |
568 tmp[2] = 't'; | 913 tmp[2] = 't'; |
569 tmp[3] = 'p'; | 914 tmp[3] = 'p'; |
570 purple_util_fetch_url(tmp, TRUE, NULL, FALSE, theme_got_url, ".tgz"); | 915 |
916 purple_util_fetch_url(tmp, TRUE, NULL, FALSE, theme_got_url, info); | |
571 g_free(tmp); | 917 g_free(tmp); |
572 } | 918 } |
573 | 919 |
574 gtk_drag_finish(dc, TRUE, FALSE, t); | 920 gtk_drag_finish(dc, TRUE, FALSE, t); |
575 } | 921 } |
576 | 922 |
577 gtk_drag_finish(dc, FALSE, FALSE, t); | 923 gtk_drag_finish(dc, FALSE, FALSE, t); |
578 } | 924 } |
579 | 925 |
580 /* Rebuild the markup for the sound theme selection for "(Custom)" themes */ | |
581 static void | |
582 pref_sound_generate_markup() | |
583 { | |
584 gboolean print_custom, customized; | |
585 const gchar *name, *author, *description, *current_theme; | |
586 gchar *markup; | |
587 PurpleSoundTheme *theme; | |
588 GtkTreeIter iter; | |
589 | |
590 customized = pidgin_sound_is_customized(); | |
591 current_theme = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/theme"); | |
592 | |
593 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(prefs_sound_themes), &iter)) { | |
594 do { | |
595 gtk_tree_model_get(GTK_TREE_MODEL(prefs_sound_themes), &iter, 2, &name, -1); | |
596 | |
597 print_custom = customized && g_str_equal(current_theme, name); | |
598 | |
599 if (g_str_equal(name, "")) | |
600 markup = g_strdup_printf("<b>(Default)</b>%s%s - None\n<span foreground='dim grey'>The default Pidgin sound theme</span>", | |
601 print_custom ? " " : "", print_custom ? "(Custom)" : ""); | |
602 else { | |
603 theme = PURPLE_SOUND_THEME(purple_theme_manager_find_theme(name, "sound")); | |
604 author = purple_theme_get_author(PURPLE_THEME(theme)); | |
605 description = purple_theme_get_description(PURPLE_THEME(theme)); | |
606 | |
607 markup = g_strdup_printf("<b>%s</b>%s%s%s%s\n<span foreground='dim grey'>%s</span>", | |
608 name, print_custom ? " " : "", print_custom ? "(Custom)" : "", | |
609 author != NULL ? " - " : "", author != NULL ? author : "", description != NULL ? description : ""); | |
610 } | |
611 | |
612 gtk_list_store_set(prefs_sound_themes, &iter, 1, markup, -1); | |
613 | |
614 g_free(markup); | |
615 | |
616 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(prefs_sound_themes), &iter)); | |
617 } | |
618 } | |
619 | |
620 /* adds the themes to the theme list from the manager so they can be sisplayed in prefs */ | |
621 static void | |
622 prefs_themes_sort(PurpleTheme *theme) | |
623 { | |
624 GdkPixbuf *pixbuf = NULL; | |
625 GtkTreeIter iter; | |
626 gchar *image_full = NULL, *markup; | |
627 const gchar *name, *author, *description; | |
628 | |
629 if (PURPLE_IS_SOUND_THEME(theme)){ | |
630 | |
631 image_full = purple_theme_get_image_full(theme); | |
632 if (image_full != NULL){ | |
633 pixbuf = gdk_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL); | |
634 g_free(image_full); | |
635 } else pixbuf = NULL; | |
636 | |
637 gtk_list_store_append(prefs_sound_themes, &iter); | |
638 gtk_list_store_set(prefs_sound_themes, &iter, 0, pixbuf, 2, purple_theme_get_name(theme), -1); | |
639 | |
640 if (pixbuf != NULL) | |
641 g_object_unref(G_OBJECT(pixbuf)); | |
642 | |
643 } else if (PIDGIN_IS_BLIST_THEME(theme) || PIDGIN_IS_STATUS_ICON_THEME(theme)){ | |
644 GtkListStore *store; | |
645 | |
646 if (PIDGIN_IS_BLIST_THEME(theme)) | |
647 store = prefs_blist_themes; | |
648 else store = prefs_status_icon_themes; | |
649 | |
650 image_full = purple_theme_get_image_full(theme); | |
651 if (image_full != NULL){ | |
652 pixbuf = gdk_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL); | |
653 g_free(image_full); | |
654 } else pixbuf = NULL; | |
655 | |
656 name = purple_theme_get_name(theme); | |
657 author = purple_theme_get_author(theme); | |
658 description = purple_theme_get_description(theme); | |
659 | |
660 markup = g_strdup_printf("<b>%s</b>%s%s\n<span foreground='dim grey'>%s</span>", name, author != NULL ? " - " : "", | |
661 author != NULL ? author : "", description != NULL ? description : ""); | |
662 | |
663 gtk_list_store_append(store, &iter); | |
664 gtk_list_store_set(store, &iter, 0, pixbuf, 1, markup, 2, name, -1); | |
665 | |
666 g_free(markup); | |
667 if (pixbuf != NULL) | |
668 g_object_unref(G_OBJECT(pixbuf)); | |
669 } | |
670 | |
671 } | |
672 | |
673 /* init all the theme variables so that the themes can be sorted later and used by pref pages */ | |
674 static void | |
675 prefs_themes_init() | |
676 { | |
677 GdkPixbuf *pixbuf = NULL; | |
678 gchar *filename; | |
679 GtkTreeIter iter; | |
680 | |
681 filename = g_build_filename(DATADIR, "icons", "hicolor", "32x32", "apps", "pidgin.png", NULL); | |
682 pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL); | |
683 g_free(filename); | |
684 | |
685 /* sound themes */ | |
686 prefs_sound_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); | |
687 | |
688 gtk_list_store_append(prefs_sound_themes, &iter); | |
689 gtk_list_store_set(prefs_sound_themes, &iter, 0, pixbuf, 2, "", -1); | |
690 | |
691 /* blist themes */ | |
692 prefs_blist_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); | |
693 | |
694 gtk_list_store_append(prefs_blist_themes, &iter); | |
695 gtk_list_store_set(prefs_blist_themes, &iter, 0, pixbuf, 1, "<b>(Default)</b> - None\n<span color='dim grey'>" | |
696 "The default Pidgin buddy list theme</span>", 2, "", -1); | |
697 | |
698 /* status icon themes */ | |
699 prefs_status_icon_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); | |
700 | |
701 gtk_list_store_append(prefs_status_icon_themes, &iter); | |
702 gtk_list_store_set(prefs_status_icon_themes, &iter, 0, pixbuf, 1, "<b>(Default)</b> - None\n<span color='dim grey'>" | |
703 "The default Pidgin status icon theme</span>", 2, "", -1); | |
704 | |
705 g_object_unref(G_OBJECT(pixbuf)); | |
706 } | |
707 | |
708 /* builds a theme combo box from a list store with colums: icon preview, markup, theme name */ | 926 /* builds a theme combo box from a list store with colums: icon preview, markup, theme name */ |
709 static GtkWidget * | 927 static GtkWidget * |
710 prefs_build_theme_combo_box(GtkListStore *store, const gchar *current_theme) | 928 prefs_build_theme_combo_box(GtkListStore *store, const gchar *current_theme, gchar *type) |
711 { | 929 { |
930 GtkCellRenderer *cell_rend; | |
712 GtkWidget *combo_box; | 931 GtkWidget *combo_box; |
713 GtkCellRenderer *cell_rend; | 932 GtkTargetEntry te[3] = {{"text/plain", 0, 0},{"text/uri-list", 0, 1},{"STRING", 0, 2}}; |
714 GtkTreeIter iter; | |
715 gchar *theme = NULL; | |
716 gboolean unset = TRUE; | |
717 | 933 |
718 g_return_val_if_fail(store != NULL && current_theme != NULL, NULL); | 934 g_return_val_if_fail(store != NULL && current_theme != NULL, NULL); |
719 | 935 |
720 combo_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); | 936 combo_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); |
721 | 937 |
729 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo_box), cell_rend, "markup", 1, NULL); | 945 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo_box), cell_rend, "markup", 1, NULL); |
730 /*#if GTK_CHECK_VERSION(2,6,0) | 946 /*#if GTK_CHECK_VERSION(2,6,0) |
731 g_object_set(cell_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); | 947 g_object_set(cell_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
732 #endif*/ | 948 #endif*/ |
733 | 949 |
734 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) { | 950 gtk_drag_dest_set(combo_box, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, te, |
735 do { | 951 sizeof(te) / sizeof(GtkTargetEntry) , GDK_ACTION_COPY | GDK_ACTION_MOVE); |
736 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 2, &theme, -1); | 952 |
737 | 953 g_signal_connect(G_OBJECT(combo_box), "drag_data_received", G_CALLBACK(theme_dnd_recv), type); |
738 if (g_str_equal(current_theme, theme)) { | |
739 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo_box), &iter); | |
740 unset = FALSE; | |
741 } | |
742 | |
743 g_free(theme); | |
744 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter)); | |
745 } | |
746 | |
747 if (unset) | |
748 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), 0); | |
749 | 954 |
750 return combo_box; | 955 return combo_box; |
751 } | 956 } |
752 | 957 |
753 /* sets the current sound theme */ | 958 /* sets the current sound theme */ |
755 prefs_set_sound_theme_cb(GtkComboBox *combo_box, gpointer user_data) | 960 prefs_set_sound_theme_cb(GtkComboBox *combo_box, gpointer user_data) |
756 { | 961 { |
757 gint i; | 962 gint i; |
758 gchar *pref; | 963 gchar *pref; |
759 gchar *new_theme; | 964 gchar *new_theme; |
760 gboolean success; | |
761 GtkTreeIter new_iter; | 965 GtkTreeIter new_iter; |
762 | 966 |
763 success = gtk_combo_box_get_active_iter(combo_box, &new_iter); | 967 if(gtk_combo_box_get_active_iter(combo_box, &new_iter)) { |
764 g_return_if_fail(success); | 968 |
765 | 969 gtk_tree_model_get(GTK_TREE_MODEL(prefs_sound_themes), &new_iter, 2, &new_theme, -1); |
766 gtk_tree_model_get(GTK_TREE_MODEL(prefs_sound_themes), &new_iter, 2, &new_theme, -1); | 970 |
767 | 971 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/sound/theme", new_theme); |
768 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/sound/theme", new_theme); | 972 |
769 | 973 /* New theme removes all customization */ |
770 /* New theme removes all customization */ | 974 for(i=0; i < PURPLE_NUM_SOUNDS; i++){ |
771 for(i=0; i < PURPLE_NUM_SOUNDS; i++){ | 975 pref = g_strdup_printf(PIDGIN_PREFS_ROOT "/sound/file/%s", |
772 pref = g_strdup_printf(PIDGIN_PREFS_ROOT "/sound/file/%s", | 976 pidgin_sound_get_event_option(i)); |
773 pidgin_sound_get_event_option(i)); | 977 purple_prefs_set_path(pref, ""); |
774 purple_prefs_set_path(pref, ""); | 978 g_free(pref); |
775 g_free(pref); | 979 } |
776 } | 980 |
777 | 981 /* gets rid of the "(Custom)" from the last selection */ |
778 /* gets rid of the "(Custom)" from the last selection */ | 982 pref_sound_generate_markup(); |
779 pref_sound_generate_markup(); | 983 |
780 | 984 gtk_entry_set_text(GTK_ENTRY(sound_entry), _("(default)")); |
781 gtk_entry_set_text(GTK_ENTRY(sound_entry), _("(default)")); | 985 |
782 | 986 g_free(new_theme); |
783 g_free(new_theme); | 987 } |
784 } | 988 } |
989 | |
785 | 990 |
786 /* Does same as normal sort, except "none" is sorted first */ | 991 /* Does same as normal sort, except "none" is sorted first */ |
787 static gint pidgin_sort_smileys (GtkTreeModel *model, | 992 static gint pidgin_sort_smileys (GtkTreeModel *model, |
788 GtkTreeIter *a, | 993 GtkTreeIter *a, |
789 GtkTreeIter *b, | 994 GtkTreeIter *b, |
819 } | 1024 } |
820 | 1025 |
821 static void | 1026 static void |
822 request_theme_file_name_cb(gpointer data, char *theme_file_name) | 1027 request_theme_file_name_cb(gpointer data, char *theme_file_name) |
823 { | 1028 { |
824 theme_install_theme(theme_file_name, NULL) ; | 1029 struct theme_info *info = g_new0(struct theme_info, 1); |
825 } | 1030 info->type = g_strdup("smiley"); |
826 | 1031 info->extension = NULL; |
827 static void | 1032 info->original_name = NULL; |
828 add_theme_button_clicked_cb(GtkWidget *widget, gpointer null) | 1033 |
829 { | 1034 theme_install_theme(theme_file_name, info); |
830 purple_request_file(NULL, _("Install Theme"), NULL, FALSE, (GCallback)request_theme_file_name_cb, NULL, NULL, NULL, NULL, NULL) ; | 1035 |
1036 g_free(info); | |
1037 } | |
1038 | |
1039 static void | |
1040 add_theme_button_clicked_cb(GtkWidget *widget, gpointer user_data) | |
1041 { | |
1042 purple_request_file(NULL, _("Install Theme"), NULL, FALSE, (GCallback)request_theme_file_name_cb, NULL, NULL, NULL, NULL, NULL); | |
831 } | 1043 } |
832 | 1044 |
833 static void | 1045 static void |
834 remove_theme_button_clicked_cb(GtkWidget *button, GtkTreeView *tv) | 1046 remove_theme_button_clicked_cb(GtkWidget *button, GtkTreeView *tv) |
835 { | 1047 { |
901 view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(smiley_theme_store)); | 1113 view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(smiley_theme_store)); |
902 | 1114 |
903 gtk_drag_dest_set(view, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, te, | 1115 gtk_drag_dest_set(view, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, te, |
904 sizeof(te) / sizeof(GtkTargetEntry) , GDK_ACTION_COPY | GDK_ACTION_MOVE); | 1116 sizeof(te) / sizeof(GtkTargetEntry) , GDK_ACTION_COPY | GDK_ACTION_MOVE); |
905 | 1117 |
906 g_signal_connect(G_OBJECT(view), "drag_data_received", G_CALLBACK(theme_dnd_recv), smiley_theme_store); | 1118 g_signal_connect(G_OBJECT(view), "drag_data_received", G_CALLBACK(theme_dnd_recv), "smiley"); |
907 | 1119 |
908 rend = gtk_cell_renderer_pixbuf_new(); | 1120 rend = gtk_cell_renderer_pixbuf_new(); |
909 smiley_theme_sel = sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); | 1121 smiley_theme_sel = sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); |
910 | 1122 |
911 /* Custom sort so "none" theme is at top of list */ | 1123 /* Custom sort so "none" theme is at top of list */ |
1161 | 1373 |
1162 /* sets the current buddy list theme */ | 1374 /* sets the current buddy list theme */ |
1163 static void | 1375 static void |
1164 prefs_set_blist_theme_cb(GtkComboBox *combo_box, gpointer user_data) | 1376 prefs_set_blist_theme_cb(GtkComboBox *combo_box, gpointer user_data) |
1165 { | 1377 { |
1166 PidginBlistTheme *theme = NULL; | 1378 PidginBlistTheme *theme = NULL; |
1167 GtkTreeIter iter; | 1379 GtkTreeIter iter; |
1168 gchar *name = NULL; | 1380 gchar *name = NULL; |
1169 | 1381 |
1170 g_return_if_fail(gtk_combo_box_get_active_iter(combo_box, &iter)); | 1382 if(gtk_combo_box_get_active_iter(combo_box, &iter)) { |
1171 gtk_tree_model_get(GTK_TREE_MODEL(prefs_blist_themes), &iter, 2, &name, -1); | 1383 |
1172 | 1384 gtk_tree_model_get(GTK_TREE_MODEL(prefs_blist_themes), &iter, 2, &name, -1); |
1173 if (name && *name) | 1385 |
1174 theme = PIDGIN_BLIST_THEME(purple_theme_manager_find_theme(name, "blist")); | 1386 if(!name || !g_str_equal(name, "")) |
1175 g_free(name); | 1387 theme = PIDGIN_BLIST_THEME(purple_theme_manager_find_theme(name, "blist")); |
1176 | 1388 |
1177 pidgin_blist_set_theme(theme); | 1389 g_free(name); |
1390 | |
1391 pidgin_blist_set_theme(theme); | |
1392 } | |
1178 } | 1393 } |
1179 | 1394 |
1180 /* sets the current icon theme */ | 1395 /* sets the current icon theme */ |
1181 static void | 1396 static void |
1182 prefs_set_status_icon_theme_cb(GtkComboBox *combo_box, gpointer user_data) | 1397 prefs_set_status_icon_theme_cb(GtkComboBox *combo_box, gpointer user_data) |
1183 { | 1398 { |
1184 PidginStatusIconTheme *theme; | 1399 PidginStatusIconTheme *theme = NULL; |
1185 GtkTreeIter iter; | 1400 GtkTreeIter iter; |
1186 gchar *name = NULL; | 1401 gchar *name = NULL; |
1187 | 1402 |
1188 g_return_if_fail(gtk_combo_box_get_active_iter(combo_box, &iter)); | 1403 if(gtk_combo_box_get_active_iter(combo_box, &iter)) { |
1189 gtk_tree_model_get(GTK_TREE_MODEL(prefs_status_icon_themes), &iter, 2, &name, -1); | 1404 |
1190 | 1405 gtk_tree_model_get(GTK_TREE_MODEL(prefs_status_icon_themes), &iter, 2, &name, -1); |
1191 theme = PIDGIN_STATUS_ICON_THEME(purple_theme_manager_find_theme(name, "status-icon")); | 1406 |
1192 g_free(name); | 1407 if(!name || !g_str_equal(name, "")) |
1193 | 1408 theme = PIDGIN_STATUS_ICON_THEME(purple_theme_manager_find_theme(name, "status-icon")); |
1194 pidgin_stock_load_status_icon_theme(theme); | 1409 |
1410 g_free(name); | |
1411 | |
1412 pidgin_stock_load_status_icon_theme(theme); | |
1413 } | |
1195 } | 1414 } |
1196 | 1415 |
1197 static GtkWidget * | 1416 static GtkWidget * |
1198 interface_page(void) | 1417 interface_page(void) |
1199 { | 1418 { |
1200 GtkWidget *ret; | 1419 GtkWidget *ret; |
1201 GtkWidget *vbox; | 1420 GtkWidget *vbox; |
1202 GtkWidget *vbox2; | 1421 GtkWidget *vbox2; |
1203 GtkWidget *label; | 1422 GtkWidget *label; |
1204 GtkWidget *combo_box; | |
1205 GtkSizeGroup *sg; | 1423 GtkSizeGroup *sg; |
1206 GList *names = NULL; | 1424 GList *names = NULL; |
1207 | 1425 |
1208 ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); | 1426 ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); |
1209 gtk_container_set_border_width(GTK_CONTAINER(ret), PIDGIN_HIG_BORDER); | 1427 gtk_container_set_border_width(GTK_CONTAINER(ret), PIDGIN_HIG_BORDER); |
1211 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | 1429 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
1212 | 1430 |
1213 /* Buddy List Themes */ | 1431 /* Buddy List Themes */ |
1214 vbox = pidgin_make_frame(ret, _("Buddy List Theme")); | 1432 vbox = pidgin_make_frame(ret, _("Buddy List Theme")); |
1215 | 1433 |
1216 combo_box = prefs_build_theme_combo_box(prefs_blist_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/theme")); | 1434 prefs_blist_themes_combo_box = prefs_build_theme_combo_box(prefs_blist_themes, |
1217 gtk_box_pack_start(GTK_BOX (vbox), combo_box, FALSE, FALSE, 0); | 1435 purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/theme"), |
1218 g_signal_connect(G_OBJECT(combo_box), "changed", (GCallback)prefs_set_blist_theme_cb, NULL); | 1436 "blist"); |
1437 | |
1438 gtk_box_pack_start(GTK_BOX (vbox), prefs_blist_themes_combo_box, FALSE, FALSE, 0); | |
1439 g_signal_connect(G_OBJECT(prefs_blist_themes_combo_box), "changed", (GCallback)prefs_set_blist_theme_cb, NULL); | |
1219 | 1440 |
1220 /* Status Icon Themes */ | 1441 /* Status Icon Themes */ |
1221 combo_box = prefs_build_theme_combo_box(prefs_status_icon_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/status/icon-theme")); | 1442 prefs_status_themes_combo_box = prefs_build_theme_combo_box(prefs_status_icon_themes, |
1222 gtk_box_pack_start(GTK_BOX (vbox), combo_box, FALSE, FALSE, 0); | 1443 purple_prefs_get_string(PIDGIN_PREFS_ROOT "/status/icon-theme"), |
1223 g_signal_connect(G_OBJECT(combo_box), "changed", (GCallback)prefs_set_status_icon_theme_cb, NULL); | 1444 "icon"); |
1445 | |
1446 gtk_box_pack_start(GTK_BOX (vbox), prefs_status_themes_combo_box, FALSE, FALSE, 0); | |
1447 g_signal_connect(G_OBJECT(prefs_status_themes_combo_box), "changed", (GCallback)prefs_set_status_icon_theme_cb, NULL); | |
1224 | 1448 |
1225 /* System Tray */ | 1449 /* System Tray */ |
1226 vbox = pidgin_make_frame(ret, _("System Tray Icon")); | 1450 vbox = pidgin_make_frame(ret, _("System Tray Icon")); |
1227 label = pidgin_prefs_dropdown(vbox, _("_Show system tray icon:"), PURPLE_PREF_STRING, | 1451 label = pidgin_prefs_dropdown(vbox, _("_Show system tray icon:"), PURPLE_PREF_STRING, |
1228 PIDGIN_PREFS_ROOT "/docklet/show", | 1452 PIDGIN_PREFS_ROOT "/docklet/show", |
1229 _("Always"), "always", | 1453 _("Always"), "always", |
1230 _("On unread messages"), "pending", | 1454 _("On unread messages"), "pending", |
1231 _("Never"), "never", | 1455 _("Never"), "never", |
1232 NULL); | 1456 NULL); |
1233 gtk_size_group_add_widget(sg, label); | 1457 gtk_size_group_add_widget(sg, label); |
1234 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | 1458 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); |
1235 | 1459 |
1236 vbox = pidgin_make_frame(ret, _("Conversation Window Hiding")); | 1460 vbox = pidgin_make_frame(ret, _("Conversation Window")); |
1237 label = pidgin_prefs_dropdown(vbox, _("_Hide new IM conversations:"), | 1461 label = pidgin_prefs_dropdown(vbox, _("_Hide new IM conversations:"), |
1238 PURPLE_PREF_STRING, PIDGIN_PREFS_ROOT "/conversations/im/hide_new", | 1462 PURPLE_PREF_STRING, PIDGIN_PREFS_ROOT "/conversations/im/hide_new", |
1239 _("Never"), "never", | 1463 _("Never"), "never", |
1240 _("When away"), "away", | 1464 _("When away"), "away", |
1241 _("Always"), "always", | 1465 _("Always"), "always", |
1242 NULL); | 1466 NULL); |
1243 gtk_size_group_add_widget(sg, label); | 1467 gtk_size_group_add_widget(sg, label); |
1244 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | 1468 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); |
1245 | 1469 |
1470 #ifdef _WIN32 | |
1471 pidgin_prefs_checkbox(_("Minimi_ze new conversation windows"), PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", vbox); | |
1472 #endif | |
1246 | 1473 |
1247 /* All the tab options! */ | 1474 /* All the tab options! */ |
1248 vbox = pidgin_make_frame(ret, _("Tabs")); | 1475 vbox = pidgin_make_frame(ret, _("Tabs")); |
1249 | 1476 |
1250 pidgin_prefs_checkbox(_("Show IMs and chats in _tabbed windows"), | 1477 pidgin_prefs_checkbox(_("Show IMs and chats in _tabbed windows"), |
1257 vbox2 = gtk_vbox_new(FALSE, 9); | 1484 vbox2 = gtk_vbox_new(FALSE, 9); |
1258 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0); | 1485 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0); |
1259 purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/conversations/tabs", | 1486 purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/conversations/tabs", |
1260 conversation_usetabs_cb, vbox2); | 1487 conversation_usetabs_cb, vbox2); |
1261 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs")) | 1488 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs")) |
1262 gtk_widget_set_sensitive(vbox2, FALSE); | 1489 gtk_widget_set_sensitive(vbox2, FALSE); |
1263 | 1490 |
1264 pidgin_prefs_checkbox(_("Show close b_utton on tabs"), | 1491 pidgin_prefs_checkbox(_("Show close b_utton on tabs"), |
1265 PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", vbox2); | 1492 PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", vbox2); |
1266 | 1493 |
1267 label = pidgin_prefs_dropdown(vbox2, _("_Placement:"), PURPLE_PREF_INT, | 1494 label = pidgin_prefs_dropdown(vbox2, _("_Placement:"), PURPLE_PREF_INT, |
1274 _("Left Vertical"), GTK_POS_LEFT|8, | 1501 _("Left Vertical"), GTK_POS_LEFT|8, |
1275 _("Right Vertical"), GTK_POS_RIGHT|8, | 1502 _("Right Vertical"), GTK_POS_RIGHT|8, |
1276 #endif | 1503 #endif |
1277 NULL); | 1504 NULL); |
1278 gtk_size_group_add_widget(sg, label); | 1505 gtk_size_group_add_widget(sg, label); |
1279 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | 1506 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); |
1280 | 1507 |
1281 names = pidgin_conv_placement_get_options(); | 1508 names = pidgin_conv_placement_get_options(); |
1282 label = pidgin_prefs_dropdown_from_list(vbox2, _("N_ew conversations:"), | 1509 label = pidgin_prefs_dropdown_from_list(vbox2, _("N_ew conversations:"), |
1283 PURPLE_PREF_STRING, PIDGIN_PREFS_ROOT "/conversations/placement", names); | 1510 PURPLE_PREF_STRING, PIDGIN_PREFS_ROOT "/conversations/placement", names); |
1284 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | 1511 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); |
1285 | 1512 |
1286 gtk_size_group_add_widget(sg, label); | 1513 gtk_size_group_add_widget(sg, label); |
1287 | 1514 |
1288 g_list_free(names); | 1515 g_list_free(names); |
1289 | 1516 |
1290 | |
1291 keyboard_shortcuts(ret); | 1517 keyboard_shortcuts(ret); |
1292 | |
1293 | 1518 |
1294 gtk_widget_show_all(ret); | 1519 gtk_widget_show_all(ret); |
1295 g_object_unref(sg); | 1520 g_object_unref(sg); |
1296 return ret; | 1521 return ret; |
1297 } | 1522 } |
1351 | 1576 |
1352 pidgin_prefs_checkbox(_("Use smooth-scrolling"), PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", vbox); | 1577 pidgin_prefs_checkbox(_("Use smooth-scrolling"), PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", vbox); |
1353 | 1578 |
1354 #ifdef _WIN32 | 1579 #ifdef _WIN32 |
1355 pidgin_prefs_checkbox(_("F_lash window when IMs are received"), PIDGIN_PREFS_ROOT "/win32/blink_im", vbox); | 1580 pidgin_prefs_checkbox(_("F_lash window when IMs are received"), PIDGIN_PREFS_ROOT "/win32/blink_im", vbox); |
1356 | |
1357 pidgin_prefs_checkbox(_("Minimi_ze new conversation windows"), PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", vbox); | |
1358 #endif | 1581 #endif |
1359 | 1582 |
1360 pidgin_prefs_labeled_spin_button(vbox, | 1583 pidgin_prefs_labeled_spin_button(vbox, |
1361 _("Minimum input area height in lines:"), | 1584 _("Minimum input area height in lines:"), |
1362 PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines", | 1585 PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines", |
1363 1, 8, NULL); | 1586 1, 8, NULL); |
1364 | |
1365 | 1587 |
1366 #if GTK_CHECK_VERSION(2,4,0) | 1588 #if GTK_CHECK_VERSION(2,4,0) |
1367 vbox = pidgin_make_frame(ret, _("Font")); | 1589 vbox = pidgin_make_frame(ret, _("Font")); |
1368 if (purple_running_gnome()) | 1590 if (purple_running_gnome()) |
1369 fontpref = pidgin_prefs_checkbox(_("Use document font from _theme"), PIDGIN_PREFS_ROOT "/conversations/use_theme_font", vbox); | 1591 fontpref = pidgin_prefs_checkbox(_("Use document font from _theme"), PIDGIN_PREFS_ROOT "/conversations/use_theme_font", vbox); |
1370 else | 1592 else |
1371 fontpref = pidgin_prefs_checkbox(_("Use font from _theme"), PIDGIN_PREFS_ROOT "/conversations/use_theme_font", vbox); | 1593 fontpref = pidgin_prefs_checkbox(_("Use font from _theme"), PIDGIN_PREFS_ROOT "/conversations/use_theme_font", vbox); |
1372 | 1594 |
1373 font_name = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font"); | 1595 font_name = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font"); |
1374 font_button = gtk_font_button_new_with_font(font_name ? font_name : NULL); | 1596 if ((font_name == NULL) || (*font_name == '\0')) { |
1597 font_button = gtk_font_button_new(); | |
1598 } else { | |
1599 font_button = gtk_font_button_new_with_font(font_name); | |
1600 } | |
1375 | 1601 |
1376 gtk_font_button_set_show_style(GTK_FONT_BUTTON(font_button), TRUE); | 1602 gtk_font_button_set_show_style(GTK_FONT_BUTTON(font_button), TRUE); |
1377 hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Conversation _font:"), NULL, font_button, FALSE, NULL); | 1603 hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Conversation _font:"), NULL, font_button, FALSE, NULL); |
1378 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font")) | 1604 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font")) |
1379 gtk_widget_set_sensitive(hbox, FALSE); | 1605 gtk_widget_set_sensitive(hbox, FALSE); |
1415 gtk_widget_show(ret); | 1641 gtk_widget_show(ret); |
1416 | 1642 |
1417 return ret; | 1643 return ret; |
1418 } | 1644 } |
1419 | 1645 |
1420 static void network_ip_changed(GtkEntry *entry, gpointer data) | 1646 static void |
1421 { | 1647 network_ip_changed(GtkEntry *entry, gpointer data) |
1422 /* | 1648 { |
1423 * TODO: It would be nice if we could validate this and show a | 1649 const gchar *text = gtk_entry_get_text(entry); |
1424 * red background in the box when the IP address is invalid | 1650 GdkColor color; |
1425 * and a green background when the IP address is valid. | 1651 |
1426 */ | 1652 if (text && *text) { |
1427 purple_network_set_public_ip(gtk_entry_get_text(entry)); | 1653 if (purple_ip_address_is_valid(text)) { |
1428 } | 1654 color.red = 0xAFFF; |
1429 | 1655 color.green = 0xFFFF; |
1430 static gboolean network_stun_server_changed_cb(GtkWidget *widget, | 1656 color.blue = 0xAFFF; |
1431 GdkEventFocus *event, gpointer data) | 1657 |
1658 purple_network_set_public_ip(text); | |
1659 } else { | |
1660 color.red = 0xFFFF; | |
1661 color.green = 0xAFFF; | |
1662 color.blue = 0xAFFF; | |
1663 } | |
1664 | |
1665 gtk_widget_modify_base(GTK_WIDGET(entry), GTK_STATE_NORMAL, &color); | |
1666 | |
1667 } else { | |
1668 purple_network_set_public_ip(""); | |
1669 gtk_widget_modify_base(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL); | |
1670 } | |
1671 } | |
1672 | |
1673 static gboolean | |
1674 network_stun_server_changed_cb(GtkWidget *widget, | |
1675 GdkEventFocus *event, gpointer data) | |
1432 { | 1676 { |
1433 GtkEntry *entry = GTK_ENTRY(widget); | 1677 GtkEntry *entry = GTK_ENTRY(widget); |
1434 purple_prefs_set_string("/purple/network/stun_server", | 1678 purple_prefs_set_string("/purple/network/stun_server", |
1435 gtk_entry_get_text(entry)); | 1679 gtk_entry_get_text(entry)); |
1436 purple_network_set_stun_server(gtk_entry_get_text(entry)); | 1680 purple_network_set_stun_server(gtk_entry_get_text(entry)); |
1437 | 1681 |
1438 return FALSE; | 1682 return FALSE; |
1439 } | 1683 } |
1440 | 1684 |
1441 static gboolean network_turn_server_changed_cb(GtkWidget *widget, | 1685 static gboolean |
1442 GdkEventFocus *event, gpointer data) | 1686 network_turn_server_changed_cb(GtkWidget *widget, |
1687 GdkEventFocus *event, gpointer data) | |
1443 { | 1688 { |
1444 GtkEntry *entry = GTK_ENTRY(widget); | 1689 GtkEntry *entry = GTK_ENTRY(widget); |
1445 purple_prefs_set_string("/purple/network/turn_server", | 1690 purple_prefs_set_string("/purple/network/turn_server", |
1446 gtk_entry_get_text(entry)); | 1691 gtk_entry_get_text(entry)); |
1447 purple_network_set_turn_server(gtk_entry_get_text(entry)); | 1692 purple_network_set_turn_server(gtk_entry_get_text(entry)); |
1448 | 1693 |
1449 return FALSE; | 1694 return FALSE; |
1450 } | 1695 } |
1451 | 1696 |
1452 static void | 1697 static void |
1453 proxy_changed_cb(const char *name, PurplePrefType type, | 1698 proxy_changed_cb(const char *name, PurplePrefType type, |
1460 gtk_widget_show_all(frame); | 1705 gtk_widget_show_all(frame); |
1461 else | 1706 else |
1462 gtk_widget_hide(frame); | 1707 gtk_widget_hide(frame); |
1463 } | 1708 } |
1464 | 1709 |
1465 static void proxy_print_option(GtkEntry *entry, int entrynum) | 1710 static void |
1711 proxy_print_option(GtkEntry *entry, int entrynum) | |
1466 { | 1712 { |
1467 if (entrynum == PROXYHOST) | 1713 if (entrynum == PROXYHOST) |
1468 purple_prefs_set_string("/purple/proxy/host", gtk_entry_get_text(entry)); | 1714 purple_prefs_set_string("/purple/proxy/host", gtk_entry_get_text(entry)); |
1469 else if (entrynum == PROXYPORT) | 1715 else if (entrynum == PROXYPORT) |
1470 purple_prefs_set_int("/purple/proxy/port", atoi(gtk_entry_get_text(entry))); | 1716 purple_prefs_set_int("/purple/proxy/port", atoi(gtk_entry_get_text(entry))); |
1506 GtkWidget *table, *label, *auto_ip_checkbox, *ports_checkbox, *spin_button; | 1752 GtkWidget *table, *label, *auto_ip_checkbox, *ports_checkbox, *spin_button; |
1507 GtkWidget *proxy_warning = NULL, *browser_warning = NULL; | 1753 GtkWidget *proxy_warning = NULL, *browser_warning = NULL; |
1508 GtkWidget *proxy_button = NULL, *browser_button = NULL; | 1754 GtkWidget *proxy_button = NULL, *browser_button = NULL; |
1509 GtkSizeGroup *sg; | 1755 GtkSizeGroup *sg; |
1510 PurpleProxyInfo *proxy_info = NULL; | 1756 PurpleProxyInfo *proxy_info = NULL; |
1757 const char *ip; | |
1758 PurpleStunNatDiscovery *stun; | |
1759 char *auto_ip_text; | |
1511 | 1760 |
1512 ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); | 1761 ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); |
1513 gtk_container_set_border_width (GTK_CONTAINER (ret), PIDGIN_HIG_BORDER); | 1762 gtk_container_set_border_width (GTK_CONTAINER (ret), PIDGIN_HIG_BORDER); |
1514 | 1763 |
1515 vbox = pidgin_make_frame (ret, _("IP Address")); | 1764 vbox = pidgin_make_frame (ret, _("IP Address")); |
1536 gtk_label_set_markup(GTK_LABEL(label), | 1785 gtk_label_set_markup(GTK_LABEL(label), |
1537 _("<span style=\"italic\">Example: stunserver.org</span>")); | 1786 _("<span style=\"italic\">Example: stunserver.org</span>")); |
1538 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | 1787 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); |
1539 gtk_container_add(GTK_CONTAINER(hbox), label); | 1788 gtk_container_add(GTK_CONTAINER(hbox), label); |
1540 | 1789 |
1541 auto_ip_checkbox = pidgin_prefs_checkbox(_("_Autodetect IP address"), | 1790 /* purple_network_get_my_ip will return the IP that was set by the user with |
1542 "/purple/network/auto_ip", vbox); | 1791 purple_network_set_public_ip, so make a lookup for the auto-detected IP |
1792 ourselves. */ | |
1793 | |
1794 /* Check if STUN discovery was already done */ | |
1795 stun = purple_stun_discover(NULL); | |
1796 if ((stun != NULL) && (stun->status == PURPLE_STUN_STATUS_DISCOVERED)) { | |
1797 ip = stun->publicip; | |
1798 } else { | |
1799 /* Attempt to get the IP from a NAT device using UPnP */ | |
1800 ip = purple_upnp_get_public_ip(); | |
1801 if (ip == NULL) { | |
1802 /* Attempt to get the IP from a NAT device using NAT-PMP */ | |
1803 ip = purple_pmp_get_public_ip(); | |
1804 if (ip == NULL) { | |
1805 /* Just fetch the IP of the local system */ | |
1806 ip = purple_network_get_local_system_ip(-1); | |
1807 } | |
1808 } | |
1809 } | |
1810 | |
1811 auto_ip_text = g_strdup_printf(_("Use _automatically detected IP address: %s"), ip); | |
1812 auto_ip_checkbox = pidgin_prefs_checkbox(auto_ip_text, "/purple/network/auto_ip", vbox); | |
1813 g_free(auto_ip_text); | |
1543 | 1814 |
1544 table = gtk_table_new(2, 2, FALSE); | 1815 table = gtk_table_new(2, 2, FALSE); |
1545 gtk_container_set_border_width(GTK_CONTAINER(table), 0); | 1816 gtk_container_set_border_width(GTK_CONTAINER(table), 0); |
1546 gtk_table_set_col_spacings(GTK_TABLE(table), 5); | 1817 gtk_table_set_col_spacings(GTK_TABLE(table), 5); |
1547 gtk_table_set_row_spacings(GTK_TABLE(table), 10); | 1818 gtk_table_set_row_spacings(GTK_TABLE(table), 10); |
1556 gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry); | 1827 gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry); |
1557 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); | 1828 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); |
1558 g_signal_connect(G_OBJECT(entry), "changed", | 1829 g_signal_connect(G_OBJECT(entry), "changed", |
1559 G_CALLBACK(network_ip_changed), NULL); | 1830 G_CALLBACK(network_ip_changed), NULL); |
1560 | 1831 |
1561 /* | 1832 gtk_entry_set_text(GTK_ENTRY(entry), purple_network_get_public_ip()); |
1562 * TODO: This could be better by showing the autodeteced | 1833 |
1563 * IP separately from the user-specified IP. | 1834 pidgin_set_accessible_label(entry, label); |
1564 */ | |
1565 if (purple_network_get_my_ip(-1) != NULL) | |
1566 gtk_entry_set_text(GTK_ENTRY(entry), | |
1567 purple_network_get_my_ip(-1)); | |
1568 | |
1569 pidgin_set_accessible_label (entry, label); | |
1570 | |
1571 | 1835 |
1572 if (purple_prefs_get_bool("/purple/network/auto_ip")) { | 1836 if (purple_prefs_get_bool("/purple/network/auto_ip")) { |
1573 gtk_widget_set_sensitive(GTK_WIDGET(table), FALSE); | 1837 gtk_widget_set_sensitive(GTK_WIDGET(table), FALSE); |
1574 } | 1838 } |
1575 | 1839 |
1617 hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), "_TURN server:", | 1881 hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), "_TURN server:", |
1618 sg, entry, TRUE, NULL); | 1882 sg, entry, TRUE, NULL); |
1619 | 1883 |
1620 pidgin_prefs_labeled_spin_button(hbox, _("_Port:"), | 1884 pidgin_prefs_labeled_spin_button(hbox, _("_Port:"), |
1621 "/purple/network/turn_port", 0, 65535, NULL); | 1885 "/purple/network/turn_port", 0, 65535, NULL); |
1622 hbox = pidgin_prefs_labeled_entry(vbox, "_Username:", | 1886 hbox = pidgin_prefs_labeled_entry(vbox, "_Username:", |
1623 "/purple/network/turn_username", sg); | 1887 "/purple/network/turn_username", sg); |
1624 pidgin_prefs_labeled_password(hbox, "_Password:", | 1888 pidgin_prefs_labeled_password(hbox, "_Password:", |
1625 "/purple/network/turn_password", NULL); | 1889 "/purple/network/turn_password", NULL); |
1626 | 1890 |
1627 if (purple_running_gnome()) { | 1891 if (purple_running_gnome()) { |
1799 | 2063 |
1800 return ret; | 2064 return ret; |
1801 } | 2065 } |
1802 | 2066 |
1803 #ifndef _WIN32 | 2067 #ifndef _WIN32 |
1804 static gboolean manual_browser_set(GtkWidget *entry, GdkEventFocus *event, gpointer data) { | 2068 static gboolean |
2069 manual_browser_set(GtkWidget *entry, GdkEventFocus *event, gpointer data) | |
2070 { | |
1805 const char *program = gtk_entry_get_text(GTK_ENTRY(entry)); | 2071 const char *program = gtk_entry_get_text(GTK_ENTRY(entry)); |
1806 | 2072 |
1807 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/browsers/command", program); | 2073 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/browsers/command", program); |
1808 | 2074 |
1809 /* carry on normally */ | 2075 /* carry on normally */ |
1810 return FALSE; | 2076 return FALSE; |
1811 } | 2077 } |
1812 | 2078 |
1813 static GList *get_available_browsers(void) | 2079 static GList * |
2080 get_available_browsers(void) | |
1814 { | 2081 { |
1815 struct browser { | 2082 struct browser { |
1816 char *name; | 2083 char *name; |
1817 char *command; | 2084 char *command; |
1818 }; | 2085 }; |
1975 | 2242 |
1976 return ret; | 2243 return ret; |
1977 } | 2244 } |
1978 | 2245 |
1979 #ifndef _WIN32 | 2246 #ifndef _WIN32 |
1980 static gint sound_cmd_yeah(GtkEntry *entry, gpointer d) | 2247 static gint |
2248 sound_cmd_yeah(GtkEntry *entry, gpointer d) | |
1981 { | 2249 { |
1982 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/sound/command", | 2250 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/sound/command", |
1983 gtk_entry_get_text(GTK_ENTRY(entry))); | 2251 gtk_entry_get_text(GTK_ENTRY(entry))); |
1984 return TRUE; | 2252 return TRUE; |
1985 } | 2253 } |
2107 gtk_entry_set_text(GTK_ENTRY(sound_entry), filename); | 2375 gtk_entry_set_text(GTK_ENTRY(sound_entry), filename); |
2108 | 2376 |
2109 pref_sound_generate_markup(); | 2377 pref_sound_generate_markup(); |
2110 } | 2378 } |
2111 | 2379 |
2112 static void select_sound(GtkWidget *button, gpointer being_NULL_is_fun) | 2380 static void |
2381 select_sound(GtkWidget *button, gpointer being_NULL_is_fun) | |
2113 { | 2382 { |
2114 gchar *pref; | 2383 gchar *pref; |
2115 const char *filename; | 2384 const char *filename; |
2116 | 2385 |
2117 pref = g_strdup_printf(PIDGIN_PREFS_ROOT "/sound/file/%s", | 2386 pref = g_strdup_printf(PIDGIN_PREFS_ROOT "/sound/file/%s", |
2127 NULL, NULL, NULL, | 2396 NULL, NULL, NULL, |
2128 GINT_TO_POINTER(sound_row_sel)); | 2397 GINT_TO_POINTER(sound_row_sel)); |
2129 } | 2398 } |
2130 | 2399 |
2131 #ifdef USE_GSTREAMER | 2400 #ifdef USE_GSTREAMER |
2132 static gchar* prefs_sound_volume_format(GtkScale *scale, gdouble val) | 2401 static gchar * |
2402 prefs_sound_volume_format(GtkScale *scale, gdouble val) | |
2133 { | 2403 { |
2134 if(val < 15) { | 2404 if(val < 15) { |
2135 return g_strdup_printf(_("Quietest")); | 2405 return g_strdup_printf(_("Quietest")); |
2136 } else if(val < 30) { | 2406 } else if(val < 30) { |
2137 return g_strdup_printf(_("Quieter")); | 2407 return g_strdup_printf(_("Quieter")); |
2146 } else { | 2416 } else { |
2147 return g_strdup_printf(_("Loudest")); | 2417 return g_strdup_printf(_("Loudest")); |
2148 } | 2418 } |
2149 } | 2419 } |
2150 | 2420 |
2151 static void prefs_sound_volume_changed(GtkRange *range) | 2421 static void |
2422 prefs_sound_volume_changed(GtkRange *range) | |
2152 { | 2423 { |
2153 int val = (int)gtk_range_get_value(GTK_RANGE(range)); | 2424 int val = (int)gtk_range_get_value(GTK_RANGE(range)); |
2154 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/sound/volume", val); | 2425 purple_prefs_set_int(PIDGIN_PREFS_ROOT "/sound/volume", val); |
2155 } | 2426 } |
2156 #endif | 2427 #endif |
2157 | 2428 |
2158 static void prefs_sound_sel(GtkTreeSelection *sel, GtkTreeModel *model) { | 2429 static void |
2430 prefs_sound_sel(GtkTreeSelection *sel, GtkTreeModel *model) | |
2431 { | |
2159 GtkTreeIter iter; | 2432 GtkTreeIter iter; |
2160 GValue val; | 2433 GValue val; |
2161 const char *file; | 2434 const char *file; |
2162 char *pref; | 2435 char *pref; |
2163 | 2436 |
2200 | 2473 |
2201 static GtkWidget * | 2474 static GtkWidget * |
2202 sound_page(void) | 2475 sound_page(void) |
2203 { | 2476 { |
2204 GtkWidget *ret; | 2477 GtkWidget *ret; |
2205 GtkWidget *vbox, *sw, *button, *combo_box; | 2478 GtkWidget *vbox, *sw, *button; |
2206 GtkSizeGroup *sg; | 2479 GtkSizeGroup *sg; |
2207 GtkTreeIter iter; | 2480 GtkTreeIter iter; |
2208 GtkWidget *event_view; | 2481 GtkWidget *event_view; |
2209 GtkListStore *event_store; | 2482 GtkListStore *event_store; |
2210 GtkCellRenderer *rend; | 2483 GtkCellRenderer *rend; |
2306 TRUE, 0, GTK_PACK_START); | 2579 TRUE, 0, GTK_PACK_START); |
2307 gtk_box_set_child_packing(GTK_BOX(vbox->parent->parent->parent), | 2580 gtk_box_set_child_packing(GTK_BOX(vbox->parent->parent->parent), |
2308 vbox->parent->parent, TRUE, TRUE, 0, GTK_PACK_START); | 2581 vbox->parent->parent, TRUE, TRUE, 0, GTK_PACK_START); |
2309 | 2582 |
2310 /* SOUND THEMES */ | 2583 /* SOUND THEMES */ |
2311 combo_box = prefs_build_theme_combo_box(prefs_sound_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/theme")); | 2584 prefs_sound_themes_combo_box = prefs_build_theme_combo_box(prefs_sound_themes, |
2312 pref_sound_generate_markup(); | 2585 purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/theme"), |
2313 gtk_box_pack_start(GTK_BOX (vbox), combo_box, FALSE, FALSE, 0); | 2586 "sound"); |
2314 | 2587 |
2315 g_signal_connect(G_OBJECT(combo_box), "changed", (GCallback)prefs_set_sound_theme_cb, NULL); | 2588 |
2589 gtk_box_pack_start(GTK_BOX (vbox), prefs_sound_themes_combo_box, FALSE, FALSE, 0); | |
2590 | |
2591 g_signal_connect(G_OBJECT(prefs_sound_themes_combo_box), "changed", (GCallback)prefs_set_sound_theme_cb, NULL); | |
2316 | 2592 |
2317 /* SOUND SELECTION */ | 2593 /* SOUND SELECTION */ |
2318 sw = gtk_scrolled_window_new(NULL,NULL); | 2594 sw = gtk_scrolled_window_new(NULL,NULL); |
2319 gtk_widget_set_size_request(sw, -1, 100); | 2595 gtk_widget_set_size_request(sw, -1, 100); |
2320 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); | 2596 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); |
2503 | 2779 |
2504 return ret; | 2780 return ret; |
2505 } | 2781 } |
2506 | 2782 |
2507 static int | 2783 static int |
2508 prefs_notebook_add_page(const char *text, | 2784 prefs_notebook_add_page(const char *text, GtkWidget *page, int ind) |
2509 GtkWidget *page, | 2785 { |
2510 int ind) { | |
2511 | |
2512 #if GTK_CHECK_VERSION(2,4,0) | 2786 #if GTK_CHECK_VERSION(2,4,0) |
2513 return gtk_notebook_append_page(GTK_NOTEBOOK(prefsnotebook), page, gtk_label_new(text)); | 2787 return gtk_notebook_append_page(GTK_NOTEBOOK(prefsnotebook), page, gtk_label_new(text)); |
2514 #else | 2788 #else |
2515 gtk_notebook_append_page(GTK_NOTEBOOK(prefsnotebook), page, gtk_label_new(text)); | 2789 gtk_notebook_append_page(GTK_NOTEBOOK(prefsnotebook), page, gtk_label_new(text)); |
2516 return gtk_notebook_page_num(GTK_NOTEBOOK(prefsnotebook), page); | 2790 return gtk_notebook_page_num(GTK_NOTEBOOK(prefsnotebook), page); |
2517 #endif | 2791 #endif |
2518 } | 2792 } |
2519 | 2793 |
2520 static void prefs_notebook_init(void) { | 2794 static void |
2795 prefs_notebook_init(void) | |
2796 { | |
2521 prefs_notebook_add_page(_("Interface"), interface_page(), notebook_page++); | 2797 prefs_notebook_add_page(_("Interface"), interface_page(), notebook_page++); |
2522 prefs_notebook_add_page(_("Conversations"), conv_page(), notebook_page++); | 2798 prefs_notebook_add_page(_("Conversations"), conv_page(), notebook_page++); |
2523 prefs_notebook_add_page(_("Smiley Themes"), theme_page(), notebook_page++); | 2799 prefs_notebook_add_page(_("Smiley Themes"), theme_page(), notebook_page++); |
2524 prefs_notebook_add_page(_("Sounds"), sound_page(), notebook_page++); | 2800 prefs_notebook_add_page(_("Sounds"), sound_page(), notebook_page++); |
2525 prefs_notebook_add_page(_("Network"), network_page(), notebook_page++); | 2801 prefs_notebook_add_page(_("Network"), network_page(), notebook_page++); |
2532 #endif | 2808 #endif |
2533 prefs_notebook_add_page(_("Logging"), logging_page(), notebook_page++); | 2809 prefs_notebook_add_page(_("Logging"), logging_page(), notebook_page++); |
2534 prefs_notebook_add_page(_("Status / Idle"), away_page(), notebook_page++); | 2810 prefs_notebook_add_page(_("Status / Idle"), away_page(), notebook_page++); |
2535 } | 2811 } |
2536 | 2812 |
2537 void pidgin_prefs_show(void) | 2813 void |
2814 pidgin_prefs_show(void) | |
2538 { | 2815 { |
2539 GtkWidget *vbox; | 2816 GtkWidget *vbox; |
2540 GtkWidget *notebook; | 2817 GtkWidget *notebook; |
2541 GtkWidget *button; | 2818 GtkWidget *button; |
2542 | 2819 |
2543 if (prefs) { | 2820 if (prefs) { |
2544 gtk_window_present(GTK_WINDOW(prefs)); | 2821 gtk_window_present(GTK_WINDOW(prefs)); |
2545 return; | 2822 return; |
2546 } | 2823 } |
2547 | 2824 |
2548 /* Refresh the list of themes before showing the preferences window */ | |
2549 purple_theme_manager_refresh(); | |
2550 | |
2551 /* add everything in the theme manager before the window is loaded */ | |
2552 if (prefs_themes_unsorted) { | |
2553 purple_theme_manager_for_each_theme(prefs_themes_sort); | |
2554 prefs_themes_unsorted = FALSE; | |
2555 } | |
2556 /* copy the preferences to tmp values... | 2825 /* copy the preferences to tmp values... |
2557 * I liked "take affect immediately" Oh well :-( */ | 2826 * I liked "take affect immediately" Oh well :-( */ |
2558 /* (that should have been "effect," right?) */ | 2827 /* (that should have been "effect," right?) */ |
2559 | 2828 |
2560 /* Back to instant-apply! I win! BU-HAHAHA! */ | 2829 /* Back to instant-apply! I win! BU-HAHAHA! */ |
2574 button = pidgin_dialog_add_button(GTK_DIALOG(prefs), GTK_STOCK_CLOSE, NULL, NULL); | 2843 button = pidgin_dialog_add_button(GTK_DIALOG(prefs), GTK_STOCK_CLOSE, NULL, NULL); |
2575 g_signal_connect_swapped(G_OBJECT(button), "clicked", | 2844 g_signal_connect_swapped(G_OBJECT(button), "clicked", |
2576 G_CALLBACK(gtk_widget_destroy), prefs); | 2845 G_CALLBACK(gtk_widget_destroy), prefs); |
2577 | 2846 |
2578 prefs_notebook_init(); | 2847 prefs_notebook_init(); |
2848 | |
2849 /* Refresh the list of themes before showing the preferences window */ | |
2850 prefs_themes_refresh(); | |
2579 | 2851 |
2580 /* Show everything. */ | 2852 /* Show everything. */ |
2581 gtk_widget_show(prefs); | 2853 gtk_widget_show(prefs); |
2582 } | 2854 } |
2583 | 2855 |
2659 smiley_theme_pref_cb, NULL); | 2931 smiley_theme_pref_cb, NULL); |
2660 | 2932 |
2661 pidgin_prefs_update_old(); | 2933 pidgin_prefs_update_old(); |
2662 } | 2934 } |
2663 | 2935 |
2664 void pidgin_prefs_update_old() | 2936 void |
2937 pidgin_prefs_update_old(void) | |
2665 { | 2938 { |
2666 const char *str; | 2939 const char *str; |
2667 | 2940 |
2668 purple_prefs_rename("/gaim/gtk", PIDGIN_PREFS_ROOT); | 2941 purple_prefs_rename("/gaim/gtk", PIDGIN_PREFS_ROOT); |
2669 | 2942 |