1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2001 CodeFactory AB
3 * Copyright (C) 2001, 2002 Anders Carlsson
4 * Copyright (C) 2003, 2004 Matthias Clasen <mclasen@redhat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 * Author: Anders Carlsson <andersca@gnome.org>
25 * Modified by the GTK+ Team and others 1997-2004. See the AUTHORS
26 * file for a list of people on the GTK+ Team. See the ChangeLog
27 * files for a list of changes. These files are distributed with
28 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
35 #include <gdk/gdkkeysyms.h>
37 #include "gtkaboutdialog.h"
38 #include "gtkbutton.h"
40 #include "gtkdialog.h"
44 #include "gtklinkbutton.h"
45 #include "gtkmarshalers.h"
46 #include "gtknotebook.h"
47 #include "gtkscrolledwindow.h"
49 #include "gtktextview.h"
51 #include "gtkiconfactory.h"
54 #include "gtkmessagedialog.h"
55 #include "gtkprivate.h"
62 * SECTION:gtkaboutdialog
63 * @Short_description: Display information about an application
64 * @Title: GtkAboutDialog
65 * @See_also:#GTK_STOCK_ABOUT
67 * The #GtkAboutDialog offers a simple way to display information about
68 * a program like its logo, name, copyright, website and license. It is
69 * also possible to give credits to the authors, documenters, translators
70 * and artists who have worked on the program. An about dialog is typically
71 * opened when the user selects the <literal>About</literal> option from
72 * the <literal>Help</literal> menu. All parts of the dialog are optional.
74 * About dialog often contain links and email addresses. #GtkAboutDialog
75 * supports this by offering global hooks, which are called when the user
76 * clicks on a link or email address, see gtk_about_dialog_set_email_hook()
77 * and gtk_about_dialog_set_url_hook(). Email addresses in the
78 * authors, documenters and artists properties are recognized by looking for
79 * <literal><user@<!-- -->host></literal>, URLs are
80 * recognized by looking for <literal>http://url</literal>, with
81 * <literal>url</literal> extending to the next space, tab or line break.
83 * <para id="gtk-about-dialog-hook-setup">
84 * Since 2.18 #GtkAboutDialog provides default website and email hooks that
88 * If you want provide your own hooks overriding the default ones, it is
89 * important to do so before setting the website and email URL properties,
91 * <informalexample><programlisting>
92 * gtk_about_dialog_set_url_hook (GTK_ABOUT_DIALOG (dialog), launch_url, NULL, NULL);
93 * gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (dialog), app_url);
94 * </programlisting></informalexample>
95 * To disable the default hooks, you can pass %NULL as the hook func. Then,
96 * the #GtkAboutDialog widget will not display the website or the
97 * email addresses as clickable.
99 * To make constructing a #GtkAboutDialog as convenient as possible, you can
100 * use the function gtk_show_about_dialog() which constructs and shows a dialog
101 * and keeps it around so that it can be shown again.
103 * Note that GTK+ sets a default title of <literal>_("About %s")</literal>
104 * on the dialog window (where %s is replaced by the name of the
105 * application, but in order to ensure proper translation of the title,
106 * applications should set the title property explicitly when constructing
107 * a #GtkAboutDialog, as shown in the following example:
108 * <informalexample><programlisting>
109 * gtk_show_about_dialog (NULL,
110 * "program-name", "ExampleCode",
111 * "logo", example_logo,
112 * "title" _("About ExampleCode"),
114 * </programlisting></informalexample>
115 * Note that prior to GTK+ 2.12, the #GtkAboutDialog:program-name property
116 * was called "name". This was changed to avoid the conflict with the
117 * #GtkWidget:name property.
121 static GdkColor default_link_color = { 0, 0, 0, 0xeeee };
122 static GdkColor default_visited_link_color = { 0, 0x5555, 0x1a1a, 0x8b8b };
124 typedef struct _GtkAboutDialogPrivate GtkAboutDialogPrivate;
125 struct _GtkAboutDialogPrivate
133 gchar *translator_credits;
140 GtkWidget *logo_image;
141 GtkWidget *name_label;
142 GtkWidget *comments_label;
143 GtkWidget *copyright_label;
144 GtkWidget *website_button;
145 GtkWidget *website_label;
147 GtkWidget *credits_button;
148 GtkWidget *credits_dialog;
149 GtkWidget *license_button;
150 GtkWidget *license_dialog;
152 GdkCursor *hand_cursor;
153 GdkCursor *regular_cursor;
155 GSList *visited_links;
157 guint hovering_over_link : 1;
158 guint wrap_license : 1;
161 #define GTK_ABOUT_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ABOUT_DIALOG, GtkAboutDialogPrivate))
176 PROP_TRANSLATOR_CREDITS,
183 static void gtk_about_dialog_finalize (GObject *object);
184 static void gtk_about_dialog_get_property (GObject *object,
188 static void gtk_about_dialog_set_property (GObject *object,
192 static void gtk_about_dialog_show (GtkWidget *widge);
193 static void update_name_version (GtkAboutDialog *about);
194 static GtkIconSet * icon_set_new_from_pixbufs (GList *pixbufs);
195 static void follow_if_link (GtkAboutDialog *about,
196 GtkTextView *text_view,
198 static void set_cursor_if_appropriate (GtkAboutDialog *about,
199 GtkTextView *text_view,
202 static void display_credits_dialog (GtkWidget *button,
204 static void display_license_dialog (GtkWidget *button,
206 static void close_cb (GtkAboutDialog *about);
207 static void default_url_hook (GtkAboutDialog *about,
210 static void default_email_hook (GtkAboutDialog *about,
211 const gchar *email_address,
214 static gboolean activate_email_hook_set = FALSE;
215 static GtkAboutDialogActivateLinkFunc activate_email_hook = NULL;
216 static gpointer activate_email_hook_data = NULL;
217 static GDestroyNotify activate_email_hook_destroy = NULL;
219 static gboolean activate_url_hook_set = FALSE;
220 static GtkAboutDialogActivateLinkFunc activate_url_hook = NULL;
221 static gpointer activate_url_hook_data = NULL;
222 static GDestroyNotify activate_url_hook_destroy = NULL;
225 default_url_hook (GtkAboutDialog *about,
227 gpointer user_data G_GNUC_UNUSED)
230 GError *error = NULL;
232 screen = gtk_widget_get_screen (GTK_WIDGET (about));
234 if (!gtk_show_uri (screen, uri, gtk_get_current_event_time (), &error)) {
237 dialog = gtk_message_dialog_new (GTK_WINDOW (about),
238 GTK_DIALOG_DESTROY_WITH_PARENT |
242 "%s", _("Could not show link"));
243 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
244 "%s", error->message);
245 g_error_free (error);
247 g_signal_connect (dialog, "response",
248 G_CALLBACK (gtk_widget_destroy), NULL);
250 gtk_window_present (GTK_WINDOW (dialog));
255 default_email_hook (GtkAboutDialog *about,
256 const gchar *email_address,
261 escaped = g_uri_escape_string (email_address, NULL, FALSE);
262 uri = g_strdup_printf ("mailto:%s", escaped);
265 default_url_hook (about, uri, user_data);
269 G_DEFINE_TYPE (GtkAboutDialog, gtk_about_dialog, GTK_TYPE_DIALOG)
272 gtk_about_dialog_class_init (GtkAboutDialogClass *klass)
274 GObjectClass *object_class;
275 GtkWidgetClass *widget_class;
277 object_class = (GObjectClass *)klass;
278 widget_class = (GtkWidgetClass *)klass;
280 object_class->set_property = gtk_about_dialog_set_property;
281 object_class->get_property = gtk_about_dialog_get_property;
283 object_class->finalize = gtk_about_dialog_finalize;
285 widget_class->show = gtk_about_dialog_show;
288 * GtkAboutDialog:program-name:
290 * The name of the program.
291 * If this is not set, it defaults to g_get_application_name().
295 g_object_class_install_property (object_class,
297 g_param_spec_string ("program-name",
299 P_("The name of the program. If this is not set, it defaults to g_get_application_name()"),
301 GTK_PARAM_READWRITE));
304 * GtkAboutDialog:version:
306 * The version of the program.
310 g_object_class_install_property (object_class,
312 g_param_spec_string ("version",
313 P_("Program version"),
314 P_("The version of the program"),
316 GTK_PARAM_READWRITE));
319 * GtkAboutDialog:copyright:
321 * Copyright information for the program.
325 g_object_class_install_property (object_class,
327 g_param_spec_string ("copyright",
328 P_("Copyright string"),
329 P_("Copyright information for the program"),
331 GTK_PARAM_READWRITE));
335 * GtkAboutDialog:comments:
337 * Comments about the program. This string is displayed in a label
338 * in the main dialog, thus it should be a short explanation of
339 * the main purpose of the program, not a detailed list of features.
343 g_object_class_install_property (object_class,
345 g_param_spec_string ("comments",
346 P_("Comments string"),
347 P_("Comments about the program"),
349 GTK_PARAM_READWRITE));
352 * GtkAboutDialog:license:
354 * The license of the program. This string is displayed in a
355 * text view in a secondary dialog, therefore it is fine to use
356 * a long multi-paragraph text. Note that the text is only wrapped
357 * in the text view if the "wrap-license" property is set to %TRUE;
358 * otherwise the text itself must contain the intended linebreaks.
362 g_object_class_install_property (object_class,
364 g_param_spec_string ("license",
366 _("The license of the program"),
368 GTK_PARAM_READWRITE));
371 * GtkAboutDialog:website:
373 * The URL for the link to the website of the program.
374 * This should be a string starting with "http://.
378 g_object_class_install_property (object_class,
380 g_param_spec_string ("website",
382 P_("The URL for the link to the website of the program"),
384 GTK_PARAM_READWRITE));
387 * GtkAboutDialog:website-label:
389 * The label for the link to the website of the program. If this is not set,
390 * it defaults to the URL specified in the
391 * <link linkend="GtkAboutDialog--website">website</link> property.
395 g_object_class_install_property (object_class,
397 g_param_spec_string ("website-label",
399 P_("The label for the link to the website of the program. If this is not set, it defaults to the URL"),
401 GTK_PARAM_READWRITE));
404 * GtkAboutDialog:authors:
406 * The authors of the program, as a %NULL-terminated array of strings.
407 * Each string may contain email addresses and URLs, which will be displayed
408 * as links, see the introduction for more details.
412 g_object_class_install_property (object_class,
414 g_param_spec_boxed ("authors",
416 P_("List of authors of the program"),
418 GTK_PARAM_READWRITE));
421 * GtkAboutDialog:documenters:
423 * The people documenting the program, as a %NULL-terminated array of strings.
424 * Each string may contain email addresses and URLs, which will be displayed
425 * as links, see the introduction for more details.
429 g_object_class_install_property (object_class,
431 g_param_spec_boxed ("documenters",
433 P_("List of people documenting the program"),
435 GTK_PARAM_READWRITE));
438 * GtkAboutDialog:artists:
440 * The people who contributed artwork to the program, as a %NULL-terminated array of strings.
441 * Each string may contain email addresses and URLs, which will be displayed
442 * as links, see the introduction for more details.
446 g_object_class_install_property (object_class,
448 g_param_spec_boxed ("artists",
450 P_("List of people who have contributed artwork to the program"),
452 GTK_PARAM_READWRITE));
456 * GtkAboutDialog:translator-credits:
458 * Credits to the translators. This string should be marked as translatable.
459 * The string may contain email addresses and URLs, which will be displayed
460 * as links, see the introduction for more details.
464 g_object_class_install_property (object_class,
465 PROP_TRANSLATOR_CREDITS,
466 g_param_spec_string ("translator-credits",
467 P_("Translator credits"),
468 P_("Credits to the translators. This string should be marked as translatable"),
470 GTK_PARAM_READWRITE));
473 * GtkAboutDialog:logo:
475 * A logo for the about box. If this is not set, it defaults to
476 * gtk_window_get_default_icon_list().
480 g_object_class_install_property (object_class,
482 g_param_spec_object ("logo",
484 P_("A logo for the about box. If this is not set, it defaults to gtk_window_get_default_icon_list()"),
486 GTK_PARAM_READWRITE));
489 * GtkAboutDialog:logo-icon-name:
491 * A named icon to use as the logo for the about box. This property
492 * overrides the <link linkend="GtkAboutDialog--logo">logo</link> property.
496 g_object_class_install_property (object_class,
498 g_param_spec_string ("logo-icon-name",
499 P_("Logo Icon Name"),
500 P_("A named icon to use as the logo for the about box."),
502 GTK_PARAM_READWRITE));
504 * GtkAboutDialog:wrap-license:
506 * Whether to wrap the text in the license dialog.
510 g_object_class_install_property (object_class,
512 g_param_spec_boolean ("wrap-license",
514 P_("Whether to wrap the license text."),
516 GTK_PARAM_READWRITE));
519 g_type_class_add_private (object_class, sizeof (GtkAboutDialogPrivate));
523 gtk_about_dialog_init (GtkAboutDialog *about)
525 GtkDialog *dialog = GTK_DIALOG (about);
526 GtkAboutDialogPrivate *priv;
527 GtkWidget *vbox, *hbox, *button, *close_button, *image;
530 priv = GTK_ABOUT_DIALOG_GET_PRIVATE (about);
531 about->private_data = priv;
534 priv->version = NULL;
535 priv->copyright = NULL;
536 priv->comments = NULL;
537 priv->website_url = NULL;
538 priv->website_text = NULL;
539 priv->translator_credits = NULL;
540 priv->license = NULL;
541 priv->authors = NULL;
542 priv->documenters = NULL;
543 priv->artists = NULL;
545 priv->hand_cursor = gdk_cursor_new (GDK_HAND2);
546 priv->regular_cursor = gdk_cursor_new (GDK_XTERM);
547 priv->hovering_over_link = FALSE;
548 priv->wrap_license = FALSE;
550 gtk_dialog_set_has_separator (dialog, FALSE);
551 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
552 gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
553 gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
556 gtk_widget_push_composite_child ();
558 vbox = gtk_vbox_new (FALSE, 8);
559 gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
560 gtk_box_pack_start (GTK_BOX (dialog->vbox), vbox, TRUE, TRUE, 0);
562 priv->logo_image = gtk_image_new ();
563 gtk_box_pack_start (GTK_BOX (vbox), priv->logo_image, FALSE, FALSE, 0);
565 priv->name_label = gtk_label_new (NULL);
566 gtk_label_set_selectable (GTK_LABEL (priv->name_label), TRUE);
567 gtk_label_set_justify (GTK_LABEL (priv->name_label), GTK_JUSTIFY_CENTER);
568 gtk_box_pack_start (GTK_BOX (vbox), priv->name_label, FALSE, FALSE, 0);
570 priv->comments_label = gtk_label_new (NULL);
571 gtk_label_set_selectable (GTK_LABEL (priv->comments_label), TRUE);
572 gtk_label_set_justify (GTK_LABEL (priv->comments_label), GTK_JUSTIFY_CENTER);
573 gtk_label_set_line_wrap (GTK_LABEL (priv->comments_label), TRUE);
574 gtk_box_pack_start (GTK_BOX (vbox), priv->comments_label, FALSE, FALSE, 0);
576 priv->copyright_label = gtk_label_new (NULL);
577 gtk_label_set_selectable (GTK_LABEL (priv->copyright_label), TRUE);
578 gtk_label_set_justify (GTK_LABEL (priv->copyright_label), GTK_JUSTIFY_CENTER);
579 gtk_box_pack_start (GTK_BOX (vbox), priv->copyright_label, FALSE, FALSE, 0);
581 hbox = gtk_hbox_new (TRUE, 0);
582 gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
584 priv->website_button = button = gtk_link_button_new ("");
585 gtk_widget_set_no_show_all (button, TRUE);
586 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
588 priv->website_label = button = gtk_label_new ("");
589 gtk_widget_set_no_show_all (button, TRUE);
590 gtk_label_set_selectable (GTK_LABEL (button), TRUE);
591 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
593 gtk_widget_show (vbox);
594 gtk_widget_show (priv->logo_image);
595 gtk_widget_show (priv->name_label);
596 gtk_widget_show (hbox);
598 /* Add the OK button */
599 close_button = gtk_dialog_add_button (GTK_DIALOG (about), GTK_STOCK_CLOSE,
600 GTK_RESPONSE_CANCEL);
601 gtk_dialog_set_default_response (GTK_DIALOG (about), GTK_RESPONSE_CANCEL);
603 /* Add the credits button */
604 button = gtk_button_new_with_mnemonic (_("C_redits"));
605 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
606 image = gtk_image_new_from_stock (GTK_STOCK_ABOUT, GTK_ICON_SIZE_BUTTON);
607 gtk_button_set_image (GTK_BUTTON (button), image);
608 gtk_widget_set_no_show_all (button, TRUE);
609 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (about)->action_area),
610 button, FALSE, TRUE, 0);
611 gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (about)->action_area), button, TRUE);
612 g_signal_connect (button, "clicked",
613 G_CALLBACK (display_credits_dialog), about);
614 priv->credits_button = button;
615 priv->credits_dialog = NULL;
617 /* Add the license button */
618 button = gtk_button_new_from_stock (_("_License"));
619 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
620 gtk_widget_set_no_show_all (button, TRUE);
621 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (about)->action_area),
622 button, FALSE, TRUE, 0);
623 gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (about)->action_area), button, TRUE);
624 g_signal_connect (button, "clicked",
625 G_CALLBACK (display_license_dialog), about);
626 priv->license_button = button;
627 priv->license_dialog = NULL;
629 gtk_window_set_resizable (GTK_WINDOW (about), FALSE);
631 gtk_widget_pop_composite_child ();
633 gtk_widget_grab_default (close_button);
634 gtk_widget_grab_focus (close_button);
637 gtk_about_dialog_set_program_name (about, NULL);
638 gtk_about_dialog_set_logo (about, NULL);
642 gtk_about_dialog_finalize (GObject *object)
644 GtkAboutDialog *about = GTK_ABOUT_DIALOG (object);
645 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
648 g_free (priv->version);
649 g_free (priv->copyright);
650 g_free (priv->comments);
651 g_free (priv->license);
652 g_free (priv->website_url);
653 g_free (priv->website_text);
654 g_free (priv->translator_credits);
656 g_strfreev (priv->authors);
657 g_strfreev (priv->documenters);
658 g_strfreev (priv->artists);
660 g_slist_foreach (priv->visited_links, (GFunc)g_free, NULL);
661 g_slist_free (priv->visited_links);
663 gdk_cursor_unref (priv->hand_cursor);
664 gdk_cursor_unref (priv->regular_cursor);
666 G_OBJECT_CLASS (gtk_about_dialog_parent_class)->finalize (object);
670 gtk_about_dialog_set_property (GObject *object,
675 GtkAboutDialog *about = GTK_ABOUT_DIALOG (object);
676 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
681 gtk_about_dialog_set_program_name (about, g_value_get_string (value));
684 gtk_about_dialog_set_version (about, g_value_get_string (value));
687 gtk_about_dialog_set_comments (about, g_value_get_string (value));
690 gtk_about_dialog_set_website (about, g_value_get_string (value));
692 case PROP_WEBSITE_LABEL:
693 gtk_about_dialog_set_website_label (about, g_value_get_string (value));
696 gtk_about_dialog_set_license (about, g_value_get_string (value));
699 gtk_about_dialog_set_copyright (about, g_value_get_string (value));
702 gtk_about_dialog_set_logo (about, g_value_get_object (value));
705 gtk_about_dialog_set_authors (about, (const gchar**)g_value_get_boxed (value));
707 case PROP_DOCUMENTERS:
708 gtk_about_dialog_set_documenters (about, (const gchar**)g_value_get_boxed (value));
711 gtk_about_dialog_set_artists (about, (const gchar**)g_value_get_boxed (value));
713 case PROP_TRANSLATOR_CREDITS:
714 gtk_about_dialog_set_translator_credits (about, g_value_get_string (value));
716 case PROP_LOGO_ICON_NAME:
717 gtk_about_dialog_set_logo_icon_name (about, g_value_get_string (value));
719 case PROP_WRAP_LICENSE:
720 priv->wrap_license = g_value_get_boolean (value);
723 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
729 gtk_about_dialog_get_property (GObject *object,
734 GtkAboutDialog *about = GTK_ABOUT_DIALOG (object);
735 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
740 g_value_set_string (value, priv->name);
743 g_value_set_string (value, priv->version);
746 g_value_set_string (value, priv->copyright);
749 g_value_set_string (value, priv->comments);
752 g_value_set_string (value, priv->website_url);
754 case PROP_WEBSITE_LABEL:
755 g_value_set_string (value, priv->website_text);
758 g_value_set_string (value, priv->license);
760 case PROP_TRANSLATOR_CREDITS:
761 g_value_set_string (value, priv->translator_credits);
764 g_value_set_boxed (value, priv->authors);
766 case PROP_DOCUMENTERS:
767 g_value_set_boxed (value, priv->documenters);
770 g_value_set_boxed (value, priv->artists);
773 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_PIXBUF)
774 g_value_set_object (value, gtk_image_get_pixbuf (GTK_IMAGE (priv->logo_image)));
776 g_value_set_object (value, NULL);
778 case PROP_LOGO_ICON_NAME:
779 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_ICON_NAME)
781 const gchar *icon_name;
783 gtk_image_get_icon_name (GTK_IMAGE (priv->logo_image), &icon_name, NULL);
784 g_value_set_string (value, icon_name);
787 g_value_set_string (value, NULL);
789 case PROP_WRAP_LICENSE:
790 g_value_set_boolean (value, priv->wrap_license);
793 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
799 update_website (GtkAboutDialog *about)
801 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
803 if (priv->website_url && (!activate_url_hook_set || activate_url_hook != NULL))
805 gtk_widget_show (priv->website_button);
806 gtk_widget_hide (priv->website_label);
808 gtk_link_button_set_uri (GTK_LINK_BUTTON (priv->website_button), priv->website_url);
809 if (priv->website_text)
810 gtk_button_set_label (GTK_BUTTON (priv->website_button), priv->website_text);
812 gtk_button_set_label (GTK_BUTTON (priv->website_button), priv->website_url);
816 gtk_widget_show (priv->website_label);
817 gtk_widget_hide (priv->website_button);
819 if (priv->website_url)
820 gtk_label_set_text (GTK_LABEL (priv->website_label), priv->website_url);
821 else if (priv->website_text)
822 gtk_label_set_text (GTK_LABEL (priv->website_label), priv->website_text);
824 gtk_widget_hide (priv->website_label);
829 gtk_about_dialog_show (GtkWidget *widget)
831 update_website (GTK_ABOUT_DIALOG (widget));
833 GTK_WIDGET_CLASS (gtk_about_dialog_parent_class)->show (widget);
837 * gtk_about_dialog_get_name:
838 * @about: a #GtkAboutDialog
840 * Returns the program name displayed in the about dialog.
842 * Return value: The program name. The string is owned by the about
843 * dialog and must not be modified.
847 * Deprecated: 2.12: Use gtk_about_dialog_get_program_name() instead.
849 G_CONST_RETURN gchar *
850 gtk_about_dialog_get_name (GtkAboutDialog *about)
852 return gtk_about_dialog_get_program_name (about);
856 * gtk_about_dialog_get_program_name:
857 * @about: a #GtkAboutDialog
859 * Returns the program name displayed in the about dialog.
861 * Return value: The program name. The string is owned by the about
862 * dialog and must not be modified.
866 G_CONST_RETURN gchar *
867 gtk_about_dialog_get_program_name (GtkAboutDialog *about)
869 GtkAboutDialogPrivate *priv;
871 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
873 priv = (GtkAboutDialogPrivate *)about->private_data;
879 update_name_version (GtkAboutDialog *about)
881 GtkAboutDialogPrivate *priv;
882 gchar *title_string, *name_string;
884 priv = (GtkAboutDialogPrivate *)about->private_data;
886 title_string = g_strdup_printf (_("About %s"), priv->name);
887 gtk_window_set_title (GTK_WINDOW (about), title_string);
888 g_free (title_string);
890 if (priv->version != NULL)
891 name_string = g_markup_printf_escaped ("<span size=\"xx-large\" weight=\"bold\">%s %s</span>",
892 priv->name, priv->version);
894 name_string = g_markup_printf_escaped ("<span size=\"xx-large\" weight=\"bold\">%s</span>",
897 gtk_label_set_markup (GTK_LABEL (priv->name_label), name_string);
899 g_free (name_string);
903 * gtk_about_dialog_set_name:
904 * @about: a #GtkAboutDialog
905 * @name: the program name
907 * Sets the name to display in the about dialog.
908 * If this is not set, it defaults to g_get_application_name().
912 * Deprecated: 2.12: Use gtk_about_dialog_set_program_name() instead.
915 gtk_about_dialog_set_name (GtkAboutDialog *about,
918 gtk_about_dialog_set_program_name (about, name);
922 * gtk_about_dialog_set_program_name:
923 * @about: a #GtkAboutDialog
924 * @name: the program name
926 * Sets the name to display in the about dialog.
927 * If this is not set, it defaults to g_get_application_name().
932 gtk_about_dialog_set_program_name (GtkAboutDialog *about,
935 GtkAboutDialogPrivate *priv;
938 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
940 priv = (GtkAboutDialogPrivate *)about->private_data;
942 priv->name = g_strdup (name ? name : g_get_application_name ());
945 update_name_version (about);
947 g_object_notify (G_OBJECT (about), "program-name");
952 * gtk_about_dialog_get_version:
953 * @about: a #GtkAboutDialog
955 * Returns the version string.
957 * Return value: The version string. The string is owned by the about
958 * dialog and must not be modified.
962 G_CONST_RETURN gchar *
963 gtk_about_dialog_get_version (GtkAboutDialog *about)
965 GtkAboutDialogPrivate *priv;
967 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
969 priv = (GtkAboutDialogPrivate *)about->private_data;
971 return priv->version;
975 * gtk_about_dialog_set_version:
976 * @about: a #GtkAboutDialog
977 * @version: the version string
979 * Sets the version string to display in the about dialog.
984 gtk_about_dialog_set_version (GtkAboutDialog *about,
985 const gchar *version)
987 GtkAboutDialogPrivate *priv;
990 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
992 priv = (GtkAboutDialogPrivate *)about->private_data;
995 priv->version = g_strdup (version);
998 update_name_version (about);
1000 g_object_notify (G_OBJECT (about), "version");
1004 * gtk_about_dialog_get_copyright:
1005 * @about: a #GtkAboutDialog
1007 * Returns the copyright string.
1009 * Return value: The copyright string. The string is owned by the about
1010 * dialog and must not be modified.
1014 G_CONST_RETURN gchar *
1015 gtk_about_dialog_get_copyright (GtkAboutDialog *about)
1017 GtkAboutDialogPrivate *priv;
1019 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1021 priv = (GtkAboutDialogPrivate *)about->private_data;
1023 return priv->copyright;
1027 * gtk_about_dialog_set_copyright:
1028 * @about: a #GtkAboutDialog
1029 * @copyright: the copyright string
1031 * Sets the copyright string to display in the about dialog.
1032 * This should be a short string of one or two lines.
1037 gtk_about_dialog_set_copyright (GtkAboutDialog *about,
1038 const gchar *copyright)
1040 GtkAboutDialogPrivate *priv;
1041 gchar *copyright_string, *tmp;
1043 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1045 priv = (GtkAboutDialogPrivate *)about->private_data;
1047 tmp = priv->copyright;
1048 priv->copyright = g_strdup (copyright);
1051 if (priv->copyright != NULL)
1053 copyright_string = g_markup_printf_escaped ("<span size=\"small\">%s</span>",
1055 gtk_label_set_markup (GTK_LABEL (priv->copyright_label), copyright_string);
1056 g_free (copyright_string);
1058 gtk_widget_show (priv->copyright_label);
1061 gtk_widget_hide (priv->copyright_label);
1063 g_object_notify (G_OBJECT (about), "copyright");
1067 * gtk_about_dialog_get_comments:
1068 * @about: a #GtkAboutDialog
1070 * Returns the comments string.
1072 * Return value: The comments. The string is owned by the about
1073 * dialog and must not be modified.
1077 G_CONST_RETURN gchar *
1078 gtk_about_dialog_get_comments (GtkAboutDialog *about)
1080 GtkAboutDialogPrivate *priv;
1082 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1084 priv = (GtkAboutDialogPrivate *)about->private_data;
1086 return priv->comments;
1090 * gtk_about_dialog_set_comments:
1091 * @about: a #GtkAboutDialog
1092 * @comments: a comments string
1094 * Sets the comments string to display in the about
1095 * dialog. This should be a short string of one or
1101 gtk_about_dialog_set_comments (GtkAboutDialog *about,
1102 const gchar *comments)
1104 GtkAboutDialogPrivate *priv;
1107 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1109 priv = (GtkAboutDialogPrivate *)about->private_data;
1111 tmp = priv->comments;
1114 priv->comments = g_strdup (comments);
1115 gtk_label_set_text (GTK_LABEL (priv->comments_label), priv->comments);
1116 gtk_widget_show (priv->comments_label);
1120 priv->comments = NULL;
1121 gtk_widget_hide (priv->comments_label);
1125 g_object_notify (G_OBJECT (about), "comments");
1129 * gtk_about_dialog_get_license:
1130 * @about: a #GtkAboutDialog
1132 * Returns the license information.
1134 * Return value: The license information. The string is owned by the about
1135 * dialog and must not be modified.
1139 G_CONST_RETURN gchar *
1140 gtk_about_dialog_get_license (GtkAboutDialog *about)
1142 GtkAboutDialogPrivate *priv;
1144 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1146 priv = (GtkAboutDialogPrivate *)about->private_data;
1148 return priv->license;
1152 * gtk_about_dialog_set_license:
1153 * @about: a #GtkAboutDialog
1154 * @license: the license information or %NULL
1156 * Sets the license information to be displayed in the secondary
1157 * license dialog. If @license is %NULL, the license button is
1163 gtk_about_dialog_set_license (GtkAboutDialog *about,
1164 const gchar *license)
1166 GtkAboutDialogPrivate *priv;
1169 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1171 priv = (GtkAboutDialogPrivate *)about->private_data;
1173 tmp = priv->license;
1176 priv->license = g_strdup (license);
1177 gtk_widget_show (priv->license_button);
1181 priv->license = NULL;
1182 gtk_widget_hide (priv->license_button);
1186 g_object_notify (G_OBJECT (about), "license");
1190 * gtk_about_dialog_get_wrap_license:
1191 * @about: a #GtkAboutDialog
1193 * Returns whether the license text in @about is
1194 * automatically wrapped.
1196 * Returns: %TRUE if the license text is wrapped
1201 gtk_about_dialog_get_wrap_license (GtkAboutDialog *about)
1203 GtkAboutDialogPrivate *priv;
1205 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), FALSE);
1207 priv = (GtkAboutDialogPrivate *)about->private_data;
1209 return priv->wrap_license;
1213 * gtk_about_dialog_set_wrap_license:
1214 * @about: a #GtkAboutDialog
1215 * @wrap_license: whether to wrap the license
1217 * Sets whether the license text in @about is
1218 * automatically wrapped.
1223 gtk_about_dialog_set_wrap_license (GtkAboutDialog *about,
1224 gboolean wrap_license)
1226 GtkAboutDialogPrivate *priv;
1228 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1230 priv = (GtkAboutDialogPrivate *)about->private_data;
1232 wrap_license = wrap_license != FALSE;
1234 if (priv->wrap_license != wrap_license)
1236 priv->wrap_license = wrap_license;
1238 g_object_notify (G_OBJECT (about), "wrap-license");
1243 * gtk_about_dialog_get_website:
1244 * @about: a #GtkAboutDialog
1246 * Returns the website URL.
1248 * Return value: The website URL. The string is owned by the about
1249 * dialog and must not be modified.
1253 G_CONST_RETURN gchar *
1254 gtk_about_dialog_get_website (GtkAboutDialog *about)
1256 GtkAboutDialogPrivate *priv;
1258 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1260 priv = (GtkAboutDialogPrivate *)about->private_data;
1262 return priv->website_url;
1266 * gtk_about_dialog_set_website:
1267 * @about: a #GtkAboutDialog
1268 * @website: a URL string starting with "http://"
1270 * Sets the URL to use for the website link.
1272 * Note that that the hook functions need to be set up
1273 * before calling this function.
1278 gtk_about_dialog_set_website (GtkAboutDialog *about,
1279 const gchar *website)
1281 GtkAboutDialogPrivate *priv;
1284 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1286 priv = (GtkAboutDialogPrivate *)about->private_data;
1288 tmp = priv->website_url;
1289 priv->website_url = g_strdup (website);
1292 update_website (about);
1294 g_object_notify (G_OBJECT (about), "website");
1298 * gtk_about_dialog_get_website_label:
1299 * @about: a #GtkAboutDialog
1301 * Returns the label used for the website link.
1303 * Return value: The label used for the website link. The string is owned by the about
1304 * dialog and must not be modified.
1308 G_CONST_RETURN gchar *
1309 gtk_about_dialog_get_website_label (GtkAboutDialog *about)
1311 GtkAboutDialogPrivate *priv;
1313 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1315 priv = (GtkAboutDialogPrivate *)about->private_data;
1317 return priv->website_text;
1321 * gtk_about_dialog_set_website_label:
1322 * @about: a #GtkAboutDialog
1323 * @website_label: the label used for the website link
1325 * Sets the label to be used for the website link.
1326 * It defaults to the website URL.
1331 gtk_about_dialog_set_website_label (GtkAboutDialog *about,
1332 const gchar *website_label)
1334 GtkAboutDialogPrivate *priv;
1337 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1339 priv = (GtkAboutDialogPrivate *)about->private_data;
1341 tmp = priv->website_text;
1342 priv->website_text = g_strdup (website_label);
1345 update_website (about);
1347 g_object_notify (G_OBJECT (about), "website-label");
1351 * gtk_about_dialog_get_authors:
1352 * @about: a #GtkAboutDialog
1354 * Returns the string which are displayed in the authors tab
1355 * of the secondary credits dialog.
1357 * Return value: A %NULL-terminated string array containing
1358 * the authors. The array is owned by the about dialog
1359 * and must not be modified.
1363 G_CONST_RETURN gchar * G_CONST_RETURN *
1364 gtk_about_dialog_get_authors (GtkAboutDialog *about)
1366 GtkAboutDialogPrivate *priv;
1368 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1370 priv = (GtkAboutDialogPrivate *)about->private_data;
1372 return (const gchar * const *) priv->authors;
1376 update_credits_button_visibility (GtkAboutDialog *about)
1378 GtkAboutDialogPrivate *priv = about->private_data;
1381 show = priv->authors != NULL ||
1382 priv->documenters != NULL ||
1383 priv->artists != NULL ||
1384 (priv->translator_credits != NULL &&
1385 strcmp (priv->translator_credits, "translator_credits") &&
1386 strcmp (priv->translator_credits, "translator-credits"));
1388 gtk_widget_show (priv->credits_button);
1390 gtk_widget_hide (priv->credits_button);
1394 * gtk_about_dialog_set_authors:
1395 * @about: a #GtkAboutDialog
1396 * @authors: a %NULL-terminated array of strings
1398 * Sets the strings which are displayed in the authors tab
1399 * of the secondary credits dialog.
1404 gtk_about_dialog_set_authors (GtkAboutDialog *about,
1405 const gchar **authors)
1407 GtkAboutDialogPrivate *priv;
1410 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1412 priv = (GtkAboutDialogPrivate *)about->private_data;
1414 tmp = priv->authors;
1415 priv->authors = g_strdupv ((gchar **)authors);
1418 update_credits_button_visibility (about);
1420 g_object_notify (G_OBJECT (about), "authors");
1424 * gtk_about_dialog_get_documenters:
1425 * @about: a #GtkAboutDialog
1427 * Returns the string which are displayed in the documenters
1428 * tab of the secondary credits dialog.
1430 * Return value: A %NULL-terminated string array containing
1431 * the documenters. The array is owned by the about dialog
1432 * and must not be modified.
1436 G_CONST_RETURN gchar * G_CONST_RETURN *
1437 gtk_about_dialog_get_documenters (GtkAboutDialog *about)
1439 GtkAboutDialogPrivate *priv;
1441 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1443 priv = (GtkAboutDialogPrivate *)about->private_data;
1445 return (const gchar * const *)priv->documenters;
1449 * gtk_about_dialog_set_documenters:
1450 * @about: a #GtkAboutDialog
1451 * @documenters: a %NULL-terminated array of strings
1453 * Sets the strings which are displayed in the documenters tab
1454 * of the secondary credits dialog.
1459 gtk_about_dialog_set_documenters (GtkAboutDialog *about,
1460 const gchar **documenters)
1462 GtkAboutDialogPrivate *priv;
1465 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1467 priv = (GtkAboutDialogPrivate *)about->private_data;
1469 tmp = priv->documenters;
1470 priv->documenters = g_strdupv ((gchar **)documenters);
1473 update_credits_button_visibility (about);
1475 g_object_notify (G_OBJECT (about), "documenters");
1479 * gtk_about_dialog_get_artists:
1480 * @about: a #GtkAboutDialog
1482 * Returns the string which are displayed in the artists tab
1483 * of the secondary credits dialog.
1485 * Return value: A %NULL-terminated string array containing
1486 * the artists. The array is owned by the about dialog
1487 * and must not be modified.
1491 G_CONST_RETURN gchar * G_CONST_RETURN *
1492 gtk_about_dialog_get_artists (GtkAboutDialog *about)
1494 GtkAboutDialogPrivate *priv;
1496 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1498 priv = (GtkAboutDialogPrivate *)about->private_data;
1500 return (const gchar * const *)priv->artists;
1504 * gtk_about_dialog_set_artists:
1505 * @about: a #GtkAboutDialog
1506 * @artists: a %NULL-terminated array of strings
1508 * Sets the strings which are displayed in the artists tab
1509 * of the secondary credits dialog.
1514 gtk_about_dialog_set_artists (GtkAboutDialog *about,
1515 const gchar **artists)
1517 GtkAboutDialogPrivate *priv;
1520 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1522 priv = (GtkAboutDialogPrivate *)about->private_data;
1524 tmp = priv->artists;
1525 priv->artists = g_strdupv ((gchar **)artists);
1528 update_credits_button_visibility (about);
1530 g_object_notify (G_OBJECT (about), "artists");
1534 * gtk_about_dialog_get_translator_credits:
1535 * @about: a #GtkAboutDialog
1537 * Returns the translator credits string which is displayed
1538 * in the translators tab of the secondary credits dialog.
1540 * Return value: The translator credits string. The string is
1541 * owned by the about dialog and must not be modified.
1545 G_CONST_RETURN gchar *
1546 gtk_about_dialog_get_translator_credits (GtkAboutDialog *about)
1548 GtkAboutDialogPrivate *priv;
1550 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1552 priv = (GtkAboutDialogPrivate *)about->private_data;
1554 return priv->translator_credits;
1558 * gtk_about_dialog_set_translator_credits:
1559 * @about: a #GtkAboutDialog
1560 * @translator_credits: the translator credits
1562 * Sets the translator credits string which is displayed in
1563 * the translators tab of the secondary credits dialog.
1565 * The intended use for this string is to display the translator
1566 * of the language which is currently used in the user interface.
1567 * Using gettext(), a simple way to achieve that is to mark the
1568 * string for translation:
1570 * gtk_about_dialog_set_translator_credits (about, _("translator-credits"));
1572 * It is a good idea to use the customary msgid "translator-credits" for this
1573 * purpose, since translators will already know the purpose of that msgid, and
1574 * since #GtkAboutDialog will detect if "translator-credits" is untranslated
1580 gtk_about_dialog_set_translator_credits (GtkAboutDialog *about,
1581 const gchar *translator_credits)
1583 GtkAboutDialogPrivate *priv;
1586 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1588 priv = (GtkAboutDialogPrivate *)about->private_data;
1590 tmp = priv->translator_credits;
1591 priv->translator_credits = g_strdup (translator_credits);
1594 update_credits_button_visibility (about);
1596 g_object_notify (G_OBJECT (about), "translator-credits");
1600 * gtk_about_dialog_get_logo:
1601 * @about: a #GtkAboutDialog
1603 * Returns the pixbuf displayed as logo in the about dialog.
1605 * Return value: the pixbuf displayed as logo. The pixbuf is
1606 * owned by the about dialog. If you want to keep a reference
1607 * to it, you have to call g_object_ref() on it.
1612 gtk_about_dialog_get_logo (GtkAboutDialog *about)
1614 GtkAboutDialogPrivate *priv;
1616 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1618 priv = (GtkAboutDialogPrivate *)about->private_data;
1620 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_PIXBUF)
1621 return gtk_image_get_pixbuf (GTK_IMAGE (priv->logo_image));
1627 icon_set_new_from_pixbufs (GList *pixbufs)
1629 GtkIconSet *icon_set = gtk_icon_set_new ();
1631 for (; pixbufs; pixbufs = pixbufs->next)
1633 GdkPixbuf *pixbuf = GDK_PIXBUF (pixbufs->data);
1635 GtkIconSource *icon_source = gtk_icon_source_new ();
1636 gtk_icon_source_set_pixbuf (icon_source, pixbuf);
1637 gtk_icon_set_add_source (icon_set, icon_source);
1638 gtk_icon_source_free (icon_source);
1645 * gtk_about_dialog_set_logo:
1646 * @about: a #GtkAboutDialog
1647 * @logo: a #GdkPixbuf, or %NULL
1649 * Sets the pixbuf to be displayed as logo in
1650 * the about dialog. If it is %NULL, the default
1651 * window icon set with gtk_window_set_default_icon ()
1657 gtk_about_dialog_set_logo (GtkAboutDialog *about,
1660 GtkAboutDialogPrivate *priv;
1662 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1664 priv = (GtkAboutDialogPrivate *)about->private_data;
1666 g_object_freeze_notify (G_OBJECT (about));
1668 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_ICON_NAME)
1669 g_object_notify (G_OBJECT (about), "logo-icon-name");
1672 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->logo_image), logo);
1675 GList *pixbufs = gtk_window_get_default_icon_list ();
1677 if (pixbufs != NULL)
1679 GtkIconSet *icon_set = icon_set_new_from_pixbufs (pixbufs);
1681 gtk_image_set_from_icon_set (GTK_IMAGE (priv->logo_image),
1682 icon_set, GTK_ICON_SIZE_DIALOG);
1684 gtk_icon_set_unref (icon_set);
1685 g_list_free (pixbufs);
1689 g_object_notify (G_OBJECT (about), "logo");
1691 g_object_thaw_notify (G_OBJECT (about));
1695 * gtk_about_dialog_get_logo_icon_name:
1696 * @about: a #GtkAboutDialog
1698 * Returns the icon name displayed as logo in the about dialog.
1700 * Return value: the icon name displayed as logo. The string is
1701 * owned by the dialog. If you want to keep a reference
1702 * to it, you have to call g_strdup() on it.
1706 G_CONST_RETURN gchar *
1707 gtk_about_dialog_get_logo_icon_name (GtkAboutDialog *about)
1709 GtkAboutDialogPrivate *priv;
1710 const gchar *icon_name = NULL;
1712 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1714 priv = (GtkAboutDialogPrivate *)about->private_data;
1716 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_ICON_NAME)
1717 gtk_image_get_icon_name (GTK_IMAGE (priv->logo_image), &icon_name, NULL);
1723 * gtk_about_dialog_set_logo_icon_name:
1724 * @about: a #GtkAboutDialog
1725 * @icon_name: an icon name, or %NULL
1727 * Sets the pixbuf to be displayed as logo in
1728 * the about dialog. If it is %NULL, the default
1729 * window icon set with gtk_window_set_default_icon()
1735 gtk_about_dialog_set_logo_icon_name (GtkAboutDialog *about,
1736 const gchar *icon_name)
1738 GtkAboutDialogPrivate *priv;
1740 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1742 priv = (GtkAboutDialogPrivate *)about->private_data;
1744 g_object_freeze_notify (G_OBJECT (about));
1746 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_PIXBUF)
1747 g_object_notify (G_OBJECT (about), "logo");
1749 gtk_image_set_from_icon_name (GTK_IMAGE (priv->logo_image), icon_name,
1750 GTK_ICON_SIZE_DIALOG);
1751 g_object_notify (G_OBJECT (about), "logo-icon-name");
1753 g_object_thaw_notify (G_OBJECT (about));
1757 follow_if_link (GtkAboutDialog *about,
1758 GtkTextView *text_view,
1761 GSList *tags = NULL, *tagp = NULL;
1762 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
1764 GtkAboutDialogActivateLinkFunc email_hook, url_hook;
1765 gpointer email_hook_data, url_hook_data;
1767 if (activate_email_hook_set)
1769 email_hook = activate_email_hook;
1770 email_hook_data = activate_email_hook_data;
1774 email_hook = default_email_hook;
1775 email_hook_data = NULL;
1778 if (activate_url_hook_set)
1780 url_hook = activate_url_hook;
1781 url_hook_data = activate_url_hook_data;
1785 url_hook = default_url_hook;
1786 url_hook_data = NULL;
1789 tags = gtk_text_iter_get_tags (iter);
1790 for (tagp = tags; tagp != NULL && !url; tagp = tagp->next)
1792 GtkTextTag *tag = tagp->data;
1794 if (email_hook != NULL)
1796 url = g_object_get_data (G_OBJECT (tag), "email");
1798 email_hook (about, url, email_hook_data);
1801 if (!url && url_hook != NULL)
1803 url = g_object_get_data (G_OBJECT (tag), "url");
1805 url_hook (about, url, url_hook_data);
1808 if (url && !g_slist_find_custom (priv->visited_links, url, (GCompareFunc)strcmp))
1810 GdkColor *style_visited_link_color;
1813 gtk_widget_ensure_style (GTK_WIDGET (about));
1814 gtk_widget_style_get (GTK_WIDGET (about),
1815 "visited-link-color", &style_visited_link_color,
1817 if (style_visited_link_color)
1819 color = *style_visited_link_color;
1820 gdk_color_free (style_visited_link_color);
1823 color = default_visited_link_color;
1825 g_object_set (G_OBJECT (tag), "foreground-gdk", &color, NULL);
1827 priv->visited_links = g_slist_prepend (priv->visited_links, g_strdup (url));
1832 g_slist_free (tags);
1836 text_view_key_press_event (GtkWidget *text_view,
1838 GtkAboutDialog *about)
1841 GtkTextBuffer *buffer;
1843 switch (event->keyval)
1848 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
1849 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
1850 gtk_text_buffer_get_insert (buffer));
1851 follow_if_link (about, GTK_TEXT_VIEW (text_view), &iter);
1862 text_view_event_after (GtkWidget *text_view,
1864 GtkAboutDialog *about)
1866 GtkTextIter start, end, iter;
1867 GtkTextBuffer *buffer;
1868 GdkEventButton *button_event;
1871 if (event->type != GDK_BUTTON_RELEASE)
1874 button_event = (GdkEventButton *)event;
1876 if (button_event->button != 1)
1879 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
1881 /* we shouldn't follow a link if the user has selected something */
1882 gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
1883 if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
1886 gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
1887 GTK_TEXT_WINDOW_WIDGET,
1888 button_event->x, button_event->y, &x, &y);
1890 gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y);
1892 follow_if_link (about, GTK_TEXT_VIEW (text_view), &iter);
1898 set_cursor_if_appropriate (GtkAboutDialog *about,
1899 GtkTextView *text_view,
1903 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
1904 GSList *tags = NULL, *tagp = NULL;
1906 gboolean hovering_over_link = FALSE;
1908 gtk_text_view_get_iter_at_location (text_view, &iter, x, y);
1910 tags = gtk_text_iter_get_tags (&iter);
1911 for (tagp = tags; tagp != NULL; tagp = tagp->next)
1913 GtkTextTag *tag = tagp->data;
1914 gchar *email = g_object_get_data (G_OBJECT (tag), "email");
1915 gchar *url = g_object_get_data (G_OBJECT (tag), "url");
1917 if (email != NULL || url != NULL)
1919 hovering_over_link = TRUE;
1924 if (hovering_over_link != priv->hovering_over_link)
1926 priv->hovering_over_link = hovering_over_link;
1928 if (hovering_over_link)
1929 gdk_window_set_cursor (gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT), priv->hand_cursor);
1931 gdk_window_set_cursor (gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT), priv->regular_cursor);
1935 g_slist_free (tags);
1939 text_view_motion_notify_event (GtkWidget *text_view,
1940 GdkEventMotion *event,
1941 GtkAboutDialog *about)
1945 gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
1946 GTK_TEXT_WINDOW_WIDGET,
1947 event->x, event->y, &x, &y);
1949 set_cursor_if_appropriate (about, GTK_TEXT_VIEW (text_view), x, y);
1951 gdk_event_request_motions (event);
1958 text_view_visibility_notify_event (GtkWidget *text_view,
1959 GdkEventVisibility *event,
1960 GtkAboutDialog *about)
1962 gint wx, wy, bx, by;
1964 gdk_window_get_pointer (text_view->window, &wx, &wy, NULL);
1966 gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
1967 GTK_TEXT_WINDOW_WIDGET,
1970 set_cursor_if_appropriate (about, GTK_TEXT_VIEW (text_view), bx, by);
1976 text_view_new (GtkAboutDialog *about,
1979 GtkWrapMode wrap_mode)
1982 gchar *q0, *q1, *q2, *r1, *r2;
1984 GtkTextView *text_view;
1985 GtkTextBuffer *buffer;
1986 gboolean linkify_email, linkify_urls;
1987 GdkColor *style_link_color;
1988 GdkColor *style_visited_link_color;
1990 GdkColor link_color;
1991 GdkColor visited_link_color;
1992 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
1994 linkify_email = (!activate_email_hook_set || activate_email_hook != NULL);
1995 linkify_urls = (!activate_url_hook_set || activate_url_hook != NULL);
1997 gtk_widget_ensure_style (GTK_WIDGET (about));
1998 gtk_widget_style_get (GTK_WIDGET (about),
1999 "link-color", &style_link_color,
2000 "visited-link-color", &style_visited_link_color,
2002 if (style_link_color)
2004 link_color = *style_link_color;
2005 gdk_color_free (style_link_color);
2008 link_color = default_link_color;
2010 if (style_visited_link_color)
2012 visited_link_color = *style_visited_link_color;
2013 gdk_color_free (style_visited_link_color);
2016 visited_link_color = default_visited_link_color;
2018 view = gtk_text_view_new ();
2019 text_view = GTK_TEXT_VIEW (view);
2020 buffer = gtk_text_view_get_buffer (text_view);
2021 gtk_text_view_set_cursor_visible (text_view, FALSE);
2022 gtk_text_view_set_editable (text_view, FALSE);
2023 gtk_text_view_set_wrap_mode (text_view, wrap_mode);
2025 gtk_text_view_set_left_margin (text_view, 8);
2026 gtk_text_view_set_right_margin (text_view, 8);
2028 g_signal_connect (view, "key-press-event",
2029 G_CALLBACK (text_view_key_press_event), about);
2030 g_signal_connect (view, "event-after",
2031 G_CALLBACK (text_view_event_after), about);
2032 g_signal_connect (view, "motion-notify-event",
2033 G_CALLBACK (text_view_motion_notify_event), about);
2034 g_signal_connect (view, "visibility-notify-event",
2035 G_CALLBACK (text_view_visibility_notify_event), about);
2037 if (strings == NULL)
2039 gtk_widget_hide (view);
2043 for (p = strings; *p; p++)
2048 q1 = linkify_email ? strchr (q0, '<') : NULL;
2049 q2 = q1 ? strchr (q1, '>') : NULL;
2050 r1 = linkify_urls ? strstr (q0, "http://") : NULL;
2053 r2 = strpbrk (r1, " \n\t");
2055 r2 = strchr (r1, '\0');
2060 if (r1 && r2 && (!q1 || !q2 || (r1 < q1)))
2070 const gchar *link_type;
2075 gtk_text_buffer_insert_at_cursor (buffer, q0, (q1 - q0) + 1);
2076 gtk_text_buffer_get_end_iter (buffer, &end);
2078 link_type = I_("email");
2082 gtk_text_buffer_insert_at_cursor (buffer, q0, q1 - q0);
2083 gtk_text_buffer_get_end_iter (buffer, &end);
2084 link_type = I_("url");
2089 link = g_strndup (q1, q2 - q1);
2091 if (g_slist_find_custom (priv->visited_links, link, (GCompareFunc)strcmp))
2092 color = visited_link_color;
2096 tag = gtk_text_buffer_create_tag (buffer, NULL,
2097 "foreground-gdk", &color,
2098 "underline", PANGO_UNDERLINE_SINGLE,
2100 g_object_set_data_full (G_OBJECT (tag), link_type, g_strdup (link), g_free);
2101 gtk_text_buffer_insert_with_tags (buffer, &end, link, -1, tag, NULL);
2107 gtk_text_buffer_insert_at_cursor (buffer, q0, -1);
2113 gtk_text_buffer_insert_at_cursor (buffer, "\n", 1);
2116 gtk_widget_show (view);
2121 add_credits_page (GtkAboutDialog *about,
2122 GtkWidget *credits_dialog,
2123 GtkWidget *notebook,
2127 GtkWidget *sw, *view;
2129 view = text_view_new (about, credits_dialog, people, GTK_WRAP_NONE);
2131 sw = gtk_scrolled_window_new (NULL, NULL);
2132 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
2134 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2135 GTK_POLICY_AUTOMATIC,
2136 GTK_POLICY_AUTOMATIC);
2137 gtk_container_add (GTK_CONTAINER (sw), view);
2139 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
2140 sw, gtk_label_new (title));
2144 display_credits_dialog (GtkWidget *button,
2147 GtkAboutDialog *about = (GtkAboutDialog *)data;
2148 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
2149 GtkWidget *dialog, *notebook;
2150 GtkDialog *credits_dialog;
2152 if (priv->credits_dialog != NULL)
2154 gtk_window_present (GTK_WINDOW (priv->credits_dialog));
2158 dialog = gtk_dialog_new_with_buttons (_("Credits"),
2160 GTK_DIALOG_DESTROY_WITH_PARENT,
2161 GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL,
2163 credits_dialog = GTK_DIALOG (dialog);
2164 gtk_dialog_set_has_separator (credits_dialog, FALSE);
2165 gtk_container_set_border_width (GTK_CONTAINER (credits_dialog), 5);
2166 gtk_box_set_spacing (GTK_BOX (credits_dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
2167 gtk_container_set_border_width (GTK_CONTAINER (credits_dialog->action_area), 5);
2169 priv->credits_dialog = dialog;
2170 gtk_window_set_default_size (GTK_WINDOW (dialog), 360, 260);
2171 gtk_dialog_set_default_response (credits_dialog, GTK_RESPONSE_CANCEL);
2173 gtk_window_set_modal (GTK_WINDOW (dialog),
2174 gtk_window_get_modal (GTK_WINDOW (about)));
2176 g_signal_connect (dialog, "response",
2177 G_CALLBACK (gtk_widget_destroy), dialog);
2178 g_signal_connect (dialog, "destroy",
2179 G_CALLBACK (gtk_widget_destroyed),
2180 &(priv->credits_dialog));
2182 notebook = gtk_notebook_new ();
2183 gtk_container_set_border_width (GTK_CONTAINER (notebook), 5);
2184 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), notebook, TRUE, TRUE, 0);
2186 if (priv->authors != NULL)
2187 add_credits_page (about, dialog, notebook, _("Written by"), priv->authors);
2189 if (priv->documenters != NULL)
2190 add_credits_page (about, dialog, notebook, _("Documented by"), priv->documenters);
2192 /* Don't show an untranslated gettext msgid */
2193 if (priv->translator_credits != NULL &&
2194 strcmp (priv->translator_credits, "translator_credits") &&
2195 strcmp (priv->translator_credits, "translator-credits"))
2197 gchar *translators[2];
2199 translators[0] = priv->translator_credits;
2200 translators[1] = NULL;
2202 add_credits_page (about, dialog, notebook, _("Translated by"), translators);
2205 if (priv->artists != NULL)
2206 add_credits_page (about, dialog, notebook, _("Artwork by"), priv->artists);
2208 gtk_widget_show_all (dialog);
2212 set_policy (GtkWidget *sw)
2214 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2215 GTK_POLICY_AUTOMATIC,
2216 GTK_POLICY_AUTOMATIC);
2220 display_license_dialog (GtkWidget *button,
2223 GtkAboutDialog *about = (GtkAboutDialog *)data;
2224 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
2225 GtkWidget *dialog, *view, *sw;
2226 GtkDialog *licence_dialog;
2229 if (priv->license_dialog != NULL)
2231 gtk_window_present (GTK_WINDOW (priv->license_dialog));
2235 dialog = gtk_dialog_new_with_buttons (_("License"),
2237 GTK_DIALOG_DESTROY_WITH_PARENT,
2238 GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL,
2240 licence_dialog = GTK_DIALOG (dialog);
2241 gtk_dialog_set_has_separator (licence_dialog, FALSE);
2242 gtk_container_set_border_width (GTK_CONTAINER (licence_dialog), 5);
2243 gtk_box_set_spacing (GTK_BOX (licence_dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
2244 gtk_container_set_border_width (GTK_CONTAINER (licence_dialog->action_area), 5);
2246 priv->license_dialog = dialog;
2247 gtk_window_set_default_size (GTK_WINDOW (dialog), 420, 320);
2248 gtk_dialog_set_default_response (licence_dialog, GTK_RESPONSE_CANCEL);
2250 gtk_window_set_modal (GTK_WINDOW (dialog),
2251 gtk_window_get_modal (GTK_WINDOW (about)));
2253 g_signal_connect (dialog, "response",
2254 G_CALLBACK (gtk_widget_destroy), dialog);
2255 g_signal_connect (dialog, "destroy",
2256 G_CALLBACK (gtk_widget_destroyed),
2257 &(priv->license_dialog));
2259 sw = gtk_scrolled_window_new (NULL, NULL);
2260 gtk_container_set_border_width (GTK_CONTAINER (sw), 5);
2261 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
2263 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2265 GTK_POLICY_AUTOMATIC);
2266 g_signal_connect (sw, "map", G_CALLBACK (set_policy), NULL);
2267 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), sw, TRUE, TRUE, 0);
2269 strings[0] = priv->license;
2271 view = text_view_new (about, dialog, strings,
2272 priv->wrap_license ? GTK_WRAP_WORD : GTK_WRAP_NONE);
2274 gtk_container_add (GTK_CONTAINER (sw), view);
2276 gtk_widget_show_all (dialog);
2280 * gtk_about_dialog_new:
2282 * Creates a new #GtkAboutDialog.
2284 * Returns: a newly created #GtkAboutDialog
2289 gtk_about_dialog_new (void)
2291 GtkAboutDialog *dialog = g_object_new (GTK_TYPE_ABOUT_DIALOG, NULL);
2293 return GTK_WIDGET (dialog);
2297 * gtk_about_dialog_set_email_hook:
2298 * @func: a function to call when an email link is activated.
2299 * @data: data to pass to @func
2300 * @destroy: #GDestroyNotify for @data
2302 * Installs a global function to be called whenever the user activates an
2303 * email link in an about dialog.
2305 * Since 2.18 there exists a default function which uses gtk_show_uri(). To
2306 * deactivate it, you can pass %NULL for @func.
2308 * Return value: the previous email hook.
2312 GtkAboutDialogActivateLinkFunc
2313 gtk_about_dialog_set_email_hook (GtkAboutDialogActivateLinkFunc func,
2315 GDestroyNotify destroy)
2317 GtkAboutDialogActivateLinkFunc old;
2319 if (activate_email_hook_destroy != NULL)
2320 (* activate_email_hook_destroy) (activate_email_hook_data);
2322 old = activate_email_hook;
2324 activate_email_hook_set = TRUE;
2325 activate_email_hook = func;
2326 activate_email_hook_data = data;
2327 activate_email_hook_destroy = destroy;
2333 * gtk_about_dialog_set_url_hook:
2334 * @func: a function to call when a URL link is activated.
2335 * @data: data to pass to @func
2336 * @destroy: #GDestroyNotify for @data
2338 * Installs a global function to be called whenever the user activates a
2339 * URL link in an about dialog.
2341 * Since 2.18 there exists a default function which uses gtk_show_uri(). To
2342 * deactivate it, you can pass %NULL for @func.
2344 * Return value: the previous URL hook.
2348 GtkAboutDialogActivateLinkFunc
2349 gtk_about_dialog_set_url_hook (GtkAboutDialogActivateLinkFunc func,
2351 GDestroyNotify destroy)
2353 GtkAboutDialogActivateLinkFunc old;
2355 if (activate_url_hook_destroy != NULL)
2356 (* activate_url_hook_destroy) (activate_url_hook_data);
2358 old = activate_url_hook;
2360 activate_url_hook_set = TRUE;
2361 activate_url_hook = func;
2362 activate_url_hook_data = data;
2363 activate_url_hook_destroy = destroy;
2369 close_cb (GtkAboutDialog *about)
2371 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
2373 if (priv->license_dialog != NULL)
2375 gtk_widget_destroy (priv->license_dialog);
2376 priv->license_dialog = NULL;
2379 if (priv->credits_dialog != NULL)
2381 gtk_widget_destroy (priv->credits_dialog);
2382 priv->credits_dialog = NULL;
2385 gtk_widget_hide (GTK_WIDGET (about));
2390 * gtk_show_about_dialog:
2391 * @parent: transient parent, or %NULL for none
2392 * @first_property_name: the name of the first property
2393 * @Varargs: value of first property, followed by more properties, %NULL-terminated
2395 * This is a convenience function for showing an application's about box.
2396 * The constructed dialog is associated with the parent window and
2397 * reused for future invocations of this function.
2402 gtk_show_about_dialog (GtkWindow *parent,
2403 const gchar *first_property_name,
2406 static GtkWidget *global_about_dialog = NULL;
2407 GtkWidget *dialog = NULL;
2411 dialog = g_object_get_data (G_OBJECT (parent), "gtk-about-dialog");
2413 dialog = global_about_dialog;
2417 dialog = gtk_about_dialog_new ();
2419 g_object_ref_sink (dialog);
2421 g_signal_connect (dialog, "delete-event",
2422 G_CALLBACK (gtk_widget_hide_on_delete), NULL);
2424 /* Close dialog on user response */
2425 g_signal_connect (dialog, "response",
2426 G_CALLBACK (close_cb), NULL);
2428 va_start (var_args, first_property_name);
2429 g_object_set_valist (G_OBJECT (dialog), first_property_name, var_args);
2434 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
2435 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
2436 g_object_set_data_full (G_OBJECT (parent),
2437 I_("gtk-about-dialog"),
2438 dialog, g_object_unref);
2441 global_about_dialog = dialog;
2445 gtk_window_present (GTK_WINDOW (dialog));
2448 #define __GTK_ABOUT_DIALOG_C__
2449 #include "gtkaliasdef.c"