[evince/wip/gmenu: 2/4] Move application-wide actions to EvApplication
- From: Lars Uebernickel <larsu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince/wip/gmenu: 2/4] Move application-wide actions to EvApplication
- Date: Mon, 3 Feb 2014 17:39:46 +0000 (UTC)
commit 35cf66c84c1931ecabe753827dd25ffef651ff74
Author: Lars Uebernickel <lars uebernickel canonical com>
Date: Thu Jan 30 15:13:25 2014 +0100
Move application-wide actions to EvApplication
"Open" and "About" actions are independent of existing windows and can
live directly on the application object. This patch also adds those two
actions to the app menu.
Small regression: the comment field is not filled with information of
the backend used for the document in the current window anymore. It's
unclear which information should be shown there when multiple windows
with different backends are open.
shell/ev-application.c | 161 ++++++++++++++++++++++++++++++++
shell/ev-application.h | 4 +
shell/ev-utils.c | 89 ++++++++++++++++++
shell/ev-utils.h | 7 ++
shell/ev-window.c | 234 +++-------------------------------------------
shell/evince-appmenu.ui | 10 ++
6 files changed, 287 insertions(+), 218 deletions(-)
---
diff --git a/shell/ev-application.c b/shell/ev-application.c
index 3a842f9..6630c36 100644
--- a/shell/ev-application.c
+++ b/shell/ev-application.c
@@ -42,6 +42,8 @@
#include "ev-application.h"
#include "ev-file-helpers.h"
#include "ev-stock-icons.h"
+#include "ev-utils.h"
+#include "ev-document-factory.h"
#ifdef ENABLE_DBUS
#include "ev-gdbus-generated.h"
@@ -1012,6 +1014,26 @@ app_help_cb (GSimpleAction *action,
}
static void
+app_about_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ EvApplication *application = user_data;
+
+ ev_application_show_about (application);
+}
+
+static void
+app_open_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ EvApplication *application = user_data;
+
+ ev_application_open (application);
+}
+
+static void
ev_application_dispose (GObject *object)
{
EvApplication *app = EV_APPLICATION (object);
@@ -1025,6 +1047,8 @@ static void
ev_application_startup (GApplication *gapplication)
{
const GActionEntry app_menu_actions[] = {
+ { "open", app_open_cb, NULL, NULL, NULL },
+ { "about", app_about_cb, NULL, NULL, NULL },
{ "help", app_help_cb, NULL, NULL, NULL },
};
@@ -1274,6 +1298,143 @@ ev_application_show_help (EvApplication *application,
g_free (uri);
}
+/**
+ * ev_application_show_about:
+ * @application: an #EvApplication
+ *
+ * Shows an about dialog for @application with the most recently
+ * focussed window as transient parent.
+ */
+void
+ev_application_show_about (EvApplication *application)
+{
+ const char *authors[] = {
+ "Martin Kretzschmar <m_kretzschmar gmx net>",
+ "Jonathan Blandford <jrb gnome org>",
+ "Marco Pesenti Gritti <marco gnome org>",
+ "Nickolay V. Shmyrev <nshmyrev yandex ru>",
+ "Bryan Clark <clarkbw gnome org>",
+ "Carlos Garcia Campos <carlosgc gnome org>",
+ "Wouter Bolsterlee <wbolster gnome org>",
+ "Christian Persch <chpe" "\100" "gnome.org>",
+ NULL
+ };
+
+ const char *documenters[] = {
+ "Nickolay V. Shmyrev <nshmyrev yandex ru>",
+ "Phil Bull <philbull gmail com>",
+ "Tiffany Antpolski <tiffany antopolski gmail com>",
+ NULL
+ };
+
+ const char *license[] = {
+ N_("Evince is free software; you can redistribute it and/or modify "
+ "it under the terms of the GNU General Public License as published by "
+ "the Free Software Foundation; either version 2 of the License, or "
+ "(at your option) any later version.\n"),
+ N_("Evince 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 General Public License for more details.\n"),
+ N_("You should have received a copy of the GNU General Public License "
+ "along with Evince; if not, write to the Free Software Foundation, Inc., "
+ "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n")
+ };
+
+ char *license_trans;
+
+#ifdef ENABLE_NLS
+ const char **p;
+
+ for (p = authors; *p; ++p)
+ *p = _(*p);
+
+ for (p = documenters; *p; ++p)
+ *p = _(*p);
+#endif
+
+ license_trans = g_strconcat (_(license[0]), "\n", _(license[1]), "\n",
+ _(license[2]), "\n", NULL);
+
+ gtk_show_about_dialog (
+ gtk_application_get_active_window (GTK_APPLICATION (application)),
+ "name", _("Evince"),
+ "version", VERSION,
+ "copyright",
+ _("© 1996–2012 The Evince authors"),
+ "license", license_trans,
+ "website", "http://www.gnome.org/projects/evince",
+ "authors", authors,
+ "documenters", documenters,
+ "translator-credits", _("translator-credits"),
+ "logo-icon-name", "evince",
+ "wrap-license", TRUE,
+ NULL);
+
+ g_free (license_trans);
+}
+
+static void
+ev_application_open_dialog_response (GtkWidget *chooser,
+ gint response_id,
+ gpointer user_data)
+{
+ if (response_id == GTK_RESPONSE_OK) {
+ GSList *uris;
+
+ ev_file_chooser_save_folder (GTK_FILE_CHOOSER (chooser),
+ G_USER_DIRECTORY_DOCUMENTS);
+
+ uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (chooser));
+
+ ev_application_open_uri_list (EV_APP, uris,
+ gtk_widget_get_screen (chooser),
+ gtk_get_current_event_time ());
+
+ g_slist_foreach (uris, (GFunc)g_free, NULL);
+ g_slist_free (uris);
+ }
+
+ gtk_widget_destroy (chooser);
+}
+
+/**
+ * ev_application_open:
+ * @application: an #EvApplication
+ *
+ * Shows an open dialog and opens the chosen document(s) in new windows.
+ *
+ * The dialog's parent will be the most recently focussed window of
+ * @application.
+ */
+void
+ev_application_open (EvApplication *application)
+{
+ GtkWidget *chooser;
+ GtkWindow *active_window;
+
+ active_window = gtk_application_get_active_window (GTK_APPLICATION (application));
+
+ chooser = gtk_file_chooser_dialog_new (_("Open Document"),
+ active_window,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("Cancel"), GTK_RESPONSE_CANCEL,
+ _("Open"), GTK_RESPONSE_OK,
+ NULL);
+
+ ev_document_factory_add_filters (chooser, NULL);
+ gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), FALSE);
+
+ ev_file_chooser_restore_folder (GTK_FILE_CHOOSER (chooser),
+ NULL, G_USER_DIRECTORY_DOCUMENTS);
+
+ g_signal_connect (chooser, "response",
+ G_CALLBACK (ev_application_open_dialog_response), NULL);
+
+ gtk_widget_show (chooser);
+}
+
GSettings *
ev_application_get_settings (EvApplication *application)
{
diff --git a/shell/ev-application.h b/shell/ev-application.h
index dadf1a7..fd9b886 100644
--- a/shell/ev-application.h
+++ b/shell/ev-application.h
@@ -76,6 +76,10 @@ void ev_application_show_help (EvApplication *applicati
GdkScreen *screen,
const char *topic);
+void ev_application_show_about (EvApplication *application);
+
+void ev_application_open (EvApplication *application);
+
GSettings * ev_application_get_settings (EvApplication *application);
G_END_DECLS
diff --git a/shell/ev-utils.c b/shell/ev-utils.c
index a3cf0da..760a8e9 100644
--- a/shell/ev-utils.c
+++ b/shell/ev-utils.c
@@ -22,6 +22,7 @@
#include "ev-utils.h"
#include "ev-file-helpers.h"
+#include "ev-application.h"
#include <string.h>
#include <math.h>
@@ -391,3 +392,91 @@ get_gdk_pixbuf_format_by_extension (const gchar *uri)
g_slist_free (pixbuf_formats);
return NULL;
}
+
+static const gchar *
+get_settings_key_for_directory (GUserDirectory directory)
+{
+ switch (directory) {
+ case G_USER_DIRECTORY_PICTURES:
+ return "pictures-directory";
+ case G_USER_DIRECTORY_DOCUMENTS:
+ default:
+ return "document-directory";
+ }
+}
+
+/**
+ * ev_file_chooser_save_folder:
+ * @file_chooser: a #GtkFileChooser
+ * @uri: (allow-none): optional fallback path
+ * @directory: the #GUserDirectory from which to restore
+ *
+ * Saves the directory of @file_chooser for @directory. Use
+ * ev_file_chooser_restore_folder() to restore this folder in a
+ * different file chooser.
+ */
+void
+ev_file_chooser_save_folder (GtkFileChooser *file_chooser,
+ GUserDirectory directory)
+{
+ gchar *uri, *folder;
+
+ folder = gtk_file_chooser_get_current_folder (file_chooser);
+ if (g_strcmp0 (folder, g_get_user_special_dir (directory)) == 0) {
+ /* Store 'nothing' if the folder is the default one */
+ uri = NULL;
+ } else {
+ uri = gtk_file_chooser_get_current_folder_uri (file_chooser);
+ }
+ g_free (folder);
+
+ g_settings_set (ev_application_get_settings (EV_APP),
+ get_settings_key_for_directory (directory),
+ "ms", uri);
+ g_free (uri);
+}
+
+/**
+ * ev_file_chooser_restore_folder:
+ * @file_chooser: a #GtkFileChooser
+ * @uri: (allow-none): optional fallback path
+ * @directory: the #GUserDirectory from which to restore
+ *
+ * Sets the folder of @file_chooser to the last-visited directory for
+ * the given @directory type.
+ */
+void
+ev_file_chooser_restore_folder (GtkFileChooser *file_chooser,
+ const gchar *uri,
+ GUserDirectory directory)
+{
+ const gchar *dir;
+ gchar *folder_uri;
+ gchar *parent_uri = NULL;
+
+ g_settings_get (ev_application_get_settings (EV_APP),
+ get_settings_key_for_directory (directory),
+ "ms", &folder_uri);
+ if (folder_uri == NULL && uri != NULL) {
+ GFile *file, *parent;
+
+ file = g_file_new_for_uri (uri);
+ parent = g_file_get_parent (file);
+ g_object_unref (file);
+ if (parent) {
+ folder_uri = parent_uri = g_file_get_uri (parent);
+ g_object_unref (parent);
+ }
+ }
+
+ if (folder_uri) {
+ gtk_file_chooser_set_current_folder_uri (file_chooser, folder_uri);
+ } else {
+ dir = g_get_user_special_dir (directory);
+ gtk_file_chooser_set_current_folder (file_chooser,
+ dir ? dir : g_get_home_dir ());
+ }
+
+ g_free (folder_uri);
+ g_free (parent_uri);
+}
diff --git a/shell/ev-utils.h b/shell/ev-utils.h
index bcbe2fb..0ebd3ab 100644
--- a/shell/ev-utils.h
+++ b/shell/ev-utils.h
@@ -42,6 +42,13 @@ gint get_num_monitors (GtkWindow * window);
void file_chooser_dialog_add_writable_pixbuf_formats (GtkFileChooser *chooser);
GdkPixbufFormat* get_gdk_pixbuf_format_by_extension (const gchar *uri);
+void ev_file_chooser_save_folder (GtkFileChooser *file_chooser,
+ GUserDirectory directory);
+
+void ev_file_chooser_restore_folder (GtkFileChooser *file_chooser,
+ const gchar *uri,
+ GUserDirectory directory);
+
G_END_DECLS
#endif /* __EV_VIEW_H__ */
diff --git a/shell/ev-window.c b/shell/ev-window.c
index 5201980..43a0034 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -262,8 +262,6 @@ struct _EvWindowPrivate {
#define GS_OVERRIDE_RESTRICTIONS "override-restrictions"
#define GS_PAGE_CACHE_SIZE "page-cache-size"
#define GS_AUTO_RELOAD "auto-reload"
-#define GS_LAST_DOCUMENT_DIRECTORY "document-directory"
-#define GS_LAST_PICTURES_DIRECTORY "pictures-directory"
#define SIDEBAR_DEFAULT_SIZE 132
#define LINKS_SIDEBAR_ID "links"
@@ -2391,124 +2389,10 @@ ev_window_reload_document (EvWindow *ev_window,
}
}
-static const gchar *
-get_settings_key_for_directory (GUserDirectory directory)
-{
- switch (directory) {
- case G_USER_DIRECTORY_PICTURES:
- return GS_LAST_PICTURES_DIRECTORY;
- case G_USER_DIRECTORY_DOCUMENTS:
- default:
- return GS_LAST_DOCUMENT_DIRECTORY;
- }
-}
-
-static void
-ev_window_file_chooser_restore_folder (EvWindow *window,
- GtkFileChooser *file_chooser,
- const gchar *uri,
- GUserDirectory directory)
-{
- const gchar *folder_uri, *dir;
- gchar *parent_uri = NULL;
-
- g_settings_get (ev_application_get_settings (EV_APP),
- get_settings_key_for_directory (directory),
- "m&s", &folder_uri);
- if (folder_uri == NULL && uri != NULL) {
- GFile *file, *parent;
-
- file = g_file_new_for_uri (uri);
- parent = g_file_get_parent (file);
- g_object_unref (file);
- if (parent) {
- folder_uri = parent_uri = g_file_get_uri (parent);
- g_object_unref (parent);
- }
- }
-
- if (folder_uri) {
- gtk_file_chooser_set_current_folder_uri (file_chooser, folder_uri);
- } else {
- dir = g_get_user_special_dir (directory);
- gtk_file_chooser_set_current_folder (file_chooser,
- dir ? dir : g_get_home_dir ());
- }
-
- g_free (parent_uri);
-}
-
-static void
-ev_window_file_chooser_save_folder (EvWindow *window,
- GtkFileChooser *file_chooser,
- GUserDirectory directory)
-{
- gchar *uri, *folder;
-
- folder = gtk_file_chooser_get_current_folder (file_chooser);
- if (g_strcmp0 (folder, g_get_user_special_dir (directory)) == 0) {
- /* Store 'nothing' if the folder is the default one */
- uri = NULL;
- } else {
- uri = gtk_file_chooser_get_current_folder_uri (file_chooser);
- }
- g_free (folder);
-
- g_settings_set (ev_application_get_settings (EV_APP),
- get_settings_key_for_directory (directory),
- "ms", uri);
- g_free (uri);
-}
-
-static void
-file_open_dialog_response_cb (GtkWidget *chooser,
- gint response_id,
- EvWindow *ev_window)
-{
- if (response_id == GTK_RESPONSE_OK) {
- GSList *uris;
-
- ev_window_file_chooser_save_folder (ev_window, GTK_FILE_CHOOSER (chooser),
- G_USER_DIRECTORY_DOCUMENTS);
-
- uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (chooser));
-
- ev_application_open_uri_list (EV_APP, uris,
- gtk_window_get_screen (GTK_WINDOW (ev_window)),
- gtk_get_current_event_time ());
-
- g_slist_foreach (uris, (GFunc)g_free, NULL);
- g_slist_free (uris);
- }
-
- gtk_widget_destroy (chooser);
-}
-
static void
ev_window_cmd_file_open (GtkAction *action, EvWindow *window)
{
- GtkWidget *chooser;
-
- chooser = gtk_file_chooser_dialog_new (_("Open Document"),
- GTK_WINDOW (window),
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL,
- GTK_STOCK_OPEN, GTK_RESPONSE_OK,
- NULL);
-
- ev_document_factory_add_filters (chooser, NULL);
- gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE);
- gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), FALSE);
-
- ev_window_file_chooser_restore_folder (window, GTK_FILE_CHOOSER (chooser),
- NULL, G_USER_DIRECTORY_DOCUMENTS);
-
- g_signal_connect (chooser, "response",
- G_CALLBACK (file_open_dialog_response_cb),
- window);
-
- gtk_widget_show (chooser);
+ ev_application_open (EV_APP);
}
static void
@@ -2933,8 +2817,8 @@ file_save_dialog_response_cb (GtkWidget *fc,
return;
}
- ev_window_file_chooser_save_folder (ev_window, GTK_FILE_CHOOSER (fc),
- G_USER_DIRECTORY_DOCUMENTS);
+ ev_file_chooser_save_folder (GTK_FILE_CHOOSER (fc),
+ G_USER_DIRECTORY_DOCUMENTS);
uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
@@ -2984,9 +2868,9 @@ ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
g_object_unref (file);
g_free (base_name);
- ev_window_file_chooser_restore_folder (ev_window, GTK_FILE_CHOOSER (fc),
- ev_window->priv->uri,
- G_USER_DIRECTORY_DOCUMENTS);
+ ev_file_chooser_restore_folder (GTK_FILE_CHOOSER (fc),
+ ev_window->priv->uri,
+ G_USER_DIRECTORY_DOCUMENTS);
g_signal_connect (fc, "response",
G_CALLBACK (file_save_dialog_response_cb),
@@ -5002,96 +4886,10 @@ ev_window_dual_mode_odd_pages_left_changed_cb (EvDocumentModel *model,
ev_document_model_get_dual_page_odd_pages_left (model));
}
-static char *
-build_comments_string (EvDocument *document)
-{
- gchar *comments = NULL;
- EvDocumentBackendInfo info;
-
- if (document && ev_document_get_backend_info (document, &info)) {
- comments = g_strdup_printf (
- _("Document Viewer\nUsing %s (%s)"),
- info.name, info.version);
- } else {
- comments = g_strdup_printf (
- _("Document Viewer"));
- }
-
- return comments;
-}
-
static void
ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
{
- const char *authors[] = {
- "Martin Kretzschmar <m_kretzschmar gmx net>",
- "Jonathan Blandford <jrb gnome org>",
- "Marco Pesenti Gritti <marco gnome org>",
- "Nickolay V. Shmyrev <nshmyrev yandex ru>",
- "Bryan Clark <clarkbw gnome org>",
- "Carlos Garcia Campos <carlosgc gnome org>",
- "Wouter Bolsterlee <wbolster gnome org>",
- "Christian Persch <chpe" "\100" "gnome.org>",
- NULL
- };
-
- const char *documenters[] = {
- "Nickolay V. Shmyrev <nshmyrev yandex ru>",
- "Phil Bull <philbull gmail com>",
- "Tiffany Antpolski <tiffany antopolski gmail com>",
- NULL
- };
-
- const char *license[] = {
- N_("Evince is free software; you can redistribute it and/or modify "
- "it under the terms of the GNU General Public License as published by "
- "the Free Software Foundation; either version 2 of the License, or "
- "(at your option) any later version.\n"),
- N_("Evince 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 General Public License for more details.\n"),
- N_("You should have received a copy of the GNU General Public License "
- "along with Evince; if not, write to the Free Software Foundation, Inc., "
- "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n")
- };
-
- char *license_trans;
- char *comments;
-
-#ifdef ENABLE_NLS
- const char **p;
-
- for (p = authors; *p; ++p)
- *p = _(*p);
-
- for (p = documenters; *p; ++p)
- *p = _(*p);
-#endif
-
- license_trans = g_strconcat (_(license[0]), "\n", _(license[1]), "\n",
- _(license[2]), "\n", NULL);
-
- comments = build_comments_string (ev_window->priv->document);
-
- gtk_show_about_dialog (
- GTK_WINDOW (ev_window),
- "name", _("Evince"),
- "version", VERSION,
- "copyright",
- _("© 1996–2012 The Evince authors"),
- "license", license_trans,
- "website", "http://www.gnome.org/projects/evince",
- "comments", comments,
- "authors", authors,
- "documenters", documenters,
- "translator-credits", _("translator-credits"),
- "logo-icon-name", "evince",
- "wrap-license", TRUE,
- NULL);
-
- g_free (comments);
- g_free (license_trans);
+ ev_application_show_about (EV_APP);
}
static void
@@ -6777,8 +6575,8 @@ image_save_dialog_response_cb (GtkWidget *fc,
return;
}
- ev_window_file_chooser_save_folder (ev_window, GTK_FILE_CHOOSER (fc),
- G_USER_DIRECTORY_PICTURES);
+ ev_file_chooser_save_folder (GTK_FILE_CHOOSER (fc),
+ G_USER_DIRECTORY_PICTURES);
uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (fc));
@@ -6882,9 +6680,9 @@ ev_view_popup_cmd_save_image_as (GtkAction *action, EvWindow *window)
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
file_chooser_dialog_add_writable_pixbuf_formats (GTK_FILE_CHOOSER (fc));
-
- ev_window_file_chooser_restore_folder (window, GTK_FILE_CHOOSER (fc), NULL,
- G_USER_DIRECTORY_PICTURES);
+
+ ev_file_chooser_restore_folder (GTK_FILE_CHOOSER (fc), NULL,
+ G_USER_DIRECTORY_PICTURES);
g_signal_connect (fc, "response",
G_CALLBACK (image_save_dialog_response_cb),
@@ -7018,8 +6816,8 @@ attachment_save_dialog_response_cb (GtkWidget *fc,
return;
}
- ev_window_file_chooser_save_folder (ev_window, GTK_FILE_CHOOSER (fc),
- G_USER_DIRECTORY_DOCUMENTS);
+ ev_file_chooser_save_folder (GTK_FILE_CHOOSER (fc),
+ G_USER_DIRECTORY_DOCUMENTS);
uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
target_file = g_file_new_for_uri (uri);
@@ -7117,8 +6915,8 @@ ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window)
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc),
ev_attachment_get_name (attachment));
- ev_window_file_chooser_restore_folder (window, GTK_FILE_CHOOSER (fc), NULL,
- G_USER_DIRECTORY_DOCUMENTS);
+ ev_file_chooser_restore_folder (GTK_FILE_CHOOSER (fc), NULL,
+ G_USER_DIRECTORY_DOCUMENTS);
g_signal_connect (fc, "response",
G_CALLBACK (attachment_save_dialog_response_cb),
diff --git a/shell/evince-appmenu.ui b/shell/evince-appmenu.ui
index 41074f3..df24f86 100644
--- a/shell/evince-appmenu.ui
+++ b/shell/evince-appmenu.ui
@@ -20,6 +20,16 @@
<menu id="appmenu">
<section>
<item>
+ <attribute name="label" translatable="yes">_Open</attribute>
+ <attribute name="action">app.open</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_About</attribute>
+ <attribute name="action">app.about</attribute>
+ </item>
+ <item>
<attribute name="label" translatable="yes">_Help</attribute>
<attribute name="action">app.help</attribute>
<attribute name="accel">F1</attribute>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]