[tepl] amtk: copy part of TeplApplicationWindow
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tepl] amtk: copy part of TeplApplicationWindow
- Date: Fri, 14 Jul 2017 14:02:14 +0000 (UTC)
commit 6c25823de703697ef73e0e6afbef6118ecf491c7
Author: Sébastien Wilmet <swilmet gnome org>
Date: Thu Jul 13 19:50:47 2017 +0200
amtk: copy part of TeplApplicationWindow
amtk/Makefile.am | 2 +
amtk/amtk-application-window.c | 605 ++++++++++++++++++++++++++++++++++++++++
amtk/amtk-application-window.h | 80 ++++++
amtk/amtk-types.h | 1 +
amtk/amtk-utils.c | 129 +++++++++
amtk/amtk-utils.h | 12 +-
amtk/amtk.h | 1 +
7 files changed, 829 insertions(+), 1 deletions(-)
---
diff --git a/amtk/Makefile.am b/amtk/Makefile.am
index 3b3d7b4..2378db4 100644
--- a/amtk/Makefile.am
+++ b/amtk/Makefile.am
@@ -15,6 +15,7 @@ amtk_public_headers = \
amtk-action-info-central-store.h \
amtk-action-info-store.h \
amtk-action-map.h \
+ amtk-application-window.h \
amtk-menu-item.h \
amtk-menu-shell.h \
amtk-types.h
@@ -24,6 +25,7 @@ amtk_public_c_files = \
amtk-action-info-central-store.c \
amtk-action-info-store.c \
amtk-action-map.c \
+ amtk-application-window.c \
amtk-menu-item.c \
amtk-menu-shell.c
diff --git a/amtk/amtk-application-window.c b/amtk/amtk-application-window.c
new file mode 100644
index 0000000..c826f58
--- /dev/null
+++ b/amtk/amtk-application-window.c
@@ -0,0 +1,605 @@
+/*
+ * This file is part of Amtk - Actions, Menus and Toolbars Kit
+ *
+ * Copyright 2017 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * Amtk 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * Amtk 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "amtk-application-window.h"
+#include <glib/gi18n-lib.h>
+#include "amtk-action-info.h"
+#include "amtk-action-info-central-store.h"
+#include "amtk-menu-item.h"
+#include "amtk-menu-shell.h"
+#include "amtk-utils.h"
+
+/**
+ * SECTION:amtk-application-window
+ * @Short_description: An extension of GtkApplicationWindow
+ * @Title: AmtkApplicationWindow
+ *
+ * #AmtkApplicationWindow extends the #GtkApplicationWindow class.
+ *
+ * Note that #AmtkApplicationWindow extends the #GtkApplicationWindow class but
+ * without subclassing it, because several libraries might want to extend
+ * #GtkApplicationWindow and an application needs to be able to use all those
+ * extensions at the same time.
+ */
+
+struct _AmtkApplicationWindowPrivate
+{
+ GtkApplicationWindow *gtk_window;
+ GtkStatusbar *statusbar;
+};
+
+enum
+{
+ PROP_0,
+ PROP_APPLICATION_WINDOW,
+ PROP_STATUSBAR,
+ N_PROPERTIES
+};
+
+#define AMTK_APPLICATION_WINDOW_KEY "amtk-application-window-key"
+#define MENU_SHELL_STATUSBAR_CONTEXT_ID_KEY "amtk-menu-shell-statusbar-context-id-key"
+#define MENU_SHELL_FOR_RECENT_CHOOSER_KEY "amtk-menu-shell-for-recent-chooser-key"
+
+static GParamSpec *properties[N_PROPERTIES];
+
+G_DEFINE_TYPE_WITH_PRIVATE (AmtkApplicationWindow, amtk_application_window, G_TYPE_OBJECT)
+
+static void
+amtk_application_window_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AmtkApplicationWindow *amtk_window = AMTK_APPLICATION_WINDOW (object);
+
+ switch (prop_id)
+ {
+ case PROP_APPLICATION_WINDOW:
+ g_value_set_object (value, amtk_application_window_get_application_window
(amtk_window));
+ break;
+
+ case PROP_STATUSBAR:
+ g_value_set_object (value, amtk_application_window_get_statusbar (amtk_window));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+amtk_application_window_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AmtkApplicationWindow *amtk_window = AMTK_APPLICATION_WINDOW (object);
+
+ switch (prop_id)
+ {
+ case PROP_APPLICATION_WINDOW:
+ g_assert (amtk_window->priv->gtk_window == NULL);
+ amtk_window->priv->gtk_window = g_value_get_object (value);
+ break;
+
+ case PROP_STATUSBAR:
+ amtk_application_window_set_statusbar (amtk_window, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+amtk_application_window_dispose (GObject *object)
+{
+ AmtkApplicationWindow *amtk_window = AMTK_APPLICATION_WINDOW (object);
+
+ amtk_window->priv->gtk_window = NULL;
+ g_clear_object (&amtk_window->priv->statusbar);
+
+ G_OBJECT_CLASS (amtk_application_window_parent_class)->dispose (object);
+}
+
+static void
+amtk_application_window_class_init (AmtkApplicationWindowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = amtk_application_window_get_property;
+ object_class->set_property = amtk_application_window_set_property;
+ object_class->dispose = amtk_application_window_dispose;
+
+ /**
+ * AmtkApplicationWindow:application-window:
+ *
+ * The #GtkApplicationWindow.
+ *
+ * Since: 2.0
+ */
+ properties[PROP_APPLICATION_WINDOW] =
+ g_param_spec_object ("application-window",
+ "GtkApplicationWindow",
+ "",
+ GTK_TYPE_APPLICATION_WINDOW,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ /**
+ * AmtkApplicationWindow:statusbar:
+ *
+ * The #GtkStatusbar. %NULL by default.
+ *
+ * Since: 2.0
+ */
+ properties[PROP_STATUSBAR] =
+ g_param_spec_object ("statusbar",
+ "GtkStatusbar",
+ "",
+ GTK_TYPE_STATUSBAR,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static void
+amtk_application_window_init (AmtkApplicationWindow *amtk_window)
+{
+ amtk_window->priv = amtk_application_window_get_instance_private (amtk_window);
+}
+
+/**
+ * amtk_application_window_get_from_gtk_application_window:
+ * @gtk_window: a #GtkApplicationWindow.
+ *
+ * Returns the #AmtkApplicationWindow of @gtk_window. The returned object is
+ * guaranteed to be the same for the lifetime of @gtk_window.
+ *
+ * Returns: (transfer none): the #AmtkApplicationWindow of @gtk_window.
+ * Since: 2.0
+ */
+AmtkApplicationWindow *
+amtk_application_window_get_from_gtk_application_window (GtkApplicationWindow *gtk_window)
+{
+ AmtkApplicationWindow *amtk_window;
+
+ g_return_val_if_fail (GTK_IS_APPLICATION_WINDOW (gtk_window), NULL);
+
+ amtk_window = g_object_get_data (G_OBJECT (gtk_window), AMTK_APPLICATION_WINDOW_KEY);
+
+ if (amtk_window == NULL)
+ {
+ amtk_window = g_object_new (AMTK_TYPE_APPLICATION_WINDOW,
+ "application-window", gtk_window,
+ NULL);
+
+ g_object_set_data_full (G_OBJECT (gtk_window),
+ AMTK_APPLICATION_WINDOW_KEY,
+ amtk_window,
+ g_object_unref);
+ }
+
+ g_return_val_if_fail (AMTK_IS_APPLICATION_WINDOW (amtk_window), NULL);
+ return amtk_window;
+}
+
+/**
+ * amtk_application_window_get_application_window:
+ * @amtk_window: a #AmtkApplicationWindow.
+ *
+ * Returns: (transfer none): the #GtkApplicationWindow of @amtk_window.
+ * Since: 2.0
+ */
+GtkApplicationWindow *
+amtk_application_window_get_application_window (AmtkApplicationWindow *amtk_window)
+{
+ g_return_val_if_fail (AMTK_IS_APPLICATION_WINDOW (amtk_window), NULL);
+
+ return amtk_window->priv->gtk_window;
+}
+
+/**
+ * amtk_application_window_get_statusbar:
+ * @amtk_window: a #AmtkApplicationWindow.
+ *
+ * Returns: (transfer none) (nullable): the #AmtkApplicationWindow:statusbar.
+ * Since: 2.0
+ */
+GtkStatusbar *
+amtk_application_window_get_statusbar (AmtkApplicationWindow *amtk_window)
+{
+ g_return_val_if_fail (AMTK_IS_APPLICATION_WINDOW (amtk_window), NULL);
+
+ return amtk_window->priv->statusbar;
+}
+
+/**
+ * amtk_application_window_set_statusbar:
+ * @amtk_window: a #AmtkApplicationWindow.
+ * @statusbar: (nullable): a #GtkStatusbar, or %NULL.
+ *
+ * Sets the #AmtkApplicationWindow:statusbar property.
+ *
+ * Since: 2.0
+ */
+void
+amtk_application_window_set_statusbar (AmtkApplicationWindow *amtk_window,
+ GtkStatusbar *statusbar)
+{
+ g_return_if_fail (AMTK_IS_APPLICATION_WINDOW (amtk_window));
+ g_return_if_fail (statusbar == NULL || GTK_IS_STATUSBAR (statusbar));
+
+ if (amtk_window->priv->statusbar == statusbar)
+ {
+ return;
+ }
+
+ if (statusbar != NULL)
+ {
+ g_object_ref_sink (statusbar);
+ }
+
+ if (amtk_window->priv->statusbar != NULL)
+ {
+ g_object_unref (amtk_window->priv->statusbar);
+ }
+
+ amtk_window->priv->statusbar = statusbar;
+ g_object_notify_by_pspec (G_OBJECT (amtk_window), properties[PROP_STATUSBAR]);
+}
+
+/* Returns: %TRUE if a context ID exists and has been set to @context_id. */
+static gboolean
+get_statusbar_context_id_for_menu_shell (AmtkApplicationWindow *amtk_window,
+ AmtkMenuShell *amtk_menu_shell,
+ gboolean create,
+ guint *context_id)
+{
+ gpointer data;
+
+ g_assert (amtk_window->priv->statusbar != NULL);
+ g_assert (context_id != NULL);
+
+ data = g_object_get_data (G_OBJECT (amtk_menu_shell), MENU_SHELL_STATUSBAR_CONTEXT_ID_KEY);
+
+ if (data == NULL && !create)
+ {
+ return FALSE;
+ }
+
+ if (data == NULL)
+ {
+ *context_id = gtk_statusbar_get_context_id (amtk_window->priv->statusbar,
+ "Show long description of menu items.");
+
+ g_object_set_data (G_OBJECT (amtk_menu_shell),
+ MENU_SHELL_STATUSBAR_CONTEXT_ID_KEY,
+ GUINT_TO_POINTER (*context_id));
+ }
+ else
+ {
+ *context_id = GPOINTER_TO_UINT (data);
+ }
+
+ return TRUE;
+}
+
+/* Free the return value with g_free(). */
+static gchar *
+get_menu_item_long_description (AmtkMenuShell *amtk_menu_shell,
+ GtkMenuItem *menu_item)
+{
+ const gchar *long_description;
+ gpointer data;
+ gboolean is_for_recent_chooser;
+
+ long_description = amtk_menu_item_get_long_description (menu_item);
+ if (long_description != NULL)
+ {
+ return g_strdup (long_description);
+ }
+
+ data = g_object_get_data (G_OBJECT (amtk_menu_shell), MENU_SHELL_FOR_RECENT_CHOOSER_KEY);
+ is_for_recent_chooser = data != NULL ? GPOINTER_TO_INT (data) : FALSE;
+
+ if (is_for_recent_chooser)
+ {
+ GtkMenuShell *gtk_menu_shell;
+ GtkRecentChooserMenu *recent_chooser_menu;
+ gchar *uri;
+ GFile *file;
+ gchar *parse_name;
+ gchar *nicer_filename;
+ gchar *ret;
+
+ gtk_menu_shell = amtk_menu_shell_get_menu_shell (amtk_menu_shell);
+ recent_chooser_menu = GTK_RECENT_CHOOSER_MENU (gtk_menu_shell);
+ uri = amtk_utils_recent_chooser_menu_get_item_uri (recent_chooser_menu, menu_item);
+
+ if (uri == NULL)
+ {
+ return NULL;
+ }
+
+ file = g_file_new_for_uri (uri);
+ g_free (uri);
+
+ parse_name = g_file_get_parse_name (file);
+ g_object_unref (file);
+
+ nicer_filename = _amtk_utils_replace_home_dir_with_tilde (parse_name);
+ g_free (parse_name);
+
+ /* Translators: %s is a filename. */
+ ret = g_strdup_printf (_("Open “%s”"), nicer_filename);
+ g_free (nicer_filename);
+
+ return ret;
+ }
+
+ return NULL;
+}
+
+static void
+menu_item_selected_cb (AmtkMenuShell *amtk_menu_shell,
+ GtkMenuItem *menu_item,
+ gpointer user_data)
+{
+ AmtkApplicationWindow *amtk_window = AMTK_APPLICATION_WINDOW (user_data);
+ gchar *long_description;
+ guint context_id;
+
+ if (amtk_window->priv->statusbar == NULL)
+ {
+ return;
+ }
+
+ long_description = get_menu_item_long_description (amtk_menu_shell, menu_item);
+ if (long_description == NULL)
+ {
+ return;
+ }
+
+ get_statusbar_context_id_for_menu_shell (amtk_window,
+ amtk_menu_shell,
+ TRUE,
+ &context_id);
+
+ gtk_statusbar_push (amtk_window->priv->statusbar,
+ context_id,
+ long_description);
+
+ g_free (long_description);
+}
+
+static void
+menu_item_deselected_cb (AmtkMenuShell *amtk_menu_shell,
+ GtkMenuItem *menu_item,
+ gpointer user_data)
+{
+ AmtkApplicationWindow *amtk_window = AMTK_APPLICATION_WINDOW (user_data);
+ const gchar *long_description;
+ gpointer data;
+ gboolean is_for_recent_chooser;
+ guint context_id;
+
+ if (amtk_window->priv->statusbar == NULL)
+ {
+ return;
+ }
+
+ long_description = amtk_menu_item_get_long_description (menu_item);
+
+ data = g_object_get_data (G_OBJECT (amtk_menu_shell), MENU_SHELL_FOR_RECENT_CHOOSER_KEY);
+ is_for_recent_chooser = data != NULL ? GPOINTER_TO_INT (data) : FALSE;
+
+ if (long_description == NULL && !is_for_recent_chooser)
+ {
+ return;
+ }
+
+ if (get_statusbar_context_id_for_menu_shell (amtk_window,
+ amtk_menu_shell,
+ FALSE,
+ &context_id))
+ {
+ gtk_statusbar_pop (amtk_window->priv->statusbar, context_id);
+ }
+}
+
+static void
+statusbar_notify_cb (AmtkApplicationWindow *amtk_window,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ AmtkMenuShell *amtk_menu_shell = AMTK_MENU_SHELL (user_data);
+
+ g_object_set_data (G_OBJECT (amtk_menu_shell),
+ MENU_SHELL_STATUSBAR_CONTEXT_ID_KEY,
+ NULL);
+}
+
+/**
+ * amtk_application_window_connect_menu_to_statusbar:
+ * @amtk_window: a #AmtkApplicationWindow.
+ * @amtk_menu_shell: a #AmtkMenuShell.
+ *
+ * Connect to the #AmtkMenuShell::menu-item-selected and
+ * #AmtkMenuShell::menu-item-deselected signals of @amtk_menu_shell to push/pop
+ * the long description of #GtkMenuItem's to the
+ * #AmtkApplicationWindow:statusbar.
+ *
+ * The long description is retrieved with amtk_menu_item_get_long_description().
+ * So amtk_menu_item_set_long_description() must have been called, which is the
+ * case if the #GtkMenuItem has been created with the functions available in
+ * #AmtkActionInfoStore.
+ *
+ * Since: 2.0
+ */
+void
+amtk_application_window_connect_menu_to_statusbar (AmtkApplicationWindow *amtk_window,
+ AmtkMenuShell *amtk_menu_shell)
+{
+ g_return_if_fail (AMTK_IS_APPLICATION_WINDOW (amtk_window));
+ g_return_if_fail (AMTK_IS_MENU_SHELL (amtk_menu_shell));
+
+ g_signal_connect_object (amtk_menu_shell,
+ "menu-item-selected",
+ G_CALLBACK (menu_item_selected_cb),
+ amtk_window,
+ 0);
+
+ g_signal_connect_object (amtk_menu_shell,
+ "menu-item-deselected",
+ G_CALLBACK (menu_item_deselected_cb),
+ amtk_window,
+ 0);
+
+ g_signal_connect_object (amtk_window,
+ "notify::statusbar",
+ G_CALLBACK (statusbar_notify_cb),
+ amtk_menu_shell,
+ 0);
+}
+
+/**
+ * amtk_application_window_connect_recent_chooser_menu_to_statusbar:
+ * @amtk_window: a #AmtkApplicationWindow.
+ * @menu: a #GtkRecentChooserMenu.
+ *
+ * An alternative to gtk_recent_chooser_set_show_tips(). Shows the full path in
+ * the #AmtkApplicationWindow:statusbar when a #GtkMenuItem of @menu is
+ * selected.
+ *
+ * The full path is retrieved with
+ * amtk_utils_recent_chooser_menu_get_item_uri().
+ *
+ * Since: 2.0
+ */
+void
+amtk_application_window_connect_recent_chooser_menu_to_statusbar (AmtkApplicationWindow *amtk_window,
+ GtkRecentChooserMenu *menu)
+{
+ AmtkMenuShell *amtk_menu_shell;
+
+ g_return_if_fail (AMTK_IS_APPLICATION_WINDOW (amtk_window));
+ g_return_if_fail (GTK_IS_RECENT_CHOOSER_MENU (menu));
+
+ amtk_menu_shell = amtk_menu_shell_get_from_gtk_menu_shell (GTK_MENU_SHELL (menu));
+
+ g_object_set_data (G_OBJECT (amtk_menu_shell),
+ MENU_SHELL_FOR_RECENT_CHOOSER_KEY,
+ GINT_TO_POINTER (TRUE));
+
+ amtk_application_window_connect_menu_to_statusbar (amtk_window, amtk_menu_shell);
+}
+
+static void
+open_recent_file_cb (GtkRecentChooser *recent_chooser,
+ gpointer user_data)
+{
+ AmtkApplicationWindow *amtk_window = AMTK_APPLICATION_WINDOW (user_data);
+ GtkApplication *gtk_app;
+ AmtkApplication *amtk_app;
+ gchar *uri;
+ GFile *file;
+
+ gtk_app = gtk_window_get_application (GTK_WINDOW (amtk_window->priv->gtk_window));
+ amtk_app = amtk_application_get_from_gtk_application (gtk_app);
+
+ uri = gtk_recent_chooser_get_current_uri (recent_chooser);
+ file = g_file_new_for_uri (uri);
+
+ amtk_application_open_simple (amtk_app, file);
+
+ g_free (uri);
+ g_object_unref (file);
+}
+
+/**
+ * amtk_application_window_create_open_recent_menu_item:
+ * @amtk_window: a #AmtkApplicationWindow.
+ *
+ * Creates a #GtkMenuItem with a simple and generic #GtkRecentChooserMenu as
+ * submenu.
+ *
+ * The #GtkRecentChooser is configured to show files only recently used with the
+ * current application, as returned by g_get_application_name(). If recent files
+ * are added to the default #GtkRecentManager with
+ * gtk_recent_manager_add_item(), the files will normally show up in the
+ * #GtkRecentChooserMenu.
+ *
+ * The #GtkRecentChooserMenu is connected to the statusbar with
+ * amtk_application_window_connect_recent_chooser_menu_to_statusbar().
+ *
+ * When the #GtkRecentChooser::item-activated signal is emitted,
+ * amtk_application_open_simple() is called, so the #GApplication must have the
+ * %G_APPLICATION_HANDLES_OPEN flag set.
+ *
+ * Returns: (transfer floating): a new #GtkMenuItem.
+ * Since: 2.0
+ */
+GtkWidget *
+amtk_application_window_create_open_recent_menu_item (AmtkApplicationWindow *amtk_window)
+{
+ GtkMenuItem *menu_item;
+ gchar *long_description;
+ GtkRecentChooserMenu *recent_chooser_menu;
+ GtkRecentChooser *recent_chooser;
+ GtkRecentFilter *filter;
+
+ g_return_val_if_fail (AMTK_IS_APPLICATION_WINDOW (amtk_window), NULL);
+
+ menu_item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("Open _Recent")));
+
+ /* Translators: %s is the application name. */
+ long_description = g_strdup_printf (_("Open a file recently used with %s"),
+ g_get_application_name ());
+ amtk_menu_item_set_long_description (menu_item, long_description);
+ g_free (long_description);
+
+ recent_chooser_menu = GTK_RECENT_CHOOSER_MENU (gtk_recent_chooser_menu_new ());
+ gtk_menu_item_set_submenu (menu_item, GTK_WIDGET (recent_chooser_menu));
+
+ recent_chooser = GTK_RECENT_CHOOSER (recent_chooser_menu);
+ gtk_recent_chooser_set_local_only (recent_chooser, FALSE);
+ gtk_recent_chooser_set_sort_type (recent_chooser, GTK_RECENT_SORT_MRU);
+
+ filter = gtk_recent_filter_new ();
+ gtk_recent_filter_add_application (filter, g_get_application_name ());
+ gtk_recent_chooser_set_filter (recent_chooser, filter);
+
+ amtk_application_window_connect_recent_chooser_menu_to_statusbar (amtk_window, recent_chooser_menu);
+
+ g_signal_connect_object (recent_chooser,
+ "item-activated",
+ G_CALLBACK (open_recent_file_cb),
+ amtk_window,
+ 0);
+
+ return GTK_WIDGET (menu_item);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/amtk/amtk-application-window.h b/amtk/amtk-application-window.h
new file mode 100644
index 0000000..918cac9
--- /dev/null
+++ b/amtk/amtk-application-window.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of Amtk - Actions, Menus and Toolbars Kit
+ *
+ * Copyright 2017 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * Amtk 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * Amtk 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef AMTK_APPLICATION_WINDOW_H
+#define AMTK_APPLICATION_WINDOW_H
+
+#if !defined (AMTK_H_INSIDE) && !defined (AMTK_COMPILATION)
+#error "Only <amtk/amtk.h> can be included directly."
+#endif
+
+#include <gtk/gtk.h>
+#include <amtk/amtk-types.h>
+
+G_BEGIN_DECLS
+
+#define AMTK_TYPE_APPLICATION_WINDOW (amtk_application_window_get_type ())
+#define AMTK_APPLICATION_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
AMTK_TYPE_APPLICATION_WINDOW, AmtkApplicationWindow))
+#define AMTK_APPLICATION_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
AMTK_TYPE_APPLICATION_WINDOW, AmtkApplicationWindowClass))
+#define AMTK_IS_APPLICATION_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
AMTK_TYPE_APPLICATION_WINDOW))
+#define AMTK_IS_APPLICATION_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
AMTK_TYPE_APPLICATION_WINDOW))
+#define AMTK_APPLICATION_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
AMTK_TYPE_APPLICATION_WINDOW, AmtkApplicationWindowClass))
+
+typedef struct _AmtkApplicationWindowClass AmtkApplicationWindowClass;
+typedef struct _AmtkApplicationWindowPrivate AmtkApplicationWindowPrivate;
+
+struct _AmtkApplicationWindow
+{
+ GObject parent;
+
+ AmtkApplicationWindowPrivate *priv;
+};
+
+struct _AmtkApplicationWindowClass
+{
+ GObjectClass parent_class;
+
+ gpointer padding[12];
+};
+
+GType amtk_application_window_get_type (void) G_GNUC_CONST;
+
+AmtkApplicationWindow * amtk_application_window_get_from_gtk_application_window (GtkApplicationWindow
*gtk_window);
+
+GtkApplicationWindow * amtk_application_window_get_application_window (AmtkApplicationWindow
*amtk_window);
+
+GtkStatusbar * amtk_application_window_get_statusbar (AmtkApplicationWindow
*amtk_window);
+
+void amtk_application_window_set_statusbar (AmtkApplicationWindow
*amtk_window,
+ GtkStatusbar
*statusbar);
+
+void amtk_application_window_connect_menu_to_statusbar (AmtkApplicationWindow
*amtk_window,
+ AmtkMenuShell
*amtk_menu_shell);
+
+void amtk_application_window_connect_recent_chooser_menu_to_statusbar
+ (AmtkApplicationWindow
*amtk_window,
+ GtkRecentChooserMenu *menu);
+
+GtkWidget * amtk_application_window_create_open_recent_menu_item (AmtkApplicationWindow
*amtk_window);
+
+G_END_DECLS
+
+#endif /* AMTK_APPLICATION_WINDOW_H */
+
+/* ex:set ts=8 noet: */
diff --git a/amtk/amtk-types.h b/amtk/amtk-types.h
index e3d359e..7575550 100644
--- a/amtk/amtk-types.h
+++ b/amtk/amtk-types.h
@@ -32,6 +32,7 @@ typedef struct _AmtkActionInfo AmtkActionInfo;
typedef struct _AmtkActionInfoEntry AmtkActionInfoEntry;
typedef struct _AmtkActionInfoStore AmtkActionInfoStore;
typedef struct _AmtkActionInfoCentralStore AmtkActionInfoCentralStore;
+typedef struct _AmtkApplicationWindow AmtkApplicationWindow;
typedef struct _AmtkMenuShell AmtkMenuShell;
G_END_DECLS
diff --git a/amtk/amtk-utils.c b/amtk/amtk-utils.c
index 091f981..c0aa974 100644
--- a/amtk/amtk-utils.c
+++ b/amtk/amtk-utils.c
@@ -18,6 +18,60 @@
*/
#include "amtk-utils.h"
+#include <string.h>
+
+/*
+ * _amtk_utils_replace_home_dir_with_tilde:
+ * @filename: the filename.
+ *
+ * Replaces the home directory with a tilde, if the home directory is present in
+ * the @filename.
+ *
+ * Returns: the new filename. Free with g_free().
+ */
+/* This function comes from gedit. */
+gchar *
+_amtk_utils_replace_home_dir_with_tilde (const gchar *filename)
+{
+ gchar *tmp;
+ gchar *home;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ /* Note that g_get_home_dir returns a const string */
+ tmp = (gchar *) g_get_home_dir ();
+
+ if (tmp == NULL)
+ {
+ return g_strdup (filename);
+ }
+
+ home = g_filename_to_utf8 (tmp, -1, NULL, NULL, NULL);
+ if (home == NULL)
+ {
+ return g_strdup (filename);
+ }
+
+ if (g_str_equal (filename, home))
+ {
+ g_free (home);
+ return g_strdup ("~");
+ }
+
+ tmp = home;
+ home = g_strdup_printf ("%s/", tmp);
+ g_free (tmp);
+
+ if (g_str_has_prefix (filename, home))
+ {
+ gchar *res = g_strdup_printf ("~/%s", filename + strlen (home));
+ g_free (home);
+ return res;
+ }
+
+ g_free (home);
+ return g_strdup (filename);
+}
/* Deep copy of @strv. */
gchar **
@@ -45,3 +99,78 @@ _amtk_utils_strv_copy (const gchar * const *strv)
return new_strv;
}
+
+static gint
+get_menu_item_position (GtkMenuShell *menu_shell,
+ GtkMenuItem *item)
+{
+ GList *children;
+ GList *l;
+ gint pos;
+ gboolean found = FALSE;
+
+ children = gtk_container_get_children (GTK_CONTAINER (menu_shell));
+
+ for (l = children, pos = 0; l != NULL; l = l->next, pos++)
+ {
+ GtkMenuItem *cur_item = l->data;
+
+ if (cur_item == item)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ g_list_free (children);
+
+ return found ? pos : -1;
+}
+
+/**
+ * amtk_utils_recent_chooser_menu_get_item_uri:
+ * @menu: a #GtkRecentChooserMenu.
+ * @item: a #GtkMenuItem.
+ *
+ * Gets the URI of @item. @item must be a child of @menu. @menu must be a
+ * #GtkRecentChooserMenu.
+ *
+ * This function has been written because the value returned by
+ * gtk_recent_chooser_get_current_uri() is not updated when #GtkMenuItem's of a
+ * #GtkRecentChooserMenu are selected/deselected.
+ *
+ * Returns: the URI of @item. Free with g_free() when no longer needed.
+ * Since: 2.0
+ */
+gchar *
+amtk_utils_recent_chooser_menu_get_item_uri (GtkRecentChooserMenu *menu,
+ GtkMenuItem *item)
+{
+ gint pos;
+ gchar **all_uris;
+ gsize length;
+ gchar *item_uri = NULL;
+
+ g_return_val_if_fail (GTK_IS_RECENT_CHOOSER_MENU (menu), NULL);
+ g_return_val_if_fail (GTK_IS_MENU_ITEM (item), NULL);
+
+ {
+ GtkWidget *item_parent;
+
+ item_parent = gtk_widget_get_parent (GTK_WIDGET (item));
+ g_return_val_if_fail (item_parent == GTK_WIDGET (menu), NULL);
+ }
+
+ pos = get_menu_item_position (GTK_MENU_SHELL (menu), item);
+ g_return_val_if_fail (pos >= 0, NULL);
+
+ all_uris = gtk_recent_chooser_get_uris (GTK_RECENT_CHOOSER (menu), &length);
+
+ if ((gsize)pos < length)
+ {
+ item_uri = g_strdup (all_uris[pos]);
+ }
+
+ g_strfreev (all_uris);
+ return item_uri;
+}
diff --git a/amtk/amtk-utils.h b/amtk/amtk-utils.h
index 7ee743e..8929849 100644
--- a/amtk/amtk-utils.h
+++ b/amtk/amtk-utils.h
@@ -20,15 +20,25 @@
#ifndef AMTK_UTILS_H
#define AMTK_UTILS_H
-#include <glib.h>
+#include <gtk/gtk.h>
G_BEGIN_DECLS
+/* File utilities */
+
+G_GNUC_INTERNAL
+gchar * _amtk_utils_replace_home_dir_with_tilde (const gchar *filename);
+
/* String utilities */
G_GNUC_INTERNAL
gchar ** _amtk_utils_strv_copy (const gchar * const *strv);
+/* Widget utilities */
+
+gchar * amtk_utils_recent_chooser_menu_get_item_uri (GtkRecentChooserMenu *menu,
+ GtkMenuItem *item);
+
G_END_DECLS
#endif /* AMTK_UTILS_H */
diff --git a/amtk/amtk.h b/amtk/amtk.h
index 985e3ad..699fbeb 100644
--- a/amtk/amtk.h
+++ b/amtk/amtk.h
@@ -28,6 +28,7 @@
#include <amtk/amtk-action-info-store.h>
#include <amtk/amtk-action-info-central-store.h>
#include <amtk/amtk-action-map.h>
+#include <amtk/amtk-application-window.h>
#include <amtk/amtk-menu-item.h>
#include <amtk/amtk-menu-shell.h>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]