X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkmodelmenu.c;h=0c3cc5e96ccd94d8fc9baf2c55f261312d16cc83;hb=3a86af43fa208786b5c848c09f9c8e1d3f060931;hp=a3d115218509fe226ea6b47fb88a3d6b470ef935;hpb=182fbba2bfad85c83c6ce9c77b43687f55691d9b;p=~andy%2Fgtk diff --git a/gtk/gtkmodelmenu.c b/gtk/gtkmodelmenu.c index a3d115218..0c3cc5e96 100644 --- a/gtk/gtkmodelmenu.c +++ b/gtk/gtkmodelmenu.c @@ -13,9 +13,7 @@ * 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. + * License along with this library. If not, see . * * Author: Matthias Clasen * Ryan Lortie @@ -23,22 +21,24 @@ #include "config.h" -#include "gtkmodelmenu.h" - -#include "gtkmenu.h" +#include "gtkmenushell.h" #include "gtkmenubar.h" +#include "gtkmenu.h" + #include "gtkseparatormenuitem.h" #include "gtkmodelmenuitem.h" +#include "gtkapplicationprivate.h" + +#define MODEL_MENU_WIDGET_DATA "gtk-model-menu-widget-data" typedef struct { - GActionObservable *actions; GMenuModel *model; - GtkAccelGroup *accels; GtkMenuShell *shell; guint update_idle; GSList *connected; gboolean with_separators; gint n_items; + gchar *action_namespace; } GtkModelMenuBinding; static void @@ -49,6 +49,7 @@ gtk_model_menu_binding_items_changed (GMenuModel *model, gpointer user_data); static void gtk_model_menu_binding_append_model (GtkModelMenuBinding *binding, GMenuModel *model, + const gchar *action_namespace, gboolean with_separators); static void @@ -65,13 +66,16 @@ gtk_model_menu_binding_free (gpointer data) binding->connected = g_slist_delete_link (binding->connected, binding->connected); } - g_object_unref (binding->actions); g_object_unref (binding->model); + g_free (binding->action_namespace); + + g_slice_free (GtkModelMenuBinding, binding); } static void gtk_model_menu_binding_append_item (GtkModelMenuBinding *binding, GMenuModel *model, + const gchar *action_namespace, gint item_index, gchar **heading) { @@ -79,14 +83,30 @@ gtk_model_menu_binding_append_item (GtkModelMenuBinding *binding, if ((section = g_menu_model_get_item_link (model, item_index, "section"))) { + gchar *section_namespace = NULL; + g_menu_model_get_item_attribute (model, item_index, "label", "s", heading); - gtk_model_menu_binding_append_model (binding, section, FALSE); + g_menu_model_get_item_attribute (model, item_index, "action-namespace", "s", §ion_namespace); + + if (action_namespace) + { + gchar *namespace = g_strjoin (".", action_namespace, section_namespace, NULL); + gtk_model_menu_binding_append_model (binding, section, namespace, FALSE); + g_free (namespace); + } + else + { + gtk_model_menu_binding_append_model (binding, section, section_namespace, FALSE); + } + + g_free (section_namespace); + g_object_unref (section); } else { GtkMenuItem *item; - item = gtk_model_menu_item_new (model, item_index, binding->actions, binding->accels); + item = gtk_model_menu_item_new (model, item_index, action_namespace); gtk_menu_shell_append (binding->shell, GTK_WIDGET (item)); gtk_widget_show (GTK_WIDGET (item)); binding->n_items++; @@ -96,6 +116,7 @@ gtk_model_menu_binding_append_item (GtkModelMenuBinding *binding, static void gtk_model_menu_binding_append_model (GtkModelMenuBinding *binding, GMenuModel *model, + const gchar *action_namespace, gboolean with_separators) { gint n, i; @@ -138,7 +159,7 @@ gtk_model_menu_binding_append_model (GtkModelMenuBinding *binding, gint our_position = binding->n_items; gchar *heading = NULL; - gtk_model_menu_binding_append_item (binding, model, i, &heading); + gtk_model_menu_binding_append_item (binding, model, action_namespace, i, &heading); if (with_separators && our_position < binding->n_items) { @@ -180,7 +201,7 @@ gtk_model_menu_binding_populate (GtkModelMenuBinding *binding) binding->n_items = 0; /* add new items from the model */ - gtk_model_menu_binding_append_model (binding, binding->model, binding->with_separators); + gtk_model_menu_binding_append_model (binding, binding->model, binding->action_namespace, binding->with_separators); } static gboolean @@ -222,52 +243,80 @@ gtk_model_menu_binding_items_changed (GMenuModel *model, } } +/** + * gtk_menu_shell_bind_model: + * @menu_shell: a #GtkMenuShell + * @model: (allow-none): the #GMenuModel to bind to or %NULL to remove + * binding + * @action_namespace: (allow-none): the namespace for actions in @model + * @with_separators: %TRUE if toplevel items in @shell should have + * separators between them + * + * Establishes a binding between a #GtkMenuShell and a #GMenuModel. + * + * The contents of @shell are removed and then refilled with menu items + * according to @model. When @model changes, @shell is updated. + * Calling this function twice on @shell with different @model will + * cause the first binding to be replaced with a binding to the new + * model. If @model is %NULL then any previous binding is undone and + * all children are removed. + * + * @with_separators determines if toplevel items (eg: sections) have + * separators inserted between them. This is typically desired for + * menus but doesn't make sense for menubars. + * + * If @action_namespace is non-%NULL then the effect is as if all + * actions mentioned in the @model have their names prefixed with the + * namespace, plus a dot. For example, if the action "quit" is + * mentioned and @action_namespace is "app" then the effective action + * name is "app.quit". + * + * For most cases you are probably better off using + * gtk_menu_new_from_model() or gtk_menu_bar_new_from_model() or just + * directly passing the #GMenuModel to gtk_application_set_app_menu() or + * gtk_application_set_menu_bar(). + * + * Since: 3.6 + */ void -gtk_model_menu_bind (GtkMenuShell *shell, - GMenuModel *model, - GActionObservable *actions, - GtkAccelGroup *accels, - gboolean with_separators) +gtk_menu_shell_bind_model (GtkMenuShell *shell, + GMenuModel *model, + const gchar *action_namespace, + gboolean with_separators) { - GtkModelMenuBinding *binding; + g_return_if_fail (GTK_IS_MENU_SHELL (shell)); + g_return_if_fail (model == NULL || G_IS_MENU_MODEL (model)); - binding = g_slice_new (GtkModelMenuBinding); - binding->model = g_object_ref (model); - binding->actions = g_object_ref (actions); - binding->accels = accels; - binding->shell = shell; - binding->update_idle = 0; - binding->connected = NULL; - binding->with_separators = with_separators; - - g_object_set_data_full (G_OBJECT (shell), "gtk-model-menu-binding", binding, gtk_model_menu_binding_free); - gtk_model_menu_binding_populate (binding); -} + if (model) + { + GtkModelMenuBinding *binding; -GtkWidget * -gtk_model_menu_create_menu (GMenuModel *model, - GActionObservable *actions, - GtkAccelGroup *accels) -{ - GtkWidget *menu; + binding = g_slice_new (GtkModelMenuBinding); + binding->model = g_object_ref (model); + binding->shell = shell; + binding->update_idle = 0; + binding->connected = NULL; + binding->with_separators = with_separators; + binding->action_namespace = g_strdup (action_namespace); - menu = gtk_menu_new (); - gtk_menu_set_accel_group (GTK_MENU (menu), accels); - gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, actions, accels, TRUE); + g_object_set_data_full (G_OBJECT (shell), "gtk-model-menu-binding", binding, gtk_model_menu_binding_free); - return menu; -} + gtk_model_menu_binding_populate (binding); + } -GtkWidget * -gtk_model_menu_create_menu_bar (GMenuModel *model, - GActionObservable *actions, - GtkAccelGroup *accels) -{ - GtkWidget *menubar; + else + { + GList *children; - menubar = gtk_menu_bar_new (); - gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, actions, accels, FALSE); + /* break existing binding */ + g_object_set_data (G_OBJECT (shell), "gtk-model-menu-binding", NULL); - return menubar; + /* remove all children */ + children = gtk_container_get_children (GTK_CONTAINER (shell)); + while (children) + { + gtk_container_remove (GTK_CONTAINER (shell), children->data); + children = g_list_delete_link (children, children); + } + } } -