Added a basic output viewer.
[pspp-builds.git] / src / ui / gui / output-viewer.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007 Free Software Foundation, Inc.
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 #include <config.h>
18 #include <gtk/gtk.h>
19 #include "window-manager.h"
20 #include "output-viewer.h"
21 #include "helper.h"
22 #include "about.h"
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27
28 #include <glade/glade.h>
29 #include <ctype.h>
30
31 struct output_viewer
32 {
33   struct editor_window parent;
34   GtkTextBuffer *buffer;  /* The buffer which contains the text */
35   GtkWidget *textview ;
36   FILE *fp;               /* The file it's viewing */
37 };
38
39
40 static void
41 cancel_urgency (GtkWindow *window,  gpointer data)
42 {
43   gtk_window_set_urgency_hint (window, FALSE);
44 }
45
46
47 static struct output_viewer *the_output_viewer = NULL;
48
49
50 /* Callback for the "delete" action (clicking the x on the top right
51    hand corner of the window) */
52 static gboolean
53 on_delete (GtkWidget *w, GdkEvent *event, gpointer user_data)
54 {
55   struct output_viewer *ov = user_data;
56
57   g_free (ov);
58
59   the_output_viewer = NULL;
60
61   unlink (OUTPUT_FILE_NAME);
62
63   return FALSE;
64 }
65
66
67 /*
68   Create a new output viewer
69 */
70 struct output_viewer *
71 new_output_viewer (void)
72 {
73   GladeXML *xml = XML_NEW ("output-viewer.glade");
74
75   struct output_viewer *ov ;
76   struct editor_window *e;
77
78   connect_help (xml);
79
80   ov = g_malloc (sizeof (*ov));
81
82   e = (struct editor_window *)ov;
83
84
85   e->window = GTK_WINDOW (get_widget_assert (xml, "output-viewer-window"));
86   ov->textview = get_widget_assert (xml, "output-viewer-textview");
87   ov->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (ov->textview));
88
89   g_signal_connect (e->window,
90                     "focus-in-event",
91                     G_CALLBACK (cancel_urgency),
92                     NULL);
93
94   {
95     /* Output uses ascii characters for tabular material.
96        So we need a monospaced font otherwise it'll look silly */
97     PangoFontDescription *font_desc =
98       pango_font_description_from_string ("monospace");
99
100     gtk_widget_modify_font (ov->textview, font_desc);
101     pango_font_description_free (font_desc);
102   }
103
104   ov->fp = NULL;
105
106   g_signal_connect (get_widget_assert (xml,"help_about"),
107                     "activate",
108                     G_CALLBACK (about_new),
109                     e->window);
110
111   g_signal_connect (get_widget_assert (xml,"help_reference"),
112                     "activate",
113                     G_CALLBACK (reference_manual),
114                     NULL);
115
116   g_signal_connect (get_widget_assert (xml,"windows_minimise-all"),
117                     "activate",
118                     G_CALLBACK (minimise_all_windows),
119                     NULL);
120
121   g_object_unref (xml);
122
123
124   g_signal_connect (e->window, "delete-event",
125                     G_CALLBACK (on_delete), ov);
126
127   return ov;
128 }
129
130
131 void
132 reload_the_viewer (void)
133 {
134   struct stat buf;
135
136   /* If there is no output, then don't do anything */
137   if (0 != stat (OUTPUT_FILE_NAME, &buf))
138     return ;
139
140   if ( NULL == the_output_viewer )
141     {
142       the_output_viewer =
143         (struct output_viewer *) window_create (WINDOW_OUTPUT, NULL);
144     }
145
146   reload_viewer (the_output_viewer);
147 }
148
149
150 void
151 reload_viewer (struct output_viewer *ov)
152 {
153   GtkTextIter end_iter;
154   char line[OUTPUT_LINE_WIDTH];
155   GtkTextMark *mark ;
156   gboolean chars_inserted = FALSE;
157
158
159   if ( ov->fp == NULL)
160     {
161       ov->fp = fopen (OUTPUT_FILE_NAME, "r");
162       if ( ov->fp == NULL)
163         {
164           g_print ("Cannot open %s\n", OUTPUT_FILE_NAME);
165           return;
166         }
167     }
168
169   gtk_text_buffer_get_end_iter (ov->buffer, &end_iter);
170
171   mark = gtk_text_buffer_create_mark (ov->buffer, NULL, &end_iter, TRUE);
172
173   /* Read in the next lot of text */
174   while (fgets (line, OUTPUT_LINE_WIDTH, ov->fp) != NULL)
175     {
176       chars_inserted = TRUE;
177       gtk_text_buffer_insert (ov->buffer, &end_iter, line, -1);
178     }
179
180   /* Scroll to where the start of this lot of text begins */
181   gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (ov->textview),
182                                 mark,
183                                 0.1, TRUE, 0.0, 0.0);
184
185
186   if ( chars_inserted )
187     gtk_window_set_urgency_hint ( ((struct editor_window *)ov)->window, TRUE);
188 }
189
190
191