summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk/gtkapplication.c98
-rw-r--r--gtk/gtkapplication.h4
2 files changed, 91 insertions, 11 deletions
diff --git a/gtk/gtkapplication.c b/gtk/gtkapplication.c
index 662e501e44..27a513a2fa 100644
--- a/gtk/gtkapplication.c
+++ b/gtk/gtkapplication.c
@@ -70,20 +70,25 @@
* associated with #GtkApplicationWindow and to the “activate” and
* 'open' #GApplication methods.
*
- * To set an application menu for a GtkApplication, use
- * gtk_application_set_app_menu(). The #GMenuModel that this function
- * expects is usually constructed using #GtkBuilder, as seen in the
- * following example. To specify a menubar that will be shown by
- * #GtkApplicationWindows, use gtk_application_set_menubar(). Use the base
- * #GActionMap interface to add actions, to respond to the user
- * selecting these menu items.
- *
- * GTK+ displays these menus as expected, depending on the platform
- * the application is running on.
+ * #GtkApplication will automatically load menus from the #GtkBuilder
+ * file located at "gtk/menus.ui", relative to the application's
+ * resource base path (see g_application_set_resource_base_path()). The
+ * menu with the ID "app-menu" is taken as the application's app menu
+ * and the menu with the ID "menubar" is taken as the application's
+ * menubar. Additional menus (most interesting submenus) can be named
+ * and accessed via gtk_application_get_menu_by_id() which allows for
+ * dynamic population of a part of the menu structure.
+ *
+ * If the files "gtk/menus-appmenu.ui" or "gtk/menus-traditional.ui" are
+ * present then these files will be used in preference, depending on the
+ * value of gtk_application_prefers_app_menu().
+ *
+ * It is also possible to provide the menus manually using
+ * gtk_application_set_app_menu() and gtk_application_set_menubar().
*
* ## A simple application ## {#gtkapplication}
*
- * [A simple example](https://git.gnome.org/browse/gtk+/tree/examples/bloatpad.c)
+ * [A simple example](https://git.gnome.org/browse/gtk+/tree/examples/bp/bloatpad.c)
*
* GtkApplication optionally registers with a session manager
* of the users session (if you set the #GtkApplication:register-session
@@ -460,6 +465,7 @@ struct _GtkApplicationPrivate
gboolean register_session;
GtkActionMuxer *muxer;
+ GtkBuilder *menus_builder;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
@@ -499,6 +505,56 @@ gtk_application_focus_in_event_cb (GtkWindow *window,
}
static void
+gtk_application_load_resources (GtkApplication *application)
+{
+ const gchar *base_path;
+
+ base_path = g_application_get_resource_base_path (G_APPLICATION (application));
+
+ if (base_path == NULL)
+ return;
+
+ /* Load the menus */
+ {
+ gchar *menuspath;
+
+ /* If the user has given a specific file for the variant of menu
+ * that we are looking for, use it with preference.
+ */
+ if (gtk_application_prefers_app_menu (application))
+ menuspath = g_strconcat (base_path, "/gtk/menus-appmenu.ui", NULL);
+ else
+ menuspath = g_strconcat (base_path, "/gtk/menus-traditional.ui", NULL);
+
+ if (g_resources_get_info (menuspath, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL))
+ application->priv->menus_builder = gtk_builder_new_from_resource (menuspath);
+ g_free (menuspath);
+
+ /* If we didn't get the specific file, fall back. */
+ if (application->priv->menus_builder == NULL)
+ {
+ menuspath = g_strconcat (base_path, "/gtk/menus.ui", NULL);
+ if (g_resources_get_info (menuspath, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL))
+ application->priv->menus_builder = gtk_builder_new_from_resource (menuspath);
+ g_free (menuspath);
+ }
+
+ if (application->priv->menus_builder)
+ {
+ GObject *menu;
+
+ menu = gtk_builder_get_object (application->priv->menus_builder, "app-menu");
+ if (menu != NULL && G_IS_MENU_MODEL (menu))
+ gtk_application_set_app_menu (application, G_MENU_MODEL (menu));
+ menu = gtk_builder_get_object (application->priv->menus_builder, "menubar");
+ if (menu != NULL && G_IS_MENU_MODEL (menu))
+ gtk_application_set_menubar (application, G_MENU_MODEL (menu));
+ }
+ }
+}
+
+
+static void
gtk_application_startup (GApplication *g_application)
{
GtkApplication *application = GTK_APPLICATION (g_application);
@@ -512,6 +568,8 @@ gtk_application_startup (GApplication *g_application)
application->priv->impl = gtk_application_impl_new (application, gdk_display_get_default ());
gtk_application_impl_startup (application->priv->impl, application->priv->register_session);
+
+ gtk_application_load_resources (application);
}
static void
@@ -767,6 +825,7 @@ gtk_application_finalize (GObject *object)
{
GtkApplication *application = GTK_APPLICATION (object);
+ g_clear_object (&application->priv->menus_builder);
g_clear_object (&application->priv->app_menu);
g_clear_object (&application->priv->menubar);
g_clear_object (&application->priv->muxer);
@@ -1627,3 +1686,20 @@ gtk_application_handle_window_map (GtkApplication *application,
{
gtk_application_impl_handle_window_map (application->priv->impl, window);
}
+
+GMenu *
+gtk_application_get_menu_by_id (GtkApplication *application,
+ const gchar *id)
+{
+ GObject *object;
+
+ if (!application->priv->menus_builder)
+ return NULL;
+
+ object = gtk_builder_get_object (application->priv->menus_builder, id);
+
+ if (!object || !G_IS_MENU (object))
+ return NULL;
+
+ return G_MENU (object);
+}
diff --git a/gtk/gtkapplication.h b/gtk/gtkapplication.h
index 9d1af95e10..6fe1ff388c 100644
--- a/gtk/gtkapplication.h
+++ b/gtk/gtkapplication.h
@@ -154,6 +154,10 @@ void gtk_application_set_accels_for_action (GtkApplication
GDK_AVAILABLE_IN_3_14
gboolean gtk_application_prefers_app_menu (GtkApplication *application);
+GDK_AVAILABLE_IN_3_14
+GMenu * gtk_application_get_menu_by_id (GtkApplication *application,
+ const gchar *id);
+
G_END_DECLS
#endif /* __GTK_APPLICATION_H__ */