From 083c48d2d2f5f388c28e8f21e94bd3f74cba0524 Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Mon, 4 Aug 2008 13:56:07 +0000 Subject: [PATCH] =?UTF-8?q?Applied=20a=20slightly=20modified=20patch=20fro?= =?UTF-8?q?m=20R=C3=B3man=20Joost=20as=20attached=20to=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2008-08-04 Sven Neumann Applied a slightly modified patch from Róman Joost as attached to bug #545963. This add links to the user manual to the tips dialog: * data/tips/gimp-tips.dtd * data/tips/gimp-tips.xml.in: add optional help IDs to the tips. * app/dialogs/tips-dialog.c * app/dialogs/tips-parser.[ch]: parse the help IDs from the tips file and show a "Learn more" link in the tips dialog. svn path=/trunk/; revision=26361 --- ChangeLog | 13 +++++ app/dialogs/tips-dialog.c | 79 ++++++++++++++++++-------- app/dialogs/tips-parser.c | 111 +++++++++++++++++++++++++------------ app/dialogs/tips-parser.h | 3 +- data/tips/gimp-tips.dtd | 1 + data/tips/gimp-tips.xml.in | 28 +++++----- 6 files changed, 162 insertions(+), 73 deletions(-) diff --git a/ChangeLog b/ChangeLog index 066c6c6bf8..7c7e2f8fba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-08-04 Sven Neumann + + Applied a slightly modified patch from Róman Joost as attached to + bug #545963. This add links to the user manual to the tips dialog: + + * data/tips/gimp-tips.dtd + * data/tips/gimp-tips.xml.in: add optional help IDs to the tips. + + * app/dialogs/tips-dialog.c + + * app/dialogs/tips-parser.[ch]: parse the help IDs from the tips + file and show a "Learn more" link in the tips dialog. + 2008-08-03 Martin Nordholts * app/display/gimpdisplayshell.c (gimp_display_shell_new): Center diff --git a/app/dialogs/tips-dialog.c b/app/dialogs/tips-dialog.c index f9275eb482..8748301b40 100644 --- a/app/dialogs/tips-dialog.c +++ b/app/dialogs/tips-dialog.c @@ -36,24 +36,26 @@ #include "gimp-intl.h" - enum { RESPONSE_PREVIOUS = 1, RESPONSE_NEXT = 2 }; -static void tips_dialog_set_tip (GimpTip *tip); -static void tips_dialog_response (GtkWidget *dialog, - gint response); -static void tips_dialog_destroy (GtkWidget *widget, - gpointer data); +static void tips_dialog_set_tip (GimpTip *tip); +static void tips_dialog_response (GtkWidget *dialog, + gint response); +static void tips_dialog_destroy (GtkWidget *widget, + GimpGuiConfig *config); +static void more_button_clicked (GtkWidget *button, + Gimp *gimp); -static GtkWidget *tips_dialog = NULL; -static GtkWidget *thetip_label = NULL; -static GList *tips = NULL; -static GList *current_tip = NULL; +static GtkWidget *tips_dialog = NULL; +static GtkWidget *tip_label = NULL; +static GtkWidget *more_button = NULL; +static GList *tips = NULL; +static GList *current_tip = NULL; GtkWidget * @@ -164,32 +166,47 @@ tips_dialog_create (Gimp *gimp) gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); gtk_widget_show (hbox); - thetip_label = gtk_label_new (NULL); - gtk_label_set_selectable (GTK_LABEL (thetip_label), TRUE); - gtk_label_set_justify (GTK_LABEL (thetip_label), GTK_JUSTIFY_LEFT); - gtk_label_set_line_wrap (GTK_LABEL (thetip_label), TRUE); - gtk_misc_set_alignment (GTK_MISC (thetip_label), 0.5, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), thetip_label, TRUE, TRUE, 0); - gtk_widget_show (thetip_label); + vbox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); + gtk_widget_show (vbox); image = gtk_image_new_from_stock (GIMP_STOCK_INFO, GTK_ICON_SIZE_DIALOG); - gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5); + gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0); gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); gtk_widget_show (image); gtk_container_set_focus_chain (GTK_CONTAINER (hbox), NULL); + tip_label = gtk_label_new (NULL); + gtk_label_set_selectable (GTK_LABEL (tip_label), TRUE); + gtk_label_set_justify (GTK_LABEL (tip_label), GTK_JUSTIFY_LEFT); + gtk_label_set_line_wrap (GTK_LABEL (tip_label), TRUE); + gtk_misc_set_alignment (GTK_MISC (tip_label), 0.5, 0.0); + gtk_box_pack_start (GTK_BOX (vbox), tip_label, TRUE, TRUE, 0); + gtk_widget_show (tip_label); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + more_button = gtk_link_button_new_with_label ("http://docs.gimp.org/", + _("Learn more")); + gtk_widget_show (more_button); + gtk_box_pack_start (GTK_BOX (hbox), more_button, FALSE, FALSE, 0); + + g_signal_connect (more_button, "clicked", + G_CALLBACK (more_button_clicked), + gimp); + tips_dialog_set_tip (current_tip->data); return tips_dialog; } static void -tips_dialog_destroy (GtkWidget *widget, - gpointer data) +tips_dialog_destroy (GtkWidget *widget, + GimpGuiConfig *config) { - GimpGuiConfig *config = GIMP_GUI_CONFIG (data); - /* the last-shown-tip is saved in sessionrc */ config->last_tip = g_list_position (tips, current_tip); @@ -227,5 +244,21 @@ tips_dialog_set_tip (GimpTip *tip) { g_return_if_fail (tip != NULL); - gtk_label_set_markup (GTK_LABEL (thetip_label), tip->thetip); + gtk_label_set_markup (GTK_LABEL (tip_label), tip->text); + + /* set the URI to unset the "visited" state */ + gtk_link_button_set_uri (GTK_LINK_BUTTON (more_button), + "http://docs.gimp.org/"); + + gtk_widget_set_sensitive (more_button, tip->help_id != NULL); +} + +static void +more_button_clicked (GtkWidget *button, + Gimp *gimp) +{ + GimpTip *tip = current_tip->data; + + if (tip->help_id) + gimp_help (gimp, NULL, NULL, tip->help_id); } diff --git a/app/dialogs/tips-parser.c b/app/dialogs/tips-parser.c index ad30f1b8a4..badb6dc454 100644 --- a/app/dialogs/tips-parser.c +++ b/app/dialogs/tips-parser.c @@ -54,6 +54,7 @@ typedef struct TipsParserState state; TipsParserState last_known_state; const gchar *locale; + const gchar *help_id; TipsParserLocaleState locale_state; gint markup_depth; gint unknown_depth; @@ -63,33 +64,38 @@ typedef struct } TipsParser; -static void tips_parser_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void tips_parser_end_element (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void tips_parser_characters (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); +static void tips_parser_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error); +static void tips_parser_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error); +static void tips_parser_characters (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error); -static void tips_parser_start_markup (TipsParser *parser, - const gchar *markup_name); -static void tips_parser_end_markup (TipsParser *parser, - const gchar *markup_name); -static void tips_parser_start_unknown (TipsParser *parser); -static void tips_parser_end_unknown (TipsParser *parser); -static void tips_parser_parse_locale (TipsParser *parser, - const gchar **names, - const gchar **values); -static void tips_parser_set_by_locale (TipsParser *parser, - gchar **dest); +static void tips_parser_start_markup (TipsParser *parser, + const gchar *markup_name); +static void tips_parser_end_markup (TipsParser *parser, + const gchar *markup_name); +static void tips_parser_start_unknown (TipsParser *parser); +static void tips_parser_end_unknown (TipsParser *parser); + +static gchar * tips_parser_parse_help_id (TipsParser *parser, + const gchar **names, + const gchar **values); + +static void tips_parser_parse_locale (TipsParser *parser, + const gchar **names, + const gchar **values); +static void tips_parser_set_by_locale (TipsParser *parser, + gchar **dest); static const GMarkupParser markup_parser = @@ -129,7 +135,7 @@ gimp_tip_new (const gchar *title, va_end (args); } - tip->thetip = g_string_free (str, FALSE); + tip->text = g_string_free (str, FALSE); return tip; } @@ -140,7 +146,9 @@ gimp_tip_free (GimpTip *tip) if (! tip) return; - g_free (tip->thetip); + g_free (tip->text); + g_free (tip->help_id); + g_slice_free (GimpTip, tip); } @@ -230,9 +238,13 @@ tips_parser_start_element (GMarkupParseContext *context, { case TIPS_START: if (strcmp (element_name, "gimp-tips") == 0) - parser->state = TIPS_IN_TIPS; + { + parser->state = TIPS_IN_TIPS; + } else - tips_parser_start_unknown (parser); + { + tips_parser_start_unknown (parser); + } break; case TIPS_IN_TIPS: @@ -240,9 +252,14 @@ tips_parser_start_element (GMarkupParseContext *context, { parser->state = TIPS_IN_TIP; parser->current_tip = g_slice_new0 (GimpTip); + parser->current_tip->help_id = tips_parser_parse_help_id (parser, + attribute_names, + attribute_values); } else - tips_parser_start_unknown (parser); + { + tips_parser_start_unknown (parser); + } break; case TIPS_IN_TIP: @@ -252,16 +269,22 @@ tips_parser_start_element (GMarkupParseContext *context, tips_parser_parse_locale (parser, attribute_names, attribute_values); } else - tips_parser_start_unknown (parser); + { + tips_parser_start_unknown (parser); + } break; case TIPS_IN_THETIP: if (strcmp (element_name, "b" ) == 0 || strcmp (element_name, "big") == 0 || strcmp (element_name, "tt" ) == 0) - tips_parser_start_markup (parser, element_name); + { + tips_parser_start_markup (parser, element_name); + } else - tips_parser_start_unknown (parser); + { + tips_parser_start_unknown (parser); + } break; case TIPS_IN_UNKNOWN: @@ -297,7 +320,7 @@ tips_parser_end_element (GMarkupParseContext *context, case TIPS_IN_THETIP: if (parser->markup_depth == 0) { - tips_parser_set_by_locale (parser, &parser->current_tip->thetip); + tips_parser_set_by_locale (parser, &parser->current_tip->text); g_string_truncate (parser->value, 0); parser->state = TIPS_IN_TIP; } @@ -387,6 +410,23 @@ tips_parser_end_unknown (TipsParser *parser) parser->state = parser->last_known_state; } +static gchar * +tips_parser_parse_help_id (TipsParser *parser, + const gchar **names, + const gchar **values) +{ + while (*names && *values) + { + if (strcmp (*names, "help") == 0 && **values) + return g_strdup (*values); + + names++; + values++; + } + + return NULL; +} + static void tips_parser_parse_locale (TipsParser *parser, const gchar **names, @@ -435,3 +475,4 @@ tips_parser_set_by_locale (TipsParser *parser, break; } } + diff --git a/app/dialogs/tips-parser.h b/app/dialogs/tips-parser.h index b77fb36235..7e44034bed 100644 --- a/app/dialogs/tips-parser.h +++ b/app/dialogs/tips-parser.h @@ -27,7 +27,8 @@ typedef struct _GimpTip GimpTip; struct _GimpTip { - gchar *thetip; + gchar *text; + gchar *help_id; }; diff --git a/data/tips/gimp-tips.dtd b/data/tips/gimp-tips.dtd index 700f8b7714..eb4f286908 100644 --- a/data/tips/gimp-tips.dtd +++ b/data/tips/gimp-tips.dtd @@ -4,6 +4,7 @@ + diff --git a/data/tips/gimp-tips.xml.in b/data/tips/gimp-tips.xml.in index a75841287d..7721f60ee9 100644 --- a/data/tips/gimp-tips.xml.in +++ b/data/tips/gimp-tips.xml.in @@ -20,20 +20,20 @@ pressing the F1 key at any time. This also works inside the menus. - + <_thetip> GIMP uses layers to let you organize your image. Think of them as a stack of slides or filters, such that looking through them you see a composite of their contents. - + <_thetip> You can perform many layer operations by right-clicking on the text label of a layer in the Layers dialog. - + <_thetip> When you save an image to work on it again later, try using XCF, GIMP's native file format (use the file extension .xcf). @@ -41,14 +41,14 @@ Once a project is completed, you can save it as JPEG, PNG, GIF, ... - + <_thetip> Most plug-ins work on the current layer of the current image. In some cases, you will have to merge all layers (Image→Flatten Image) if you want the plug-in to work on the whole image. - + <_thetip> If a layer's name in the Layers dialog is displayed in bold, this layer doesn't have an alpha-channel. You can add an alpha-channel @@ -91,14 +91,14 @@ (or optionally hold Spacebar while you move the mouse). - + <_thetip> Click and drag on a ruler to place a guide on an image. All dragged selections will snap to the guides. You can remove guides by dragging them off the image with the Move tool. - + <_thetip> You can drag a layer from the Layers dialog and drop it onto the toolbox. This will create a new image containing only that layer. @@ -128,28 +128,28 @@ current one. - + <_thetip> You can draw simple squares or circles using Edit→Stroke Selection. It strokes the edge of your current selection. More complex shapes can be drawn using the Path tool or with Filters→Render→Gfig. - + <_thetip> If you stroke a path (Edit→Stroke Path), the paint tools can be used with their current settings. You can use the Paintbrush in gradient mode or even the Eraser or the Smudge tool. - + <_thetip> You can create and edit complex selections using the Path tool. The Paths dialog allows you to work on multiple paths and to convert them to selections. - + <_thetip> You can use the paint tools to change the selection. Click on the "Quick Mask" button at the bottom left of an image window. @@ -157,7 +157,7 @@ again to convert it back to a normal selection. - + <_thetip> You can save a selection to a channel (Select→Save to Channel) and then modify this channel with any paint tools. Using the buttons in @@ -208,7 +208,7 @@ an image (if your window manager doesn't trap those keys...). - + <_thetip> Ctrl-click with the Bucket Fill tool to have it use the background color instead of the foreground color. @@ -216,7 +216,7 @@ sets the background color instead of the foreground color. - + <_thetip> Ctrl-drag with the Rotate tool will constrain the rotation to 15 degree angles.