diff options
author | Alexander Larsson <alexl@redhat.com> | 2009-06-17 12:56:05 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2009-06-17 12:56:05 +0200 |
commit | 7303f3c9fdc2fcb75907a3fd81cc4a44446931a7 (patch) | |
tree | 7607ea832b4c8ddb1f61240b7ca43299f9f67e6e /gtk | |
parent | c08bf93fe5fd0f7192aec9ad0358da246c211e0f (diff) | |
parent | 1a385c50f041cdcc8ee88b27af85094901c2b05d (diff) | |
download | gtk+-7303f3c9fdc2fcb75907a3fd81cc4a44446931a7.tar.gz |
Merge branch 'master' into client-side-windows
This updates client-side-windows to the the latest soname
change for easier testing.
Conflicts:
gdk/x11/gdkwindow-x11.c
tests/Makefile.am
Diffstat (limited to 'gtk')
48 files changed, 2980 insertions, 697 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index d80dc7f56a..6d7a03865d 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -230,6 +230,7 @@ gtk_public_h_sources = \ gtkimcontextsimple.h \ gtkimmodule.h \ gtkimmulticontext.h \ + gtkinfobar.h \ gtkinputdialog.h \ gtkinvisible.h \ gtkitem.h \ @@ -486,6 +487,7 @@ gtk_base_c_sources = \ gtkimcontextsimple.c \ gtkimmodule.c \ gtkimmulticontext.c \ + gtkinfobar.c \ gtkinputdialog.c \ gtkinvisible.c \ gtkitem.c \ @@ -110,6 +110,7 @@ #include <gtk/gtkimcontext.h> #include <gtk/gtkimcontextsimple.h> #include <gtk/gtkimmulticontext.h> +#include <gtk/gtkinfobar.h> #include <gtk/gtkinputdialog.h> #include <gtk/gtkinvisible.h> #include <gtk/gtkitem.h> diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index d9ddbf8691..ac4fa2cf72 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -690,7 +690,9 @@ gtk_cell_renderer_toggle_set_radio #if IN_HEADER(__GTK_CELL_VIEW_H__) #if IN_FILE(__GTK_CELL_VIEW_C__) +#ifndef GTK_DISABLE_DEPRECATED gtk_cell_view_get_cell_renderers +#endif gtk_cell_view_get_displayed_row gtk_cell_view_get_model gtk_cell_view_get_size_of_row @@ -2986,6 +2988,10 @@ gtk_print_operation_is_finished gtk_print_operation_cancel gtk_print_operation_draw_page_finish gtk_print_operation_set_defer_drawing +gtk_print_operation_set_support_selection +gtk_print_operation_get_support_selection +gtk_print_operation_set_has_selection +gtk_print_operation_get_has_selection #endif #endif @@ -3110,6 +3116,11 @@ gtk_print_unix_dialog_get_settings gtk_print_unix_dialog_get_selected_printer gtk_print_unix_dialog_add_custom_tab gtk_print_unix_dialog_set_manual_capabilities +gtk_print_unix_dialog_get_manual_capabilities +gtk_print_unix_dialog_set_support_selection +gtk_print_unix_dialog_get_support_selection +gtk_print_unix_dialog_set_has_selection +gtk_print_unix_dialog_get_has_selection #endif #endif #endif @@ -4593,7 +4604,9 @@ gtk_tree_view_column_clear_attributes gtk_tree_view_column_clicked gtk_tree_view_column_focus_cell gtk_tree_view_column_get_alignment +#ifndef GTK_DISABLE_DEPRECATED gtk_tree_view_column_get_cell_renderers +#endif gtk_tree_view_column_get_clickable gtk_tree_view_column_get_expand gtk_tree_view_column_get_fixed_width @@ -5155,6 +5168,24 @@ gtk_win32_embed_widget_get_type G_GNUC_CONST #endif #endif +#if IN_HEADER(__GTK_INFO_BAR_H__) +#if IN_FILE(__GTK_INFO_BAR_C__) +gtk_info_bar_get_type G_GNUC_CONST +gtk_info_bar_new +gtk_info_bar_new_with_buttons +gtk_info_bar_get_action_area +gtk_info_bar_get_content_area +gtk_info_bar_add_action_widget +gtk_info_bar_add_button +gtk_info_bar_add_buttons +gtk_info_bar_set_response_sensitive +gtk_info_bar_set_default_response +gtk_info_bar_response +gtk_info_bar_set_message_type +gtk_info_bar_get_message_type +#endif +#endif + #ifdef INCLUDE_VARIABLES gtk_binary_age gtk_interface_age diff --git a/gtk/gtkaboutdialog.c b/gtk/gtkaboutdialog.c index b073c98228..91d30fe344 100644 --- a/gtk/gtkaboutdialog.c +++ b/gtk/gtkaboutdialog.c @@ -2303,7 +2303,7 @@ gtk_about_dialog_set_email_hook (GtkAboutDialogActivateLinkFunc func, * Installs a global function to be called whenever the user activates a * URL link in an about dialog. * - * Since 2.18 here exists a default function which uses gtk_show_uri(). To + * Since 2.18 there exists a default function which uses gtk_show_uri(). To * deactivate it, you can pass %NULL for @func. * * Return value: the previous URL hook. diff --git a/gtk/gtkactivatable.c b/gtk/gtkactivatable.c index 8e1483726c..65c166b87e 100644 --- a/gtk/gtkactivatable.c +++ b/gtk/gtkactivatable.c @@ -449,7 +449,7 @@ gtk_activatable_do_set_related_action (GtkActivatable *activatable, /* Some apps are using the object data directly... * so continue to set it for a bit longer */ - g_object_set_data (activatable, "gtk-action", NULL); + g_object_set_data (G_OBJECT (activatable), "gtk-action", NULL); /* * We don't want prev_action to be activated @@ -478,7 +478,7 @@ gtk_activatable_do_set_related_action (GtkActivatable *activatable, _gtk_action_add_to_proxy_list (action, GTK_WIDGET (activatable)); - g_object_set_data (activatable, "gtk-action", action); + g_object_set_data (G_OBJECT (activatable), "gtk-action", action); } } } diff --git a/gtk/gtkassistant.c b/gtk/gtkassistant.c index 4e8f155aea..b7ed75641d 100644 --- a/gtk/gtkassistant.c +++ b/gtk/gtkassistant.c @@ -217,7 +217,7 @@ gtk_assistant_class_init (GtkAssistantClass *class) * @assistant: the #GtkAssistant * @page: the current page * - * The ::prepared signal is emitted when a new page is set as the assistant's + * The ::prepare signal is emitted when a new page is set as the assistant's * current page, before making the new page visible. A handler for this signal * can do any preparation which are necessary before showing @page. * @@ -237,14 +237,14 @@ gtk_assistant_class_init (GtkAssistantClass *class) * @assistant: the @GtkAssistant * * The ::apply signal is emitted when the apply button is clicked. The default - * behavior of the #GtkAssistant is to switch to the page after the current page, - * unless the current page is the last one. + * behavior of the #GtkAssistant is to switch to the page after the current + * page, unless the current page is the last one. * - * A handler for the ::apply signal should carry out the actions for which the - * wizard has collected data. If the action takes a long time to complete, you - * might consider to put a page of type GTK_ASSISTANT_PAGE_PROGRESS after the - * confirmation page and handle this operation within the ::prepare signal of - * the progress page. + * A handler for the ::apply signal should carry out the actions for which + * the wizard has collected data. If the action takes a long time to complete, + * you might consider to put a page of type %GTK_ASSISTANT_PAGE_PROGRESS + * after the confirmation page and handle this operation within the + * #GtkAssistant::prepare signal of the progress page. * * Since: 2.10 */ @@ -263,7 +263,7 @@ gtk_assistant_class_init (GtkAssistantClass *class) * * The ::close signal is emitted either when the close button of * a summary page is clicked, or when the apply button in the last - * page in the flow (of type GTK_ASSISTANT_PAGE_CONFIRM) is clicked. + * page in the flow (of type %GTK_ASSISTANT_PAGE_CONFIRM) is clicked. * * Since: 2.10 */ @@ -296,7 +296,7 @@ gtk_assistant_class_init (GtkAssistantClass *class) /** * GtkAssistant:page-type: * - * The type of the assistant page. + * The type of the assistant page. * * Since: 2.10 */ @@ -312,7 +312,7 @@ gtk_assistant_class_init (GtkAssistantClass *class) /** * GtkAssistant:title: * - * The title that is displayed in the page header. + * The title that is displayed in the page header. * * If title and header-image are both %NULL, no header is displayed. * @@ -346,7 +346,7 @@ gtk_assistant_class_init (GtkAssistantClass *class) /** * GtkAssistant:header-image: * - * The image that is displayed next to the page. + * The image that is displayed next to the page. * * Set this to %NULL to make the sidebar disappear. * @@ -430,14 +430,12 @@ compute_last_button_state (GtkAssistant *assistant) page_info = g_list_nth_data (priv->pages, page_num); count++; - - g_assert (page_info); } /* make the last button visible if we can skip multiple - * pages and end on a confirmation or summary page + * pages and end on a confirmation or summary page */ - if (count > 1 && + if (count > 1 && page_info && (page_info->type == GTK_ASSISTANT_PAGE_CONFIRM || page_info->type == GTK_ASSISTANT_PAGE_SUMMARY)) { @@ -2174,7 +2172,7 @@ gtk_assistant_set_page_complete (GtkAssistant *assistant, * @assistant: a #GtkAssistant * @page: a page of @assistant * - * Gets whether @page is complete.. + * Gets whether @page is complete. * * Return value: %TRUE if @page is complete. * @@ -2267,7 +2265,7 @@ gtk_assistant_accessible_ref_child (AtkObject *accessible, return NULL; else if (index < n_pages) { - GtkAssistantPage *page = g_list_nth_data (priv->pages, index / 2); + GtkAssistantPage *page = g_list_nth_data (priv->pages, index); child = page->page; title = gtk_assistant_get_page_title (assistant, child); diff --git a/gtk/gtkbbox.c b/gtk/gtkbbox.c index 609e45dc33..b2a0acf922 100644 --- a/gtk/gtkbbox.c +++ b/gtk/gtkbbox.c @@ -26,6 +26,7 @@ #include "config.h" #include "gtkbbox.h" +#include "gtkorientable.h" #include "gtkprivate.h" #include "gtkintl.h" #include "gtkalias.h" @@ -48,6 +49,10 @@ static void gtk_button_box_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void gtk_button_box_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_button_box_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); static void gtk_button_box_set_child_property (GtkContainer *container, GtkWidget *child, guint property_id, @@ -80,6 +85,9 @@ gtk_button_box_class_init (GtkButtonBoxClass *class) gobject_class->set_property = gtk_button_box_set_property; gobject_class->get_property = gtk_button_box_get_property; + widget_class->size_request = gtk_button_box_size_request; + widget_class->size_allocate = gtk_button_box_size_allocate; + container_class->set_child_property = gtk_button_box_set_child_property; container_class->get_child_property = gtk_button_box_get_child_property; @@ -471,5 +479,346 @@ _gtk_button_box_child_requisition (GtkWidget *widget, *height = needed_height; } +/* this is a kludge function to support the deprecated + * gtk_[vh]button_box_set_layout_default() just in case anyone is still + * using it (why?) + */ +static GtkButtonBoxStyle +gtk_button_box_kludge_get_layout_default (GtkButtonBox *widget) +{ + GtkOrientation orientation; + + orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + return gtk_hbutton_box_get_layout_default (); + else + return gtk_vbutton_box_get_layout_default (); +} + +static void +gtk_button_box_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkBox *box; + GtkButtonBox *bbox; + gint nvis_children; + gint child_width; + gint child_height; + gint spacing; + GtkButtonBoxStyle layout; + GtkOrientation orientation; + + box = GTK_BOX (widget); + bbox = GTK_BUTTON_BOX (widget); + + orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)); + spacing = box->spacing; + layout = bbox->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE + ? bbox->layout_style : gtk_button_box_kludge_get_layout_default (GTK_BUTTON_BOX (widget)); + + _gtk_button_box_child_requisition (widget, + &nvis_children, + NULL, + &child_width, + &child_height); + + if (nvis_children == 0) + { + requisition->width = 0; + requisition->height = 0; + } + else + { + switch (layout) + { + case GTK_BUTTONBOX_SPREAD: + if (orientation == GTK_ORIENTATION_HORIZONTAL) + requisition->width = + nvis_children*child_width + ((nvis_children+1)*spacing); + else + requisition->height = + nvis_children*child_height + ((nvis_children+1)*spacing); + + break; + case GTK_BUTTONBOX_EDGE: + case GTK_BUTTONBOX_START: + case GTK_BUTTONBOX_END: + case GTK_BUTTONBOX_CENTER: + if (orientation == GTK_ORIENTATION_HORIZONTAL) + requisition->width = + nvis_children*child_width + ((nvis_children-1)*spacing); + else + requisition->height = + nvis_children*child_height + ((nvis_children-1)*spacing); + + break; + default: + g_assert_not_reached (); + break; + } + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + requisition->height = child_height; + } + else + { + requisition->width = child_width; + } + } + + requisition->width += GTK_CONTAINER (box)->border_width * 2; + requisition->height += GTK_CONTAINER (box)->border_width * 2; +} + +static void +gtk_button_box_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkBox *base_box; + GtkButtonBox *box; + GtkBoxChild *child; + GList *children; + GtkAllocation child_allocation; + gint nvis_children; + gint n_secondaries; + gint child_width; + gint child_height; + gint x = 0; + gint y = 0; + gint secondary_x = 0; + gint secondary_y = 0; + gint width; + gint height; + gint childspace; + gint childspacing = 0; + GtkButtonBoxStyle layout; + gint spacing; + GtkOrientation orientation; + + orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)); + base_box = GTK_BOX (widget); + box = GTK_BUTTON_BOX (widget); + spacing = base_box->spacing; + layout = box->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE + ? box->layout_style : gtk_button_box_kludge_get_layout_default (GTK_BUTTON_BOX (widget)); + _gtk_button_box_child_requisition (widget, + &nvis_children, + &n_secondaries, + &child_width, + &child_height); + widget->allocation = *allocation; + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + width = allocation->width - GTK_CONTAINER (box)->border_width*2; + else + height = allocation->height - GTK_CONTAINER (box)->border_width*2; + + switch (layout) + { + case GTK_BUTTONBOX_SPREAD: + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + childspacing = (width - (nvis_children * child_width)) + / (nvis_children + 1); + x = allocation->x + GTK_CONTAINER (box)->border_width + + childspacing; + secondary_x = x + ((nvis_children - n_secondaries) + * (child_width + childspacing)); + } + else + { + childspacing = (height - (nvis_children * child_height)) + / (nvis_children + 1); + y = allocation->y + GTK_CONTAINER (box)->border_width + + childspacing; + secondary_y = y + ((nvis_children - n_secondaries) + * (child_height + childspacing)); + } + + break; + + case GTK_BUTTONBOX_EDGE: + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (nvis_children >= 2) + { + childspacing = (width - (nvis_children * child_width)) + / (nvis_children - 1); + x = allocation->x + GTK_CONTAINER (box)->border_width; + secondary_x = x + ((nvis_children - n_secondaries) + * (child_width + childspacing)); + } + else + { + /* one or zero children, just center */ + childspacing = width; + x = secondary_x = allocation->x + + (allocation->width - child_width) / 2; + } + } + else + { + if (nvis_children >= 2) + { + childspacing = (height - (nvis_children*child_height)) + / (nvis_children-1); + y = allocation->y + GTK_CONTAINER (box)->border_width; + secondary_y = y + ((nvis_children - n_secondaries) + * (child_height + childspacing)); + } + else + { + /* one or zero children, just center */ + childspacing = height; + y = secondary_y = allocation->y + + (allocation->height - child_height) / 2; + } + } + + break; + + case GTK_BUTTONBOX_START: + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + childspacing = spacing; + x = allocation->x + GTK_CONTAINER (box)->border_width; + secondary_x = allocation->x + allocation->width + - child_width * n_secondaries + - spacing * (n_secondaries - 1) + - GTK_CONTAINER (box)->border_width; + } + else + { + childspacing = spacing; + y = allocation->y + GTK_CONTAINER (box)->border_width; + secondary_y = allocation->y + allocation->height + - child_height * n_secondaries + - spacing * (n_secondaries - 1) + - GTK_CONTAINER (box)->border_width; + } + + break; + + case GTK_BUTTONBOX_END: + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + childspacing = spacing; + x = allocation->x + allocation->width + - child_width * (nvis_children - n_secondaries) + - spacing * (nvis_children - n_secondaries - 1) + - GTK_CONTAINER (box)->border_width; + secondary_x = allocation->x + GTK_CONTAINER (box)->border_width; + } + else + { + childspacing = spacing; + y = allocation->y + allocation->height + - child_height * (nvis_children - n_secondaries) + - spacing * (nvis_children - n_secondaries - 1) + - GTK_CONTAINER (box)->border_width; + secondary_y = allocation->y + GTK_CONTAINER (box)->border_width; + } + + break; + + case GTK_BUTTONBOX_CENTER: + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + childspacing = spacing; + x = allocation->x + + (allocation->width + - (child_width * (nvis_children - n_secondaries) + + spacing * (nvis_children - n_secondaries - 1)))/2 + + (n_secondaries * child_width + n_secondaries * spacing)/2; + secondary_x = allocation->x + GTK_CONTAINER (box)->border_width; + } + else + { + childspacing = spacing; + y = allocation->y + + (allocation->height + - (child_height * (nvis_children - n_secondaries) + + spacing * (nvis_children - n_secondaries - 1)))/2 + + (n_secondaries * child_height + n_secondaries * spacing)/2; + secondary_y = allocation->y + GTK_CONTAINER (box)->border_width; + } + + break; + + default: + g_assert_not_reached(); + break; + } + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + y = allocation->y + (allocation->height - child_height) / 2; + childspace = child_width + childspacing; + } + else + { + x = allocation->x + (allocation->width - child_width) / 2; + childspace = child_height + childspacing; + } + + children = GTK_BOX (box)->children; + + while (children) + { + child = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (child->widget)) + { + child_allocation.width = child_width; + child_allocation.height = child_height; + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + child_allocation.y = y; + + if (child->is_secondary) + { + child_allocation.x = secondary_x; + secondary_x += childspace; + } + else + { + child_allocation.x = x; + x += childspace; + } + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) + child_allocation.x = (allocation->x + allocation->width) + - (child_allocation.x + child_width - allocation->x); + } + else + { + child_allocation.x = x; + + if (child->is_secondary) + { + child_allocation.y = secondary_y; + secondary_y += childspace; + } + else + { + child_allocation.y = y; + y += childspace; + } + } + + gtk_widget_size_allocate (child->widget, &child_allocation); + } + } +} + #define __GTK_BUTTON_BOX_C__ #include "gtkaliasdef.c" diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c index c5cb2d8938..f6f12a5bf6 100644 --- a/gtk/gtkbuilderparser.c +++ b/gtk/gtkbuilderparser.c @@ -893,40 +893,6 @@ start_element (GMarkupParseContext *context, element_name); } -/* This function is taken from gettext.h - * GNU gettext uses '\004' to separate context and msgid in .mo files. - */ -static const char * -_dpgettext (const char *domain, - const char *msgctxt, - const char *msgid) -{ - size_t msgctxt_len = strlen (msgctxt) + 1; - size_t msgid_len = strlen (msgid) + 1; - const char *translation; - char* msg_ctxt_id; - - msg_ctxt_id = g_alloca (msgctxt_len + msgid_len); - - memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); - msg_ctxt_id[msgctxt_len - 1] = '\004'; - memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); - - translation = g_dgettext (domain, msg_ctxt_id); - - if (translation == msg_ctxt_id) - { - /* try the old way of doing message contexts, too */ - msg_ctxt_id[msgctxt_len - 1] = '|'; - translation = g_dgettext (domain, msg_ctxt_id); - - if (translation == msg_ctxt_id) - return msgid; - } - - return translation; -} - gchar * _gtk_builder_parser_translate (const gchar *domain, const gchar *context, @@ -935,7 +901,7 @@ _gtk_builder_parser_translate (const gchar *domain, const char *s; if (context) - s = _dpgettext (domain, context, text); + s = g_dpgettext2 (domain, context, text); else s = g_dgettext (domain, text); diff --git a/gtk/gtkcellrendererpixbuf.c b/gtk/gtkcellrendererpixbuf.c index 0431295e41..c0ec609688 100644 --- a/gtk/gtkcellrendererpixbuf.c +++ b/gtk/gtkcellrendererpixbuf.c @@ -284,39 +284,6 @@ gtk_cell_renderer_pixbuf_get_property (GObject *object, } static void -unset_image_properties (GtkCellRendererPixbuf *cell) -{ - GtkCellRendererPixbufPrivate *priv; - - priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (cell); - - if (priv->stock_id) - { - g_free (priv->stock_id); - priv->stock_id = NULL; - g_object_notify (G_OBJECT (cell), "stock-id"); - } - if (priv->icon_name) - { - g_free (priv->icon_name); - priv->icon_name = NULL; - g_object_notify (G_OBJECT (cell), "icon-name"); - } - if (cell->pixbuf) - { - g_object_unref (cell->pixbuf); - cell->pixbuf = NULL; - g_object_notify (G_OBJECT (cell), "pixbuf"); - } - if (priv->gicon) - { - g_object_unref (priv->gicon); - priv->gicon = NULL; - g_object_notify (G_OBJECT (cell), "gicon"); - } -} - -static void gtk_cell_renderer_pixbuf_set_property (GObject *object, guint param_id, const GValue *value, @@ -330,8 +297,30 @@ gtk_cell_renderer_pixbuf_set_property (GObject *object, switch (param_id) { case PROP_PIXBUF: - unset_image_properties (cellpixbuf); - cellpixbuf->pixbuf = (GdkPixbuf *) g_value_dup_object (value); + if (cellpixbuf->pixbuf) + g_object_unref (cellpixbuf->pixbuf); + cellpixbuf->pixbuf = (GdkPixbuf*) g_value_dup_object (value); + if (cellpixbuf->pixbuf) + { + if (priv->stock_id) + { + g_free (priv->stock_id); + priv->stock_id = NULL; + g_object_notify (object, "stock-id"); + } + if (priv->icon_name) + { + g_free (priv->icon_name); + priv->icon_name = NULL; + g_object_notify (object, "icon-name"); + } + if (priv->gicon) + { + g_object_unref (priv->gicon); + priv->gicon = NULL; + g_object_notify (object, "gicon"); + } + } break; case PROP_PIXBUF_EXPANDER_OPEN: if (cellpixbuf->pixbuf_expander_open) @@ -344,8 +333,38 @@ gtk_cell_renderer_pixbuf_set_property (GObject *object, cellpixbuf->pixbuf_expander_closed = (GdkPixbuf*) g_value_dup_object (value); break; case PROP_STOCK_ID: - unset_image_properties (cellpixbuf); + if (priv->stock_id) + { + if (cellpixbuf->pixbuf) + { + g_object_unref (cellpixbuf->pixbuf); + cellpixbuf->pixbuf = NULL; + g_object_notify (object, "pixbuf"); + } + g_free (priv->stock_id); + } priv->stock_id = g_value_dup_string (value); + if (priv->stock_id) + { + if (cellpixbuf->pixbuf) + { + g_object_unref (cellpixbuf->pixbuf); + cellpixbuf->pixbuf = NULL; + g_object_notify (object, "pixbuf"); + } + if (priv->icon_name) + { + g_free (priv->icon_name); + priv->icon_name = NULL; + g_object_notify (object, "icon-name"); + } + if (priv->gicon) + { + g_object_unref (priv->gicon); + priv->gicon = NULL; + g_object_notify (object, "gicon"); + } + } break; case PROP_STOCK_SIZE: priv->stock_size = g_value_get_uint (value); @@ -355,15 +374,75 @@ gtk_cell_renderer_pixbuf_set_property (GObject *object, priv->stock_detail = g_value_dup_string (value); break; case PROP_ICON_NAME: - unset_image_properties (cellpixbuf); + if (priv->icon_name) + { + if (cellpixbuf->pixbuf) + { + g_object_unref (cellpixbuf->pixbuf); + cellpixbuf->pixbuf = NULL; + g_object_notify (object, "pixbuf"); + } + g_free (priv->icon_name); + } priv->icon_name = g_value_dup_string (value); + if (priv->icon_name) + { + if (cellpixbuf->pixbuf) + { + g_object_unref (cellpixbuf->pixbuf); + cellpixbuf->pixbuf = NULL; + g_object_notify (object, "pixbuf"); + } + if (priv->stock_id) + { + g_free (priv->stock_id); + priv->stock_id = NULL; + g_object_notify (object, "stock-id"); + } + if (priv->gicon) + { + g_object_unref (priv->gicon); + priv->gicon = NULL; + g_object_notify (object, "gicon"); + } + } break; case PROP_FOLLOW_STATE: priv->follow_state = g_value_get_boolean (value); break; case PROP_GICON: - unset_image_properties (cellpixbuf); + if (priv->gicon) + { + if (cellpixbuf->pixbuf) + { + g_object_unref (cellpixbuf->pixbuf); + cellpixbuf->pixbuf = NULL; + g_object_notify (object, "pixbuf"); + } + g_object_unref (priv->gicon); + } priv->gicon = (GIcon *) g_value_dup_object (value); + if (priv->gicon) + { + if (cellpixbuf->pixbuf) + { + g_object_unref (cellpixbuf->pixbuf); + cellpixbuf->pixbuf = NULL; + g_object_notify (object, "pixbuf"); + } + if (priv->stock_id) + { + g_free (priv->stock_id); + priv->stock_id = NULL; + g_object_notify (object, "stock-id"); + } + if (priv->icon_name) + { + g_free (priv->icon_name); + priv->icon_name = NULL; + g_object_notify (object, "icon-name"); + } + } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); diff --git a/gtk/gtkcellview.c b/gtk/gtkcellview.c index 43cdce1cc1..6add539de8 100644 --- a/gtk/gtkcellview.c +++ b/gtk/gtkcellview.c @@ -1053,7 +1053,9 @@ gtk_cell_view_set_background_color (GtkCellView *cell_view, * g_list_free() when no longer needed. * * Since: 2.6 - */ + * + * Deprecated: 2.18: use gtk_cell_layout_get_cells() instead. + **/ GList * gtk_cell_view_get_cell_renderers (GtkCellView *cell_view) { diff --git a/gtk/gtkcellview.h b/gtk/gtkcellview.h index c07f24960c..73de84e191 100644 --- a/gtk/gtkcellview.h +++ b/gtk/gtkcellview.h @@ -72,7 +72,9 @@ gboolean gtk_cell_view_get_size_of_row (GtkCellView *cell_v void gtk_cell_view_set_background_color (GtkCellView *cell_view, const GdkColor *color); +#ifndef GTK_DISABLE_DEPRECATED GList *gtk_cell_view_get_cell_renderers (GtkCellView *cell_view); +#endif G_END_DECLS diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c index 1628789a55..3e6fbefc18 100644 --- a/gtk/gtkcombobox.c +++ b/gtk/gtkcombobox.c @@ -1701,7 +1701,7 @@ cell_view_is_sensitive (GtkCellView *cell_view) GList *cells, *list; gboolean sensitive; - cells = gtk_cell_view_get_cell_renderers (cell_view); + cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cell_view)); sensitive = FALSE; for (list = cells; list; list = list->next) @@ -1738,7 +1738,7 @@ tree_column_row_is_sensitive (GtkComboBox *combo_box, priv->model, iter, FALSE, FALSE); - cells = gtk_tree_view_column_get_cell_renderers (priv->column); + cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->column)); sensitive = FALSE; for (list = cells; list; list = list->next) @@ -4103,7 +4103,7 @@ gtk_combo_box_list_select_func (GtkTreeSelection *selection, gtk_tree_view_column_cell_set_cell_data (column, model, &iter, FALSE, FALSE); - cell = cells = gtk_tree_view_column_get_cell_renderers (column); + cell = cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column)); while (cell) { g_object_get (cell->data, diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index b8e5fbc09f..8bbb4d24da 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -33,6 +33,12 @@ #include "gdk/gdkkeysyms.h" +#ifdef GDK_WINDOWING_X11 +#include <X11/Xlib.h> +#include <X11/keysym.h> +#include "gdk/x11/gdkx.h" +#endif + #include "gtkdnd.h" #include "gtkiconfactory.h" #include "gtkicontheme.h" @@ -393,6 +399,139 @@ gtk_drag_get_ipc_widget (GtkWidget *widget) } +#ifdef GDK_WINDOWING_X11 + +/* + * We want to handle a handful of keys during DND, e.g. Escape to abort. + * Grabbing the keyboard has the unfortunate side-effect of preventing + * useful things such as using Alt-Tab to cycle between windows or + * switching workspaces. Therefore, we just grab the few keys we are + * interested in. Note that we need to put the grabs on the root window + * in order for them to still work when the focus is moved to another + * app/workspace. + * + * GDK needs a little help to successfully deliver root key events... + */ + +static GdkFilterReturn +root_key_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data) +{ + XEvent *ev = (XEvent *)xevent; + + if ((ev->type == KeyPress || ev->type == KeyRelease) && + ev->xkey.root == ev->xkey.window) + ev->xkey.window = (Window)data; + + return GDK_FILTER_CONTINUE; +} + +typedef struct { + gint keysym; + gint modifiers; +} GrabKey; + +static GrabKey grab_keys[] = { + { XK_Escape, 0 }, + { XK_space, 0 }, + { XK_KP_Space, 0 }, + { XK_Return, 0 }, + { XK_KP_Enter, 0 }, + { XK_Up, 0 }, + { XK_Up, Mod1Mask }, + { XK_Down, 0 }, + { XK_Down, Mod1Mask }, + { XK_Left, 0 }, + { XK_Left, Mod1Mask }, + { XK_Right, 0 }, + { XK_Right, Mod1Mask }, + { XK_KP_Up, 0 }, + { XK_KP_Up, Mod1Mask }, + { XK_KP_Down, 0 }, + { XK_KP_Down, Mod1Mask }, + { XK_KP_Left, 0 }, + { XK_KP_Left, Mod1Mask }, + { XK_KP_Right, 0 }, + { XK_KP_Right, Mod1Mask } +}; + +static void +grab_dnd_keys (GtkWidget *widget, + guint32 time) +{ + guint i; + GdkWindow *window, *root; + gint keycode; + + window = widget->window; + root = gdk_screen_get_root_window (gtk_widget_get_screen (widget)); + + gdk_error_trap_push (); + + for (i = 0; i < G_N_ELEMENTS (grab_keys); ++i) + { + keycode = XKeysymToKeycode (GDK_WINDOW_XDISPLAY (window), grab_keys[i].keysym); + XGrabKey (GDK_WINDOW_XDISPLAY (window), + keycode, grab_keys[i].modifiers, + GDK_WINDOW_XID (root), + FALSE, + GrabModeAsync, + GrabModeAsync); + } + + gdk_flush (); + gdk_error_trap_pop (); + + gdk_window_add_filter (NULL, root_key_filter, (gpointer) GDK_WINDOW_XID (window)); +} + +static void +ungrab_dnd_keys (GtkWidget *widget, + guint32 time) +{ + guint i; + GdkWindow *window, *root; + gint keycode; + + window = widget->window; + root = gdk_screen_get_root_window (gtk_widget_get_screen (widget)); + + gdk_window_remove_filter (NULL, root_key_filter, (gpointer) GDK_WINDOW_XID (window)); + + gdk_error_trap_push (); + + for (i = 0; i < G_N_ELEMENTS (grab_keys); ++i) + { + keycode = XKeysymToKeycode (GDK_WINDOW_XDISPLAY (window), grab_keys[i].keysym); + XUngrabKey (GDK_WINDOW_XDISPLAY (window), + keycode, grab_keys[i].modifiers, + GDK_WINDOW_XID (root)); + } + + gdk_flush (); + gdk_error_trap_pop (); +} + +#else + +static void +grab_dnd_keys (GtkWidget *widget, + guint32 time) +{ + gdk_keyboard_grab (widget->window, FALSE, time); +} + +static void +ungrab_dnd_keys (GtkWidget *widget, + guint32 time) +{ + gdk_display_keyboard_ungrab (gtk_widget_get_display (widget), time); +} + +#endif + + /*************************************************************** * gtk_drag_release_ipc_widget: * Releases widget retrieved with gtk_drag_get_ipc_widget () @@ -408,6 +547,7 @@ gtk_drag_release_ipc_widget (GtkWidget *widget) GdkScreen *screen = gtk_widget_get_screen (widget); GSList *drag_widgets = g_object_get_data (G_OBJECT (screen), "gtk-dnd-ipc-widgets"); + ungrab_dnd_keys (widget, GDK_CURRENT_TIME); if (window->group) gtk_window_group_remove_window (window->group, window); drag_widgets = g_slist_prepend (drag_widgets, widget); @@ -2224,8 +2364,8 @@ gtk_drag_begin_internal (GtkWidget *widget, return NULL; } - gdk_keyboard_grab (ipc_widget->window, FALSE, time); - + grab_dnd_keys (ipc_widget, time); + /* We use a GTK grab here to override any grabs that the widget * we are dragging from might have held */ @@ -3965,7 +4105,7 @@ gtk_drag_end (GtkDragSourceInfo *info, guint32 time) info); gdk_display_pointer_ungrab (display, time); - gdk_display_keyboard_ungrab (display, time); + ungrab_dnd_keys (info->ipc_widget, time); gtk_grab_remove (info->ipc_widget); /* Send on a release pair to the original diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index a21e94f57f..5473143f72 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -6448,6 +6448,11 @@ gtk_entry_ensure_pixbuf (GtkEntry *entry, icon_info->stock_id, GTK_ICON_SIZE_MENU, NULL); + if (!icon_info->pixbuf) + icon_info->pixbuf = gtk_widget_render_icon (GTK_WIDGET (entry), + GTK_STOCK_MISSING_IMAGE, + GTK_ICON_SIZE_MENU, + NULL); GTK_WIDGET_STATE (entry) = state; break; diff --git a/gtk/gtkentrycompletion.c b/gtk/gtkentrycompletion.c index 820449dc1a..a3a01be9ff 100644 --- a/gtk/gtkentrycompletion.c +++ b/gtk/gtkentrycompletion.c @@ -758,7 +758,7 @@ gtk_entry_completion_get_cells (GtkCellLayout *cell_layout) priv = GTK_ENTRY_COMPLETION_GET_PRIVATE (cell_layout); - return gtk_tree_view_column_get_cell_renderers (priv->column); + return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->column)); } /* all those callbacks */ @@ -1426,9 +1426,6 @@ _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion) gtk_tree_view_columns_autosize (GTK_TREE_VIEW (completion->priv->tree_view)); gtk_widget_set_size_request (completion->priv->tree_view, width, items * height); - /* default on no match */ - completion->priv->current_selected = -1; - if (actions) { gtk_widget_show (completion->priv->action_view); @@ -1489,7 +1486,7 @@ _gtk_entry_completion_popup (GtkEntryCompletion *completion) completion->priv->ignore_enter = TRUE; column = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0); - renderers = gtk_tree_view_column_get_cell_renderers (column); + renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column)); gtk_widget_ensure_style (completion->priv->tree_view); g_object_set (GTK_CELL_RENDERER (renderers->data), "cell-background-gdk", &completion->priv->tree_view->style->bg[GTK_STATE_NORMAL], @@ -1498,6 +1495,9 @@ _gtk_entry_completion_popup (GtkEntryCompletion *completion) gtk_widget_show_all (completion->priv->vbox); + /* default on no match */ + completion->priv->current_selected = -1; + _gtk_entry_completion_resize_popup (completion); toplevel = gtk_widget_get_toplevel (completion->priv->entry); diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h index 9262aeaf78..2dc9f8fcdc 100644 --- a/gtk/gtkenums.h +++ b/gtk/gtkenums.h @@ -208,6 +208,15 @@ typedef enum typedef enum { + GTK_MESSAGE_INFO, + GTK_MESSAGE_WARNING, + GTK_MESSAGE_QUESTION, + GTK_MESSAGE_ERROR, + GTK_MESSAGE_OTHER +} GtkMessageType; + +typedef enum +{ GTK_PIXELS, GTK_INCHES, GTK_CENTIMETERS @@ -485,7 +494,8 @@ typedef enum { GTK_PRINT_PAGES_ALL, GTK_PRINT_PAGES_CURRENT, - GTK_PRINT_PAGES_RANGES + GTK_PRINT_PAGES_RANGES, + GTK_PRINT_PAGES_SELECTION } GtkPrintPages; typedef enum diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index 5f40411551..7dc98676e4 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -145,6 +145,8 @@ typedef struct _GtkFileChooserDefaultClass GtkFileChooserDefaultClass; #define MAX_LOADING_TIME 500 +#define DEFAULT_NEW_FOLDER_NAME _("Type name of new folder") + struct _GtkFileChooserDefaultClass { GtkVBoxClass parent_class; @@ -189,14 +191,6 @@ typedef enum { SHORTCUT_TYPE_RECENT } ShortcutType; -/* Column numbers for the file list */ -enum { - FILE_LIST_COL_NAME, - FILE_LIST_COL_SIZE, - FILE_LIST_COL_MTIME, - FILE_LIST_COL_NUM_COLUMNS -}; - /* Column numbers for the search model. * Keep this in sync with search_setup_model() */ @@ -804,6 +798,8 @@ _gtk_file_chooser_default_init (GtkFileChooserDefault *impl) impl->pending_select_files = NULL; impl->location_mode = LOCATION_MODE_PATH_BAR; impl->operation_mode = OPERATION_MODE_BROWSE; + impl->sort_column = FILE_LIST_COL_NAME; + impl->sort_order = GTK_SORT_ASCENDING; impl->recent_manager = gtk_recent_manager_get_default (); gtk_box_set_spacing (GTK_BOX (impl), 12); @@ -960,6 +956,9 @@ gtk_file_chooser_default_finalize (GObject *object) if (impl->preview_file) g_object_unref (impl->preview_file); + if (impl->browse_path_bar_size_group) + g_object_unref (impl->browse_path_bar_size_group); + load_remove_timer (impl); /* Free all the Models we have */ @@ -1743,7 +1742,7 @@ shortcuts_insert_file (GtkFileChooserDefault *impl, gtk_tree_path_free (p); cancellable = _gtk_file_system_get_info (request->impl->file_system, request->file, - "standard::is-hidden,standard::display-name,standard::icon", + "standard::is-hidden,standard::is-backup,standard::display-name,standard::icon", get_file_info_finished, request); gtk_list_store_set (impl->shortcuts_model, &iter, @@ -2418,7 +2417,9 @@ edited_idle_cb (GtkFileChooserDefault *impl) gtk_widget_set_sensitive (impl->browse_new_folder_button, TRUE); - if (impl->edited_new_text) /* not cancelled? */ + if (impl->edited_new_text /* not cancelled? */ + && (strlen (impl->edited_new_text) != 0) + && (strcmp (impl->edited_new_text, DEFAULT_NEW_FOLDER_NAME) != 0)) /* Don't create folder if name is empty or has not been edited */ { GError *error = NULL; GFile *file; @@ -3706,7 +3707,7 @@ rename_selected_bookmark (GtkFileChooserDefault *impl) { path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter); column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), 0); - renderers = gtk_tree_view_column_get_cell_renderers (column); + renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column)); cell = g_list_nth_data (renderers, 1); g_list_free (renderers); g_object_set (cell, "editable", TRUE, NULL); @@ -4453,35 +4454,70 @@ list_button_press_event_cb (GtkWidget *widget, return TRUE; } +typedef struct { + OperationMode operation_mode; + gint general_column; + gint model_column; +} ColumnMap; + +/* Sigh. Each operation mode has different sort column IDs. This table + * translates between them. + */ +static const ColumnMap column_map[] = { + { OPERATION_MODE_BROWSE, FILE_LIST_COL_NAME, FILE_LIST_COL_NAME }, + { OPERATION_MODE_BROWSE, FILE_LIST_COL_SIZE, FILE_LIST_COL_SIZE }, + { OPERATION_MODE_BROWSE, FILE_LIST_COL_MTIME, FILE_LIST_COL_MTIME }, + + { OPERATION_MODE_SEARCH, FILE_LIST_COL_NAME, SEARCH_MODEL_COL_FILE }, + { OPERATION_MODE_SEARCH, FILE_LIST_COL_SIZE, SEARCH_MODEL_COL_SIZE }, + { OPERATION_MODE_SEARCH, FILE_LIST_COL_MTIME, SEARCH_MODEL_COL_MTIME }, + + { OPERATION_MODE_RECENT, FILE_LIST_COL_NAME, RECENT_MODEL_COL_FILE }, + { OPERATION_MODE_RECENT, FILE_LIST_COL_SIZE, 0 }, + { OPERATION_MODE_RECENT, FILE_LIST_COL_MTIME, RECENT_MODEL_COL_INFO } +}; + +static gint +general_column_to_model_column (GtkFileChooserDefault *impl, gint general_column) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (column_map); i++) + if (column_map[i].operation_mode == impl->operation_mode + && column_map[i].general_column == general_column) + return column_map[i].model_column; + + g_assert_not_reached (); + return 0; +} + +static gint +model_column_to_general_column (GtkFileChooserDefault *impl, gint model_column) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (column_map); i++) + if (column_map[i].operation_mode == impl->operation_mode + && column_map[i].model_column == model_column) + return column_map[i].general_column; + + g_assert_not_reached (); + return 0; +} + /* Sets the sort column IDs for the file list based on the operation mode */ static void file_list_set_sort_column_ids (GtkFileChooserDefault *impl) { int name_id, mtime_id, size_id; - name_id = mtime_id = size_id = 0; - - switch (impl->operation_mode) - { - case OPERATION_MODE_BROWSE: - name_id = FILE_LIST_COL_NAME; - mtime_id = FILE_LIST_COL_MTIME; - size_id = FILE_LIST_COL_SIZE; - break; - case OPERATION_MODE_SEARCH: - name_id = SEARCH_MODEL_COL_FILE; - mtime_id = SEARCH_MODEL_COL_MTIME; - size_id = SEARCH_MODEL_COL_SIZE; - break; - case OPERATION_MODE_RECENT: - name_id = RECENT_MODEL_COL_FILE; - mtime_id = RECENT_MODEL_COL_INFO; - break; - } + name_id = general_column_to_model_column (impl, FILE_LIST_COL_NAME); + mtime_id = general_column_to_model_column (impl, FILE_LIST_COL_MTIME); + size_id = general_column_to_model_column (impl, FILE_LIST_COL_SIZE); - gtk_tree_view_column_set_sort_column_id (impl->list_name_column, name_id); + gtk_tree_view_column_set_sort_column_id (impl->list_name_column, name_id); gtk_tree_view_column_set_sort_column_id (impl->list_mtime_column, mtime_id); - gtk_tree_view_column_set_sort_column_id (impl->list_size_column, size_id); + gtk_tree_view_column_set_sort_column_id (impl->list_size_column, size_id); } static gboolean @@ -4634,7 +4670,6 @@ create_file_list (GtkFileChooserDefault *impl) gtk_tree_view_column_set_expand (impl->list_name_column, TRUE); gtk_tree_view_column_set_resizable (impl->list_name_column, TRUE); gtk_tree_view_column_set_title (impl->list_name_column, _("Name")); - gtk_tree_view_column_set_sort_column_id (impl->list_name_column, FILE_LIST_COL_NAME); renderer = gtk_cell_renderer_pixbuf_new (); gtk_tree_view_column_pack_start (impl->list_name_column, renderer, FALSE); @@ -4664,7 +4699,6 @@ create_file_list (GtkFileChooserDefault *impl) gtk_tree_view_column_pack_start (column, renderer, TRUE); /* bug: it doesn't expand */ gtk_tree_view_column_set_cell_data_func (column, renderer, list_size_data_func, impl, NULL); - gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_SIZE); gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), column); impl->list_size_column = column; @@ -4852,6 +4886,7 @@ save_folder_combo_create (GtkFileChooserDefault *impl) NULL); cell = gtk_cell_renderer_text_new (); + g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell, "text", SHORTCUTS_COL_NAME, @@ -5201,6 +5236,8 @@ location_button_create (GtkFileChooserDefault *impl) impl->location_button = g_object_new (GTK_TYPE_TOGGLE_BUTTON, "image", image, NULL); + + gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->location_button); g_signal_connect (impl->location_button, "toggled", G_CALLBACK (location_button_toggled_cb), impl); @@ -5216,7 +5253,6 @@ static GtkWidget * browse_widgets_create (GtkFileChooserDefault *impl) { GtkWidget *vbox; - GtkWidget *hbox; GtkWidget *hpaned; GtkWidget *widget; GtkSizeGroup *size_group; @@ -5226,26 +5262,31 @@ browse_widgets_create (GtkFileChooserDefault *impl) vbox = gtk_vbox_new (FALSE, 12); /* Location widgets */ - hbox = gtk_hbox_new (FALSE, 12); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - impl->browse_path_bar_hbox = hbox; + impl->browse_path_bar_hbox = gtk_hbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (vbox), impl->browse_path_bar_hbox, FALSE, FALSE, 0); + gtk_widget_show (impl->browse_path_bar_hbox); + + /* Size group that allows the path bar to be the same size between modes */ + impl->browse_path_bar_size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); + gtk_size_group_set_ignore_hidden (impl->browse_path_bar_size_group, FALSE); + + /* Location button */ location_button_create (impl); - gtk_box_pack_start (GTK_BOX (hbox), impl->location_button, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->location_button, FALSE, FALSE, 0); /* Path bar */ impl->browse_path_bar = create_path_bar (impl); g_signal_connect (impl->browse_path_bar, "path-clicked", G_CALLBACK (path_bar_clicked), impl); gtk_widget_show_all (impl->browse_path_bar); - gtk_box_pack_start (GTK_BOX (hbox), impl->browse_path_bar, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_path_bar, TRUE, TRUE, 0); /* Create Folder */ impl->browse_new_folder_button = gtk_button_new_with_mnemonic (_("Create Fo_lder")); g_signal_connect (impl->browse_new_folder_button, "clicked", G_CALLBACK (new_folder_button_clicked), impl); - gtk_box_pack_end (GTK_BOX (hbox), impl->browse_new_folder_button, FALSE, FALSE, 0); + gtk_box_pack_end (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_new_folder_button, FALSE, FALSE, 0); /* Box for the location label and entry */ @@ -6009,6 +6050,35 @@ get_is_file_filtered (GtkFileChooserDefault *impl, } static void +set_sort_column (GtkFileChooserDefault *impl) +{ + GtkTreeSortable *sortable; + + switch (impl->operation_mode) + { + case OPERATION_MODE_BROWSE: + sortable = GTK_TREE_SORTABLE (impl->sort_model); + break; + + case OPERATION_MODE_SEARCH: + sortable = GTK_TREE_SORTABLE (impl->search_model_sort); + break; + + case OPERATION_MODE_RECENT: + sortable = GTK_TREE_SORTABLE (impl->recent_model_sort); + break; + + default: + g_assert_not_reached (); + return; + } + + gtk_tree_sortable_set_sort_column_id (sortable, + general_column_to_model_column (impl, impl->sort_column), + impl->sort_order); +} + +static void settings_load (GtkFileChooserDefault *impl) { GtkFileChooserSettings *settings; @@ -6016,6 +6086,8 @@ settings_load (GtkFileChooserDefault *impl) gboolean show_hidden; gboolean expand_folders; gboolean show_size_column; + gint sort_column; + GtkSortType sort_order; settings = _gtk_file_chooser_settings_new (); @@ -6023,6 +6095,8 @@ settings_load (GtkFileChooserDefault *impl) show_hidden = _gtk_file_chooser_settings_get_show_hidden (settings); expand_folders = _gtk_file_chooser_settings_get_expand_folders (settings); show_size_column = _gtk_file_chooser_settings_get_show_size_column (settings); + sort_column = _gtk_file_chooser_settings_get_sort_column (settings); + sort_order = _gtk_file_chooser_settings_get_sort_order (settings); g_object_unref (settings); @@ -6037,6 +6111,10 @@ settings_load (GtkFileChooserDefault *impl) impl->show_size_column = show_size_column; if (impl->list_size_column) gtk_tree_view_column_set_visible (impl->list_size_column, show_size_column); + + impl->sort_column = sort_column; + impl->sort_order = sort_order; + set_sort_column (impl); } static void @@ -6075,6 +6153,8 @@ settings_save (GtkFileChooserDefault *impl) _gtk_file_chooser_settings_set_show_hidden (settings, gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl))); _gtk_file_chooser_settings_set_expand_folders (settings, impl->expand_folders); _gtk_file_chooser_settings_set_show_size_column (settings, impl->show_size_column); + _gtk_file_chooser_settings_set_sort_column (settings, impl->sort_column); + _gtk_file_chooser_settings_set_sort_order (settings, impl->sort_order); save_dialog_geometry (impl, settings); @@ -6089,7 +6169,6 @@ static void gtk_file_chooser_default_realize (GtkWidget *widget) { GtkFileChooserDefault *impl; - char *current_working_dir; impl = GTK_FILE_CHOOSER_DEFAULT (widget); @@ -6296,10 +6375,15 @@ static void list_sort_column_changed_cb (GtkTreeSortable *sortable, GtkFileChooserDefault *impl) { + gint sort_column_id; GtkSortType sort_type; - if (gtk_tree_sortable_get_sort_column_id (sortable, NULL, &sort_type)) - impl->list_sort_ascending = (sort_type == GTK_SORT_ASCENDING); + if (gtk_tree_sortable_get_sort_column_id (sortable, &sort_column_id, &sort_type)) + { + impl->list_sort_ascending = (sort_type == GTK_SORT_ASCENDING); + impl->sort_column = model_column_to_general_column (impl, sort_column_id); + impl->sort_order = sort_type; + } } static void @@ -6343,7 +6427,7 @@ load_set_model (GtkFileChooserDefault *impl) gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->sort_model), FILE_LIST_COL_SIZE, size_sort_func, impl, NULL); gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->sort_model), FILE_LIST_COL_MTIME, mtime_sort_func, impl, NULL); gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (impl->sort_model), NULL, NULL, NULL); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->sort_model), FILE_LIST_COL_NAME, GTK_SORT_ASCENDING); + set_sort_column (impl); impl->list_sort_ascending = TRUE; profile_msg (" gtk_tree_model_sort_new_with_model end", NULL); @@ -6501,7 +6585,8 @@ show_and_select_files_finished_loading (GtkFolder *folder, if (info) { if (!have_hidden) - have_hidden = g_file_info_get_is_hidden (info); + have_hidden = g_file_info_get_is_hidden (info) + || g_file_info_get_is_backup (info); if (!have_filtered) have_filtered = (! _gtk_file_info_consider_as_directory (info)) && @@ -6604,7 +6689,7 @@ show_and_select_files (GtkFileChooserDefault *impl, impl->show_and_select_files_cancellable = _gtk_file_system_get_folder (impl->file_system, parent_file, - "standard::is-hidden,standard::type,standard::name,standard::content-type", + "standard::is-hidden,standard::is-backup,standard::type,standard::name,standard::content-type", show_and_select_files_get_folder_cb, info); profile_end ("end", NULL); @@ -7035,13 +7120,14 @@ update_current_folder_get_info_cb (GCancellable *cancellable, } else { - /* Error and bail out, ignoring "not found" errors since they're useless: + /* Error and bail out, ignoring "not found" errors since they're useless: * they only happen when a program defaults to a folder that has been (re)moved. */ if (!g_error_matches (data->original_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - error_changing_folder_dialog (impl, data->original_file, data->original_error); + error_changing_folder_dialog (impl, data->original_file, data->original_error); else g_error_free (data->original_error); + g_object_unref (data->original_file); goto out; @@ -7050,7 +7136,13 @@ update_current_folder_get_info_cb (GCancellable *cancellable, if (data->original_file) { - error_changing_folder_dialog (impl, data->original_file, data->original_error); + /* Error and bail out, ignoring "not found" errors since they're useless: + * they only happen when a program defaults to a folder that has been (re)moved. + */ + if (!g_error_matches (data->original_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + error_changing_folder_dialog (impl, data->original_file, data->original_error); + else + g_error_free (data->original_error); g_object_unref (data->original_file); } @@ -9290,9 +9382,7 @@ search_setup_model (GtkFileChooserDefault *impl) SEARCH_MODEL_COL_SIZE, search_column_size_sort_func, impl, NULL); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->search_model_sort), - SEARCH_MODEL_COL_MTIME, - GTK_SORT_DESCENDING); + set_sort_column (impl); /* EB: setting the model here will make the hits list update feel * more "alive" than setting the model at the end of the search @@ -9393,12 +9483,20 @@ static void search_setup_widgets (GtkFileChooserDefault *impl) { GtkWidget *label; + GtkWidget *image; impl->search_hbox = gtk_hbox_new (FALSE, 12); + + /* Image */ + + image = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON); + gtk_size_group_add_widget (GTK_SIZE_GROUP (impl->browse_path_bar_size_group), image); + gtk_box_pack_start (GTK_BOX (impl->search_hbox), image, FALSE, FALSE, 5); /* Label */ - label = gtk_label_new_with_mnemonic (_("_Search:")); + label = gtk_label_new (NULL); + gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("<b>_Search:</b>")); gtk_box_pack_start (GTK_BOX (impl->search_hbox), label, FALSE, FALSE, 0); /* Entry */ @@ -9450,6 +9548,35 @@ search_setup_widgets (GtkFileChooserDefault *impl) /* FMQ: hide the filter combo? */ } +/* Stops running operations like populating the browse model, searches, and the recent-files model */ +static void +stop_operation (GtkFileChooserDefault *impl, OperationMode mode) +{ + switch (mode) + { + case OPERATION_MODE_BROWSE: + stop_loading_and_clear_list_model (impl); + break; + + case OPERATION_MODE_SEARCH: + search_stop_searching (impl, FALSE); + search_clear_model (impl, TRUE); + + gtk_widget_destroy (impl->search_hbox); + impl->search_hbox = NULL; + impl->search_entry = NULL; + break; + + case OPERATION_MODE_RECENT: + recent_stop_loading (impl); + recent_clear_model (impl, TRUE); + + gtk_widget_destroy (impl->recent_hbox); + impl->recent_hbox = NULL; + break; + } +} + /* Main entry point to the searching functions; this gets called when the user * activates the Search shortcut. */ @@ -9467,21 +9594,7 @@ search_activate (GtkFileChooserDefault *impl) previous_mode = impl->operation_mode; impl->operation_mode = OPERATION_MODE_SEARCH; - switch (previous_mode) - { - case OPERATION_MODE_RECENT: - recent_stop_loading (impl); - recent_clear_model (impl, TRUE); - break; - - case OPERATION_MODE_BROWSE: - stop_loading_and_clear_list_model (impl); - break; - - case OPERATION_MODE_SEARCH: - g_assert_not_reached (); - break; - } + stop_operation (impl, previous_mode); g_assert (impl->search_hbox == NULL); g_assert (impl->search_entry == NULL); @@ -9572,6 +9685,9 @@ recent_switch_to_browse_mode (GtkFileChooserDefault *impl) recent_stop_loading (impl); recent_clear_model (impl, TRUE); + gtk_widget_destroy (impl->recent_hbox); + impl->recent_hbox = NULL; + gtk_widget_show (impl->browse_path_bar); gtk_widget_show (impl->browse_new_folder_button); @@ -9797,9 +9913,7 @@ recent_setup_model (GtkFileChooserDefault *impl) RECENT_MODEL_COL_INFO, recent_column_mtime_sort_func, impl, NULL); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->recent_model_sort), - RECENT_MODEL_COL_INFO, - GTK_SORT_DESCENDING); + set_sort_column (impl); } typedef struct @@ -10103,9 +10217,29 @@ recent_should_respond (GtkFileChooserDefault *impl) static void recent_hide_entry (GtkFileChooserDefault *impl) { + GtkWidget *label; + GtkWidget *image; + + impl->recent_hbox = gtk_hbox_new (FALSE, 12); + + /* Image */ + image = gtk_image_new_from_icon_name ("document-open-recent", GTK_ICON_SIZE_BUTTON); + gtk_size_group_add_widget (impl->browse_path_bar_size_group, image); + gtk_box_pack_start (GTK_BOX (impl->recent_hbox), image, FALSE, FALSE, 5); + + /* Label */ + label = gtk_label_new (NULL); + gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("<b>Recently Used</b>")); + gtk_box_pack_start (GTK_BOX (impl->recent_hbox), label, FALSE, FALSE, 0); + gtk_widget_hide (impl->browse_path_bar); gtk_widget_hide (impl->browse_new_folder_button); + /* Box for recent widgets */ + gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->recent_hbox, TRUE, TRUE, 0); + gtk_widget_show_all (impl->recent_hbox); + + /* Hide the location widgets temporarily */ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) { @@ -10128,25 +10262,7 @@ recent_activate (GtkFileChooserDefault *impl) previous_mode = impl->operation_mode; impl->operation_mode = OPERATION_MODE_RECENT; - switch (previous_mode) - { - case OPERATION_MODE_SEARCH: - search_stop_searching (impl, FALSE); - search_clear_model (impl, TRUE); - - gtk_widget_destroy (impl->search_hbox); - impl->search_hbox = NULL; - impl->search_entry = NULL; - break; - - case OPERATION_MODE_BROWSE: - stop_loading_and_clear_list_model (impl); - break; - - case OPERATION_MODE_RECENT: - g_assert_not_reached (); - break; - } + stop_operation (impl, previous_mode); recent_hide_entry (impl); @@ -10403,7 +10519,7 @@ shortcuts_activate_volume (GtkFileChooserDefault *impl, if (!_gtk_file_system_volume_is_mounted (volume)) { - GtkMountOperation *mount_op; + GMountOperation *mount_op; set_busy_cursor (impl, TRUE); @@ -11026,7 +11142,7 @@ list_name_data_func (GtkTreeViewColumn *tree_column, if (!info) { g_object_set (cell, - "text", _("Type name of new folder"), + "text", DEFAULT_NEW_FOLDER_NAME, "sensitive", TRUE, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL); diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h index ee561a1569..400a211270 100644 --- a/gtk/gtkfilechooserprivate.h +++ b/gtk/gtkfilechooserprivate.h @@ -28,6 +28,7 @@ #include "gtkrecentmanager.h" #include "gtksearchengine.h" #include "gtkquery.h" +#include "gtksizegroup.h" #include "gtktreemodelsort.h" #include "gtktreestore.h" #include "gtktreeview.h" @@ -181,6 +182,7 @@ struct _GtkFileChooserDefault GtkWidget *browse_files_popup_menu_size_column_item; GtkWidget *browse_new_folder_button; GtkWidget *browse_path_bar_hbox; + GtkSizeGroup *browse_path_bar_size_group; GtkWidget *browse_path_bar; GtkFileSystemModel *browse_files_model; @@ -196,6 +198,7 @@ struct _GtkFileChooserDefault GtkTreeModelSort *search_model_sort; /* OPERATION_MODE_RECENT */ + GtkWidget *recent_hbox; GtkRecentManager *recent_manager; GtkListStore *recent_model; guint load_recent_id; @@ -279,6 +282,9 @@ struct _GtkFileChooserDefault gulong toplevel_set_focus_id; GtkWidget *toplevel_last_focus_widget; + gint sort_column; + GtkSortType sort_order; + #if 0 GdkDragContext *shortcuts_drag_context; GSource *shortcuts_drag_outside_idle; diff --git a/gtk/gtkfilechoosersettings.c b/gtk/gtkfilechoosersettings.c index fe3543d2c4..1553c36fd4 100644 --- a/gtk/gtkfilechoosersettings.c +++ b/gtk/gtkfilechoosersettings.c @@ -46,6 +46,14 @@ #define GEOMETRY_Y_KEY "GeometryY" #define GEOMETRY_WIDTH_KEY "GeometryWidth" #define GEOMETRY_HEIGHT_KEY "GeometryHeight" +#define SORT_COLUMN_KEY "SortColumn" +#define SORT_ORDER_KEY "SortOrder" + +#define COLUMN_NAME_STRING "name" +#define COLUMN_MTIME_STRING "modified" +#define COLUMN_SIZE_STRING "size" +#define SORT_ASCENDING_STRING "ascending" +#define SORT_DESCENDING_STRING "descending" #define MODE_PATH_BAR "path-bar" #define MODE_FILENAME_ENTRY "filename-entry" @@ -104,6 +112,7 @@ ensure_settings_read (GtkFileChooserSettings *settings) GError *error; GKeyFile *key_file; gchar *location_mode_str, *filename; + gchar *sort_column, *sort_order; gboolean value; if (settings->settings_read) @@ -129,6 +138,8 @@ ensure_settings_read (GtkFileChooserSettings *settings) if (!g_key_file_has_group (key_file, SETTINGS_GROUP)) goto out; + /* Location mode */ + location_mode_str = g_key_file_get_string (key_file, SETTINGS_GROUP, LOCATION_MODE_KEY, NULL); if (location_mode_str) @@ -144,6 +155,8 @@ ensure_settings_read (GtkFileChooserSettings *settings) g_free (location_mode_str); } + /* Show hidden */ + value = g_key_file_get_boolean (key_file, SETTINGS_GROUP, SHOW_HIDDEN_KEY, &error); if (error) @@ -151,6 +164,8 @@ ensure_settings_read (GtkFileChooserSettings *settings) else settings->show_hidden = value != FALSE; + /* Expand folders */ + value = g_key_file_get_boolean (key_file, SETTINGS_GROUP, EXPAND_FOLDERS_KEY, &error); if (error) @@ -158,6 +173,8 @@ ensure_settings_read (GtkFileChooserSettings *settings) else settings->expand_folders = value != FALSE; + /* Show size column */ + value = g_key_file_get_boolean (key_file, SETTINGS_GROUP, SHOW_SIZE_COLUMN_KEY, &error); if (error) @@ -165,11 +182,49 @@ ensure_settings_read (GtkFileChooserSettings *settings) else settings->show_size_column = value != FALSE; + /* Geometry */ + get_int_key (key_file, SETTINGS_GROUP, GEOMETRY_X_KEY, &settings->geometry_x); get_int_key (key_file, SETTINGS_GROUP, GEOMETRY_Y_KEY, &settings->geometry_y); get_int_key (key_file, SETTINGS_GROUP, GEOMETRY_WIDTH_KEY, &settings->geometry_width); get_int_key (key_file, SETTINGS_GROUP, GEOMETRY_HEIGHT_KEY, &settings->geometry_height); + /* Sort column */ + + sort_column = g_key_file_get_string (key_file, SETTINGS_GROUP, + SORT_COLUMN_KEY, NULL); + if (sort_column) + { + if (EQ (COLUMN_NAME_STRING, sort_column)) + settings->sort_column = FILE_LIST_COL_NAME; + else if (EQ (COLUMN_MTIME_STRING, sort_column)) + settings->sort_column = FILE_LIST_COL_MTIME; + else if (EQ (COLUMN_SIZE_STRING, sort_column)) + settings->sort_column = FILE_LIST_COL_SIZE; + else + g_warning ("Unknown sort column name '%s' encountered in filechooser settings", + sort_column); + + g_free (sort_column); + } + + /* Sort order */ + + sort_order = g_key_file_get_string (key_file, SETTINGS_GROUP, + SORT_ORDER_KEY, NULL); + if (sort_order) + { + if (EQ (SORT_ASCENDING_STRING, sort_order)) + settings->sort_order = GTK_SORT_ASCENDING; + else if (EQ (SORT_DESCENDING_STRING, sort_order)) + settings->sort_order = GTK_SORT_DESCENDING; + else + g_warning ("Unknown sort column order '%s' encountered in filechooser settings", + sort_order); + + g_free (sort_order); + } + out: g_key_file_free (key_file); @@ -189,6 +244,8 @@ static void _gtk_file_chooser_settings_init (GtkFileChooserSettings *settings) { settings->location_mode = LOCATION_MODE_PATH_BAR; + settings->sort_order = GTK_SORT_ASCENDING; + settings->sort_column = FILE_LIST_COL_NAME; settings->show_hidden = FALSE; settings->expand_folders = FALSE; settings->show_size_column = FALSE; @@ -288,6 +345,34 @@ _gtk_file_chooser_settings_set_geometry (GtkFileChooserSettings *settings, settings->geometry_height = height; } +gint +_gtk_file_chooser_settings_get_sort_column (GtkFileChooserSettings *settings) +{ + ensure_settings_read (settings); + return settings->sort_column; +} + +void +_gtk_file_chooser_settings_set_sort_column (GtkFileChooserSettings *settings, + gint sort_column) +{ + settings->sort_column = sort_column; +} + +GtkSortType +_gtk_file_chooser_settings_get_sort_order (GtkFileChooserSettings *settings) +{ + ensure_settings_read (settings); + return settings->sort_order; +} + +void +_gtk_file_chooser_settings_set_sort_order (GtkFileChooserSettings *settings, + GtkSortType sort_order) +{ + settings->sort_order = sort_order; +} + gboolean _gtk_file_chooser_settings_save (GtkFileChooserSettings *settings, GError **error) @@ -296,6 +381,8 @@ _gtk_file_chooser_settings_save (GtkFileChooserSettings *settings, gchar *filename; gchar *dirname; gchar *contents; + gchar *sort_column; + gchar *sort_order; gsize len; gboolean retval; GKeyFile *key_file; @@ -317,6 +404,40 @@ _gtk_file_chooser_settings_save (GtkFileChooserSettings *settings, return FALSE; } + switch (settings->sort_column) + { + case FILE_LIST_COL_NAME: + sort_column = COLUMN_NAME_STRING; + break; + + case FILE_LIST_COL_MTIME: + sort_column = COLUMN_MTIME_STRING; + break; + + case FILE_LIST_COL_SIZE: + sort_column = COLUMN_SIZE_STRING; + break; + + default: + g_assert_not_reached (); + sort_column = NULL; + } + + switch (settings->sort_order) + { + case GTK_SORT_ASCENDING: + sort_order = SORT_ASCENDING_STRING; + break; + + case GTK_SORT_DESCENDING: + sort_order = SORT_DESCENDING_STRING; + break; + + default: + g_assert_not_reached (); + sort_order = NULL; + } + key_file = g_key_file_new (); /* Initialise with the on-disk keyfile, so we keep unknown options */ @@ -338,6 +459,10 @@ _gtk_file_chooser_settings_save (GtkFileChooserSettings *settings, GEOMETRY_WIDTH_KEY, settings->geometry_width); g_key_file_set_integer (key_file, SETTINGS_GROUP, GEOMETRY_HEIGHT_KEY, settings->geometry_height); + g_key_file_set_string (key_file, SETTINGS_GROUP, + SORT_COLUMN_KEY, sort_column); + g_key_file_set_string (key_file, SETTINGS_GROUP, + SORT_ORDER_KEY, sort_order); contents = g_key_file_to_data (key_file, &len, error); g_key_file_free (key_file); diff --git a/gtk/gtkfilechoosersettings.h b/gtk/gtkfilechoosersettings.h index 1bc45aa253..5fd7ad2e5a 100644 --- a/gtk/gtkfilechoosersettings.h +++ b/gtk/gtkfilechoosersettings.h @@ -29,6 +29,14 @@ G_BEGIN_DECLS #define GTK_FILE_CHOOSER_SETTINGS_TYPE (_gtk_file_chooser_settings_get_type ()) +/* Column numbers for the file list */ +enum { + FILE_LIST_COL_NAME, + FILE_LIST_COL_SIZE, + FILE_LIST_COL_MTIME, + FILE_LIST_COL_NUM_COLUMNS +}; + typedef struct _GtkFileChooserSettings GtkFileChooserSettings; typedef struct _GtkFileChooserSettingsClass GtkFileChooserSettingsClass; @@ -38,6 +46,9 @@ struct _GtkFileChooserSettings LocationMode location_mode; + GtkSortType sort_order; + gint sort_column; + int geometry_x; int geometry_y; int geometry_width; @@ -74,6 +85,14 @@ gboolean _gtk_file_chooser_settings_get_show_size_column (GtkFileChooserSettings void _gtk_file_chooser_settings_set_show_size_column (GtkFileChooserSettings *settings, gboolean show_column); +gint _gtk_file_chooser_settings_get_sort_column (GtkFileChooserSettings *settings); +void _gtk_file_chooser_settings_set_sort_column (GtkFileChooserSettings *settings, + gint sort_column); + +GtkSortType _gtk_file_chooser_settings_get_sort_order (GtkFileChooserSettings *settings); +void _gtk_file_chooser_settings_set_sort_order (GtkFileChooserSettings *settings, + GtkSortType sort_order); + void _gtk_file_chooser_settings_get_geometry (GtkFileChooserSettings *settings, int *out_x, int *out_y, diff --git a/gtk/gtkfilesystemmodel.c b/gtk/gtkfilesystemmodel.c index 79eb10c25b..1d0b736d07 100644 --- a/gtk/gtkfilesystemmodel.c +++ b/gtk/gtkfilesystemmodel.c @@ -1336,7 +1336,8 @@ file_model_node_is_visible (GtkFileSystemModel *model, model->show_folders != is_folder) return FALSE; - if (!model->show_hidden && g_file_info_get_is_hidden (info)) + if (!model->show_hidden && + (g_file_info_get_is_hidden (info) || g_file_info_get_is_backup (info))) return FALSE; if (model->filter_func && diff --git a/gtk/gtkfontsel.c b/gtk/gtkfontsel.c index 84ee9dc85a..c3593c88b8 100644 --- a/gtk/gtkfontsel.c +++ b/gtk/gtkfontsel.c @@ -90,7 +90,7 @@ /* These are what we use as the standard font sizes, for the size list. */ static const guint16 font_sizes[] = { - 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28, 32, 36, 40, 48, 56, 64, 72 }; diff --git a/gtk/gtkhandlebox.c b/gtk/gtkhandlebox.c index 2215689567..46e9592bf2 100644 --- a/gtk/gtkhandlebox.c +++ b/gtk/gtkhandlebox.c @@ -1079,7 +1079,8 @@ gtk_handle_box_button_press (GtkWidget *widget, gint root_x, root_y; gint width, height; - gtk_invisible_set_screen (GTK_INVISIBLE (invisible), gtk_widget_get_screen (hb)); + gtk_invisible_set_screen (GTK_INVISIBLE (invisible), + gtk_widget_get_screen (GTK_WIDGET (hb))); gdk_window_get_deskrelative_origin (hb->bin_window, &desk_x, &desk_y); gdk_window_get_origin (hb->bin_window, &root_x, &root_y); gdk_drawable_get_size (hb->bin_window, &width, &height); diff --git a/gtk/gtkhbbox.c b/gtk/gtkhbbox.c index d7835faaa9..d852daf0a2 100644 --- a/gtk/gtkhbbox.c +++ b/gtk/gtkhbbox.c @@ -26,15 +26,11 @@ #include "config.h" #include "gtkhbbox.h" +#include "gtkorientable.h" #include "gtkintl.h" #include "gtkalias.h" -static void gtk_hbutton_box_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_hbutton_box_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); - static gint default_spacing = 30; static gint default_layout_style = GTK_BUTTONBOX_EDGE; @@ -43,18 +39,13 @@ G_DEFINE_TYPE (GtkHButtonBox, gtk_hbutton_box, GTK_TYPE_BUTTON_BOX) static void gtk_hbutton_box_class_init (GtkHButtonBoxClass *class) { - GtkWidgetClass *widget_class; - - widget_class = (GtkWidgetClass*) class; - - widget_class->size_request = gtk_hbutton_box_size_request; - widget_class->size_allocate = gtk_hbutton_box_size_allocate; } static void gtk_hbutton_box_init (GtkHButtonBox *hbutton_box) { - /* button_box_init has done everything already */ + gtk_orientable_set_orientation (GTK_ORIENTABLE (hbutton_box), + GTK_ORIENTATION_HORIZONTAL); } GtkWidget* @@ -105,186 +96,5 @@ gtk_hbutton_box_get_layout_default (void) return default_layout_style; } - - -static void -gtk_hbutton_box_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - GtkBox *box; - GtkButtonBox *bbox; - gint nvis_children; - gint child_width; - gint child_height; - gint spacing; - GtkButtonBoxStyle layout; - - box = GTK_BOX (widget); - bbox = GTK_BUTTON_BOX (widget); - - spacing = box->spacing; - layout = bbox->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE - ? bbox->layout_style : default_layout_style; - - _gtk_button_box_child_requisition (widget, - &nvis_children, - NULL, - &child_width, - &child_height); - - if (nvis_children == 0) - { - requisition->width = 0; - requisition->height = 0; - } - else - { - switch (layout) - { - case GTK_BUTTONBOX_SPREAD: - requisition->width = - nvis_children*child_width + ((nvis_children+1)*spacing); - break; - case GTK_BUTTONBOX_EDGE: - case GTK_BUTTONBOX_START: - case GTK_BUTTONBOX_END: - case GTK_BUTTONBOX_CENTER: - requisition->width = nvis_children*child_width + ((nvis_children-1)*spacing); - break; - default: - g_assert_not_reached(); - break; - } - - requisition->height = child_height; - } - - requisition->width += GTK_CONTAINER (box)->border_width * 2; - requisition->height += GTK_CONTAINER (box)->border_width * 2; -} - - - -static void -gtk_hbutton_box_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GtkBox *base_box; - GtkButtonBox *box; - GtkBoxChild *child; - GList *children; - GtkAllocation child_allocation; - gint nvis_children; - gint n_secondaries; - gint child_width; - gint child_height; - gint x = 0; - gint secondary_x = 0; - gint y = 0; - gint width; - gint childspace; - gint childspacing = 0; - GtkButtonBoxStyle layout; - gint spacing; - - base_box = GTK_BOX (widget); - box = GTK_BUTTON_BOX (widget); - spacing = base_box->spacing; - layout = box->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE - ? box->layout_style : default_layout_style; - _gtk_button_box_child_requisition (widget, - &nvis_children, - &n_secondaries, - &child_width, - &child_height); - widget->allocation = *allocation; - width = allocation->width - GTK_CONTAINER (box)->border_width*2; - switch (layout) - { - case GTK_BUTTONBOX_SPREAD: - childspacing = (width - (nvis_children * child_width)) / (nvis_children + 1); - x = allocation->x + GTK_CONTAINER (box)->border_width + childspacing; - secondary_x = x + ((nvis_children - n_secondaries) * (child_width + childspacing)); - break; - case GTK_BUTTONBOX_EDGE: - if (nvis_children >= 2) - { - childspacing = (width - (nvis_children * child_width)) / (nvis_children - 1); - x = allocation->x + GTK_CONTAINER (box)->border_width; - secondary_x = x + ((nvis_children - n_secondaries) * (child_width + childspacing)); - } - else - { - /* one or zero children, just center */ - childspacing = width; - x = secondary_x = allocation->x + (allocation->width - child_width) / 2; - } - break; - case GTK_BUTTONBOX_START: - childspacing = spacing; - x = allocation->x + GTK_CONTAINER (box)->border_width; - secondary_x = allocation->x + allocation->width - - child_width * n_secondaries - - spacing * (n_secondaries - 1) - - GTK_CONTAINER (box)->border_width; - break; - case GTK_BUTTONBOX_END: - childspacing = spacing; - x = allocation->x + allocation->width - - child_width * (nvis_children - n_secondaries) - - spacing * (nvis_children - n_secondaries - 1) - - GTK_CONTAINER (box)->border_width; - secondary_x = allocation->x + GTK_CONTAINER (box)->border_width; - break; - case GTK_BUTTONBOX_CENTER: - childspacing = spacing; - x = allocation->x + - (allocation->width - - (child_width * (nvis_children - n_secondaries) - + spacing * (nvis_children - n_secondaries - 1)))/2 - + (n_secondaries * child_width + n_secondaries * spacing)/2; - secondary_x = allocation->x + GTK_CONTAINER (box)->border_width; - break; - default: - g_assert_not_reached(); - break; - } - - - y = allocation->y + (allocation->height - child_height) / 2; - childspace = child_width + childspacing; - - children = GTK_BOX (box)->children; - - while (children) - { - child = children->data; - children = children->next; - - if (GTK_WIDGET_VISIBLE (child->widget)) - { - child_allocation.width = child_width; - child_allocation.height = child_height; - child_allocation.y = y; - - if (child->is_secondary) - { - child_allocation.x = secondary_x; - secondary_x += childspace; - } - else - { - child_allocation.x = x; - x += childspace; - } - - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) - child_allocation.x = (allocation->x + allocation->width) - (child_allocation.x + child_width - allocation->x); - - gtk_widget_size_allocate (child->widget, &child_allocation); - } - } -} - #define __GTK_HBUTTON_BOX_C__ #include "gtkaliasdef.c" diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index 3a413f0ed2..afbc229222 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -9014,12 +9014,14 @@ gtk_icon_view_accessible_model_row_changed (GtkTreeModel *tree_model, GtkIconViewItem *item; GtkIconViewAccessible *a11y_view; GtkIconViewItemAccessible *a11y_item; - gchar *name, *text; + const gchar *name; + gchar *text; atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data)); a11y_view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj); index = gtk_tree_path_get_indices(path)[0]; - a11y_item = gtk_icon_view_accessible_find_child (atk_obj, index); + a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE ( + gtk_icon_view_accessible_find_child (atk_obj, index)); if (a11y_item) { diff --git a/gtk/gtkinfobar.c b/gtk/gtkinfobar.c new file mode 100644 index 0000000000..c96bd84b52 --- /dev/null +++ b/gtk/gtkinfobar.c @@ -0,0 +1,1263 @@ +/* + * gtkinfobar.c + * This file is part of GTK+ + * + * Copyright (C) 2005 - Paolo Maggi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +/* + * Modified by the gedit Team, 2005. See the AUTHORS file for a + * list of people on the gtk Team. + * See the gedit ChangeLog files for a list of changes. + * + * Modified by the GTK+ team, 2008-2009. + */ + + +#include "config.h" + +#include <stdlib.h> + +#include "gtkinfobar.h" +#include "gtkaccessible.h" +#include "gtkbuildable.h" +#include "gtkbox.h" +#include "gtkvbbox.h" +#include "gtklabel.h" +#include "gtkbutton.h" +#include "gtkenums.h" +#include "gtkbindings.h" +#include "gtkdialog.h" +#include "gtkintl.h" +#include "gtkprivate.h" +#include "gtkstock.h" +#include "gdkkeysyms.h" +#include "gtkalias.h" + + +/** + * SECTION:gtkinfobar + * @short_description: Report important messages to the user + * @include: gtk/gtk.h + * @see_also: #GtkStatusbar, #GtkMessageDialog + * + * #GtkInfoBar is a widget that can be used to show messages to + * the user without showing a dialog. It is often temporarily shown + * at the top or bottom of a document. In contrast to #GtkDialog, which + * has a horizontal action area at the bottom, #GtkInfoBar has a + * vertical action area at the side. + * + * The API of #GtkInfoBar is very similar to #GtkDialog, allowing you + * to add buttons to the action area with gtk_info_bar_add_button() or + * gtk_info_bar_new_with_buttons(). The sensitivity of action widgets + * can be controlled with gtk_info_bar_set_response_sensitive(). + * To add widgets to the main content area of a #GtkInfoBar, use + * gtk_info_bar_get_content_area() and add your widgets to the container. + * + * Similar to #GtkMessageDialog, the contents of a #GtkInfoBar can by + * classified as error message, warning, informational message, etc, + * by using gtk_info_bar_set_message_type(). GTK+ uses the message type + * to determine the background color of the message area. + * + * <example> + * <title>Simple GtkInfoBar usage.</title> + * <programlisting> + * /* set up info bar */ + * info_bar = gtk_info_bar_new (); + * gtk_widget_set_no_show_all (info_bar, TRUE); + * message_label = gtk_label_new (""); + * gtk_widget_show (message_label); + * content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar)); + * gtk_container_add (GTK_CONTAINER (content_area), message_label); + * gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), + * GTK_STOCK_OK, GTK_RESPONSE_OK); + * g_signal_connect (info_bar, "response", + * G_CALLBACK (gtk_widget_hide), NULL); + * gtk_table_attach (GTK_TABLE (table), + * info_bar, + * 0, 1, 2, 3, + * GTK_EXPAND | GTK_FILL, 0, + * 0, 0); + * + * /* ... */ + * + * /* show an error message */ + * gtk_label_set_text (GTK_LABEL (message_label), error_message); + * gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), + * GTK_MESSAGE_ERROR); + * gtk_widget_show (info_bar); + * </programlisting> + * </example> + * + * <refsect2 id="GtkInfoBar-BUILDER-UI"> + * <title>GtkInfoBar as GtkBuildable</title> + * <para> + * The GtkInfoBar implementation of the GtkBuildable interface exposes + * the content area and action area as internal children with the names + * "content_area" and "action_area". + * </para> + * <para> + * GtkInfoBar supports a custom <action-widgets> element, which + * can contain multiple <action-widget> elements. The "response" + * attribute specifies a numeric response, and the content of the element + * is the id of widget (which should be a child of the dialogs @action_area). + * </para> + * </refsect2> + */ + +#define GTK_INFO_BAR_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), \ + GTK_TYPE_INFO_BAR, \ + GtkInfoBarPrivate)) + +enum +{ + PROP_0, + PROP_MESSAGE_TYPE +}; + +struct _GtkInfoBarPrivate +{ + GtkWidget *content_area; + GtkWidget *action_area; + + GtkMessageType message_type; +}; + +typedef struct _ResponseData ResponseData; + +struct _ResponseData +{ + gint response_id; +}; + +enum +{ + RESPONSE, + CLOSE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + + +static void gtk_info_bar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_info_bar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void gtk_info_bar_style_set (GtkWidget *widget, + GtkStyle *prev_style); +static gboolean gtk_info_bar_expose (GtkWidget *widget, + GdkEventExpose *event); +static void gtk_info_bar_buildable_interface_init (GtkBuildableIface *iface); +static GObject *gtk_info_bar_buildable_get_internal_child (GtkBuildable *buildable, + GtkBuilder *builder, + const gchar *childname); +static gboolean gtk_info_bar_buildable_custom_tag_start (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + GMarkupParser *parser, + gpointer *data); +static void gtk_info_bar_buildable_custom_finished (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + gpointer user_data); + + +G_DEFINE_TYPE_WITH_CODE (GtkInfoBar, gtk_info_bar, GTK_TYPE_HBOX, + G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, + gtk_info_bar_buildable_interface_init)) + +static void +gtk_info_bar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkInfoBar *info_bar; + GtkInfoBarPrivate *priv; + + info_bar = GTK_INFO_BAR (object); + priv = GTK_INFO_BAR_GET_PRIVATE (info_bar); + + switch (prop_id) + { + case PROP_MESSAGE_TYPE: + gtk_info_bar_set_message_type (info_bar, g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_info_bar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkInfoBar *info_bar; + GtkInfoBarPrivate *priv; + + info_bar = GTK_INFO_BAR (object); + priv = GTK_INFO_BAR_GET_PRIVATE (info_bar); + + switch (prop_id) + { + case PROP_MESSAGE_TYPE: + g_value_set_enum (value, gtk_info_bar_get_message_type (info_bar)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_info_bar_finalize (GObject *object) +{ + G_OBJECT_CLASS (gtk_info_bar_parent_class)->finalize (object); +} + +static void +response_data_free (gpointer data) +{ + g_slice_free (ResponseData, data); +} + +static ResponseData * +get_response_data (GtkWidget *widget, + gboolean create) +{ + ResponseData *ad = g_object_get_data (G_OBJECT (widget), + "gtk-info-bar-response-data"); + + if (ad == NULL && create) + { + ad = g_slice_new (ResponseData); + + g_object_set_data_full (G_OBJECT (widget), + I_("gtk-info-bar-response-data"), + ad, + response_data_free); + } + + return ad; +} + +static GtkWidget * +find_button (GtkInfoBar *info_bar, + gint response_id) +{ + GList *children, *list; + GtkWidget *child = NULL; + + children = gtk_container_get_children (GTK_CONTAINER (info_bar->priv->action_area)); + + for (list = children; list; list = list->next) + { + ResponseData *rd = get_response_data (list->data, FALSE); + + if (rd && rd->response_id == response_id) + { + child = list->data; + break; + } + } + + g_list_free (children); + + return child; +} + +static void +gtk_info_bar_close (GtkInfoBar *info_bar) +{ + if (!find_button (info_bar, GTK_RESPONSE_CANCEL)) + return; + + gtk_info_bar_response (GTK_INFO_BAR (info_bar), + GTK_RESPONSE_CANCEL); +} + +static gboolean +gtk_info_bar_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + GtkInfoBarPrivate *priv = GTK_INFO_BAR_GET_PRIVATE (widget); + gboolean use_tooltip_style; + const char* type_detail[] = { + "infobar-info", + "infobar-warning", + "infobar-question", + "infobar-error", + "infobar" + }; + const char *detail; + + gtk_widget_style_get (widget, + "use-tooltip-style", &use_tooltip_style, + NULL); + + if (use_tooltip_style) + detail = "toolbar"; + else + detail = type_detail[priv->message_type]; + + gtk_paint_flat_box (widget->style, + widget->window, + GTK_STATE_NORMAL, + GTK_SHADOW_OUT, + NULL, + widget, + detail, + widget->allocation.x, + widget->allocation.y, + widget->allocation.width + 1, + widget->allocation.height + 1); + + if (GTK_WIDGET_CLASS (gtk_info_bar_parent_class)->expose_event) + GTK_WIDGET_CLASS (gtk_info_bar_parent_class)->expose_event (widget, event); + + return FALSE; +} + +static void +gtk_info_bar_class_init (GtkInfoBarClass *klass) +{ + GtkWidgetClass *widget_class; + GObjectClass *object_class; + GtkBindingSet *binding_set; + + widget_class = GTK_WIDGET_CLASS (klass); + object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = gtk_info_bar_get_property; + object_class->set_property = gtk_info_bar_set_property; + object_class->finalize = gtk_info_bar_finalize; + + widget_class->style_set = gtk_info_bar_style_set; + widget_class->expose_event = gtk_info_bar_expose; + + klass->close = gtk_info_bar_close; + + /** + * GtkInfoBar:message-type: + * + * The type of the message. + * + * The type is used to determine the colors to use in the info bar. + * The following symbolic color names can by used to customize + * these colors: + * "info_fg_color", "info_bg_color", + * "warning_fg_color", "warning_bg_color", + * "question_fg_color", "question_bg_color", + * "error_fg_color", "error_bg_color", + * "other_fg_color", "other_bg_color". + * + * Since: 2.18 + */ + g_object_class_install_property (object_class, + PROP_MESSAGE_TYPE, + g_param_spec_enum ("message-type", + P_("Message Type"), + P_("The type of message"), + GTK_TYPE_MESSAGE_TYPE, + GTK_MESSAGE_OTHER, + GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + /** + * GtkInfoBar::response: + * @info_bar: the object on which the signal is emitted + * @response_id: the response ID + * + * Emitted when an action widget is clicked or the application programmer + * calls gtk_dialog_response(). The @response_id depends on which action + * widget was clicked. + * + * Since: 2.18 + */ + signals[RESPONSE] = g_signal_new (I_("response"), + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkInfoBarClass, response), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + /** + * GtkInfoBar::close: + * + * The ::close signal is a + * <link linkend="keybinding-signals">keybinding signal</link> + * which gets emitted when the user uses a keybinding to dismiss + * the info bar. + * + * The default binding for this signal is the Escape key. + * + * Since: 2.18 + */ + signals[CLOSE] = g_signal_new (I_("close"), + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkInfoBarClass, close), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * GtkInfoBar:content-area-border: + * + * The width of the border around the content + * content area of the info bar. + * + * Since: 2.18 + */ + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("content-area-border", + P_("Content area border"), + P_("Width of border around the content area"), + 0, + G_MAXINT, + 8, + GTK_PARAM_READABLE)); + + /** + * GtkInfoBar:content-area-spacing: + * + * The default spacing used between elements of the + * content area of the info bar. + * + * Since: 2.18 + */ + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("content-area-spacing", + P_("Content area spacing"), + P_("Spacing between elements of the area"), + 0, + G_MAXINT, + 16, + GTK_PARAM_READABLE)); + + /** + * GtkInfoBar:button-spacing: + * + * Spacing between buttons in the action area of the info bar. + * + * Since: 2.18 + */ + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("button-spacing", + P_("Button spacing"), + P_("Spacing between buttons"), + 0, + G_MAXINT, + 6, + GTK_PARAM_READABLE)); + + /** + * GtkInfoBar:action-area-border: + * + * Width of the border around the action area of the info bar. + * + * Since: 2.18 + */ + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("action-area-border", + P_("Action area border"), + P_("Width of border around the action area"), + 0, + G_MAXINT, + 5, + GTK_PARAM_READABLE)); + + /** + * GtkInfoBar:use-tooltip-style: + * + * When %TRUE, use the same background/foreground color as #GtkTooltip. + * Otherwise, GTK+ uses #GtkInfoBar::message-type to determine which + * symbolic colors to use. + * + * Since: 2.18 + */ + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boolean ("use-tooltip-style", + P_("Use tooltip style"), + P_("Wether to use the same style as GtkTooltip for drawing"), + TRUE, + GTK_PARAM_READABLE)); + + binding_set = gtk_binding_set_by_class (klass); + + gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, "close", 0); + + g_type_class_add_private (object_class, sizeof (GtkInfoBarPrivate)); +} + +static void +gtk_info_bar_update_colors (GtkInfoBar *info_bar) +{ + GtkWidget *widget = (GtkWidget*)info_bar; + GtkInfoBarPrivate *priv; + GdkColor default_border_color = { 0, 0xb800, 0xad00, 0x9d00 }; + GdkColor default_fill_color = { 0, 0xff00, 0xff00, 0xbf00 }; + GdkColor *fg, *bg; + GdkColor sym_fg, sym_bg; + gboolean use_tooltip_style; + GtkStyle *style; + const char* fg_color_name[] = { + "info_fg_color", + "warning_fg_color", + "question_fg_color", + "error_fg_color", + "other_fg_color" + }; + const char* bg_color_name[] = { + "info_bg_color", + "warning_bg_color", + "question_bg_color", + "error_bg_color", + "other_bg_color" + }; + gboolean has_color; + + priv = GTK_INFO_BAR_GET_PRIVATE (info_bar); + style = gtk_widget_get_style (widget); + + gtk_widget_style_get (widget, + "use-tooltip-style", &use_tooltip_style, NULL); + + has_color = FALSE; + + if (gtk_style_lookup_color (style, fg_color_name[priv->message_type], &sym_fg) && + gtk_style_lookup_color (style, bg_color_name[priv->message_type], &sym_bg)) + { + fg = &sym_fg; + bg = &sym_bg; + has_color = TRUE; + } + else if (use_tooltip_style) + { + style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget), + "gtk-tooltip", "GtkTooltip", G_TYPE_NONE); + if (style) + { + fg = &style->fg[GTK_STATE_NORMAL]; + bg = &style->bg[GTK_STATE_NORMAL]; + } + else + { + fg = &default_border_color; + bg = &default_fill_color; + } + + has_color = TRUE; + } + + if (has_color) + { + if (!gdk_color_equal (bg, &widget->style->bg[GTK_STATE_NORMAL])) + gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, bg); + if (!gdk_color_equal (fg, &widget->style->fg[GTK_STATE_NORMAL])) + gtk_widget_modify_fg (widget, GTK_STATE_NORMAL, fg); + } +} + +static void +gtk_info_bar_style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + GtkInfoBar *info_bar = GTK_INFO_BAR (widget); + gint button_spacing; + gint action_area_border; + gint content_area_spacing; + gint content_area_border; + + gtk_widget_style_get (widget, + "button-spacing", &button_spacing, + "action-area-border", &action_area_border, + "content-area-spacing", &content_area_spacing, + "content-area-border", &content_area_border, + NULL); + + gtk_box_set_spacing (GTK_BOX (info_bar->priv->action_area), button_spacing); + gtk_container_set_border_width (GTK_CONTAINER (info_bar->priv->action_area), + action_area_border); + gtk_box_set_spacing (GTK_BOX (info_bar->priv->content_area), content_area_spacing); + gtk_container_set_border_width (GTK_CONTAINER (info_bar->priv->content_area), + content_area_border); + + gtk_info_bar_update_colors (info_bar); +} + +static void +gtk_info_bar_init (GtkInfoBar *info_bar) +{ + GtkWidget *content_area; + GtkWidget *action_area; + + gtk_widget_push_composite_child (); + + info_bar->priv = GTK_INFO_BAR_GET_PRIVATE (info_bar); + + content_area = gtk_hbox_new (FALSE, 0); + gtk_widget_show (content_area); + gtk_box_pack_start (GTK_BOX (info_bar), content_area, TRUE, TRUE, 0); + + action_area = gtk_vbutton_box_new (); + gtk_widget_show (action_area); + gtk_button_box_set_layout (GTK_BUTTON_BOX (action_area), GTK_BUTTONBOX_END); + gtk_box_pack_start (GTK_BOX (info_bar), action_area, FALSE, TRUE, 0); + + gtk_widget_set_app_paintable (GTK_WIDGET (info_bar), TRUE); + + info_bar->priv->content_area = content_area; + info_bar->priv->action_area = action_area; + + gtk_widget_pop_composite_child (); +} + +static GtkBuildableIface *parent_buildable_iface; + +static void +gtk_info_bar_buildable_interface_init (GtkBuildableIface *iface) +{ + parent_buildable_iface = g_type_interface_peek_parent (iface); + iface->get_internal_child = gtk_info_bar_buildable_get_internal_child; + iface->custom_tag_start = gtk_info_bar_buildable_custom_tag_start; + iface->custom_finished = gtk_info_bar_buildable_custom_finished; +} + +static GObject * +gtk_info_bar_buildable_get_internal_child (GtkBuildable *buildable, + GtkBuilder *builder, + const gchar *childname) +{ + if (strcmp (childname, "content_area") == 0) + return G_OBJECT (GTK_INFO_BAR (buildable)->priv->content_area); + else if (strcmp (childname, "action_area") == 0) + return G_OBJECT (GTK_INFO_BAR (buildable)->priv->action_area); + + return parent_buildable_iface->get_internal_child (buildable, + builder, + childname); +} + +static gint +get_response_for_widget (GtkInfoBar *info_bar, + GtkWidget *widget) +{ + ResponseData *rd; + + rd = get_response_data (widget, FALSE); + if (!rd) + return GTK_RESPONSE_NONE; + else + return rd->response_id; +} + +static void +action_widget_activated (GtkWidget *widget, + GtkInfoBar *info_bar) +{ + gint response_id; + + response_id = get_response_for_widget (info_bar, widget); + gtk_info_bar_response (info_bar, response_id); +} + +/** + * gtk_info_bar_add_action_widget: + * @info_bar: a #GtkInfoBar + * @child: an activatable widget + * @response_id: response ID for @child + * + * Add an activatable widget to the action area of a #GtkInfoBar, + * connecting a signal handler that will emit the #GtkInfoBar::response + * signal on the message area when the widget is activated. The widget + * is appended to the end of the message areas action area. + * + * Since: 2.18 + */ +void +gtk_info_bar_add_action_widget (GtkInfoBar *info_bar, + GtkWidget *child, + gint response_id) +{ + ResponseData *ad; + guint signal_id; + + g_return_if_fail (GTK_IS_INFO_BAR (info_bar)); + g_return_if_fail (GTK_IS_WIDGET (child)); + + ad = get_response_data (child, TRUE); + + ad->response_id = response_id; + + if (GTK_IS_BUTTON (child)) + signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON); + else + signal_id = GTK_WIDGET_GET_CLASS (child)->activate_signal; + + if (signal_id) + { + GClosure *closure; + + closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated), + G_OBJECT (info_bar)); + g_signal_connect_closure_by_id (child, signal_id, 0, closure, FALSE); + } + else + g_warning ("Only 'activatable' widgets can be packed into the action area of a GtkInfoBar"); + + gtk_box_pack_end (GTK_BOX (info_bar->priv->action_area), + child, FALSE, FALSE, 0); + if (response_id == GTK_RESPONSE_HELP) + gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (info_bar->priv->action_area), + child, TRUE); +} + +/** + * gtk_info_bar_get_action_area: + * @info_bar: a #GtkInfoBar + * + * Returns the action area of @info_bar. + * + * Returns: the action area. + * + * Since: 2.18 + */ +GtkWidget* +gtk_info_bar_get_action_area (GtkInfoBar *info_bar) +{ + g_return_val_if_fail (GTK_IS_INFO_BAR (info_bar), NULL); + + return info_bar->priv->action_area; +} + +/** + * gtk_info_bar_get_content_area: + * @info_bar: a #GtkInfoBar + * + * Returns the content area of @info_bar. + * + * Returns: the content area. + * + * Since: 2.18 + */ +GtkWidget* +gtk_info_bar_get_content_area (GtkInfoBar *info_bar) +{ + g_return_val_if_fail (GTK_IS_INFO_BAR (info_bar), NULL); + + return info_bar->priv->content_area; +} + +/** + * gtk_info_bar_add_button: + * @info_bar: a #GtkInfoBar + * @button_text: text of button, or stock ID + * @response_id: response ID for the button + * + * Adds a button with the given text (or a stock button, if button_text + * is a stock ID) and sets things up so that clicking the button will emit + * the "response" signal with the given response_id. The button is appended + * to the end of the info bars's action area. The button widget is + * returned, but usually you don't need it. + * + * Returns: the button widget that was added + * + * Since: 2.18 + */ +GtkWidget* +gtk_info_bar_add_button (GtkInfoBar *info_bar, + const gchar *button_text, + gint response_id) +{ + GtkWidget *button; + + g_return_val_if_fail (GTK_IS_INFO_BAR (info_bar), NULL); + g_return_val_if_fail (button_text != NULL, NULL); + + button = gtk_button_new_from_stock (button_text); + + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + + gtk_widget_show (button); + + gtk_info_bar_add_action_widget (info_bar, button, response_id); + + return button; +} + +static void +add_buttons_valist (GtkInfoBar *info_bar, + const gchar *first_button_text, + va_list args) +{ + const gchar* text; + gint response_id; + + g_return_if_fail (GTK_IS_INFO_BAR (info_bar)); + + if (first_button_text == NULL) + return; + + text = first_button_text; + response_id = va_arg (args, gint); + + while (text != NULL) + { + gtk_info_bar_add_button (info_bar, text, response_id); + + text = va_arg (args, gchar*); + if (text == NULL) + break; + + response_id = va_arg (args, int); + } +} + +/** + * gtk_info_bar_add_buttons: + * @info_bar: a #GtkInfoBar + * @first_button_text: button text or stock ID + * @...: response ID for first button, then more text-response_id pairs, + * ending with %NULL + * + * Adds more buttons, same as calling gtk_info_bar_add_button() + * repeatedly. The variable argument list should be %NULL-terminated + * as with gtk_info_bar_new_with_buttons(). Each button must have both + * text and response ID. + * + * Since: 2.18 + */ +void +gtk_info_bar_add_buttons (GtkInfoBar *info_bar, + const gchar *first_button_text, + ...) +{ + va_list args; + + va_start (args, first_button_text); + add_buttons_valist (info_bar, first_button_text, args); + va_end (args); +} + +/** + * gtk_info_bar_new: + * + * Creates a new #GtkInfoBar object. + * + * Returns: a new #GtkInfoBar object + * + * Since: 2.18 + */ +GtkWidget * +gtk_info_bar_new (void) +{ + return g_object_new (GTK_TYPE_INFO_BAR, NULL); +} + +/** + * gtk_info_bar_new_with_buttons: + * @first_button_text: stock ID or text to go in first button, or %NULL + * @...: response ID for first button, then additional buttons, ending + * with %NULL + * + * Creates a new #GtkInfoBar with buttons. Button text/response ID + * pairs should be listed, with a %NULL pointer ending the list. + * Button text can be either a stock ID such as %GTK_STOCK_OK, or + * some arbitrary text. A response ID can be any positive number, + * or one of the values in the #GtkResponseType enumeration. If the + * user clicks one of these dialog buttons, GtkInfoBar will emit + * the "response" signal with the corresponding response ID. + * + * Returns: a new #GtkInfoBar + */ +GtkWidget* +gtk_info_bar_new_with_buttons (const gchar *first_button_text, + ...) +{ + GtkInfoBar *info_bar; + va_list args; + + info_bar = GTK_INFO_BAR (gtk_info_bar_new ()); + + va_start (args, first_button_text); + add_buttons_valist (info_bar, first_button_text, args); + va_end (args); + + return GTK_WIDGET (info_bar); +} + +/** + * gtk_info_bar_set_response_sensitive: + * @info_bar: a #GtkInfoBar + * @response_id: a response ID + * @setting: TRUE for sensitive + * + * Calls gtk_widget_set_sensitive (widget, setting) for each + * widget in the info bars's action area with the given response_id. + * A convenient way to sensitize/desensitize dialog buttons. + * + * Since: 2.18 + */ +void +gtk_info_bar_set_response_sensitive (GtkInfoBar *info_bar, + gint response_id, + gboolean setting) +{ + GList *children, *list; + + g_return_if_fail (GTK_IS_INFO_BAR (info_bar)); + + children = gtk_container_get_children (GTK_CONTAINER (info_bar->priv->action_area)); + + for (list = children; list; list = list->next) + { + GtkWidget *widget = list->data; + ResponseData *rd = get_response_data (widget, FALSE); + + if (rd && rd->response_id == response_id) + gtk_widget_set_sensitive (widget, setting); + } + + g_list_free (children); +} + +/** + * gtk_info_bar_set_default_response: + * @info_bar: a #GtkInfoBar + * @response_id: a response ID + * + * Sets the last widget in the info bar's action area with + * the given response_id as the default widget for the dialog. + * Pressing "Enter" normally activates the default widget. + * + * Since: 2.18 + */ +void +gtk_info_bar_set_default_response (GtkInfoBar *info_bar, + gint response_id) +{ + GList *children, *list; + + g_return_if_fail (GTK_IS_INFO_BAR (info_bar)); + + children = gtk_container_get_children (GTK_CONTAINER (info_bar->priv->action_area)); + + for (list = children; list; list = list->next) + { + GtkWidget *widget = list->data; + ResponseData *rd = get_response_data (widget, FALSE); + + if (rd && rd->response_id == response_id) + gtk_widget_grab_default (widget); + } + + g_list_free (children); +} + +/** + * gtk_info_bar_response: + * @info_bar: a #GtkInfoBar + * @response_id: a response ID + * + * Emits the 'response' signal with the given @response_id. + * + * Since: 2.18 + */ +void +gtk_info_bar_response (GtkInfoBar *info_bar, + gint response_id) +{ + g_return_if_fail (GTK_IS_INFO_BAR (info_bar)); + + g_signal_emit (info_bar, signals[RESPONSE], 0, response_id); +} + +typedef struct +{ + gchar *widget_name; + gchar *response_id; +} ActionWidgetInfo; + +typedef struct +{ + GtkInfoBar *info_bar; + GtkBuilder *builder; + GSList *items; + gchar *response; +} ActionWidgetsSubParserData; + +static void +attributes_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **names, + const gchar **values, + gpointer user_data, + GError **error) +{ + ActionWidgetsSubParserData *parser_data = (ActionWidgetsSubParserData*)user_data; + guint i; + + if (strcmp (element_name, "action-widget") == 0) + { + for (i = 0; names[i]; i++) + if (strcmp (names[i], "response") == 0) + parser_data->response = g_strdup (values[i]); + } + else if (strcmp (element_name, "action-widgets") == 0) + return; + else + g_warning ("Unsupported tag for GtkInfoBar: %s\n", element_name); +} + +static void +attributes_text_element (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + ActionWidgetsSubParserData *parser_data = (ActionWidgetsSubParserData*)user_data; + ActionWidgetInfo *item; + + if (!parser_data->response) + return; + + item = g_new (ActionWidgetInfo, 1); + item->widget_name = g_strndup (text, text_len); + item->response_id = parser_data->response; + parser_data->items = g_slist_prepend (parser_data->items, item); + parser_data->response = NULL; +} + +static const GMarkupParser attributes_parser = +{ + attributes_start_element, + NULL, + attributes_text_element, +}; + +gboolean +gtk_info_bar_buildable_custom_tag_start (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + GMarkupParser *parser, + gpointer *data) +{ + ActionWidgetsSubParserData *parser_data; + + if (child) + return FALSE; + + if (strcmp (tagname, "action-widgets") == 0) + { + parser_data = g_slice_new0 (ActionWidgetsSubParserData); + parser_data->info_bar = GTK_INFO_BAR (buildable); + parser_data->items = NULL; + + *parser = attributes_parser; + *data = parser_data; + return TRUE; + } + + return parent_buildable_iface->custom_tag_start (buildable, builder, child, + tagname, parser, data); +} + +static void +gtk_info_bar_buildable_custom_finished (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + gpointer user_data) +{ + GSList *l; + ActionWidgetsSubParserData *parser_data; + GObject *object; + GtkInfoBar *info_bar; + ResponseData *ad; + guint signal_id; + + if (strcmp (tagname, "action-widgets")) + { + parent_buildable_iface->custom_finished (buildable, builder, child, + tagname, user_data); + return; + } + + info_bar = GTK_INFO_BAR (buildable); + parser_data = (ActionWidgetsSubParserData*)user_data; + parser_data->items = g_slist_reverse (parser_data->items); + + for (l = parser_data->items; l; l = l->next) + { + ActionWidgetInfo *item = l->data; + + object = gtk_builder_get_object (builder, item->widget_name); + if (!object) + { + g_warning ("Unknown object %s specified in action-widgets of %s", + item->widget_name, + gtk_buildable_get_name (GTK_BUILDABLE (buildable))); + continue; + } + + ad = get_response_data (GTK_WIDGET (object), TRUE); + ad->response_id = atoi (item->response_id); + + if (GTK_IS_BUTTON (object)) + signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON); + else + signal_id = GTK_WIDGET_GET_CLASS (object)->activate_signal; + + if (signal_id) + { + GClosure *closure; + + closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated), + G_OBJECT (info_bar)); + g_signal_connect_closure_by_id (object, + signal_id, + 0, + closure, + FALSE); + } + + if (ad->response_id == GTK_RESPONSE_HELP) + gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (info_bar->priv->action_area), + GTK_WIDGET (object), TRUE); + + g_free (item->widget_name); + g_free (item->response_id); + g_free (item); + } + g_slist_free (parser_data->items); + g_slice_free (ActionWidgetsSubParserData, parser_data); +} + +/** + * gtk_info_bar_set_message_type: + * @info_bar: a #GtkInfoBar + * @message_type: a #GtkMessageType + * + * Sets the message type of the message area. + * GTK+ uses this type to determine what color to use + * when drawing the message area. + * + * Since: 2.18 + */ +void +gtk_info_bar_set_message_type (GtkInfoBar *info_bar, + GtkMessageType message_type) +{ + GtkInfoBarPrivate *priv; + AtkObject *atk_obj; + + g_return_if_fail (GTK_IS_INFO_BAR (info_bar)); + + priv = GTK_INFO_BAR_GET_PRIVATE (info_bar); + + if (priv->message_type != message_type) + { + priv->message_type = message_type; + + gtk_info_bar_update_colors (info_bar); + gtk_widget_queue_draw (GTK_WIDGET (info_bar)); + + atk_obj = gtk_widget_get_accessible (GTK_WIDGET (info_bar)); + if (GTK_IS_ACCESSIBLE (atk_obj)) + { + GtkStockItem item; + const char *stock_id = NULL; + + atk_object_set_role (atk_obj, ATK_ROLE_ALERT); + + switch (message_type) + { + case GTK_MESSAGE_INFO: + stock_id = GTK_STOCK_DIALOG_INFO; + break; + + case GTK_MESSAGE_QUESTION: + stock_id = GTK_STOCK_DIALOG_QUESTION; + break; + + case GTK_MESSAGE_WARNING: + stock_id = GTK_STOCK_DIALOG_WARNING; + break; + + case GTK_MESSAGE_ERROR: + stock_id = GTK_STOCK_DIALOG_ERROR; + break; + + case GTK_MESSAGE_OTHER: + break; + + default: + g_warning ("Unknown GtkMessageType %u", message_type); + break; + } + + if (stock_id) + { + gtk_stock_lookup (stock_id, &item); + atk_object_set_name (atk_obj, item.label); + } + } + + g_object_notify (G_OBJECT (info_bar), "message-type"); + } +} + +/** + * gtk_info_bar_get_message_type: + * @info_bar: a #GtkInfoBar + * + * Returns the message type of the message area. + * + * Returns: the message type of the message area. + * + * Since: 2.18 + */ +GtkMessageType +gtk_info_bar_get_message_type (GtkInfoBar *info_bar) +{ + GtkInfoBarPrivate *priv; + + g_return_val_if_fail (GTK_IS_INFO_BAR (info_bar), GTK_MESSAGE_OTHER); + + priv = GTK_INFO_BAR_GET_PRIVATE (info_bar); + + return priv->message_type; +} + + +#define __GTK_INFO_BAR_C__ +#include "gtkaliasdef.c" diff --git a/gtk/gtkinfobar.h b/gtk/gtkinfobar.h new file mode 100644 index 0000000000..cbc206a120 --- /dev/null +++ b/gtk/gtkinfobar.h @@ -0,0 +1,116 @@ +/* + * gtkinfobar.h + * This file is part of GTK+ + * + * Copyright (C) 2005 - Paolo Maggi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +/* + * Modified by the gedit Team, 2005. See the gedit AUTHORS file for a + * list of people on the gedit Team. + * See the gedit ChangeLog files for a list of changes. + * + * Modified by the GTK+ Team, 2008-2009. + */ + +#ifndef __GTK_INFO_BAR_H__ +#define __GTK_INFO_BAR_H__ + +#include <gtk/gtkhbox.h> +#include <gtk/gtkenums.h> + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GTK_TYPE_INFO_BAR (gtk_info_bar_get_type()) +#define GTK_INFO_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INFO_BAR, GtkInfoBar)) +#define GTK_INFO_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_INFO_BAR, GtkInfoBarClass)) +#define GTK_IS_INFO_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_INFO_BAR)) +#define GTK_IS_INFO_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_INFO_BAR)) +#define GTK_INFO_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_INFO_BAR, GtkInfoBarClass)) + + +typedef struct _GtkInfoBarPrivate GtkInfoBarPrivate; +typedef struct _GtkInfoBarClass GtkInfoBarClass; +typedef struct _GtkInfoBar GtkInfoBar; + + +struct _GtkInfoBar +{ + GtkHBox parent; + + /*< private > */ + GtkInfoBarPrivate *priv; +}; + + +struct _GtkInfoBarClass +{ + GtkHBoxClass parent_class; + + /* Signals */ + void (* response) (GtkInfoBar *info_bar, gint response_id); + + /* Keybinding signals */ + void (* close) (GtkInfoBar *info_bar); + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); + void (*_gtk_reserved5) (void); + void (*_gtk_reserved6) (void); +}; + +GType gtk_info_bar_get_type (void) G_GNUC_CONST; +GtkWidget *gtk_info_bar_new (void); + +GtkWidget *gtk_info_bar_new_with_buttons (const gchar *first_button_text, + ...); + +GtkWidget *gtk_info_bar_get_action_area (GtkInfoBar *info_bar); +GtkWidget *gtk_info_bar_get_content_area (GtkInfoBar *info_bar); +void gtk_info_bar_add_action_widget (GtkInfoBar *info_bar, + GtkWidget *child, + gint response_id); +GtkWidget *gtk_info_bar_add_button (GtkInfoBar *info_bar, + const gchar *button_text, + gint response_id); +void gtk_info_bar_add_buttons (GtkInfoBar *info_bar, + const gchar *first_button_text, + ...); +void gtk_info_bar_set_response_sensitive (GtkInfoBar *info_bar, + gint response_id, + gboolean setting); +void gtk_info_bar_set_default_response (GtkInfoBar *info_bar, + gint response_id); + +/* Emit response signal */ +void gtk_info_bar_response (GtkInfoBar *info_bar, + gint response_id); + +void gtk_info_bar_set_message_type (GtkInfoBar *info_bar, + GtkMessageType message_type); +GtkMessageType gtk_info_bar_get_message_type (GtkInfoBar *info_bar); + +G_END_DECLS + +#endif /* __GTK_INFO_BAR_H__ */ diff --git a/gtk/gtkmessagedialog.h b/gtk/gtkmessagedialog.h index 947773c76d..1bb1ec5fc2 100644 --- a/gtk/gtkmessagedialog.h +++ b/gtk/gtkmessagedialog.h @@ -32,20 +32,12 @@ #define __GTK_MESSAGE_DIALOG_H__ #include <gtk/gtkdialog.h> +#include <gtk/gtkenums.h> G_BEGIN_DECLS typedef enum { - GTK_MESSAGE_INFO, - GTK_MESSAGE_WARNING, - GTK_MESSAGE_QUESTION, - GTK_MESSAGE_ERROR, - GTK_MESSAGE_OTHER -} GtkMessageType; - -typedef enum -{ GTK_BUTTONS_NONE, GTK_BUTTONS_OK, GTK_BUTTONS_CLOSE, diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c index a1a5093bd2..a9d2da3900 100644 --- a/gtk/gtkpathbar.c +++ b/gtk/gtkpathbar.c @@ -330,7 +330,13 @@ gtk_path_bar_size_request (GtkWidget *widget, { button_data = BUTTON_DATA (list->data); gtk_widget_size_request (button_data->button, &child_requisition); - requisition->width = MAX (child_requisition.width, requisition->width); + + if (button_data->type == NORMAL_BUTTON) + /* Use 2*Height as button width because of ellipsized label. */ + requisition->width = MAX (child_requisition.height * 2, requisition->width); + else + requisition->width = MAX (child_requisition.width, requisition->width); + requisition->height = MAX (child_requisition.height, requisition->height); } @@ -455,7 +461,6 @@ gtk_path_bar_size_allocate (GtkWidget *widget, gint border_width; gboolean need_sliders = FALSE; gint up_slider_offset = 0; - gint down_slider_offset = 0; widget->allocation = *allocation; @@ -572,9 +577,14 @@ gtk_path_bar_size_allocate (GtkWidget *widget, for (list = first_button; list; list = list->prev) { - child = BUTTON_DATA (list->data)->button; + ButtonData *button_data; + + button_data = BUTTON_DATA (list->data); + child = button_data->button; + + child_allocation.width = MIN (child->requisition.width, + allocation_width - (path_bar->spacing + path_bar->slider_width) * 2); - child_allocation.width = child->requisition.width; if (direction == GTK_TEXT_DIR_RTL) child_allocation.x -= child_allocation.width; @@ -591,21 +601,21 @@ gtk_path_bar_size_allocate (GtkWidget *widget, break; } - gtk_widget_set_child_visible (BUTTON_DATA (list->data)->button, TRUE); + if (child_allocation.width < child->requisition.width) + { + if (!gtk_widget_get_has_tooltip (child)) + gtk_widget_set_tooltip_text (child, button_data->dir_name); + } + else if (gtk_widget_get_has_tooltip (child)) + gtk_widget_set_tooltip_text (child, NULL); + + gtk_widget_set_child_visible (child, TRUE); gtk_widget_size_allocate (child, &child_allocation); if (direction == GTK_TEXT_DIR_RTL) - { - child_allocation.x -= path_bar->spacing; - down_slider_offset = child_allocation.x - widget->allocation.x - path_bar->slider_width; - down_slider_offset = border_width; - } + child_allocation.x -= path_bar->spacing; else - { - down_slider_offset = child_allocation.x - widget->allocation.x; - down_slider_offset = allocation->width - border_width - path_bar->slider_width; - child_allocation.x += child_allocation.width + path_bar->spacing; - } + child_allocation.x += child_allocation.width + path_bar->spacing; } /* Now we go hide all the widgets that don't fit */ while (list) @@ -633,7 +643,14 @@ gtk_path_bar_size_allocate (GtkWidget *widget, if (need_sliders) { child_allocation.width = path_bar->slider_width; - child_allocation.x = down_slider_offset + allocation->x; + + if (direction == GTK_TEXT_DIR_RTL) + child_allocation.x = border_width; + else + child_allocation.x = allocation->width - border_width - path_bar->slider_width; + + child_allocation.x += allocation->x; + gtk_widget_size_allocate (path_bar->down_slider_button, &child_allocation); gtk_widget_set_child_visible (path_bar->down_slider_button, TRUE); @@ -775,11 +792,7 @@ gtk_path_bar_scroll_down (GtkPathBar *path_bar) { GList *list; GList *down_button = NULL; - GList *up_button = NULL; gint space_available; - gint space_needed; - gint border_width; - GtkTextDirection direction; if (path_bar->ignore_click) { @@ -795,9 +808,6 @@ gtk_path_bar_scroll_down (GtkPathBar *path_bar) gtk_widget_queue_resize (GTK_WIDGET (path_bar)); - border_width = GTK_CONTAINER (path_bar)->border_width; - direction = gtk_widget_get_direction (GTK_WIDGET (path_bar)); - /* We find the button at the 'down' end that we have to make * visible */ for (list = path_bar->button_list; list; list = list->next) @@ -808,37 +818,24 @@ gtk_path_bar_scroll_down (GtkPathBar *path_bar) break; } } - - /* Find the last visible button on the 'up' end - */ - for (list = g_list_last (path_bar->button_list); list; list = list->prev) - { - if (gtk_widget_get_child_visible (BUTTON_DATA (list->data)->button)) - { - up_button = list; - break; - } - } - /* We check if down_button might be NULL in cases where the pathbar's horizontal size is smaller - * than the button and it doesn't get displayed. e.g., on Windows it might be "My Documents and Settings" + space_available = (GTK_WIDGET (path_bar)->allocation.width + - 2 * GTK_CONTAINER (path_bar)->border_width + - 2 * path_bar->spacing - 2 * path_bar->slider_width + - BUTTON_DATA (down_button->data)->button->allocation.width); + path_bar->first_scrolled_button = down_button; + + /* We have space_available free space that's not being used. + * So we walk down from the end, adding buttons until we use all free space. */ - space_needed = down_button ? BUTTON_DATA (down_button->data)->button->allocation.width : 0 + path_bar->spacing; - if (direction == GTK_TEXT_DIR_RTL) - space_available = path_bar->down_slider_button->allocation.x - GTK_WIDGET (path_bar)->allocation.x; - else - space_available = (GTK_WIDGET (path_bar)->allocation.x + GTK_WIDGET (path_bar)->allocation.width - border_width) - - (path_bar->down_slider_button->allocation.x + path_bar->down_slider_button->allocation.width); - - /* We have space_available extra space that's not being used. We - * need space_needed space to make the button fit. So we walk down - * from the end, removing buttons until we get all the space we - * need. */ - while (space_available < space_needed) + while (space_available > 0) { - space_available += BUTTON_DATA (up_button->data)->button->allocation.width + path_bar->spacing; - up_button = up_button->prev; - path_bar->first_scrolled_button = up_button; + path_bar->first_scrolled_button = down_button; + down_button = down_button->next; + if (!down_button) + break; + space_available -= (BUTTON_DATA (down_button->data)->button->allocation.width + + path_bar->spacing); } } @@ -1484,6 +1481,7 @@ make_directory_button (GtkPathBar *path_bar, case NORMAL_BUTTON: default: button_data->label = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (button_data->label), PANGO_ELLIPSIZE_END); label_alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); gtk_container_add (GTK_CONTAINER (label_alignment), button_data->label); child = label_alignment; @@ -1663,7 +1661,7 @@ gtk_path_bar_get_info_callback (GCancellable *cancellable, } display_name = g_file_info_get_display_name (info); - is_hidden = g_file_info_get_is_hidden (info); + is_hidden = g_file_info_get_is_hidden (info) || g_file_info_get_is_backup (info); gtk_widget_push_composite_child (); button_data = make_directory_button (file_info->path_bar, display_name, @@ -1691,7 +1689,7 @@ gtk_path_bar_get_info_callback (GCancellable *cancellable, file_info->path_bar->get_info_cancellable = _gtk_file_system_get_info (file_info->path_bar->file_system, file_info->file, - "standard::display-name,standard::is-hidden", + "standard::display-name,standard::is-hidden,standard::is-backup", gtk_path_bar_get_info_callback, file_info); } @@ -1729,7 +1727,7 @@ _gtk_path_bar_set_file (GtkPathBar *path_bar, path_bar->get_info_cancellable = _gtk_file_system_get_info (path_bar->file_system, info->file, - "standard::display-name,standard::is-hidden", + "standard::display-name,standard::is-hidden,standard::is-backup", gtk_path_bar_get_info_callback, info); diff --git a/gtk/gtkprintoperation-private.h b/gtk/gtkprintoperation-private.h index 718f16df6f..8c800eaea5 100644 --- a/gtk/gtkprintoperation-private.h +++ b/gtk/gtkprintoperation-private.h @@ -54,6 +54,8 @@ struct _GtkPrintOperationPrivate guint cancelled : 1; guint allow_async : 1; guint is_sync : 1; + guint support_selection : 1; + guint has_selection : 1; GtkPageDrawingState page_drawing_state; diff --git a/gtk/gtkprintoperation-unix.c b/gtk/gtkprintoperation-unix.c index ad8bc126f8..765752b158 100644 --- a/gtk/gtkprintoperation-unix.c +++ b/gtk/gtkprintoperation-unix.c @@ -421,6 +421,12 @@ get_print_dialog (GtkPrintOperation *op, gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (pd), priv->current_page); + gtk_print_unix_dialog_set_support_selection (GTK_PRINT_UNIX_DIALOG (pd), + priv->support_selection); + + gtk_print_unix_dialog_set_has_selection (GTK_PRINT_UNIX_DIALOG (pd), + priv->has_selection); + g_signal_emit_by_name (op, "create-custom-widget", &priv->custom_widget); diff --git a/gtk/gtkprintoperation.c b/gtk/gtkprintoperation.c index d0e6fb9aae..966417b22f 100644 --- a/gtk/gtkprintoperation.c +++ b/gtk/gtkprintoperation.c @@ -163,6 +163,8 @@ gtk_print_operation_init (GtkPrintOperation *operation) priv->export_filename = NULL; priv->track_print_status = FALSE; priv->is_sync = FALSE; + priv->support_selection = FALSE; + priv->has_selection = FALSE; priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY; @@ -223,6 +225,7 @@ preview_iface_is_selected (GtkPrintOperationPreview *preview, switch (priv->print_pages) { + case GTK_PRINT_PAGES_SELECTION: case GTK_PRINT_PAGES_ALL: return (page_nr >= 0) && (page_nr < priv->nr_of_pages); case GTK_PRINT_PAGES_CURRENT: @@ -830,9 +833,9 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class) * @setup: actual page setup * @settings: actual print settings * - * Emmited after change of selected printer. The actual page setup and + * Emitted after change of selected printer. The actual page setup and * print settings are passed to the custom widget, which can actualize - * itself according to this change. + * itself according to this change. * * Since: 2.18 */ @@ -1193,6 +1196,39 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class) NULL, GTK_PARAM_READWRITE)); + /** + * GtkPrintOperation:support-selection: + * + * If %TRUE, the print operation will support print of selection. + * This allows the print dialog to show a "Selection" button. + * + * Since: 2.18 + */ + g_object_class_install_property (gobject_class, + PROP_TRACK_PRINT_STATUS, + g_param_spec_boolean ("support-selection", + P_("Support Selection"), + P_("TRUE if the print operation will support print of selection."), + FALSE, + GTK_PARAM_READWRITE)); + + /** + * GtkPrintOperation:has-selection: + * + * Determines whether there is a selection in your application. + * This can allow your application to print the selection. + * This is typically used to make a "Selection" button sensitive. + * + * Since: 2.18 + */ + g_object_class_install_property (gobject_class, + PROP_TRACK_PRINT_STATUS, + g_param_spec_boolean ("has-selection", + P_("Has Selection"), + P_("TRUE if a selecion exists."), + FALSE, + GTK_PARAM_READWRITE)); + } /** @@ -2976,7 +3012,99 @@ gtk_print_operation_cancel (GtkPrintOperation *op) op->priv->cancelled = TRUE; } +/** + * gtk_print_operation_set_support_selection: + * @op: a #GtkPrintOperation + * @support_selection: %TRUE to support selection + * + * Sets whether selection is supported by #GtkPrintOperation. + * + * Since: 2.18 + */ +void +gtk_print_operation_set_support_selection (GtkPrintOperation *op, + gboolean support_selection) +{ + GtkPrintOperationPrivate *priv; + g_return_if_fail (GTK_IS_PRINT_OPERATION (op)); + + priv = op->priv; + + support_selection = support_selection != FALSE; + if (priv->support_selection != support_selection) + { + priv->support_selection = support_selection; + g_object_notify (G_OBJECT (op), "support-selection"); + } +} + +/** + * gtk_print_operation_get_support_selection: + * @op: a #GtkPrintOperation + * + * Gets the value of #GtkPrintOperation::support-selection property. + * + * Returns: whether the application supports print of selection + * + * Since: 2.18 + */ +gboolean +gtk_print_operation_get_support_selection (GtkPrintOperation *op) +{ + g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE); + + return op->priv->support_selection; +} + +/** + * gtk_print_operation_set_has_selection: + * @op: a #GtkPrintOperation + * @has_selection: %TRUE indicates that a selection exists + * + * Sets whether there is a selection to print. + * + * Application has to set number of pages to which the selection + * will draw by gtk_print_operation_set_n_pages() in a callback of + * #GtkPrintOperation::begin-print. + * + * Since: 2.18 + */ +void +gtk_print_operation_set_has_selection (GtkPrintOperation *op, + gboolean has_selection) +{ + GtkPrintOperationPrivate *priv; + + g_return_if_fail (GTK_IS_PRINT_OPERATION (op)); + + priv = op->priv; + + has_selection = has_selection != FALSE; + if (priv->has_selection != has_selection) + { + priv->has_selection = has_selection; + g_object_notify (G_OBJECT (op), "has-selection"); + } +} + +/** + * gtk_print_operation_get_has_selection: + * @op: a #GtkPrintOperation + * + * Gets the value of #GtkPrintOperation::has-selection property. + * + * Returns: whether there is a selection + * + * Since: 2.18 + */ +gboolean +gtk_print_operation_get_has_selection (GtkPrintOperation *op) +{ + g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE); + + return op->priv->has_selection; +} #define __GTK_PRINT_OPERATION_C__ #include "gtkaliasdef.c" diff --git a/gtk/gtkprintoperation.h b/gtk/gtkprintoperation.h index af46332fcf..aee3d95ec6 100644 --- a/gtk/gtkprintoperation.h +++ b/gtk/gtkprintoperation.h @@ -178,6 +178,12 @@ gboolean gtk_print_operation_is_finished (GtkPrintOper void gtk_print_operation_cancel (GtkPrintOperation *op); void gtk_print_operation_draw_page_finish (GtkPrintOperation *op); void gtk_print_operation_set_defer_drawing (GtkPrintOperation *op); +void gtk_print_operation_set_support_selection (GtkPrintOperation *op, + gboolean support_selection); +gboolean gtk_print_operation_get_support_selection (GtkPrintOperation *op); +void gtk_print_operation_set_has_selection (GtkPrintOperation *op, + gboolean has_selection); +gboolean gtk_print_operation_get_has_selection (GtkPrintOperation *op); GtkPageSetup *gtk_print_run_page_setup_dialog (GtkWindow *parent, GtkPageSetup *page_setup, diff --git a/gtk/gtkprintsettings.c b/gtk/gtkprintsettings.c index 4328960f9e..e50208017b 100644 --- a/gtk/gtkprintsettings.c +++ b/gtk/gtkprintsettings.c @@ -1356,6 +1356,9 @@ gtk_print_settings_get_print_pages (GtkPrintSettings *settings) if (val == NULL || (strcmp (val, "all") == 0)) return GTK_PRINT_PAGES_ALL; + if (strcmp (val, "selection") == 0) + return GTK_PRINT_PAGES_SELECTION; + if (strcmp (val, "current") == 0) return GTK_PRINT_PAGES_CURRENT; @@ -1389,6 +1392,9 @@ gtk_print_settings_set_print_pages (GtkPrintSettings *settings, case GTK_PRINT_PAGES_CURRENT: str = "current"; break; + case GTK_PRINT_PAGES_SELECTION: + str = "selection"; + break; case GTK_PRINT_PAGES_RANGES: str = "ranges"; break; diff --git a/gtk/gtkprintunixdialog.c b/gtk/gtkprintunixdialog.c index 92c93e9300..85fa6eaa78 100644 --- a/gtk/gtkprintunixdialog.c +++ b/gtk/gtkprintunixdialog.c @@ -115,7 +115,10 @@ enum { PROP_PAGE_SETUP, PROP_CURRENT_PAGE, PROP_PRINT_SETTINGS, - PROP_SELECTED_PRINTER + PROP_SELECTED_PRINTER, + PROP_MANUAL_CAPABILITIES, + PROP_SUPPORT_SELECTION, + PROP_HAS_SELECTION }; enum { @@ -143,8 +146,13 @@ struct GtkPrintUnixDialogPrivate GtkPageSetup *page_setup; gboolean page_setup_set; + gboolean support_selection; + gboolean has_selection; + GtkWidget *all_pages_radio; GtkWidget *current_page_radio; + GtkWidget *selection_radio; + GtkWidget *range_table; GtkWidget *page_range_radio; GtkWidget *page_range_entry; @@ -286,6 +294,31 @@ gtk_print_unix_dialog_class_init (GtkPrintUnixDialogClass *class) GTK_TYPE_PRINTER, GTK_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_MANUAL_CAPABILITIES, + g_param_spec_flags ("manual-capabilities", + P_("Manual Capabilites"), + P_("Capabilities the application can handle"), + GTK_TYPE_PRINT_CAPABILITIES, + 0, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_SUPPORT_SELECTION, + g_param_spec_boolean ("support-selection", + P_("Support Selection"), + P_("Whether the dialog supports selection"), + FALSE, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_HAS_SELECTION, + g_param_spec_boolean ("has-selection", + P_("Has Selection"), + P_("Whether the application has a selection"), + FALSE, + GTK_PARAM_READWRITE)); + g_type_class_add_private (class, sizeof (GtkPrintUnixDialogPrivate)); } @@ -428,6 +461,9 @@ gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog) priv->page_setup = gtk_page_setup_new (); priv->page_setup_set = FALSE; + priv->support_selection = FALSE; + priv->has_selection = FALSE; + g_signal_connect (dialog, "destroy", (GCallback) gtk_print_unix_dialog_destroy, @@ -783,6 +819,15 @@ gtk_print_unix_dialog_set_property (GObject *object, case PROP_PRINT_SETTINGS: gtk_print_unix_dialog_set_settings (dialog, g_value_get_object (value)); break; + case PROP_MANUAL_CAPABILITIES: + gtk_print_unix_dialog_set_manual_capabilities (dialog, g_value_get_flags (value)); + break; + case PROP_SUPPORT_SELECTION: + gtk_print_unix_dialog_set_support_selection (dialog, g_value_get_boolean (value)); + break; + case PROP_HAS_SELECTION: + gtk_print_unix_dialog_set_has_selection (dialog, g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -812,6 +857,15 @@ gtk_print_unix_dialog_get_property (GObject *object, case PROP_SELECTED_PRINTER: g_value_set_object (value, priv->current_printer); break; + case PROP_MANUAL_CAPABILITIES: + g_value_set_flags (value, priv->manual_capabilities); + break; + case PROP_SUPPORT_SELECTION: + g_value_set_boolean (value, priv->support_selection); + break; + case PROP_HAS_SELECTION: + g_value_set_boolean (value, priv->has_selection); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1803,7 +1857,8 @@ create_main_page (GtkPrintUnixDialog *dialog) gtk_widget_show (hbox); gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); - table = gtk_table_new (3, 2, FALSE); + table = gtk_table_new (4, 2, FALSE); + priv->range_table = table; gtk_table_set_row_spacings (GTK_TABLE (table), 6); gtk_table_set_col_spacings (GTK_TABLE (table), 12); frame = wrap_in_frame (_("Range"), table); @@ -1826,6 +1881,17 @@ create_main_page (GtkPrintUnixDialog *dialog) 0, 2, 1, 2, GTK_FILL, 0, 0, 0); + + radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)), + _("Se_lection")); + + gtk_widget_set_sensitive (radio, priv->has_selection); + priv->selection_radio = radio; + gtk_table_attach (GTK_TABLE (table), radio, + 0, 2, 2, 3, GTK_FILL, 0, + 0, 0); + gtk_table_set_row_spacing (GTK_TABLE (table), 2, 0); + radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)), _("Pag_es:")); range_tooltip = _("Specify one or more page ranges,\n e.g. 1-3,7,11"); gtk_widget_set_tooltip_text (radio, range_tooltip); @@ -1833,7 +1899,7 @@ create_main_page (GtkPrintUnixDialog *dialog) priv->page_range_radio = radio; gtk_widget_show (radio); gtk_table_attach (GTK_TABLE (table), radio, - 0, 1, 2, 3, GTK_FILL, 0, + 0, 1, 3, 4, GTK_FILL, 0, 0, 0); entry = gtk_entry_new (); gtk_widget_set_tooltip_text (entry, range_tooltip); @@ -1842,7 +1908,7 @@ create_main_page (GtkPrintUnixDialog *dialog) priv->page_range_entry = entry; gtk_widget_show (entry); gtk_table_attach (GTK_TABLE (table), entry, - 1, 2, 2, 3, GTK_FILL, 0, + 1, 2, 3, 4, GTK_FILL, 0, 0, 0); g_signal_connect (radio, "toggled", G_CALLBACK (update_entry_sensitivity), entry); update_entry_sensitivity (radio, entry); @@ -2030,6 +2096,8 @@ dialog_get_print_pages (GtkPrintUnixDialog *dialog) return GTK_PRINT_PAGES_ALL; else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->current_page_radio))) return GTK_PRINT_PAGES_CURRENT; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->selection_radio))) + return GTK_PRINT_PAGES_SELECTION; else return GTK_PRINT_PAGES_RANGES; } @@ -2044,6 +2112,8 @@ dialog_set_print_pages (GtkPrintUnixDialog *dialog, gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->page_range_radio), TRUE); else if (pages == GTK_PRINT_PAGES_CURRENT) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->current_page_radio), TRUE); + else if (pages == GTK_PRINT_PAGES_SELECTION) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->selection_radio), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->all_pages_radio), TRUE); } @@ -3410,21 +3480,162 @@ gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog *dialog, { GtkPrintUnixDialogPrivate *priv = dialog->priv; - priv->manual_capabilities = capabilities; - update_dialog_from_capabilities (dialog); + if (priv->manual_capabilities != capabilities) + { + priv->manual_capabilities = capabilities; + update_dialog_from_capabilities (dialog); - if (priv->current_printer) + if (priv->current_printer) + { + GtkTreeSelection *selection; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview)); + + g_object_unref (priv->current_printer); + priv->current_printer = NULL; + priv->internal_printer_change = TRUE; + selected_printer_changed (selection, dialog); + priv->internal_printer_change = FALSE; + } + + g_object_notify (G_OBJECT (dialog), "manual-capabilities"); + } +} + +/** + * gtk_print_unix_dialog_get_manual_capabilities: + * @dialog: a #GtkPrintUnixDialog + * + * Gets the value of #GtkPrintUnixDialog::manual-capabilities property. + * + * Returns: the printing capabilities + * + * Since: 2.18 + */ +GtkPrintCapabilities +gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog) +{ + g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE); + + return dialog->priv->manual_capabilities; +} + +/** + * gtk_print_unix_dialog_set_support_selection: + * @dialog: a #GtkPrintUnixDialog + * @support_selection: %TRUE to allow print selection + * + * Sets whether the print dialog allows user to print a selection. + * + * Since: 2.18 + */ +void +gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog, + gboolean support_selection) +{ + GtkPrintUnixDialogPrivate *priv; + + g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog)); + + priv = dialog->priv; + + support_selection = support_selection != FALSE; + if (priv->support_selection != support_selection) { - GtkTreeSelection *selection; + priv->support_selection = support_selection; - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview)); + if (priv->selection_radio) + { + if (support_selection) + { + gtk_widget_set_sensitive (priv->selection_radio, priv->has_selection); + gtk_table_set_row_spacing (GTK_TABLE (priv->range_table), + 2, + gtk_table_get_default_row_spacing (GTK_TABLE (priv->range_table))); + gtk_widget_show (priv->selection_radio); + } + else + { + gtk_widget_set_sensitive (priv->selection_radio, FALSE); + gtk_table_set_row_spacing (GTK_TABLE (priv->range_table), 2, 0); + gtk_widget_hide (priv->selection_radio); + } + } - g_object_unref (priv->current_printer); - priv->current_printer = NULL; - priv->internal_printer_change = TRUE; - selected_printer_changed (selection, dialog); - priv->internal_printer_change = FALSE; - } + g_object_notify (G_OBJECT (dialog), "support-selection"); + } +} + +/** + * gtk_print_unix_dialog_get_support_selection: + * @dialog: a #GtkPrintUnixDialog + * + * Gets the value of #GtkPrintUnixDialog::support-selection property. + * + * Returns: whether the application supports print of selection + * + * Since: 2.18 + */ +gboolean +gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog) +{ + g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE); + + return dialog->priv->support_selection; +} + +/** + * gtk_print_unix_dialog_set_has_selection: + * @dialog: a #GtkPrintUnixDialog + * @has_selection: %TRUE indicates that a selection exists + * + * Sets whether a selection exists. + * + * Since: 2.18 + */ +void +gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog, + gboolean has_selection) +{ + GtkPrintUnixDialogPrivate *priv; + + g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog)); + + priv = dialog->priv; + + has_selection = has_selection != FALSE; + if (priv->has_selection != has_selection) + { + priv->has_selection = has_selection; + + if (priv->selection_radio) + { + if (priv->support_selection) + gtk_widget_set_sensitive (priv->selection_radio, has_selection); + else + gtk_widget_set_sensitive (priv->selection_radio, FALSE); + } + + g_object_notify (G_OBJECT (dialog), "has-selection"); + } +} + +/** + * gtk_print_unix_dialog_get_has_selection: + * @dialog: a #GtkPrintUnixDialog + * + * Gets the value of #GtkPrintUnixDialog::has-selection property. + * + * Returns: whether there is a selection + * + * Since: 2.18 + */ +gboolean +gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog) +{ + g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE); + + return dialog->priv->has_selection; } #define __GTK_PRINT_UNIX_DIALOG_C__ diff --git a/gtk/gtkprintunixdialog.h b/gtk/gtkprintunixdialog.h index c7a919f9dc..0d7efccfc3 100644 --- a/gtk/gtkprintunixdialog.h +++ b/gtk/gtkprintunixdialog.h @@ -83,6 +83,13 @@ void gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog GtkWidget *tab_label); void gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog *dialog, GtkPrintCapabilities capabilities); +GtkPrintCapabilities gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog); +void gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog, + gboolean support_selection); +gboolean gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog); +void gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog, + gboolean has_selection); +gboolean gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog); G_END_DECLS diff --git a/gtk/gtkrecentmanager.c b/gtk/gtkrecentmanager.c index 317b3d5f5e..5cedaa0e54 100644 --- a/gtk/gtkrecentmanager.c +++ b/gtk/gtkrecentmanager.c @@ -1735,15 +1735,16 @@ recent_app_info_free (RecentAppInfo *app_info) * storage specification, they will be expanded. * * Return value: %TRUE if an application with @app_name has registered this - * resource inside the recently used list, or %FALSE otherwise. You should - * free the returned command line using g_free(). + * resource inside the recently used list, or %FALSE otherwise. The + * @app_exec string is owned by the #GtkRecentInfo and should not be + * modified or freed * * Since: 2.10 */ gboolean gtk_recent_info_get_application_info (GtkRecentInfo *info, const gchar *app_name, - gchar **app_exec, + const gchar **app_exec, guint *count, time_t *time_) { diff --git a/gtk/gtkrecentmanager.h b/gtk/gtkrecentmanager.h index 4127e67b21..ccc6581594 100644 --- a/gtk/gtkrecentmanager.h +++ b/gtk/gtkrecentmanager.h @@ -186,7 +186,7 @@ time_t gtk_recent_info_get_visited (GtkRecentInfo *info gboolean gtk_recent_info_get_private_hint (GtkRecentInfo *info); gboolean gtk_recent_info_get_application_info (GtkRecentInfo *info, const gchar *app_name, - gchar **app_exec, + const gchar **app_exec, guint *count, time_t *time_); gchar ** gtk_recent_info_get_applications (GtkRecentInfo *info, diff --git a/gtk/gtkstatusicon.c b/gtk/gtkstatusicon.c index f2ed5012a1..3e89f5362c 100644 --- a/gtk/gtkstatusicon.c +++ b/gtk/gtkstatusicon.c @@ -1022,10 +1022,13 @@ gtk_status_icon_set_property (GObject *object, break; case PROP_HAS_TOOLTIP: gtk_status_icon_set_has_tooltip (status_icon, g_value_get_boolean (value)); + break; case PROP_TOOLTIP_TEXT: gtk_status_icon_set_tooltip_text (status_icon, g_value_get_string (value)); + break; case PROP_TOOLTIP_MARKUP: gtk_status_icon_set_tooltip_markup (status_icon, g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gtk/gtkstock.c b/gtk/gtkstock.c index 5dd0cea713..153ef0877c 100644 --- a/gtk/gtkstock.c +++ b/gtk/gtkstock.c @@ -451,7 +451,7 @@ static const GtkStockItem builtin_items [] = * return (gchar*)g_dpgettext2 (GETTEXT_PACKAGE, msgctxt, msgid); * } * - * /* ... &ast/ + * /* ... */ * * gtk_stock_add (items, G_N_ELEMENTS (items)); * gtk_stock_set_translate_func ("odd-item-domain", my_translate_func, "odd items"); diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h index 384c176982..44259abe35 100644 --- a/gtk/gtktreeprivate.h +++ b/gtk/gtktreeprivate.h @@ -238,6 +238,8 @@ struct _GtkTreeViewPrivate guint post_validation_flag : 1; + /* Whether our key press handler is to avoid sending an unhandled binding to the search entry */ + guint search_entry_avoid_unhandled_binding : 1; /* Auto expand/collapse timeout in hover mode */ guint auto_expand_timeout; diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index caa517c07a..068b2369a4 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -5377,6 +5377,12 @@ gtk_tree_view_key_press (GtkWidget *widget, if (GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->key_press_event (widget, event)) return TRUE; + if (tree_view->priv->search_entry_avoid_unhandled_binding) + { + tree_view->priv->search_entry_avoid_unhandled_binding = FALSE; + return FALSE; + } + /* We pass the event to the search_entry. If its text changes, then we start * the typeahead find capabilities. */ if (GTK_WIDGET_HAS_FOCUS (tree_view) @@ -10231,27 +10237,21 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view) GdkModifierType state; if (! GTK_WIDGET_HAS_FOCUS (tree_view)) - return FALSE; + goto out; cursor_path = NULL; if (tree_view->priv->cursor) cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); if (cursor_path == NULL) - return FALSE; + goto out; _gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node); if (cursor_tree == NULL) { gtk_tree_path_free (cursor_path); - return FALSE; - } - - if (gtk_get_current_event_state (&state)) - { - if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) - tree_view->priv->ctrl_pressed = TRUE; + goto out; } if (cursor_tree->parent_node) @@ -10262,19 +10262,30 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view) gtk_tree_path_up (cursor_path); + if (gtk_get_current_event_state (&state)) + { + if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) + tree_view->priv->ctrl_pressed = TRUE; + } + gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE); - } + gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node); - gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node); + gtk_widget_grab_focus (GTK_WIDGET (tree_view)); + gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL); + gtk_tree_path_free (cursor_path); - gtk_widget_grab_focus (GTK_WIDGET (tree_view)); - gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL); - gtk_tree_path_free (cursor_path); + tree_view->priv->ctrl_pressed = FALSE; - tree_view->priv->ctrl_pressed = FALSE; + return TRUE; + } - return TRUE; + out: + + tree_view->priv->search_entry_avoid_unhandled_binding = TRUE; + return FALSE; } + static gboolean gtk_tree_view_search_entry_flush_timeout (GtkTreeView *tree_view) { @@ -10320,7 +10331,7 @@ gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view) return; toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view)); - screen = gtk_widget_get_screen (tree_view); + screen = gtk_widget_get_screen (GTK_WIDGET (tree_view)); if (tree_view->priv->search_window != NULL) { diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 24f99e4c15..bf98fdf1ad 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -1548,6 +1548,8 @@ gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column) * in no particular order. The list must be freed with g_list_free(). * * Return value: A list of #GtkCellRenderers + * + * Deprecated: 2.18: use gtk_cell_layout_get_cells() instead. **/ GList * gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column) diff --git a/gtk/gtktreeviewcolumn.h b/gtk/gtktreeviewcolumn.h index 9238a623ce..b06e845d9f 100644 --- a/gtk/gtktreeviewcolumn.h +++ b/gtk/gtktreeviewcolumn.h @@ -135,7 +135,9 @@ void gtk_tree_view_column_pack_end (GtkTreeViewCol GtkCellRenderer *cell, gboolean expand); void gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column); +#ifndef GTK_DISABLE_DEPRECATED GList *gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column); +#endif void gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell_renderer, const gchar *attribute, diff --git a/gtk/gtkvbbox.c b/gtk/gtkvbbox.c index e42db03b36..5198e46a30 100644 --- a/gtk/gtkvbbox.c +++ b/gtk/gtkvbbox.c @@ -26,15 +26,11 @@ #include "config.h" #include "gtkvbbox.h" +#include "gtkorientable.h" #include "gtkintl.h" #include "gtkalias.h" -static void gtk_vbutton_box_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_vbutton_box_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); - static gint default_spacing = 10; static GtkButtonBoxStyle default_layout_style = GTK_BUTTONBOX_EDGE; @@ -43,18 +39,13 @@ G_DEFINE_TYPE (GtkVButtonBox, gtk_vbutton_box, GTK_TYPE_BUTTON_BOX) static void gtk_vbutton_box_class_init (GtkVButtonBoxClass *class) { - GtkWidgetClass *widget_class; - - widget_class = (GtkWidgetClass*) class; - - widget_class->size_request = gtk_vbutton_box_size_request; - widget_class->size_allocate = gtk_vbutton_box_size_allocate; } static void gtk_vbutton_box_init (GtkVButtonBox *vbutton_box) { - /* button_box_init has done everything allready */ + gtk_orientable_set_orientation (GTK_ORIENTABLE (vbutton_box), + GTK_ORIENTATION_VERTICAL); } GtkWidget* @@ -107,185 +98,5 @@ gtk_vbutton_box_get_layout_default (void) return default_layout_style; } - - - -static void -gtk_vbutton_box_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - GtkBox *box; - GtkButtonBox *bbox; - gint nvis_children; - gint child_width; - gint child_height; - gint spacing; - GtkButtonBoxStyle layout; - - box = GTK_BOX (widget); - bbox = GTK_BUTTON_BOX (widget); - - spacing = box->spacing; - layout = bbox->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE - ? bbox->layout_style : default_layout_style; - - _gtk_button_box_child_requisition (widget, - &nvis_children, - NULL, - &child_width, - &child_height); - - if (nvis_children == 0) - { - requisition->width = 0; - requisition->height = 0; - } - else - { - switch (layout) - { - case GTK_BUTTONBOX_SPREAD: - requisition->height = - nvis_children*child_height + ((nvis_children+1)*spacing); - break; - case GTK_BUTTONBOX_EDGE: - case GTK_BUTTONBOX_START: - case GTK_BUTTONBOX_END: - case GTK_BUTTONBOX_CENTER: - requisition->height = - nvis_children*child_height + ((nvis_children-1)*spacing); - break; - default: - g_assert_not_reached(); - break; - } - - requisition->width = child_width; - } - - requisition->width += GTK_CONTAINER (box)->border_width * 2; - requisition->height += GTK_CONTAINER (box)->border_width * 2; -} - - - -static void -gtk_vbutton_box_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GtkBox *base_box; - GtkButtonBox *box; - GtkBoxChild *child; - GList *children; - GtkAllocation child_allocation; - gint nvis_children; - gint n_secondaries; - gint child_width; - gint child_height; - gint x = 0; - gint y = 0; - gint secondary_y = 0; - gint height; - gint childspace; - gint childspacing = 0; - GtkButtonBoxStyle layout; - gint spacing; - - base_box = GTK_BOX (widget); - box = GTK_BUTTON_BOX (widget); - spacing = base_box->spacing; - layout = box->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE - ? box->layout_style : default_layout_style; - _gtk_button_box_child_requisition (widget, - &nvis_children, - &n_secondaries, - &child_width, - &child_height); - widget->allocation = *allocation; - height = allocation->height - GTK_CONTAINER (box)->border_width*2; - switch (layout) - { - case GTK_BUTTONBOX_SPREAD: - childspacing = (height - (nvis_children * child_height)) / (nvis_children + 1); - y = allocation->y + GTK_CONTAINER (box)->border_width + childspacing; - secondary_y = y + ((nvis_children - n_secondaries) * (child_height + childspacing)); - break; - case GTK_BUTTONBOX_EDGE: - if (nvis_children >= 2) - { - childspacing = (height - (nvis_children*child_height)) / (nvis_children-1); - y = allocation->y + GTK_CONTAINER (box)->border_width; - secondary_y = y + ((nvis_children - n_secondaries) * (child_height + childspacing)); - } - else - { - /* one or zero children, just center */ - childspacing = height; - y = secondary_y = allocation->y + (allocation->height - child_height) / 2; - } - break; - case GTK_BUTTONBOX_START: - childspacing = spacing; - y = allocation->y + GTK_CONTAINER (box)->border_width; - secondary_y = allocation->y + allocation->height - - child_height * n_secondaries - - spacing * (n_secondaries - 1) - - GTK_CONTAINER (box)->border_width; - break; - case GTK_BUTTONBOX_END: - childspacing = spacing; - y = allocation->y + allocation->height - - child_height * (nvis_children - n_secondaries) - - spacing * (nvis_children - n_secondaries - 1) - - GTK_CONTAINER (box)->border_width; - secondary_y = allocation->y + GTK_CONTAINER (box)->border_width; - break; - case GTK_BUTTONBOX_CENTER: - childspacing = spacing; - y = allocation->y + - (allocation->height - - (child_height * (nvis_children - n_secondaries) - + spacing * (nvis_children - n_secondaries - 1)))/2 - + (n_secondaries * child_height + n_secondaries * spacing)/2; - secondary_y = allocation->y + GTK_CONTAINER (box)->border_width; - break; - default: - g_assert_not_reached(); - break; - } - - - x = allocation->x + (allocation->width - child_width) / 2; - childspace = child_height + childspacing; - - children = GTK_BOX (box)->children; - - while (children) - { - child = children->data; - children = children->next; - - if (GTK_WIDGET_VISIBLE (child->widget)) - { - child_allocation.width = child_width; - child_allocation.height = child_height; - child_allocation.x = x; - - if (child->is_secondary) - { - child_allocation.y = secondary_y; - secondary_y += childspace; - } - else - { - child_allocation.y = y; - y += childspace; - } - - gtk_widget_size_allocate (child->widget, &child_allocation); - } - } -} - #define __GTK_VBBOX_C__ #include "gtkaliasdef.c" diff --git a/gtk/tests/builder.c b/gtk/tests/builder.c index 7b2cc19b60..f5a85ac4fa 100644 --- a/gtk/tests/builder.c +++ b/gtk/tests/builder.c @@ -1147,7 +1147,7 @@ test_treeview_column (void) g_assert (GTK_IS_TREE_VIEW_COLUMN (column)); g_assert (strcmp (gtk_tree_view_column_get_title (column), "Test") == 0); - renderers = gtk_tree_view_column_get_cell_renderers (column); + renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column)); g_assert (g_list_length (renderers) == 1); renderer = g_list_nth_data (renderers, 0); g_assert (renderer); @@ -1423,7 +1423,7 @@ test_cell_view (void) path = gtk_tree_path_new_first (); gtk_cell_view_set_displayed_row (GTK_CELL_VIEW (cellview), path); - renderers = gtk_cell_view_get_cell_renderers (GTK_CELL_VIEW (cellview)); + renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cellview)); g_assert (renderers); g_assert (g_list_length (renderers) == 1); @@ -2483,6 +2483,56 @@ test_file (const gchar *filename) builder = NULL; } +static void +test_message_area (void) +{ + GtkBuilder *builder; + GError *error; + GObject *obj, *obj1; + const gchar buffer[] = + "<interface>" + " <object class=\"GtkInfoBar\" id=\"infobar1\">" + " <child internal-child=\"content_area\">" + " <object class=\"GtkHBox\" id=\"contentarea1\">" + " <child>" + " <object class=\"GtkLabel\" id=\"content\">" + " <property name=\"label\" translatable=\"yes\">Message</property>" + " </object>" + " </child>" + " </object>" + " </child>" + " <child internal-child=\"action_area\">" + " <object class=\"GtkVButtonBox\" id=\"actionarea1\">" + " <child>" + " <object class=\"GtkButton\" id=\"button_ok\">" + " <property name=\"label\">gtk-ok</property>" + " <property name=\"use-stock\">yes</property>" + " </object>" + " </child>" + " </object>" + " </child>" + " <action-widgets>" + " <action-widget response=\"1\">button_ok</action-widget>" + " </action-widgets>" + " </object>" + "</interface>"; + + error = NULL; + builder = builder_new_from_string (buffer, -1, NULL); + g_assert (error == NULL); + obj = gtk_builder_get_object (builder, "infobar1"); + g_assert (GTK_IS_INFO_BAR (obj)); + obj1 = gtk_builder_get_object (builder, "content"); + g_assert (GTK_IS_LABEL (obj1)); + g_assert (gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (obj1))) == GTK_WIDGET (obj)); + + obj1 = gtk_builder_get_object (builder, "button_ok"); + g_assert (GTK_IS_BUTTON (obj1)); + g_assert (gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (obj1))) == GTK_WIDGET (obj)); + + g_object_unref (builder); +} + int main (int argc, char **argv) { @@ -2525,6 +2575,7 @@ main (int argc, char **argv) g_test_add_func ("/Builder/Requires", test_requires); g_test_add_func ("/Builder/AddObjects", test_add_objects); g_test_add_func ("/Builder/Menus", test_menus); + g_test_add_func ("/Builder/MessageArea", test_message_area); return g_test_run(); } diff --git a/gtk/tests/treeview-scrolling.c b/gtk/tests/treeview-scrolling.c index 5ee24c123b..0207dbcff2 100644 --- a/gtk/tests/treeview-scrolling.c +++ b/gtk/tests/treeview-scrolling.c @@ -728,7 +728,7 @@ scroll_new_row (ScrollFixture *fixture, /* Set up a signal handler to acquire the editable widget */ column = gtk_tree_view_get_column (GTK_TREE_VIEW (fixture->tree_view), 0); - renderers = gtk_tree_view_column_get_cell_renderers (column); + renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column)); g_signal_connect (G_OBJECT (renderers->data), "editing-started", G_CALLBACK (scroll_new_row_editing_started), diff --git a/gtk/updateiconcache.c b/gtk/updateiconcache.c index f6a5cfff20..edd68c03cf 100644 --- a/gtk/updateiconcache.c +++ b/gtk/updateiconcache.c @@ -1687,7 +1687,7 @@ main (int argc, char **argv) { if (path) { - g_printerr (_("No theme index file.")); + g_printerr (_("No theme index file.\n")); } else { |