f203ea773eb3622641e88f7a352b1ec6518bf4e7
[pspp] / src / ui / gui / help-menu.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013, 2015, 2016  Free Software Foundation
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17
18 #include <config.h>
19
20 #include <gtk/gtk.h>
21
22 #include "libpspp/cast.h"
23 #include "libpspp/copyleft.h"
24 #include "libpspp/message.h"
25 #include "libpspp/version.h"
26 #include "ui/gui/help-menu.h"
27
28 #include "gl/configmake.h"
29 #include "gl/relocatable.h"
30
31 #include <gettext.h>
32 #define _(msgid) gettext (msgid)
33 #define N_(msgid) msgid
34
35 /* Try to open html documentation uri via the default
36    browser on the operating system */
37 #ifdef __APPLE__
38 #define HTMLOPENAPP "open"
39 #elif  _WIN32
40 #define HTMLOPENAPP "wscript"
41 #else
42 #define HTMLOPENAPP "xdg-open"
43 #endif
44
45 static const gchar *artists[] = { "Bastián Díaz", "Hugo Alejandro", NULL};
46
47 static void
48 about_new (GtkMenuItem *mmm, GtkWindow *parent)
49 {
50   GtkWidget *about =  gtk_about_dialog_new ();
51
52   gtk_about_dialog_set_logo_icon_name (GTK_ABOUT_DIALOG (about), "pspp");
53
54   gtk_window_set_icon_name (GTK_WINDOW (about), "pspp");
55
56   gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (about), PACKAGE_URL);
57
58   gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (about),
59                                 announced_version);
60
61   gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG (about),
62                                 (const gchar **) authors);
63
64   gtk_about_dialog_set_artists (GTK_ABOUT_DIALOG (about),
65                                 artists);
66
67   gtk_about_dialog_set_license (GTK_ABOUT_DIALOG (about),
68                                 copyleft);
69
70   gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG (about),
71                                  _("A program for the analysis of sampled data"));
72
73   gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG (about),
74                                   "Free Software Foundation");
75
76   gtk_about_dialog_set_translator_credits
77     (
78      GTK_ABOUT_DIALOG (about),
79      /* TRANSLATORS: Do not translate this string.  Instead, put the names of the people
80         who have helped in the translation. */
81      _("translator-credits")
82 );
83
84   gtk_window_set_transient_for (GTK_WINDOW (about), parent);
85
86   gtk_window_set_modal (GTK_WINDOW (about), TRUE);
87
88   gtk_dialog_run (GTK_DIALOG (about));
89
90   gtk_widget_hide (about);
91 }
92
93
94 /* Opening the htmluri in windows via cmd /start uri opens
95    the windows command shell for a moment. The alternative is
96    to start a script via wscript. This will not be visible*/
97 #ifdef _WIN32
98 static gboolean open_windows_help (const gchar *helpuri,
99                                    GError **err)
100 {
101   gchar *vbsfilename = NULL;
102   gchar *vbs = NULL;
103   gboolean result;
104   vbsfilename = g_build_filename (g_get_tmp_dir (),
105                                   "pspp-help-open.vbs",
106                                   NULL);
107   vbs = g_strdup_printf("CreateObject(\"WScript.Shell\").Run \"%s\"",
108                         helpuri);
109   result = g_file_set_contents (vbsfilename,
110                                 vbs,
111                                 strlen(vbs),
112                                 err);
113   g_free (vbs);
114   if (!result)
115     goto error;
116
117   gchar *argv[] = {CONST_CAST (gchar *, "wscript"), vbsfilename, 0};
118
119   result = g_spawn_async (NULL, argv,
120                           NULL, G_SPAWN_SEARCH_PATH,
121                           NULL, NULL, NULL, err);
122  error:
123   g_free (vbsfilename);
124   return result;
125 }
126 #endif
127
128 /* Open the manual at PAGE with the following priorities
129    First: local yelp help system
130    Second: browser with local html doc dir in path pspp.html/<helppage>.html
131    Third:  browers with Internet html help at gnu.org */
132 void
133 online_help (const char *page)
134 {
135   GError *htmlerr = NULL;
136   gchar *htmlfilename = NULL;
137   gchar *htmlfullname = NULL;
138   gchar *htmluri = NULL;
139
140   if (page == NULL)
141     {
142       htmlfilename = g_strdup ("index.html");
143     }
144   else
145     {
146       gchar **tokens = NULL;
147       const int maxtokens = 5;
148       int idx ;
149       /* The page will be translated to the htmlfilename
150          page                   htmlfilename
151          GRAPH#SCATTERPLOT      SCATTERPLOT.html
152          QUICK-CLUSTER          QUICK-CLUSTER.html
153          which is valid for the multiple page html doc*/
154       tokens = g_strsplit (page, "#", maxtokens);
155       for (idx = 0; idx < maxtokens && tokens[idx]; idx++)
156         ;
157       htmlfilename = g_strdup_printf ("%s.html", tokens[idx-1]);
158       g_strfreev (tokens);
159     }
160   /* Hint: pspp.html is a directory...*/
161   htmlfullname = g_strdup_printf ("%s/%s", relocate (DOCDIR "/pspp.html"),
162                                   htmlfilename);
163   if (g_file_test (relocate (DOCDIR "/pspp.html"), G_FILE_TEST_IS_DIR))
164     {
165       GError *urierr = NULL;
166       htmluri =  g_filename_to_uri (htmlfullname,NULL, &urierr);
167       if (!htmluri)
168         {
169           msg (ME, _("Help path conversion error: %s"), urierr->message);
170           htmluri = htmlfullname;
171         }
172       g_clear_error (&urierr);
173     }
174   else
175     htmluri = g_strdup_printf (PACKAGE_URL "manual/html_node/%s",
176                                htmlfilename);
177   g_free (htmlfullname);
178   g_free (htmlfilename);
179
180   /* The following **SHOULD** work but it does not on 28.5.2016
181      g_app_info_launch_default_for_uri (htmluri, NULL, &err);
182      osx: wine is started to launch the uri...
183      windows: not so bad, but the first access does not work*/
184
185 #ifdef _WIN32
186   bool ok = open_windows_help (htmluri, &htmlerr);
187 #else
188   gchar *htmlargv[3] = {CONST_CAST (char *, HTMLOPENAPP), htmluri, 0};
189   bool ok = g_spawn_async (NULL, htmlargv,
190                            NULL, G_SPAWN_SEARCH_PATH,
191                            NULL, NULL, NULL, &htmlerr);
192 #endif
193   if (!ok)
194     {
195       msg (ME, _("Cannot open via html: %s "
196                  "with uri: %s "
197                  "The PSSP manual is also available at %s"),
198                   htmlerr->message,
199                   htmluri,
200                   PACKAGE_URL "documentation.html");
201     }
202
203   g_free (htmluri);
204   g_clear_error (&htmlerr);
205 }
206
207 static void
208 reference_manual (GtkMenuItem *menu, gpointer data)
209 {
210   online_help (NULL);
211 }
212
213 GtkWidget *
214 create_help_menu (GtkWindow *toplevel)
215 {
216   GtkWidget *menuitem = gtk_menu_item_new_with_mnemonic (_("_Help"));
217   GtkWidget *menu = gtk_menu_new ();
218
219   GtkWidget *help_about = gtk_menu_item_new_with_mnemonic (_("_About"));
220   GtkWidget *help_ref = gtk_menu_item_new_with_mnemonic (_("_Reference Manual"));
221
222   GtkAccelGroup *accel_group = gtk_accel_group_new ();
223
224   gtk_window_add_accel_group (toplevel, accel_group);
225
226   gtk_widget_add_accelerator (help_ref,
227                               "activate", accel_group,
228                               GDK_KEY_F1, 0,
229                               GTK_ACCEL_VISIBLE);
230
231   gtk_menu_attach (GTK_MENU (menu), help_ref, 0, 1, 0, 1);
232   gtk_menu_attach (GTK_MENU (menu), help_about, 0, 1, 1, 2);
233
234   g_signal_connect (help_about, "activate", G_CALLBACK (about_new), toplevel);
235   g_signal_connect (help_ref, "activate", G_CALLBACK (reference_manual), NULL);
236
237   g_object_set (menuitem, "submenu", menu, NULL);
238
239   gtk_widget_show_all (menuitem);
240
241   g_object_unref (accel_group);
242
243   return menuitem;
244 }