Commit 4ed4ccc7 authored by Matthias Clasen's avatar Matthias Clasen Committed by Matthias Clasen

New widget: GtkAboutDialog.

2004-07-12  Matthias Clasen  <mclasen@redhat.com>

	* gtk/gtkaboutdialog.h:
	* gtk/gtkaboutdialog.c: New widget: GtkAboutDialog.

	* gtk/Makefile.am (gtk_public_h_sources, gtk_c_sources):
	* gtk/gtk.h: Add GtkAboutDialog. (#109435, Paolo Borelli,
	patch by Matthias Clasen)
parent 37610bc3
2004-07-12 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkaboutdialog.h:
* gtk/gtkaboutdialog.c: New widget: GtkAboutDialog.
* gtk/Makefile.am (gtk_public_h_sources, gtk_c_sources):
* gtk/gtk.h: Add GtkAboutDialog. (#109435, Paolo Borelli,
patch by Matthias Clasen)
* gtk/gtkrc.c (_gtk_rc_init): Apply the gtk-default-menu-item-style
to cell view menu items as well. (#147405, John Cupitt)
......
2004-07-12 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkaboutdialog.h:
* gtk/gtkaboutdialog.c: New widget: GtkAboutDialog.
* gtk/Makefile.am (gtk_public_h_sources, gtk_c_sources):
* gtk/gtk.h: Add GtkAboutDialog. (#109435, Paolo Borelli,
patch by Matthias Clasen)
* gtk/gtkrc.c (_gtk_rc_init): Apply the gtk-default-menu-item-style
to cell view menu items as well. (#147405, John Cupitt)
......
2004-07-12 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkaboutdialog.h:
* gtk/gtkaboutdialog.c: New widget: GtkAboutDialog.
* gtk/Makefile.am (gtk_public_h_sources, gtk_c_sources):
* gtk/gtk.h: Add GtkAboutDialog. (#109435, Paolo Borelli,
patch by Matthias Clasen)
* gtk/gtkrc.c (_gtk_rc_init): Apply the gtk-default-menu-item-style
to cell view menu items as well. (#147405, John Cupitt)
......
2004-07-12 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkaboutdialog.h:
* gtk/gtkaboutdialog.c: New widget: GtkAboutDialog.
* gtk/Makefile.am (gtk_public_h_sources, gtk_c_sources):
* gtk/gtk.h: Add GtkAboutDialog. (#109435, Paolo Borelli,
patch by Matthias Clasen)
* gtk/gtkrc.c (_gtk_rc_init): Apply the gtk-default-menu-item-style
to cell view menu items as well. (#147405, John Cupitt)
......
......@@ -98,6 +98,7 @@ libtool_opts = \
# by configure)
gtk_public_h_sources = \
gtk.h \
gtkaboutdialog.h \
gtkaccelgroup.h \
gtkaccellabel.h \
gtkaccelmap.h \
......@@ -303,6 +304,7 @@ gtk_private_h_sources = \
# GTK+ C sources to build the library from
gtk_c_sources = \
fnmatch.c \
gtkaboutdialog.c \
gtkaccelgroup.c \
gtkaccellabel.c \
gtkaccelmap.c \
......
......@@ -29,6 +29,7 @@
#include <gdk/gdk.h>
#include <gtk/gtkaboutdialog.h>
#include <gtk/gtkaccelgroup.h>
#include <gtk/gtkaccellabel.h>
#include <gtk/gtkaccelmap.h>
......
/* GTK - The GIMP Toolkit
* Copyright (C) 2001 CodeFactory AB
* Copyright (C) 2001, 2002 Anders Carlsson
* Copyright (C) 2003, 2004 Matthias Clasen <mclasen@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Author: Anders Carlsson <andersca@gnu.org>
*
* Modified by the GTK+ Team and others 1997-2004. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include <config.h>
#include <gdk/gdkkeysyms.h>
#include "gtkaboutdialog.h"
#include "gtkbutton.h"
#include "gtkbbox.h"
#include "gtkdialog.h"
#include "gtkhbox.h"
#include "gtkimage.h"
#include "gtklabel.h"
#include "gtkmarshalers.h"
#include "gtknotebook.h"
#include "gtkscrolledwindow.h"
#include "gtkstock.h"
#include "gtktextview.h"
#include "gtkvbox.h"
#include "gtkviewport.h"
#include "gtkiconfactory.h"
#include "gtkintl.h"
#include <string.h>
typedef struct _GtkAboutDialogPrivate GtkAboutDialogPrivate;
struct _GtkAboutDialogPrivate
{
gchar *name;
gchar *version;
gchar *copyright;
gchar *comments;
gchar *website;
gchar *website_label;
gchar *translator_credits;
gchar *license;
gchar **authors;
gchar **documenters;
gchar **artists;
GtkWidget *logo_image;
GtkWidget *name_label;
GtkWidget *comments_label;
GtkWidget *copyright_label;
GtkWidget *website_button;
GtkWidget *credits_button;
GtkWidget *credits_dialog;
GtkWidget *license_button;
GtkWidget *license_dialog;
GdkCursor *hand_cursor;
GdkCursor *regular_cursor;
gboolean hovering_over_link;
};
#define GTK_ABOUT_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ABOUT_DIALOG, GtkAboutDialogPrivate))
enum
{
PROP_0,
PROP_NAME,
PROP_VERSION,
PROP_COPYRIGHT,
PROP_COMMENTS,
PROP_WEBSITE,
PROP_WEBSITE_LABEL,
PROP_LICENSE,
PROP_AUTHORS,
PROP_DOCUMENTERS,
PROP_TRANSLATOR_CREDITS,
PROP_ARTISTS,
PROP_LOGO
};
static void gtk_about_dialog_finalize (GObject *object);
static void gtk_about_dialog_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gtk_about_dialog_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void update_name_version (GtkAboutDialog *about);
static GtkIconSet * icon_set_new_from_pixbufs (GList *pixbufs);
static void activate_url (GtkWidget *widget,
gpointer data);
static void set_link_button_text (GtkWidget *about,
GtkWidget *button,
gchar *text);
static GtkWidget * create_link_button (GtkWidget *about,
gchar *text,
gchar *url,
GCallback callback,
gpointer data);
static void follow_if_link (GtkAboutDialog *about,
GtkTextIter *iter);
static void set_cursor_if_appropriate (GtkAboutDialog *about,
GtkTextView *text_view,
gint x,
gint y);
static void add_credits_page (GtkAboutDialog *about,
GtkWidget *notebook,
gchar *title,
gchar **people);
static gboolean credits_key_press_event (GtkWidget *text_view,
GdkEventKey *event,
GtkAboutDialog *about);
static gboolean credits_event_after (GtkWidget *text_view,
GdkEvent *event,
GtkAboutDialog *about);
static gboolean credits_motion_notify_event (GtkWidget *text_view,
GdkEventMotion *event,
GtkAboutDialog *about);
static gboolean credits_visibility_notify_event (GtkWidget *text_view,
GdkEventVisibility *event,
GtkAboutDialog *about);
static void display_credits_dialog (GtkWidget *button,
gpointer data);
static void display_license_dialog (GtkWidget *button,
gpointer data);
static GtkAboutDialogActivateLinkFunc activate_email_hook = NULL;
static GtkAboutDialogActivateLinkFunc activate_url_hook = NULL;
G_DEFINE_TYPE (GtkAboutDialog, gtk_about_dialog, GTK_TYPE_DIALOG);
static void
gtk_about_dialog_class_init (GtkAboutDialogClass *klass)
{
GObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkDialogClass *dialog_class;
object_class = (GObjectClass *)klass;
widget_class = (GtkWidgetClass *)klass;
dialog_class = (GtkDialogClass *)klass;
object_class->set_property = gtk_about_dialog_set_property;
object_class->get_property = gtk_about_dialog_get_property;
object_class->finalize = gtk_about_dialog_finalize;
g_object_class_install_property (object_class,
PROP_NAME,
g_param_spec_string ("name",
P_("Program name"),
P_("The name of the program. If this is not set, it defaults to g_get_application_name()"),
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_VERSION,
g_param_spec_string ("version",
P_("Program version"),
P_("The version of the program"),
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_COPYRIGHT,
g_param_spec_string ("copyright",
P_("Copyright string"),
P_("Copyright information for the program"),
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_COMMENTS,
g_param_spec_string ("comments",
P_("Comments string"),
P_("Comments about the program"),
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_LICENSE,
g_param_spec_string ("license",
_("License"),
_("The license of the program"),
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_WEBSITE,
g_param_spec_string ("website",
P_("Website URL"),
P_("The URL for the link to the website of the program"),
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_WEBSITE_LABEL,
g_param_spec_string ("website_label",
P_("Website label"),
P_("The label for the link to the website of the program. If this is not set, it defaults to the URL"),
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_AUTHORS,
g_param_spec_boxed ("authors",
P_("Authors"),
P_("List of authors of the programs"),
G_TYPE_STRV,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_DOCUMENTERS,
g_param_spec_boxed ("documenters",
P_("Documenters"),
P_("List of people documenting the program"),
G_TYPE_STRV,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ARTISTS,
g_param_spec_boxed ("artists",
P_("Artists"),
P_("List of people who have contributed artwork to the program"),
G_TYPE_STRV,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_TRANSLATOR_CREDITS,
g_param_spec_string ("translator_credits",
P_("Translator credits"),
P_("Credits to the translators. This string should be marked as translatable"),
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_LOGO,
g_param_spec_object ("logo",
P_("Logo"),
P_("A logo for the about box. If this is not set, it defaults to gtk_window_get_default_icon_list()"),
GDK_TYPE_PIXBUF,
G_PARAM_READWRITE));
/* Style properties */
gtk_widget_class_install_style_property (widget_class,
g_param_spec_boxed ("link_color",
P_("Link Color"),
P_("Color of hyperlinks"),
GDK_TYPE_COLOR,
G_PARAM_READABLE));
g_type_class_add_private (object_class, sizeof (GtkAboutDialogPrivate));
}
static void
gtk_about_dialog_init (GtkAboutDialog *about)
{
GtkAboutDialogPrivate *priv;
GtkWidget *vbox, *hbox, *button;
/* Data */
priv = GTK_ABOUT_DIALOG_GET_PRIVATE (about);
about->private_data = priv;
priv->name = NULL;
priv->version = NULL;
priv->copyright = NULL;
priv->comments = NULL;
priv->website = NULL;
priv->website_label = NULL;
priv->translator_credits = NULL;
priv->authors = NULL;
priv->documenters = NULL;
priv->artists = NULL;
priv->hand_cursor = gdk_cursor_new (GDK_HAND2);
priv->regular_cursor = gdk_cursor_new (GDK_XTERM);
priv->hovering_over_link = FALSE;
/* Widgets */
gtk_widget_push_composite_child ();
vbox = gtk_vbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (about)->vbox), vbox, TRUE, TRUE, 0);
priv->logo_image = gtk_image_new ();
gtk_box_pack_start (GTK_BOX (vbox), priv->logo_image, FALSE, FALSE, 0);
priv->name_label = gtk_label_new (NULL);
gtk_label_set_selectable (GTK_LABEL (priv->name_label), TRUE);
gtk_label_set_justify (GTK_LABEL (priv->name_label), GTK_JUSTIFY_CENTER);
gtk_box_pack_start (GTK_BOX (vbox), priv->name_label, FALSE, FALSE, 0);
priv->comments_label = gtk_label_new (NULL);
gtk_label_set_selectable (GTK_LABEL (priv->comments_label), TRUE);
gtk_label_set_justify (GTK_LABEL (priv->comments_label), GTK_JUSTIFY_CENTER);
gtk_label_set_line_wrap (GTK_LABEL (priv->comments_label), TRUE);
gtk_box_pack_start (GTK_BOX (vbox), priv->comments_label, FALSE, FALSE, 0);
priv->copyright_label = gtk_label_new (NULL);
gtk_label_set_selectable (GTK_LABEL (priv->copyright_label), TRUE);
gtk_label_set_justify (GTK_LABEL (priv->copyright_label), GTK_JUSTIFY_CENTER);
gtk_box_pack_start (GTK_BOX (vbox), priv->copyright_label, FALSE, FALSE, 0);
button = create_link_button (GTK_WIDGET (about), "", "",
G_CALLBACK (activate_url), about);
hbox = gtk_hbox_new (TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
priv->website_button = button;
gtk_widget_show (vbox);
gtk_widget_show (priv->logo_image);
gtk_widget_show (priv->name_label);
gtk_widget_show (hbox);
/* Add the OK button */
gtk_dialog_add_button (GTK_DIALOG (about), GTK_STOCK_OK, GTK_RESPONSE_OK);
gtk_dialog_set_default_response (GTK_DIALOG (about), GTK_RESPONSE_OK);
/* Add the credits button */
button = gtk_button_new_from_stock (_("_Credits"));
gtk_box_pack_end (GTK_BOX (GTK_DIALOG (about)->action_area),
button, FALSE, TRUE, 0);
gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (about)->action_area), button, TRUE);
g_signal_connect (button, "clicked", G_CALLBACK (display_credits_dialog), about);
priv->credits_button = button;
priv->credits_dialog = NULL;
/* Add the license button */
button = gtk_button_new_from_stock (_("_License"));
gtk_box_pack_end (GTK_BOX (GTK_DIALOG (about)->action_area),
button, FALSE, TRUE, 0);
gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (about)->action_area), button, TRUE);
g_signal_connect (button, "clicked", G_CALLBACK (display_license_dialog), about);
priv->license_button = button;
priv->license_dialog = NULL;
gtk_window_set_resizable (GTK_WINDOW (about), FALSE);
gtk_widget_pop_composite_child ();
}
static void
gtk_about_dialog_finalize (GObject *object)
{
GtkAboutDialog *about = GTK_ABOUT_DIALOG (object);
GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
g_free (priv->name);
g_free (priv->version);
g_free (priv->copyright);
g_free (priv->comments);
g_free (priv->license);
g_free (priv->website);
g_free (priv->website_label);
g_free (priv->translator_credits);
g_strfreev (priv->authors);
g_strfreev (priv->documenters);
g_strfreev (priv->artists);
g_free (priv);
about->private_data = NULL;
G_OBJECT_CLASS (gtk_about_dialog_parent_class)->finalize (object);
}
static void
gtk_about_dialog_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkAboutDialog *about = GTK_ABOUT_DIALOG (object);
switch (prop_id)
{
case PROP_NAME:
gtk_about_dialog_set_name (about, g_value_get_string (value));
break;
case PROP_VERSION:
gtk_about_dialog_set_version (about, g_value_get_string (value));
break;
case PROP_COMMENTS:
gtk_about_dialog_set_comments (about, g_value_get_string (value));
break;
case PROP_WEBSITE:
gtk_about_dialog_set_website (about, g_value_get_string (value));
break;
case PROP_WEBSITE_LABEL:
gtk_about_dialog_set_website_label (about, g_value_get_string (value));
break;
case PROP_LICENSE:
gtk_about_dialog_set_license (about, g_value_get_string (value));
break;
case PROP_COPYRIGHT:
gtk_about_dialog_set_copyright (about, g_value_get_string (value));
break;
case PROP_LOGO:
gtk_about_dialog_set_logo (about, g_value_get_object (value));
break;
case PROP_AUTHORS:
gtk_about_dialog_set_authors (about, (gchar**)g_value_get_boxed (value));
break;
case PROP_DOCUMENTERS:
gtk_about_dialog_set_documenters (about, (gchar**)g_value_get_boxed (value));
break;
case PROP_ARTISTS:
gtk_about_dialog_set_artists (about, (gchar**)g_value_get_boxed (value));
break;
case PROP_TRANSLATOR_CREDITS:
gtk_about_dialog_set_translator_credits (about, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_about_dialog_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkAboutDialog *about = GTK_ABOUT_DIALOG (object);
GtkAboutDialogPrivate *priv = (GtkAboutDialogPrivate *)about->private_data;
switch (prop_id)
{
case PROP_NAME:
g_value_set_string (value, priv->name);
break;
case PROP_VERSION:
g_value_set_string (value, priv->version);
break;
case PROP_COPYRIGHT:
g_value_set_string (value, priv->copyright);
break;
case PROP_COMMENTS:
g_value_set_string (value, priv->comments);
break;
case PROP_WEBSITE:
g_value_set_string (value, priv->website);
break;
case PROP_WEBSITE_LABEL:
g_value_set_string (value, priv->website_label);
break;
case PROP_LICENSE:
g_value_set_string (value, priv->license);
break;
case PROP_TRANSLATOR_CREDITS:
g_value_set_string (value, priv->translator_credits);
break;
case PROP_AUTHORS:
g_value_set_boxed (value, priv->authors);
break;
case PROP_DOCUMENTERS:
g_value_set_boxed (value, priv->documenters);
break;
case PROP_ARTISTS:
g_value_set_boxed (value, priv->artists);
break;
case PROP_LOGO:
g_value_set_object (value, gtk_image_get_pixbuf (GTK_IMAGE (priv->logo_image)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/**
* gtk_about_dialog_get_name:
* @about: a #GtkAboutDialog
*
* Returns the program name displayed in the about dialog.
*
* Return value: The program name. The string is owned by the about
* dialog and must not be modified.
*
* Since: 2.6
**/
G_CONST_RETURN gchar *
gtk_about_dialog_get_name (GtkAboutDialog *about)
{
GtkAboutDialogPrivate *priv;
g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
priv = (GtkAboutDialogPrivate *)about->private_data;
return priv->name;
}
static void
update_name_version (GtkAboutDialog *about)
{
GtkAboutDialogPrivate *priv;
gchar *title_string, *name_string;
priv = (GtkAboutDialogPrivate *)about->private_data;
title_string = g_strdup_printf (_("About %s"), priv->name);
gtk_window_set_title (GTK_WINDOW (about), title_string);
g_free (title_string);
if (priv->version != NULL)
name_string = g_markup_printf_escaped ("<span size=\"xx-large\" weight=\"bold\">%s %s</span>",
priv->name, priv->version);
else
name_string = g_markup_printf_escaped ("<span size=\"xx-large\" weight=\"bold\">%s</span>",
priv->name);
gtk_label_set_markup (GTK_LABEL (priv->name_label), name_string);
g_free (name_string);
}
/**
* gtk_about_dialog_set_name:
* @about: a #GtkAboutDialog
* @name: the program name
*
* Sets the name to display in the about dialog.
* If this is not set, it defaults to g_get_application_name().
*
* Since: 2.6
**/
void
gtk_about_dialog_set_name (GtkAboutDialog *about,
const gchar *name)
{
GtkAboutDialogPrivate *priv;
gchar *tmp;
g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
priv = (GtkAboutDialogPrivate *)about->private_data;
tmp = priv->name;
priv->name = g_strdup (name ? name : g_get_application_name ());
g_free (tmp);
update_name_version (about);
g_object_notify (G_OBJECT (about), "name");
}
/**
* gtk_about_dialog_get_version:
* @about: a #GtkAboutDialog
*
* Returns the version string.
*
* Return value: The version string. The string is owned by the about
* dialog and must not be modified.
*
* Since: 2.6
**/
G_CONST_RETURN gchar *
gtk_about_dialog_get_version (GtkAboutDialog *about)
{
GtkAboutDialogPrivate *priv;
g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
priv = (GtkAboutDialogPrivate *)about->private_data;
return priv->version;
}
/**
* gtk_about_dialog_set_version:
* @about: a #GtkAboutDialog
* @version: the version string
*
* Sets the version string to display in the about dialog.
*
* Since: 2.6
**/
void
gtk_about_dialog_set_version (GtkAboutDialog *about,
const gchar *version)
{
GtkAboutDialogPrivate *priv;
gchar *tmp;
g_return_if_fail (GTK_IS_ABOUT_DIALOG (about));
priv = (GtkAboutDialogPrivate *)about->private_data;
tmp = priv->version;
priv->version = version ? g_strdup (version) : NULL;
g_free (tmp);
update_name_version (about);
g_object_notify (G_OBJECT (about), "version");
}
/**
* gtk_about_dialog_get_copyright:
* @about: a #GtkAboutDialog
*
* Returns the copyright string.
*
* Return value: The copyright string. The string is owned by the about
* dialog and must not be modified.
*
* Since: 2.6
**/
G_CONST_RETURN gchar *
gtk_about_dialog_get_copyright (GtkAboutDialog *about)
{
GtkAboutDialogPrivate *priv;
g_return_val_if_fail (GTK_IS_ABOUT_DIALOG (about), NULL);
priv = (GtkAboutDialogPrivate *)about->private_data;
return priv->copyright;
}
/**
* gtk_about_dialog_set_copyright:
* @about: a #GtkAboutDialog
* @copyright: the copyright string
*
* Sets the copyright string to display in the about dialog.
* This should be a short string of one or two lines.
*
* Since: 2.6
**/
void
gtk_about_dialog_set_copyright (GtkAboutDialog *about,
const gchar *copyright)
{
GtkAboutDialogPrivate *priv;
gchar *copyright_string, *tmp;