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/.
33 #include <gdk/gdkkeysyms.h>
35 #include "gtkaboutdialog.h"
36 #include "gtkbutton.h"
38 #include "gtkdialog.h"
42 #include "gtkmarshalers.h"
43 #include "gtknotebook.h"
44 #include "gtkscrolledwindow.h"
46 #include "gtktextview.h"
48 #include "gtkviewport.h"
49 #include "gtkiconfactory.h"
50 #include "gtkprivate.h"
57 typedef struct _GtkAboutDialogPrivate GtkAboutDialogPrivate;
58 struct _GtkAboutDialogPrivate
66 gchar *translator_credits;
73 GtkWidget *logo_image;
74 GtkWidget *name_label;
75 GtkWidget *comments_label;
76 GtkWidget *copyright_label;
77 GtkWidget *website_button;
79 GtkWidget *credits_button;
80 GtkWidget *credits_dialog;
81 GtkWidget *license_button;
82 GtkWidget *license_dialog;
84 GdkCursor *hand_cursor;
85 GdkCursor *regular_cursor;
86 gboolean hovering_over_link;
87 gboolean wrap_license;
90 #define GTK_ABOUT_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ABOUT_DIALOG, GtkAboutDialogPrivate))
105 PROP_TRANSLATOR_CREDITS,
112 static void gtk_about_dialog_finalize (GObject *object);
113 static void gtk_about_dialog_get_property (GObject *object,
117 static void gtk_about_dialog_set_property (GObject *object,
121 static void gtk_about_dialog_style_set (GtkWidget *widget,
122 GtkStyle *previous_style);
123 static void dialog_style_set (GtkWidget *widget,
124 GtkStyle *previous_style,
126 static void update_name_version (GtkAboutDialog *about);
127 static GtkIconSet * icon_set_new_from_pixbufs (GList *pixbufs);
128 static void activate_url (GtkWidget *widget,
130 static void set_link_button_text (GtkWidget *about,
133 static GtkWidget * create_link_button (GtkWidget *about,
138 static void follow_if_link (GtkAboutDialog *about,
140 static void set_cursor_if_appropriate (GtkAboutDialog *about,
141 GtkTextView *text_view,
144 static void add_credits_page (GtkAboutDialog *about,
148 static gboolean credits_key_press_event (GtkWidget *text_view,
150 GtkAboutDialog *about);
151 static gboolean credits_event_after (GtkWidget *text_view,
153 GtkAboutDialog *about);
154 static gboolean credits_motion_notify_event (GtkWidget *text_view,
155 GdkEventMotion *event,
156 GtkAboutDialog *about);
157 static gboolean credits_visibility_notify_event (GtkWidget *text_view,
158 GdkEventVisibility *event,
159 GtkAboutDialog *about);
160 static void display_credits_dialog (GtkWidget *button,
162 static void display_license_dialog (GtkWidget *button,
164 static void close_cb (GtkAboutDialog *about);
167 static GtkAboutDialogActivateLinkFunc activate_email_hook = NULL;
168 static gpointer activate_email_hook_data = NULL;
169 static GDestroyNotify activate_email_hook_destroy = NULL;
171 static GtkAboutDialogActivateLinkFunc activate_url_hook = NULL;
172 static gpointer activate_url_hook_data = NULL;
173 static GDestroyNotify activate_url_hook_destroy = NULL;
175 G_DEFINE_TYPE (GtkAboutDialog, gtk_about_dialog, GTK_TYPE_DIALOG);
178 gtk_about_dialog_class_init (GtkAboutDialogClass *klass)
180 GObjectClass *object_class;
181 GtkWidgetClass *widget_class;
182 GtkDialogClass *dialog_class;
184 object_class = (GObjectClass *)klass;
185 widget_class = (GtkWidgetClass *)klass;
186 dialog_class = (GtkDialogClass *)klass;
188 object_class->set_property = gtk_about_dialog_set_property;
189 object_class->get_property = gtk_about_dialog_get_property;
191 object_class->finalize = gtk_about_dialog_finalize;
193 widget_class->style_set = gtk_about_dialog_style_set;
196 * GtkAboutDialog:name:
198 * The name of the program.
199 * If this is not set, it defaults to g_get_application_name().
203 g_object_class_install_property (object_class,
205 g_param_spec_string ("name",
207 P_("The name of the program. If this is not set, it defaults to g_get_application_name()"),
209 GTK_PARAM_READWRITE));
212 * GtkAboutDialog:version:
214 * The version of the program.
218 g_object_class_install_property (object_class,
220 g_param_spec_string ("version",
221 P_("Program version"),
222 P_("The version of the program"),
224 GTK_PARAM_READWRITE));
227 * GtkAboutDialog:copyright:
229 * Copyright information for the program.
233 g_object_class_install_property (object_class,
235 g_param_spec_string ("copyright",
236 P_("Copyright string"),
237 P_("Copyright information for the program"),
239 GTK_PARAM_READWRITE));
243 * GtkAboutDialog:comments:
245 * Comments about the program. This string is displayed in a label
246 * in the main dialog, thus it should be a short explanation of
247 * the main purpose of the program, not a detailed list of features.
251 g_object_class_install_property (object_class,
253 g_param_spec_string ("comments",
254 P_("Comments string"),
255 P_("Comments about the program"),
257 GTK_PARAM_READWRITE));
260 * GtkAboutDialog:license:
262 * The license of the program. This string is displayed in a
263 * text view in a secondary dialog, therefore it is fine to use
264 * a long multi-paragraph text. Note that the text is only wrapped
265 * in the text view if the "wrap-license" property is set to %TRUE;
266 * otherwise the text itself must contain the intended linebreaks.
270 g_object_class_install_property (object_class,
272 g_param_spec_string ("license",
274 _("The license of the program"),
276 GTK_PARAM_READWRITE));
279 * GtkAboutDialog:website:
281 * The URL for the link to the website of the program.
282 * This should be a string starting with "http://.
286 g_object_class_install_property (object_class,
288 g_param_spec_string ("website",
290 P_("The URL for the link to the website of the program"),
292 GTK_PARAM_READWRITE));
295 * GtkAboutDialog:website-label:
297 * The label for the link to the website of the program. If this is not set,
298 * it defaults to the URL specified in the
299 * <link linkend="GtkAboutDialog--website">website</link> property.
303 g_object_class_install_property (object_class,
305 g_param_spec_string ("website-label",
307 P_("The label for the link to the website of the program. If this is not set, it defaults to the URL"),
309 GTK_PARAM_READWRITE));
312 * GtkAboutDialog:authors:
314 * The authors of the program, as a %NULL-terminated array of strings.
315 * Each string may contain email addresses and URLs, which will be displayed
316 * as links, see the introduction for more details.
320 g_object_class_install_property (object_class,
322 g_param_spec_boxed ("authors",
324 P_("List of authors of the program"),
326 GTK_PARAM_READWRITE));
329 * GtkAboutDialog:documenters:
331 * The people documenting the program, as a %NULL-terminated array of strings.
332 * Each string may contain email addresses and URLs, which will be displayed
333 * as links, see the introduction for more details.
337 g_object_class_install_property (object_class,
339 g_param_spec_boxed ("documenters",
341 P_("List of people documenting the program"),
343 GTK_PARAM_READWRITE));
346 * GtkAboutDialog:artists:
348 * The people who contributed artwork to the program, as a %NULL-terminated array of strings.
349 * Each string may contain email addresses and URLs, which will be displayed
350 * as links, see the introduction for more details.
354 g_object_class_install_property (object_class,
356 g_param_spec_boxed ("artists",
358 P_("List of people who have contributed artwork to the program"),
360 GTK_PARAM_READWRITE));
364 * GtkAboutDialog:translator-credits:
366 * Credits to the translators. This string should be marked as translatable.
367 * The string may contain email addresses and URLs, which will be displayed
368 * as links, see the introduction for more details.
372 g_object_class_install_property (object_class,
373 PROP_TRANSLATOR_CREDITS,
374 g_param_spec_string ("translator-credits",
375 P_("Translator credits"),
376 P_("Credits to the translators. This string should be marked as translatable"),
378 GTK_PARAM_READWRITE));
381 * GtkAboutDialog:logo:
383 * A logo for the about box. If this is not set, it defaults to
384 * gtk_window_get_default_icon_list().
388 g_object_class_install_property (object_class,
390 g_param_spec_object ("logo",
392 P_("A logo for the about box. If this is not set, it defaults to gtk_window_get_default_icon_list()"),
394 GTK_PARAM_READWRITE));
397 * GtkAboutDialog:logo-icon-name:
399 * A named icon to use as the logo for the about box. This property
400 * overrides the <link linkend="GtkAboutDialog--logo">logo</link> property.
404 g_object_class_install_property (object_class,
406 g_param_spec_string ("logo-icon-name",
407 P_("Logo Icon Name"),
408 P_("A named icon to use as the logo for the about box."),
410 GTK_PARAM_READWRITE));
412 * GtkAboutDialog:wrap-license:
414 * Whether to wrap the text in the license dialog.
418 g_object_class_install_property (object_class,
420 g_param_spec_boolean ("wrap-license",
422 P_("Whether to wrap the license text."),
424 GTK_PARAM_READWRITE));
426 /* Style properties */
427 gtk_widget_class_install_style_property (widget_class,
428 g_param_spec_boxed ("link-color",
430 P_("Color of hyperlinks"),
432 GTK_PARAM_READABLE));
434 g_type_class_add_private (object_class, sizeof (GtkAboutDialogPrivate));
438 gtk_about_dialog_init (GtkAboutDialog *about)
440 GtkAboutDialogPrivate *priv;
441 GtkWidget *vbox, *hbox, *button;
444 priv = GTK_ABOUT_DIALOG_GET_PRIVATE (about);
445 about->private_data = priv;
448 priv->version = NULL;
449 priv->copyright = NULL;
450 priv->comments = NULL;
451 priv->website = NULL;
452 priv->website_label = NULL;
453 priv->translator_credits = NULL;
454 priv->license = NULL;
455 priv->authors = NULL;
456 priv->documenters = NULL;
457 priv->artists = NULL;
459 priv->hand_cursor = gdk_cursor_new (GDK_HAND2);
460 priv->regular_cursor = gdk_cursor_new (GDK_XTERM);
461 priv->hovering_over_link = FALSE;
462 priv->wrap_license = FALSE;
464 gtk_dialog_set_has_separator (GTK_DIALOG (about), FALSE);
467 gtk_widget_push_composite_child ();
468 vbox = gtk_vbox_new (FALSE, 8);
470 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (about)->vbox), vbox, TRUE, TRUE, 0);
472 priv->logo_image = gtk_image_new ();
473 gtk_box_pack_start (GTK_BOX (vbox), priv->logo_image, FALSE, FALSE, 0);
475 priv->name_label = gtk_label_new (NULL);
476 gtk_label_set_selectable (GTK_LABEL (priv->name_label), TRUE);
477 gtk_label_set_justify (GTK_LABEL (priv->name_label), GTK_JUSTIFY_CENTER);
478 gtk_box_pack_start (GTK_BOX (vbox), priv->name_label, FALSE, FALSE, 0);
480 priv->comments_label = gtk_label_new (NULL);
481 gtk_label_set_selectable (GTK_LABEL (priv->comments_label), TRUE);
482 gtk_label_set_justify (GTK_LABEL (priv->comments_label), GTK_JUSTIFY_CENTER);
483 gtk_label_set_line_wrap (GTK_LABEL (priv->comments_label), TRUE);
484 gtk_box_pack_start (GTK_BOX (vbox), priv->comments_label, FALSE, FALSE, 0);
486 priv->copyright_label = gtk_label_new (NULL);
487 gtk_label_set_selectable (GTK_LABEL (priv->copyright_label), TRUE);
488 gtk_label_set_justify (GTK_LABEL (priv->copyright_label), GTK_JUSTIFY_CENTER);
489 gtk_box_pack_start (GTK_BOX (vbox), priv->copyright_label, FALSE, FALSE, 0);
491 button = create_link_button (GTK_WIDGET (about), "", "",
492 G_CALLBACK (activate_url), about);
494 hbox = gtk_hbox_new (TRUE, 0);
495 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
496 gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
497 priv->website_button = button;
499 gtk_widget_show (vbox);
500 gtk_widget_show (priv->logo_image);
501 gtk_widget_show (priv->name_label);
502 gtk_widget_show (hbox);
504 /* Add the OK button */
505 gtk_dialog_add_button (GTK_DIALOG (about), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
506 gtk_dialog_set_default_response (GTK_DIALOG (about), GTK_RESPONSE_CLOSE);
508 /* Add the credits button */
509 button = gtk_button_new_from_stock (_("C_redits"));
510 gtk_widget_set_no_show_all (button, TRUE);
511 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (about)->action_area),
512 button, FALSE, TRUE, 0);
513 gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (about)->action_area), button, TRUE);
514 g_signal_connect (button, "clicked", G_CALLBACK (display_credits_dialog), about);
515 priv->credits_button = button;
516 priv->credits_dialog = NULL;
518 /* Add the license button */
519 button = gtk_button_new_from_stock (_("_License"));
520 gtk_widget_set_no_show_all (button, TRUE);
521 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (about)->action_area),
522 button, FALSE, TRUE, 0);
523 gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (about)->action_area), button, TRUE);
524 g_signal_connect (button, "clicked", G_CALLBACK (display_license_dialog), about);
525 priv->license_button = button;
526 priv->license_dialog = NULL;
528 gtk_window_set_resizable (GTK_WINDOW (about), FALSE);
530 gtk_widget_pop_composite_child ();
533 gtk_about_dialog_set_name (about, NULL);
534 gtk_about_dialog_set_logo (about, NULL);
536 /* Close dialog on user response */
537 g_signal_connect (about, "response", G_CALLBACK (close_cb), NULL);
541 gtk_about_dialog_finalize (GObject *object)
543 GtkAboutDialog *about = GTK_ABOUT_DIALOG (object);
544 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
547 g_free (priv->version);
548 g_free (priv->copyright);
549 g_free (priv->comments);
550 g_free (priv->license);
551 g_free (priv->website);
552 g_free (priv->website_label);
553 g_free (priv->translator_credits);
555 g_strfreev (priv->authors);
556 g_strfreev (priv->documenters);
557 g_strfreev (priv->artists);
559 gdk_cursor_unref (priv->hand_cursor);
560 gdk_cursor_unref (priv->regular_cursor);
562 G_OBJECT_CLASS (gtk_about_dialog_parent_class)->finalize (object);
566 gtk_about_dialog_set_property (GObject *object,
571 GtkAboutDialog *about = GTK_ABOUT_DIALOG (object);
572 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
577 gtk_about_dialog_set_name (about, g_value_get_string (value));
580 gtk_about_dialog_set_version (about, g_value_get_string (value));
583 gtk_about_dialog_set_comments (about, g_value_get_string (value));
586 gtk_about_dialog_set_website (about, g_value_get_string (value));
588 case PROP_WEBSITE_LABEL:
589 gtk_about_dialog_set_website_label (about, g_value_get_string (value));
592 gtk_about_dialog_set_license (about, g_value_get_string (value));
595 gtk_about_dialog_set_copyright (about, g_value_get_string (value));
598 gtk_about_dialog_set_logo (about, g_value_get_object (value));
601 gtk_about_dialog_set_authors (about, (const gchar**)g_value_get_boxed (value));
603 case PROP_DOCUMENTERS:
604 gtk_about_dialog_set_documenters (about, (const gchar**)g_value_get_boxed (value));
607 gtk_about_dialog_set_artists (about, (const gchar**)g_value_get_boxed (value));
609 case PROP_TRANSLATOR_CREDITS:
610 gtk_about_dialog_set_translator_credits (about, g_value_get_string (value));
612 case PROP_LOGO_ICON_NAME:
613 gtk_about_dialog_set_logo_icon_name (about, g_value_get_string (value));
615 case PROP_WRAP_LICENSE:
616 priv->wrap_license = g_value_get_boolean (value);
619 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
625 gtk_about_dialog_get_property (GObject *object,
630 GtkAboutDialog *about = GTK_ABOUT_DIALOG (object);
631 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
636 g_value_set_string (value, priv->name);
639 g_value_set_string (value, priv->version);
642 g_value_set_string (value, priv->copyright);
645 g_value_set_string (value, priv->comments);
648 g_value_set_string (value, priv->website);
650 case PROP_WEBSITE_LABEL:
651 g_value_set_string (value, priv->website_label);
654 g_value_set_string (value, priv->license);
656 case PROP_TRANSLATOR_CREDITS:
657 g_value_set_string (value, priv->translator_credits);
660 g_value_set_boxed (value, priv->authors);
662 case PROP_DOCUMENTERS:
663 g_value_set_boxed (value, priv->documenters);
666 g_value_set_boxed (value, priv->artists);
669 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_PIXBUF)
670 g_value_set_object (value, gtk_image_get_pixbuf (GTK_IMAGE (priv->logo_image)));
672 g_value_set_object (value, NULL);
674 case PROP_LOGO_ICON_NAME:
675 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_ICON_NAME)
677 const gchar *icon_name;
679 gtk_image_get_icon_name (GTK_IMAGE (priv->logo_image), &icon_name, NULL);
680 g_value_set_string (value, icon_name);
683 g_value_set_string (value, NULL);
685 case PROP_WRAP_LICENSE:
686 g_value_set_boolean (value, priv->wrap_license);
689 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
695 dialog_style_set (GtkWidget *widget,
696 GtkStyle *previous_style,
701 dialog = GTK_DIALOG (widget);
703 /* Override the style properties with HIG-compliant spacings. Ugh.
704 * http://developer.gnome.org/projects/gup/hig/1.0/layout.html#layout-dialogs
705 * http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-spacing
708 gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 12);
709 gtk_box_set_spacing (GTK_BOX (dialog->vbox), 12);
711 gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 0);
712 gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
716 gtk_about_dialog_style_set (GtkWidget *widget,
717 GtkStyle *previous_style)
719 if (GTK_WIDGET_CLASS (gtk_about_dialog_parent_class)->style_set)
720 GTK_WIDGET_CLASS (gtk_about_dialog_parent_class)->style_set (widget, previous_style);
722 dialog_style_set (widget, previous_style, NULL);
726 * gtk_about_dialog_get_name:
727 * @about: a #GtkAboutDialog
729 * Returns the program name displayed in the about dialog.
731 * Return value: The program name. The string is owned by the about
732 * dialog and must not be modified.
736 G_CONST_RETURN gchar *
737 gtk_about_dialog_get_name (GtkAboutDialog *about)
739 GtkAboutDialogPrivate *priv;
741 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
743 priv = (GtkAboutDialogPrivate *)about->private_data;
749 update_name_version (GtkAboutDialog *about)
751 GtkAboutDialogPrivate *priv;
752 gchar *title_string, *name_string;
754 priv = (GtkAboutDialogPrivate *)about->private_data;
756 title_string = g_strdup_printf (_("About %s"), priv->name);
757 gtk_window_set_title (GTK_WINDOW (about), title_string);
758 g_free (title_string);
760 if (priv->version != NULL)
761 name_string = g_markup_printf_escaped ("<span size=\"xx-large\" weight=\"bold\">%s %s</span>",
762 priv->name, priv->version);
764 name_string = g_markup_printf_escaped ("<span size=\"xx-large\" weight=\"bold\">%s</span>",
767 gtk_label_set_markup (GTK_LABEL (priv->name_label), name_string);
769 g_free (name_string);
773 * gtk_about_dialog_set_name:
774 * @about: a #GtkAboutDialog
775 * @name: the program name
777 * Sets the name to display in the about dialog.
778 * If this is not set, it defaults to g_get_application_name().
783 gtk_about_dialog_set_name (GtkAboutDialog *about,
786 GtkAboutDialogPrivate *priv;
789 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
791 priv = (GtkAboutDialogPrivate *)about->private_data;
793 priv->name = g_strdup (name ? name : g_get_application_name ());
796 update_name_version (about);
798 g_object_notify (G_OBJECT (about), "name");
802 * gtk_about_dialog_get_version:
803 * @about: a #GtkAboutDialog
805 * Returns the version string.
807 * Return value: The version string. The string is owned by the about
808 * dialog and must not be modified.
812 G_CONST_RETURN gchar *
813 gtk_about_dialog_get_version (GtkAboutDialog *about)
815 GtkAboutDialogPrivate *priv;
817 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
819 priv = (GtkAboutDialogPrivate *)about->private_data;
821 return priv->version;
825 * gtk_about_dialog_set_version:
826 * @about: a #GtkAboutDialog
827 * @version: the version string
829 * Sets the version string to display in the about dialog.
834 gtk_about_dialog_set_version (GtkAboutDialog *about,
835 const gchar *version)
837 GtkAboutDialogPrivate *priv;
840 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
842 priv = (GtkAboutDialogPrivate *)about->private_data;
845 priv->version = version ? g_strdup (version) : NULL;
848 update_name_version (about);
850 g_object_notify (G_OBJECT (about), "version");
854 * gtk_about_dialog_get_copyright:
855 * @about: a #GtkAboutDialog
857 * Returns the copyright string.
859 * Return value: The copyright string. The string is owned by the about
860 * dialog and must not be modified.
864 G_CONST_RETURN gchar *
865 gtk_about_dialog_get_copyright (GtkAboutDialog *about)
867 GtkAboutDialogPrivate *priv;
869 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
871 priv = (GtkAboutDialogPrivate *)about->private_data;
873 return priv->copyright;
877 * gtk_about_dialog_set_copyright:
878 * @about: a #GtkAboutDialog
879 * @copyright: the copyright string
881 * Sets the copyright string to display in the about dialog.
882 * This should be a short string of one or two lines.
887 gtk_about_dialog_set_copyright (GtkAboutDialog *about,
888 const gchar *copyright)
890 GtkAboutDialogPrivate *priv;
891 gchar *copyright_string, *tmp;
893 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
895 priv = (GtkAboutDialogPrivate *)about->private_data;
897 tmp = priv->copyright;
898 priv->copyright = copyright ? g_strdup (copyright) : NULL;
901 if (priv->copyright != NULL)
903 copyright_string = g_markup_printf_escaped ("<span size=\"small\">%s</span>",
905 gtk_label_set_markup (GTK_LABEL (priv->copyright_label), copyright_string);
906 g_free (copyright_string);
908 gtk_widget_show (priv->copyright_label);
911 gtk_widget_hide (priv->copyright_label);
913 g_object_notify (G_OBJECT (about), "copyright");
917 * gtk_about_dialog_get_comments:
918 * @about: a #GtkAboutDialog
920 * Returns the comments string.
922 * Return value: The comments. The string is owned by the about
923 * dialog and must not be modified.
927 G_CONST_RETURN gchar *
928 gtk_about_dialog_get_comments (GtkAboutDialog *about)
930 GtkAboutDialogPrivate *priv;
932 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
934 priv = (GtkAboutDialogPrivate *)about->private_data;
936 return priv->comments;
940 * gtk_about_dialog_set_comments:
941 * @about: a #GtkAboutDialog
942 * @comments: a comments string
944 * Sets the comments string to display in the about
945 * dialog. This should be a short string of one or
951 gtk_about_dialog_set_comments (GtkAboutDialog *about,
952 const gchar *comments)
954 GtkAboutDialogPrivate *priv;
957 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
959 priv = (GtkAboutDialogPrivate *)about->private_data;
961 tmp = priv->comments;
964 priv->comments = g_strdup (comments);
965 gtk_label_set_text (GTK_LABEL (priv->comments_label), priv->comments);
966 gtk_widget_show (priv->comments_label);
970 priv->comments = NULL;
971 gtk_widget_hide (priv->comments_label);
975 g_object_notify (G_OBJECT (about), "comments");
979 * gtk_about_dialog_get_license:
980 * @about: a #GtkAboutDialog
982 * Returns the license information.
984 * Return value: The license information. The string is owned by the about
985 * dialog and must not be modified.
989 G_CONST_RETURN gchar *
990 gtk_about_dialog_get_license (GtkAboutDialog *about)
992 GtkAboutDialogPrivate *priv;
994 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
996 priv = (GtkAboutDialogPrivate *)about->private_data;
998 return priv->license;
1002 * gtk_about_dialog_set_license:
1003 * @about: a #GtkAboutDialog
1004 * @license: the license information or %NULL
1006 * Sets the license information to be displayed in the secondary
1007 * license dialog. If @license is %NULL, the license button is
1013 gtk_about_dialog_set_license (GtkAboutDialog *about,
1014 const gchar *license)
1016 GtkAboutDialogPrivate *priv;
1019 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1021 priv = (GtkAboutDialogPrivate *)about->private_data;
1023 tmp = priv->license;
1026 priv->license = g_strdup (license);
1027 gtk_widget_show (priv->license_button);
1031 priv->license = NULL;
1032 gtk_widget_hide (priv->license_button);
1036 g_object_notify (G_OBJECT (about), "license");
1040 * gtk_about_dialog_get_wrap_license:
1041 * @about: a #GtkAboutDialog
1043 * Returns whether the license text in @about is
1044 * automatically wrapped.
1046 * Returns: %TRUE if the license text is wrapped
1051 gtk_about_dialog_get_wrap_license (GtkAboutDialog *about)
1053 GtkAboutDialogPrivate *priv;
1055 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), FALSE);
1057 priv = (GtkAboutDialogPrivate *)about->private_data;
1059 return priv->wrap_license;
1063 * gtk_about_dialog_set_wrap_license:
1064 * @about: a #GtkAboutDialog
1065 * @wrap_license: whether to wrap the license
1067 * Sets whether the license text in @about is
1068 * automatically wrapped.
1073 gtk_about_dialog_set_wrap_license (GtkAboutDialog *about,
1074 gboolean wrap_license)
1076 GtkAboutDialogPrivate *priv;
1078 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1080 priv = (GtkAboutDialogPrivate *)about->private_data;
1082 wrap_license = wrap_license != FALSE;
1084 if (priv->wrap_license != wrap_license)
1086 priv->wrap_license = wrap_license;
1088 g_object_notify (G_OBJECT (about), "wrap-license");
1093 * gtk_about_dialog_get_website:
1094 * @about: a #GtkAboutDialog
1096 * Returns the website URL.
1098 * Return value: The website URL. The string is owned by the about
1099 * dialog and must not be modified.
1103 G_CONST_RETURN gchar *
1104 gtk_about_dialog_get_website (GtkAboutDialog *about)
1106 GtkAboutDialogPrivate *priv;
1108 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1110 priv = (GtkAboutDialogPrivate *)about->private_data;
1112 return priv->website;
1116 * gtk_about_dialog_set_website:
1117 * @about: a #GtkAboutDialog
1118 * @website: a URL string starting with "http://"
1120 * Sets the URL to use for the website link.
1125 gtk_about_dialog_set_website (GtkAboutDialog *about,
1126 const gchar *website)
1128 GtkAboutDialogPrivate *priv;
1131 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1133 priv = (GtkAboutDialogPrivate *)about->private_data;
1135 tmp = priv->website;
1136 if (website != NULL)
1138 priv->website = g_strdup (website);
1139 if (activate_url_hook != NULL)
1141 g_object_set_data_full (G_OBJECT (priv->website_button),
1142 "url", g_strdup (website), g_free);
1143 if (priv->website_label == NULL)
1144 gtk_about_dialog_set_website_label (about, website);
1148 GtkWidget *hbox = priv->website_button->parent;
1149 gtk_widget_destroy (priv->website_button);
1150 priv->website_button = gtk_label_new (website);
1151 gtk_label_set_selectable (GTK_LABEL (priv->website_button), TRUE);
1152 gtk_container_add (GTK_CONTAINER (hbox), priv->website_button);
1153 gtk_widget_show (priv->website_button);
1158 priv->website = NULL;
1159 g_object_set_data (G_OBJECT (priv->website_button), "url", NULL);
1160 gtk_widget_hide (priv->website_button);
1164 g_object_notify (G_OBJECT (about), "website");
1168 * gtk_about_dialog_get_website_label:
1169 * @about: a #GtkAboutDialog
1171 * Returns the label used for the website link.
1173 * Return value: The label used for the website link. The string is owned by the about
1174 * dialog and must not be modified.
1178 G_CONST_RETURN gchar *
1179 gtk_about_dialog_get_website_label (GtkAboutDialog *about)
1181 GtkAboutDialogPrivate *priv;
1183 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1185 priv = (GtkAboutDialogPrivate *)about->private_data;
1187 return priv->website_label;
1191 * gtk_about_dialog_set_website_label:
1192 * @about: a #GtkAboutDialog
1193 * @website_label: the label used for the website link
1195 * Sets the label to be used for the website link.
1196 * It defaults to the website URL.
1201 gtk_about_dialog_set_website_label (GtkAboutDialog *about,
1202 const gchar *website_label)
1204 GtkAboutDialogPrivate *priv;
1207 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1209 priv = (GtkAboutDialogPrivate *)about->private_data;
1211 tmp = priv->website_label;
1212 if (activate_url_hook != NULL)
1214 if (website_label != NULL)
1216 priv->website_label = g_strdup (website_label);
1217 set_link_button_text (GTK_WIDGET (about),
1218 priv->website_button,
1219 priv->website_label);
1220 gtk_widget_show (priv->website_button);
1224 priv->website_label = NULL;
1225 gtk_widget_hide (priv->website_button);
1230 g_object_notify (G_OBJECT (about), "website-label");
1234 * gtk_about_dialog_get_authors:
1235 * @about: a #GtkAboutDialog
1237 * Returns the string which are displayed in the authors tab
1238 * of the secondary credits dialog.
1240 * Return value: A %NULL-terminated string array containing
1241 * the authors. The array is owned by the about dialog
1242 * and must not be modified.
1246 G_CONST_RETURN gchar * G_CONST_RETURN *
1247 gtk_about_dialog_get_authors (GtkAboutDialog *about)
1249 GtkAboutDialogPrivate *priv;
1251 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1253 priv = (GtkAboutDialogPrivate *)about->private_data;
1255 return (const gchar * const *) priv->authors;
1259 * gtk_about_dialog_set_authors:
1260 * @about: a #GtkAboutDialog
1261 * @authors: a %NULL-terminated array of strings
1263 * Sets the strings which are displayed in the authors tab
1264 * of the secondary credits dialog.
1269 gtk_about_dialog_set_authors (GtkAboutDialog *about,
1270 const gchar **authors)
1272 GtkAboutDialogPrivate *priv;
1275 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1277 priv = (GtkAboutDialogPrivate *)about->private_data;
1279 tmp = priv->authors;
1280 priv->authors = g_strdupv ((gchar **)authors);
1283 if (priv->authors != NULL)
1284 gtk_widget_show (priv->credits_button);
1286 g_object_notify (G_OBJECT (about), "authors");
1290 * gtk_about_dialog_get_documenters:
1291 * @about: a #GtkAboutDialog
1293 * Returns the string which are displayed in the documenters
1294 * tab of the secondary credits dialog.
1296 * Return value: A %NULL-terminated string array containing
1297 * the documenters. The array is owned by the about dialog
1298 * and must not be modified.
1302 G_CONST_RETURN gchar * G_CONST_RETURN *
1303 gtk_about_dialog_get_documenters (GtkAboutDialog *about)
1305 GtkAboutDialogPrivate *priv;
1307 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1309 priv = (GtkAboutDialogPrivate *)about->private_data;
1311 return (const gchar * const *)priv->documenters;
1315 * gtk_about_dialog_set_documenters:
1316 * @about: a #GtkAboutDialog
1317 * @documenters: a %NULL-terminated array of strings
1319 * Sets the strings which are displayed in the documenters tab
1320 * of the secondary credits dialog.
1325 gtk_about_dialog_set_documenters (GtkAboutDialog *about,
1326 const gchar **documenters)
1328 GtkAboutDialogPrivate *priv;
1331 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1333 priv = (GtkAboutDialogPrivate *)about->private_data;
1335 tmp = priv->documenters;
1336 priv->documenters = g_strdupv ((gchar **)documenters);
1339 if (priv->documenters != NULL)
1340 gtk_widget_show (priv->credits_button);
1342 g_object_notify (G_OBJECT (about), "documenters");
1346 * gtk_about_dialog_get_artists:
1347 * @about: a #GtkAboutDialog
1349 * Returns the string which are displayed in the artists tab
1350 * of the secondary credits dialog.
1352 * Return value: A %NULL-terminated string array containing
1353 * the artists. The array is owned by the about dialog
1354 * and must not be modified.
1358 G_CONST_RETURN gchar * G_CONST_RETURN *
1359 gtk_about_dialog_get_artists (GtkAboutDialog *about)
1361 GtkAboutDialogPrivate *priv;
1363 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1365 priv = (GtkAboutDialogPrivate *)about->private_data;
1367 return (const gchar * const *)priv->artists;
1371 * gtk_about_dialog_set_artists:
1372 * @about: a #GtkAboutDialog
1373 * @artists: a %NULL-terminated array of strings
1375 * Sets the strings which are displayed in the artists tab
1376 * of the secondary credits dialog.
1381 gtk_about_dialog_set_artists (GtkAboutDialog *about,
1382 const gchar **artists)
1384 GtkAboutDialogPrivate *priv;
1387 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1389 priv = (GtkAboutDialogPrivate *)about->private_data;
1391 tmp = priv->artists;
1392 priv->artists = g_strdupv ((gchar **)artists);
1395 if (priv->artists != NULL)
1396 gtk_widget_show (priv->credits_button);
1398 g_object_notify (G_OBJECT (about), "artists");
1402 * gtk_about_dialog_get_translator_credits:
1403 * @about: a #GtkAboutDialog
1405 * Returns the translator credits string which is displayed
1406 * in the translators tab of the secondary credits dialog.
1408 * Return value: The translator credits string. The string is
1409 * owned by the about dialog and must not be modified.
1413 G_CONST_RETURN gchar *
1414 gtk_about_dialog_get_translator_credits (GtkAboutDialog *about)
1416 GtkAboutDialogPrivate *priv;
1418 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1420 priv = (GtkAboutDialogPrivate *)about->private_data;
1422 return priv->translator_credits;
1426 * gtk_about_dialog_set_translator_credits:
1427 * @about: a #GtkAboutDialog
1428 * @translator_credits: the translator credits
1430 * Sets the translator credits string which is displayed in
1431 * the translators tab of the secondary credits dialog.
1433 * The intended use for this string is to display the translator
1434 * of the language which is currently used in the user interface.
1435 * Using gettext(), a simple way to achieve that is to mark the
1436 * string for translation:
1437 * <informalexample><programlisting>
1438 * gtk_about_dialog_set_translator_credits (about, _("translator-credits"));
1439 * </programlisting></informalexample>
1440 * It is a good idea to use the customary msgid "translator-credits" for this
1441 * purpose, since translators will already know the purpose of that msgid, and
1442 * since #GtkAboutDialog will detect if "translator-credits" is untranslated
1448 gtk_about_dialog_set_translator_credits (GtkAboutDialog *about,
1449 const gchar *translator_credits)
1451 GtkAboutDialogPrivate *priv;
1454 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1456 priv = (GtkAboutDialogPrivate *)about->private_data;
1458 tmp = priv->translator_credits;
1459 priv->translator_credits = g_strdup (translator_credits);
1462 if (priv->translator_credits != NULL)
1463 gtk_widget_show (priv->credits_button);
1465 g_object_notify (G_OBJECT (about), "translator-credits");
1469 * gtk_about_dialog_get_logo:
1470 * @about: a #GtkAboutDialog
1472 * Returns the pixbuf displayed as logo in the about dialog.
1474 * Return value: the pixbuf displayed as logo. The pixbuf is
1475 * owned by the about dialog. If you want to keep a reference
1476 * to it, you have to call g_object_ref() on it.
1481 gtk_about_dialog_get_logo (GtkAboutDialog *about)
1483 GtkAboutDialogPrivate *priv;
1485 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1487 priv = (GtkAboutDialogPrivate *)about->private_data;
1489 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_PIXBUF)
1490 return gtk_image_get_pixbuf (GTK_IMAGE (priv->logo_image));
1496 icon_set_new_from_pixbufs (GList *pixbufs)
1498 GtkIconSet *icon_set = gtk_icon_set_new ();
1500 for (; pixbufs; pixbufs = pixbufs->next)
1502 GdkPixbuf *pixbuf = GDK_PIXBUF (pixbufs->data);
1504 GtkIconSource *icon_source = gtk_icon_source_new ();
1505 gtk_icon_source_set_pixbuf (icon_source, pixbuf);
1506 gtk_icon_set_add_source (icon_set, icon_source);
1507 gtk_icon_source_free (icon_source);
1514 * gtk_about_dialog_set_logo:
1515 * @about: a #GtkAboutDialog
1516 * @logo: a #GdkPixbuf, or %NULL
1518 * Sets the pixbuf to be displayed as logo in
1519 * the about dialog. If it is %NULL, the default
1520 * window icon set with gtk_window_set_default_icon ()
1526 gtk_about_dialog_set_logo (GtkAboutDialog *about,
1529 GtkAboutDialogPrivate *priv;
1531 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1533 priv = (GtkAboutDialogPrivate *)about->private_data;
1535 g_object_freeze_notify (G_OBJECT (about));
1537 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_ICON_NAME)
1538 g_object_notify (G_OBJECT (about), "logo-icon-name");
1541 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->logo_image), logo);
1544 GList *pixbufs = gtk_window_get_default_icon_list ();
1546 if (pixbufs != NULL)
1548 GtkIconSet *icon_set = icon_set_new_from_pixbufs (pixbufs);
1550 gtk_image_set_from_icon_set (GTK_IMAGE (priv->logo_image),
1551 icon_set, GTK_ICON_SIZE_DIALOG);
1553 gtk_icon_set_unref (icon_set);
1554 g_list_free (pixbufs);
1558 g_object_notify (G_OBJECT (about), "logo");
1560 g_object_thaw_notify (G_OBJECT (about));
1564 * gtk_about_dialog_get_logo_icon_name:
1565 * @about: a #GtkAboutDialog
1567 * Returns the icon name displayed as logo in the about dialog.
1569 * Return value: the icon name displayed as logo. The string is
1570 * owned by the dialog. If you want to keep a reference
1571 * to it, you have to call g_strdup() on it.
1575 G_CONST_RETURN gchar *
1576 gtk_about_dialog_get_logo_icon_name (GtkAboutDialog *about)
1578 GtkAboutDialogPrivate *priv;
1579 const gchar *icon_name = NULL;
1581 g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
1583 priv = (GtkAboutDialogPrivate *)about->private_data;
1585 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_ICON_NAME)
1586 gtk_image_get_icon_name (GTK_IMAGE (priv->logo_image), &icon_name, NULL);
1592 * gtk_about_dialog_set_logo_icon_name:
1593 * @about: a #GtkAboutDialog
1594 * @icon_name: an icon name, or %NULL
1596 * Sets the pixbuf to be displayed as logo in
1597 * the about dialog. If it is %NULL, the default
1598 * window icon set with gtk_window_set_default_icon()
1604 gtk_about_dialog_set_logo_icon_name (GtkAboutDialog *about,
1605 const gchar *icon_name)
1607 GtkAboutDialogPrivate *priv;
1609 g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
1611 priv = (GtkAboutDialogPrivate *)about->private_data;
1613 g_object_freeze_notify (G_OBJECT (about));
1615 if (gtk_image_get_storage_type (GTK_IMAGE (priv->logo_image)) == GTK_IMAGE_PIXBUF)
1616 g_object_notify (G_OBJECT (about), "logo");
1618 gtk_image_set_from_icon_name (GTK_IMAGE (priv->logo_image), icon_name,
1619 GTK_ICON_SIZE_DIALOG);
1620 g_object_notify (G_OBJECT (about), "logo-icon-name");
1622 g_object_thaw_notify (G_OBJECT (about));
1626 activate_url (GtkWidget *widget,
1629 GtkAboutDialog *about = GTK_ABOUT_DIALOG (data);
1630 gchar *url = g_object_get_data (G_OBJECT (widget), "url");
1632 if (activate_url_hook != NULL)
1633 (* activate_url_hook) (about, url, activate_url_hook_data);
1637 set_link_button_text (GtkWidget *about,
1643 GdkColor *style_link_color;
1644 GdkColor link_color = { 0, 0, 0, 0xffff };
1646 gtk_widget_ensure_style (about);
1647 gtk_widget_style_get (about, "link_color", &style_link_color, NULL);
1648 if (style_link_color)
1650 link_color = *style_link_color;
1651 gdk_color_free (style_link_color);
1654 link = g_markup_printf_escaped ("<span foreground=\"#%04x%04x%04x\" underline=\"single\">%s</span>",
1655 link_color.red, link_color.green, link_color.blue, text);
1657 label = gtk_bin_get_child (GTK_BIN (button));
1658 gtk_label_set_markup (GTK_LABEL (label), link);
1663 link_button_enter (GtkWidget *widget,
1664 GdkEventCrossing *event,
1665 GtkAboutDialog *about)
1667 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
1668 gdk_window_set_cursor (widget->window, priv->hand_cursor);
1674 link_button_leave (GtkWidget *widget,
1675 GdkEventCrossing *event,
1676 GtkAboutDialog *about)
1678 gdk_window_set_cursor (widget->window, NULL);
1684 create_link_button (GtkWidget *about,
1692 button = gtk_button_new_with_label ("");
1693 GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
1694 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
1696 g_object_set_data_full (G_OBJECT (button), "url", g_strdup (url), g_free);
1697 set_link_button_text (about, button, text);
1699 g_signal_connect (button, "clicked", callback, data);
1700 g_signal_connect (button, "enter_notify_event",
1701 G_CALLBACK (link_button_enter), data);
1702 g_signal_connect (button, "leave_notify_event",
1703 G_CALLBACK (link_button_leave), data);
1709 follow_if_link (GtkAboutDialog *about,
1712 GSList *tags = NULL, *tagp = NULL;
1714 tags = gtk_text_iter_get_tags (iter);
1715 for (tagp = tags; tagp != NULL; tagp = tagp->next)
1717 GtkTextTag *tag = tagp->data;
1718 gchar *email = g_object_get_data (G_OBJECT (tag), "email");
1719 gchar *url = g_object_get_data (G_OBJECT (tag), "url");
1721 if (email != NULL && activate_email_hook != NULL)
1723 (* activate_email_hook) (about, email, activate_email_hook_data);
1727 if (url != NULL && activate_url_hook != NULL)
1729 (* activate_url_hook) (about, url, activate_url_hook_data);
1735 g_slist_free (tags);
1739 credits_key_press_event (GtkWidget *text_view,
1741 GtkAboutDialog *about)
1744 GtkTextBuffer *buffer;
1746 switch (event->keyval)
1750 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
1751 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
1752 gtk_text_buffer_get_insert (buffer));
1753 follow_if_link (about, &iter);
1764 credits_event_after (GtkWidget *text_view,
1766 GtkAboutDialog *about)
1768 GtkTextIter start, end, iter;
1769 GtkTextBuffer *buffer;
1770 GdkEventButton *button_event;
1773 if (event->type != GDK_BUTTON_RELEASE)
1776 button_event = (GdkEventButton *)event;
1778 if (button_event->button != 1)
1781 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
1783 /* we shouldn't follow a link if the user has selected something */
1784 gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
1785 if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
1788 gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
1789 GTK_TEXT_WINDOW_WIDGET,
1790 button_event->x, button_event->y, &x, &y);
1792 gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y);
1794 follow_if_link (about, &iter);
1800 set_cursor_if_appropriate (GtkAboutDialog *about,
1801 GtkTextView *text_view,
1805 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
1806 GSList *tags = NULL, *tagp = NULL;
1807 GtkTextBuffer *buffer;
1809 gboolean hovering_over_link = FALSE;
1811 buffer = gtk_text_view_get_buffer (text_view);
1813 gtk_text_view_get_iter_at_location (text_view, &iter, x, y);
1815 tags = gtk_text_iter_get_tags (&iter);
1816 for (tagp = tags; tagp != NULL; tagp = tagp->next)
1818 GtkTextTag *tag = tagp->data;
1819 gchar *email = g_object_get_data (G_OBJECT (tag), "email");
1820 gchar *url = g_object_get_data (G_OBJECT (tag), "url");
1822 if (email != NULL || url != NULL)
1824 hovering_over_link = TRUE;
1829 if (hovering_over_link != priv->hovering_over_link)
1831 priv->hovering_over_link = hovering_over_link;
1833 if (hovering_over_link)
1834 gdk_window_set_cursor (gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT), priv->hand_cursor);
1836 gdk_window_set_cursor (gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT), priv->regular_cursor);
1840 g_slist_free (tags);
1844 credits_motion_notify_event (GtkWidget *text_view,
1845 GdkEventMotion *event,
1846 GtkAboutDialog *about)
1850 gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
1851 GTK_TEXT_WINDOW_WIDGET,
1852 event->x, event->y, &x, &y);
1854 set_cursor_if_appropriate (about, GTK_TEXT_VIEW (text_view), x, y);
1856 gdk_window_get_pointer (text_view->window, NULL, NULL, NULL);
1863 credits_visibility_notify_event (GtkWidget *text_view,
1864 GdkEventVisibility *event,
1865 GtkAboutDialog *about)
1867 gint wx, wy, bx, by;
1869 gdk_window_get_pointer (text_view->window, &wx, &wy, NULL);
1871 gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
1872 GTK_TEXT_WINDOW_WIDGET,
1875 set_cursor_if_appropriate (about, GTK_TEXT_VIEW (text_view), bx, by);
1881 text_view_style_set (GtkWidget *widget, GtkStyle *prev_style, GtkWidget *text_view)
1883 gtk_widget_modify_base (text_view, GTK_STATE_NORMAL,
1884 &widget->style->bg[GTK_STATE_NORMAL]);
1888 add_credits_page (GtkAboutDialog *about,
1889 GtkWidget *notebook,
1894 gchar *q0, *q1, *q2, *r1, *r2;
1895 GtkWidget *sw, *view;
1896 GtkTextBuffer *buffer;
1897 gboolean linkify_email, linkify_urls;
1898 GdkColor *style_link_color;
1899 GdkColor link_color = { 0, 0, 0, 0xffff };
1901 linkify_email = (activate_email_hook != NULL);
1902 linkify_urls = (activate_url_hook != NULL);
1904 gtk_widget_ensure_style (GTK_WIDGET (about));
1905 gtk_widget_style_get (GTK_WIDGET (about), "link_color", &style_link_color, NULL);
1906 if (style_link_color)
1908 link_color = *style_link_color;
1909 gdk_color_free (style_link_color);
1912 view = gtk_text_view_new ();
1913 g_signal_connect_object (about, "style_set",
1914 G_CALLBACK (text_view_style_set), view, 0);
1916 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
1917 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
1918 gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
1920 gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 8);
1921 gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 8);
1923 g_signal_connect (view, "key-press-event",
1924 G_CALLBACK (credits_key_press_event), about);
1925 g_signal_connect (view, "event-after",
1926 G_CALLBACK (credits_event_after), about);
1927 g_signal_connect (view, "motion-notify-event",
1928 G_CALLBACK (credits_motion_notify_event), about);
1929 g_signal_connect (view, "visibility-notify-event",
1930 G_CALLBACK (credits_visibility_notify_event), about);
1932 sw = gtk_scrolled_window_new (NULL, NULL);
1933 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
1935 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
1936 GTK_POLICY_AUTOMATIC,
1937 GTK_POLICY_AUTOMATIC);
1938 gtk_container_add (GTK_CONTAINER (sw), view);
1940 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1941 sw, gtk_label_new (title));
1945 gtk_widget_hide (view);
1949 gtk_widget_show (view);
1951 for (p = people; *p; p++)
1956 q1 = linkify_email ? strchr (q0, '<') : NULL;
1957 q2 = q1 ? strchr (q1, '>') : NULL;
1958 r1 = linkify_urls ? strstr (q0, "http://") : NULL;
1961 r2 = strpbrk (r1, " \n\t");
1963 r2 = strchr (r1, '\0');
1968 if (r1 && r2 && (!q1 || !q2 || (r1 < q1)))
1981 gtk_text_buffer_insert_at_cursor (buffer, q0, q1 - q0);
1982 gtk_text_buffer_get_end_iter (buffer, &end);
1990 link_type = "email";
1995 link = g_strndup (q1, q2 - q1);
1996 tag = gtk_text_buffer_create_tag (buffer, NULL,
1997 "foreground_gdk", &link_color,
1998 "underline", PANGO_UNDERLINE_SINGLE,
2000 g_object_set_data_full (G_OBJECT (tag), link_type, g_strdup (link), g_free);
2001 gtk_text_buffer_insert_with_tags (buffer, &end, link, -1, tag, NULL);
2007 gtk_text_buffer_insert_at_cursor (buffer, q0, -1);
2013 gtk_text_buffer_insert_at_cursor (buffer, "\n", 1);
2018 display_credits_dialog (GtkWidget *button,
2021 GtkAboutDialog *about = (GtkAboutDialog *)data;
2022 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
2023 GtkWidget *dialog, *notebook;
2025 if (priv->credits_dialog != NULL)
2027 gtk_window_present (GTK_WINDOW (priv->credits_dialog));
2031 dialog = gtk_dialog_new_with_buttons (_("Credits"),
2033 GTK_DIALOG_DESTROY_WITH_PARENT,
2034 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
2036 gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
2038 priv->credits_dialog = dialog;
2039 gtk_window_set_default_size (GTK_WINDOW (dialog), 360, 260);
2040 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
2042 gtk_window_set_modal (GTK_WINDOW (dialog),
2043 gtk_window_get_modal (GTK_WINDOW (about)));
2045 g_signal_connect (dialog, "response",
2046 G_CALLBACK (gtk_widget_destroy), dialog);
2047 g_signal_connect (dialog, "destroy",
2048 G_CALLBACK (gtk_widget_destroyed),
2049 &(priv->credits_dialog));
2050 g_signal_connect (dialog, "style_set",
2051 G_CALLBACK (dialog_style_set), NULL);
2053 notebook = gtk_notebook_new ();
2054 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), notebook, TRUE, TRUE, 0);
2056 if (priv->authors != NULL)
2057 add_credits_page (about, notebook, _("Written by"), priv->authors);
2059 if (priv->documenters != NULL)
2060 add_credits_page (about, notebook, _("Documented by"), priv->documenters);
2062 /* Don't show an untranslated gettext msgid */
2063 if (priv->translator_credits != NULL &&
2064 strcmp (priv->translator_credits, "translator_credits") &&
2065 strcmp (priv->translator_credits, "translator-credits"))
2067 gchar *translators[2];
2069 translators[0] = priv->translator_credits;
2070 translators[1] = NULL;
2072 add_credits_page (about, notebook, _("Translated by"), translators);
2075 if (priv->artists != NULL)
2076 add_credits_page (about, notebook, _("Artwork by"), priv->artists);
2078 gtk_widget_show_all (dialog);
2082 set_policy (GtkWidget *sw)
2084 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2085 GTK_POLICY_AUTOMATIC,
2086 GTK_POLICY_AUTOMATIC);
2090 display_license_dialog (GtkWidget *button,
2093 GtkAboutDialog *about = (GtkAboutDialog *)data;
2094 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
2095 GtkWidget *dialog, *view, *sw;
2097 if (priv->license_dialog != NULL)
2099 gtk_window_present (GTK_WINDOW (priv->license_dialog));
2103 dialog = gtk_dialog_new_with_buttons (_("License"),
2105 GTK_DIALOG_DESTROY_WITH_PARENT,
2106 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
2108 gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
2109 priv->license_dialog = dialog;
2110 gtk_window_set_default_size (GTK_WINDOW (dialog), 420, 320);
2111 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
2113 gtk_window_set_modal (GTK_WINDOW (dialog),
2114 gtk_window_get_modal (GTK_WINDOW (about)));
2116 g_signal_connect (dialog, "response",
2117 G_CALLBACK (gtk_widget_destroy), dialog);
2118 g_signal_connect (dialog, "destroy",
2119 G_CALLBACK (gtk_widget_destroyed),
2120 &(priv->license_dialog));
2121 g_signal_connect (dialog, "style_set",
2122 G_CALLBACK (dialog_style_set), NULL);
2124 sw = gtk_scrolled_window_new (NULL, NULL);
2125 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
2127 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2129 GTK_POLICY_AUTOMATIC);
2130 g_signal_connect (sw, "map", G_CALLBACK (set_policy), NULL);
2131 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), sw, TRUE, TRUE, 0);
2133 view = gtk_text_view_new ();
2134 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view),
2135 priv->wrap_license ? GTK_WRAP_WORD : GTK_WRAP_NONE);
2136 gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)),
2139 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
2140 gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
2142 gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 8);
2143 gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 8);
2145 gtk_container_add (GTK_CONTAINER (sw), view);
2147 gtk_widget_show_all (dialog);
2151 close_cb (GtkAboutDialog *about)
2153 GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
2155 if (priv->license_dialog != NULL)
2157 gtk_widget_destroy (priv->license_dialog);
2158 priv->license_dialog = NULL;
2161 if (priv->credits_dialog != NULL)
2163 gtk_widget_destroy (priv->credits_dialog);
2164 priv->credits_dialog = NULL;
2167 gtk_widget_hide (GTK_WIDGET (about));
2172 * gtk_about_dialog_new:
2174 * Creates a new #GtkAboutDialog.
2176 * Returns: a newly created #GtkAboutDialog
2181 gtk_about_dialog_new (void)
2183 GtkAboutDialog *dialog = g_object_new (GTK_TYPE_ABOUT_DIALOG, NULL);
2185 return GTK_WIDGET (dialog);
2189 * gtk_about_dialog_set_email_hook:
2190 * @func: a function to call when an email link is activated.
2191 * @data: data to pass to @func
2192 * @destroy: #GDestroyNotify for @data
2194 * Installs a global function to be called whenever the user activates an
2195 * email link in an about dialog.
2197 * Return value: the previous email hook.
2201 GtkAboutDialogActivateLinkFunc
2202 gtk_about_dialog_set_email_hook (GtkAboutDialogActivateLinkFunc func,
2204 GDestroyNotify destroy)
2206 GtkAboutDialogActivateLinkFunc old;
2208 if (activate_email_hook_destroy != NULL)
2209 (* activate_email_hook_destroy) (activate_email_hook_data);
2211 old = activate_email_hook;
2213 activate_email_hook = func;
2214 activate_email_hook_data = data;
2215 activate_email_hook_destroy = destroy;
2221 * gtk_about_dialog_set_url_hook:
2222 * @func: a function to call when a URL link is activated.
2223 * @data: data to pass to @func
2224 * @destroy: #GDestroyNotify for @data
2226 * Installs a global function to be called whenever the user activates a
2227 * URL link in an about dialog.
2229 * Return value: the previous URL hook.
2233 GtkAboutDialogActivateLinkFunc
2234 gtk_about_dialog_set_url_hook (GtkAboutDialogActivateLinkFunc func,
2236 GDestroyNotify destroy)
2238 GtkAboutDialogActivateLinkFunc old;
2240 if (activate_url_hook_destroy != NULL)
2241 (* activate_url_hook_destroy) (activate_url_hook_data);
2243 old = activate_url_hook;
2245 activate_url_hook = func;
2246 activate_url_hook_data = data;
2247 activate_url_hook_destroy = destroy;
2253 * gtk_show_about_dialog:
2254 * @parent: transient parent, or %NULL for none
2255 * @first_property_name: the name of the first property
2256 * @Varargs: value of first property, followed by more properties, %NULL-terminated
2258 * This is a convenience function for showing an application's about box.
2259 * The constructed dialog is associated with the parent window and
2260 * reused for future invocations of this function.
2265 gtk_show_about_dialog (GtkWindow *parent,
2266 const gchar *first_property_name,
2269 static GtkWidget *global_about_dialog = NULL;
2270 GtkWidget *dialog = NULL;
2274 dialog = g_object_get_data (G_OBJECT (parent), "gtk-about-dialog");
2276 dialog = global_about_dialog;
2280 dialog = gtk_about_dialog_new ();
2282 g_object_ref (dialog);
2283 gtk_object_sink (GTK_OBJECT (dialog));
2285 g_signal_connect (dialog, "delete_event", G_CALLBACK (gtk_widget_hide_on_delete), NULL);
2287 va_start (var_args, first_property_name);
2288 g_object_set_valist (G_OBJECT (dialog), first_property_name, var_args);
2293 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
2294 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
2295 g_object_set_data_full (G_OBJECT (parent), "gtk-about-dialog",
2296 dialog, g_object_unref);
2299 global_about_dialog = dialog;
2303 gtk_window_present (GTK_WINDOW (dialog));
2306 #define __GTK_ABOUT_DIALOG_C__
2307 #include "gtkaliasdef.c"