Patch #5676 (syntax string source).
[pspp-builds.git] / src / ui / gui / data-editor.c
1 /*
2     PSPPIRE --- A Graphical User Interface for PSPP
3     Copyright (C) 2006, 2007  Free Software Foundation
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18     02110-1301, USA. */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <gettext.h>
23
24 #include <glade/glade.h>
25 #include <gtk/gtk.h>
26
27 #include "window-manager.h"
28 #include <gtksheet/gtksheet.h>
29
30 #include "helper.h"
31 #include "about.h"
32 #include "psppire-dialog.h"
33 #include "psppire-var-select.h"
34
35 #define _(msgid) gettext (msgid)
36 #define N_(msgid) msgid
37
38 #include "data-editor.h"
39 #include "syntax-editor.h"
40 #include <language/syntax-string-source.h>
41 #include "window-manager.h"
42
43 #include "psppire-data-store.h"
44 #include "psppire-var-store.h"
45
46 #include "weight-cases-dialog.h"
47
48
49 static void insert_variable (GtkCheckMenuItem *m, gpointer data);
50
51
52 /* Switch between the VAR SHEET and the DATA SHEET */
53 enum {PAGE_DATA_SHEET = 0, PAGE_VAR_SHEET};
54
55 static gboolean click2column (GtkWidget *w, gint col, gpointer data);
56
57 static gboolean click2row (GtkWidget *w, gint row, gpointer data);
58
59
60 static void select_sheet (struct data_editor *de, guint page_num);
61
62
63 /* Callback for when the dictionary changes properties*/
64 static void on_weight_change (GObject *, gint, gpointer);
65 static void on_filter_change (GObject *, gint, gpointer);
66 static void on_split_change (PsppireDict *, gpointer);
67
68 static void data_var_select (GtkNotebook *notebook,
69                             GtkNotebookPage *page,
70                             guint page_num,
71                             gpointer user_data);
72
73 static void status_bar_activate (GtkCheckMenuItem *, gpointer);
74
75 static void grid_lines_activate (GtkCheckMenuItem *, gpointer);
76
77 static void data_sheet_activate (GtkCheckMenuItem *, gpointer);
78
79 static void variable_sheet_activate (GtkCheckMenuItem *, gpointer );
80
81 static void fonts_activate (GtkMenuItem *, gpointer);
82
83 static void value_labels_activate (GtkCheckMenuItem *, gpointer);
84 static void value_labels_toggled (GtkToggleToolButton *, gpointer);
85
86
87 static void file_quit (GtkCheckMenuItem *, gpointer );
88
89 static void on_clear_activate (GtkMenuItem *, gpointer);
90
91 static void
92 enable_edit_clear (GtkWidget *w, gint row, gpointer data)
93 {
94   struct data_editor *de = data;
95
96   GtkWidget *menuitem = get_widget_assert (de->xml, "edit_clear");
97
98   gtk_widget_set_sensitive (menuitem, TRUE);
99 }
100
101 static gboolean
102 disable_edit_clear (GtkWidget *w, gint x, gint y, gpointer data)
103 {
104   struct data_editor *de = data;
105
106   GtkWidget *menuitem = get_widget_assert (de->xml, "edit_clear");
107
108   gtk_widget_set_sensitive (menuitem, FALSE);
109
110   return FALSE;
111 }
112
113 static void weight_cases_dialog (GObject *o, gpointer data);
114
115
116 /*
117   Create a new data editor.
118 */
119 struct data_editor *
120 new_data_editor (void)
121 {
122   struct data_editor *de ;
123   struct editor_window *e;
124   GtkSheet *var_sheet ;
125   PsppireVarStore *vs;
126
127   de = g_malloc (sizeof (*de));
128
129   e = (struct editor_window *) de;
130
131   de->xml = glade_xml_new (PKGDATADIR "/data-editor.glade", NULL, NULL);
132
133
134   var_sheet = GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
135
136   vs = PSPPIRE_VAR_STORE (gtk_sheet_get_model (var_sheet));
137
138   g_signal_connect (vs->dict, "weight-changed",
139                     G_CALLBACK (on_weight_change),
140                     de);
141
142   g_signal_connect (vs->dict, "filter-changed",
143                     G_CALLBACK (on_filter_change),
144                     de);
145
146   g_signal_connect (vs->dict, "split-changed",
147                     G_CALLBACK (on_split_change),
148                     de);
149
150   connect_help (de->xml);
151
152   de->invoke_weight_cases_dialog =
153     gtk_action_new ("weight-cases-dialog",
154                     _("Weights"),
155                     _("Weight cases by variable"),
156                     "pspp-weight-cases");
157
158
159   g_signal_connect (de->invoke_weight_cases_dialog, "activate",
160                     G_CALLBACK (weight_cases_dialog), de);
161
162   e->window = GTK_WINDOW (get_widget_assert (de->xml, "data_editor"));
163
164   g_signal_connect (get_widget_assert (de->xml,"file_new_data"),
165                     "activate",
166                     G_CALLBACK (new_data_window),
167                     e->window);
168
169   g_signal_connect (get_widget_assert (de->xml,"file_open_data"),
170                     "activate",
171                     G_CALLBACK (open_data_window),
172                     e->window);
173
174   g_signal_connect (get_widget_assert (de->xml,"file_new_syntax"),
175                     "activate",
176                     G_CALLBACK (new_syntax_window),
177                     e->window);
178
179   g_signal_connect (get_widget_assert (de->xml,"file_open_syntax"),
180                     "activate",
181                     G_CALLBACK (open_syntax_window),
182                     e->window);
183
184
185   g_signal_connect (get_widget_assert (de->xml,"edit_clear"),
186                     "activate",
187                     G_CALLBACK (on_clear_activate),
188                     de);
189
190
191   g_signal_connect (get_widget_assert (de->xml,"data_insert-variable"),
192                     "activate",
193                     G_CALLBACK (insert_variable),
194                     de);
195
196   gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
197                             get_widget_assert (de->xml, "data_weight-cases")
198                             );
199
200   /* 
201   g_signal_connect (get_widget_assert (de->xml,"data_weight-cases"),
202                     "activate",
203                     G_CALLBACK (weight_cases_dialog),
204                     de);
205   */
206
207
208   g_signal_connect (get_widget_assert (de->xml,"help_about"),
209                     "activate",
210                     G_CALLBACK (about_new),
211                     e->window);
212
213
214   g_signal_connect (get_widget_assert (de->xml,"help_reference"),
215                     "activate",
216                     G_CALLBACK (reference_manual),
217                     e->window);
218
219
220
221   g_signal_connect (get_widget_assert (de->xml,"data_sheet"),
222                     "double-click-column",
223                     G_CALLBACK (click2column),
224                     de);
225
226
227   g_signal_connect (get_widget_assert (de->xml, "variable_sheet"),
228                     "double-click-row",
229                     GTK_SIGNAL_FUNC (click2row),
230                     de);
231
232
233   g_signal_connect (get_widget_assert (de->xml, "variable_sheet"),
234                     "select-row",
235                     GTK_SIGNAL_FUNC (enable_edit_clear),
236                     de);
237
238   g_signal_connect (get_widget_assert (de->xml, "variable_sheet"),
239                     "activate",
240                     GTK_SIGNAL_FUNC (disable_edit_clear),
241                     de);
242
243
244   g_signal_connect (get_widget_assert (de->xml, "notebook"),
245                     "switch-page",
246                     G_CALLBACK (data_var_select), de);
247
248
249
250   g_signal_connect (get_widget_assert (de->xml, "view_statusbar"),
251                     "activate",
252                     G_CALLBACK (status_bar_activate), de);
253
254
255   g_signal_connect (get_widget_assert (de->xml, "view_gridlines"),
256                     "activate",
257                     G_CALLBACK (grid_lines_activate), de);
258
259
260
261   g_signal_connect (get_widget_assert (de->xml, "view_data"),
262                     "activate",
263                     G_CALLBACK (data_sheet_activate), de);
264
265   g_signal_connect (get_widget_assert (de->xml, "view_variables"),
266                     "activate",
267                     G_CALLBACK (variable_sheet_activate), de);
268
269
270
271   g_signal_connect (get_widget_assert (de->xml, "view_fonts"),
272                     "activate",
273                     G_CALLBACK (fonts_activate), de);
274
275
276
277   g_signal_connect (get_widget_assert (de->xml, "view_valuelabels"),
278                     "activate",
279                     G_CALLBACK (value_labels_activate), de);
280
281
282   g_signal_connect (get_widget_assert (de->xml, "togglebutton-value-labels"),
283                     "toggled",
284                     G_CALLBACK (value_labels_toggled), de);
285
286
287   gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
288                             get_widget_assert (de->xml, "button-weight-cases")
289                             );
290
291   g_signal_connect (get_widget_assert (de->xml, "file_quit"),
292                     "activate",
293                     G_CALLBACK (file_quit), de);
294
295
296   g_signal_connect (get_widget_assert (de->xml, "windows_minimise_all"),
297                     "activate",
298                     G_CALLBACK (minimise_all_windows), NULL);
299
300
301
302   select_sheet (de, PAGE_DATA_SHEET);
303
304   return de;
305 }
306
307
308 /* Callback which occurs when the var sheet's row title
309    button is double clicked */
310 static gboolean
311 click2row (GtkWidget *w, gint row, gpointer data)
312 {
313   struct data_editor *de = data;
314
315   gint current_row, current_column;
316
317   GtkWidget *data_sheet  = get_widget_assert (de->xml, "data_sheet");
318
319   data_editor_select_sheet (de, PAGE_DATA_SHEET);
320
321   gtk_sheet_get_active_cell (GTK_SHEET (data_sheet),
322                              &current_row, &current_column);
323
324   gtk_sheet_set_active_cell (GTK_SHEET (data_sheet), current_row, row);
325
326   return FALSE;
327 }
328
329
330 /* Callback which occurs when the data sheet's column title
331    is double clicked */
332 static gboolean
333 click2column (GtkWidget *w, gint col, gpointer data)
334 {
335   struct data_editor *de = data;
336
337   gint current_row, current_column;
338
339   GtkWidget *var_sheet  = get_widget_assert (de->xml, "variable_sheet");
340
341   data_editor_select_sheet (de, PAGE_VAR_SHEET);
342
343   gtk_sheet_get_active_cell (GTK_SHEET (var_sheet),
344                              &current_row, &current_column);
345
346   gtk_sheet_set_active_cell (GTK_SHEET (var_sheet), col, current_column);
347
348   return FALSE;
349 }
350
351
352 void
353 new_data_window (GtkMenuItem *menuitem, gpointer parent)
354 {
355   window_create (WINDOW_DATA, NULL);
356 }
357
358
359 static void
360 select_sheet (struct data_editor *de, guint page_num)
361 {
362   GtkWidget *insert_variable = get_widget_assert (de->xml, "data_insert-variable");
363   GtkWidget *insert_cases = get_widget_assert (de->xml, "insert-cases");
364
365   GtkWidget *view_data = get_widget_assert (de->xml, "view_data");
366   GtkWidget *view_variables = get_widget_assert (de->xml, "view_variables");
367
368   switch (page_num)
369     {
370     case PAGE_VAR_SHEET:
371       gtk_widget_hide (view_variables);
372       gtk_widget_show (view_data);
373       gtk_widget_set_sensitive (insert_variable, TRUE);
374       gtk_widget_set_sensitive (insert_cases, FALSE);
375       break;
376     case PAGE_DATA_SHEET:
377       gtk_widget_show (view_variables);
378       gtk_widget_hide (view_data);
379 #if 0
380       gtk_widget_set_sensitive (insert_cases, TRUE);
381 #endif
382       break;
383     default:
384       g_assert_not_reached ();
385       break;
386     }
387 }
388
389
390 static void
391 data_var_select (GtkNotebook *notebook,
392                 GtkNotebookPage *page,
393                 guint page_num,
394                 gpointer user_data)
395 {
396   struct data_editor *de = user_data;
397
398   select_sheet (de, page_num);
399 }
400
401
402
403
404 void
405 data_editor_select_sheet (struct data_editor *de, gint page)
406 {
407   gtk_notebook_set_current_page
408    (
409     GTK_NOTEBOOK (get_widget_assert (de->xml,"notebook")), page
410     );
411 }
412
413
414 void
415 open_data_window (GtkMenuItem *menuitem, gpointer parent)
416 {
417   bool finished = FALSE;
418
419   GtkWidget *dialog;
420
421   GtkFileFilter *filter ;
422
423   dialog = gtk_file_chooser_dialog_new (_("Open"),
424                                         GTK_WINDOW (parent),
425                                         GTK_FILE_CHOOSER_ACTION_OPEN,
426                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
427                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
428                                         NULL);
429
430   filter = gtk_file_filter_new ();
431   gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
432   gtk_file_filter_add_pattern (filter, "*.sav");
433   gtk_file_filter_add_pattern (filter, "*.SAV");
434   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
435
436   filter = gtk_file_filter_new ();
437   gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
438   gtk_file_filter_add_pattern (filter, "*.por");
439   gtk_file_filter_add_pattern (filter, "*.POR");
440   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
441
442   filter = gtk_file_filter_new ();
443   gtk_file_filter_set_name (filter, _("All Files"));
444   gtk_file_filter_add_pattern (filter, "*");
445   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
446
447   do {
448
449     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
450       {
451         gchar *file_name =
452           gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
453
454         g_free (file_name);
455       }
456     else
457       finished = TRUE;
458
459   } while ( ! finished ) ;
460
461   gtk_widget_destroy (dialog);
462 }
463
464
465
466
467 static void
468 status_bar_activate (GtkCheckMenuItem *menuitem, gpointer data)
469 {
470   struct data_editor *de = data;
471   GtkWidget *statusbar = get_widget_assert (de->xml, "status-bar");
472
473   if ( gtk_check_menu_item_get_active (menuitem) )
474     gtk_widget_show (statusbar);
475   else
476     gtk_widget_hide (statusbar);
477 }
478
479
480 static void
481 grid_lines_activate (GtkCheckMenuItem *menuitem, gpointer data)
482 {
483   struct data_editor *de = data;
484   const bool grid_visible = gtk_check_menu_item_get_active (menuitem);
485
486   gtk_sheet_show_grid (GTK_SHEET (get_widget_assert (de->xml,
487                                                      "variable_sheet")),
488                        grid_visible);
489
490   gtk_sheet_show_grid (GTK_SHEET (get_widget_assert (de->xml, "data_sheet")),
491                        grid_visible);
492 }
493
494
495
496 static void
497 data_sheet_activate (GtkCheckMenuItem *menuitem, gpointer data)
498 {
499   struct data_editor *de = data;
500
501   data_editor_select_sheet (de, PAGE_DATA_SHEET);
502 }
503
504
505 static void
506 variable_sheet_activate (GtkCheckMenuItem *menuitem, gpointer data)
507 {
508   struct data_editor *de = data;
509
510   data_editor_select_sheet (de, PAGE_VAR_SHEET);
511 }
512
513
514 static void
515 fonts_activate (GtkMenuItem *menuitem, gpointer data)
516 {
517   struct data_editor *de = data;
518   GtkWidget *dialog =
519     gtk_font_selection_dialog_new (_("Font Selection"));
520
521   gtk_window_set_transient_for (GTK_WINDOW (dialog),
522                                 GTK_WINDOW (get_widget_assert (de->xml,
523                                                                "data_editor")));
524   if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
525     {
526       GtkSheet *data_sheet =
527         GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
528
529       GtkSheet *var_sheet =
530         GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
531
532       PsppireDataStore *ds = PSPPIRE_DATA_STORE (gtk_sheet_get_model (data_sheet));
533       PsppireVarStore *vs = PSPPIRE_VAR_STORE (gtk_sheet_get_model (var_sheet));
534
535       const gchar *font = gtk_font_selection_dialog_get_font_name
536         (GTK_FONT_SELECTION_DIALOG (dialog));
537
538       PangoFontDescription* font_desc =
539         pango_font_description_from_string (font);
540
541       psppire_var_store_set_font (vs, font_desc);
542       psppire_data_store_set_font (ds, font_desc);
543     }
544
545   gtk_widget_hide (dialog);
546 }
547
548
549 /* The next two callbacks are mutually co-operative */
550
551 /* Callback for the value labels menu item */
552 static void
553 value_labels_activate (GtkCheckMenuItem *menuitem, gpointer data)
554 {
555   struct data_editor *de = data;
556
557   GtkSheet *data_sheet = GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
558
559   GtkToggleToolButton *tb =
560     GTK_TOGGLE_TOOL_BUTTON (get_widget_assert (de->xml,
561                                                "togglebutton-value-labels"));
562
563   PsppireDataStore *ds = PSPPIRE_DATA_STORE (gtk_sheet_get_model (data_sheet));
564
565   gboolean show_value_labels = gtk_check_menu_item_get_active (menuitem);
566
567   gtk_toggle_tool_button_set_active (tb, show_value_labels);
568
569   psppire_data_store_show_labels (ds, show_value_labels);
570 }
571
572
573 /* Callback for the value labels tooglebutton */
574 static void
575 value_labels_toggled (GtkToggleToolButton *toggle_tool_button,
576                       gpointer data)
577 {
578   struct data_editor *de = data;
579
580   GtkSheet *data_sheet = GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
581
582   GtkCheckMenuItem *item =
583     GTK_CHECK_MENU_ITEM (get_widget_assert (de->xml, "view_valuelabels"));
584
585   PsppireDataStore *ds = PSPPIRE_DATA_STORE (gtk_sheet_get_model (data_sheet));
586
587   gboolean show_value_labels =
588     gtk_toggle_tool_button_get_active (toggle_tool_button);
589
590   gtk_check_menu_item_set_active (item, show_value_labels);
591
592   psppire_data_store_show_labels (ds, show_value_labels);
593 }
594
595
596 static void
597 file_quit (GtkCheckMenuItem *menuitem, gpointer data)
598 {
599   /* FIXME: Need to be more intelligent here.
600      Give the user the opportunity to save any unsaved data.
601   */
602   gtk_main_quit ();
603 }
604
605
606
607 /* Callback for when the Clear item in the edit menu is activated */
608 static void
609 on_clear_activate (GtkMenuItem *menuitem, gpointer data)
610 {
611   struct data_editor *de = data;
612
613   GtkNotebook *notebook = GTK_NOTEBOOK (get_widget_assert (de->xml,
614                                                            "notebook"));
615
616   switch ( gtk_notebook_get_current_page (notebook) )
617     {
618     case PAGE_VAR_SHEET:
619       {
620         GtkSheet *var_sheet =
621           GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
622
623         PsppireVarStore *vs = PSPPIRE_VAR_STORE
624           (gtk_sheet_get_model (var_sheet) );
625
626         /* This shouldn't be able to happen, because the menuitem
627            should be disabled */
628         g_return_if_fail (var_sheet->state  ==  GTK_SHEET_ROW_SELECTED );
629
630         psppire_dict_delete_variables (vs->dict,
631                                        var_sheet->range.row0,
632                                        1 +
633                                        var_sheet->range.rowi -
634                                        var_sheet->range.row0 );
635       }
636       break;
637       case PAGE_DATA_SHEET:
638         break;
639       default:
640         g_assert_not_reached ();
641     }
642 }
643
644
645 /* Insert a new variable before the current row in the variable sheet,
646    or before the current column in the data sheet, whichever is selected */
647 static void
648 insert_variable (GtkCheckMenuItem *m, gpointer data)
649 {
650   struct data_editor *de = data;
651   gint posn;
652
653   GtkWidget *notebook = get_widget_assert (de->xml, "notebook");
654
655   GtkSheet *var_sheet =
656     GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
657
658   PsppireVarStore *vs = PSPPIRE_VAR_STORE
659     (gtk_sheet_get_model (var_sheet) );
660
661   switch ( gtk_notebook_get_current_page ( GTK_NOTEBOOK (notebook)) )
662     {
663     case PAGE_VAR_SHEET:
664       posn = var_sheet->active_cell.row;
665       break;
666     case PAGE_DATA_SHEET:
667       {
668         GtkSheet *data_sheet =
669           GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
670
671         if ( data_sheet->state == GTK_SHEET_COLUMN_SELECTED )
672           posn = data_sheet->range.col0;
673         else
674           posn = data_sheet->active_cell.col;
675       }
676       break;
677     default:
678       g_assert_not_reached ();
679     }
680
681   psppire_dict_insert_variable (vs->dict, posn, NULL);
682 }
683
684 /* Callback for when the dictionary changes its split variables */
685 static void
686 on_split_change (PsppireDict *dict, gpointer data)
687 {
688   struct data_editor *de = data;
689
690   size_t n_split_vars = dict_get_split_cnt (dict->dict);
691
692   GtkWidget *split_status_area =
693     get_widget_assert (de->xml, "split-file-status-area");
694
695   if ( n_split_vars == 0 )
696     {
697       gtk_label_set_text (GTK_LABEL (split_status_area), _("No Split"));
698     }
699   else
700     {
701       gint i;
702       GString *text;
703       struct variable *const * split_vars = dict_get_split_vars (dict->dict);
704
705       text = g_string_new (_("Split by "));
706
707       for (i = 0 ; i < n_split_vars - 1; ++i )
708         {
709           g_string_append_printf (text, "%s, ", var_get_name (split_vars[i]));
710         }
711       g_string_append (text, var_get_name (split_vars[i]));
712
713       gtk_label_set_text (GTK_LABEL (split_status_area), text->str);
714
715       g_string_free (text, TRUE);
716     }
717 }
718
719
720 /* Callback for when the dictionary changes its filter variable */
721 static void
722 on_filter_change (GObject *o, gint filter_index, gpointer data)
723 {
724   struct data_editor *de = data;
725   GtkWidget *filter_status_area =
726     get_widget_assert (de->xml, "filter-use-status-area");
727
728   if ( filter_index == -1 )
729     {
730       gtk_label_set_text (GTK_LABEL (filter_status_area), _("Filter off"));
731     }
732   else
733     {
734       GtkSheet *var_sheet =
735         GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
736
737       PsppireVarStore *vs = PSPPIRE_VAR_STORE
738         (gtk_sheet_get_model (var_sheet) );
739
740       struct variable *var = psppire_dict_get_variable (vs->dict,
741                                                         filter_index);
742
743       gchar *text = g_strdup_printf (_("Filter by %s"), var_get_name (var));
744
745       gtk_label_set_text (GTK_LABEL (filter_status_area), text);
746
747       g_free (text);
748     }
749 }
750
751 /* Callback for when the dictionary changes its weights */
752 static void
753 on_weight_change (GObject *o, gint weight_index, gpointer data)
754 {
755   struct data_editor *de = data;
756   GtkWidget *weight_status_area =
757     get_widget_assert (de->xml, "weight-status-area");
758
759   if ( weight_index == -1 )
760     {
761       gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
762     }
763   else
764     {
765       GtkSheet *var_sheet =
766         GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
767
768       PsppireVarStore *vs = PSPPIRE_VAR_STORE
769         (gtk_sheet_get_model (var_sheet) );
770
771       struct variable *var = psppire_dict_get_variable (vs->dict,
772                                                         weight_index);
773
774       gchar *text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
775
776       gtk_label_set_text (GTK_LABEL (weight_status_area), text);
777
778       g_free (text);
779     }
780 }
781
782 static void
783 weight_cases_dialog (GObject *o, gpointer data)
784 {
785   gint response;
786   struct data_editor *de = data;
787   GtkSheet *var_sheet =
788     GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
789
790
791   GladeXML *xml = glade_xml_new (PKGDATADIR "/psppire.glade",
792                                  "weight-cases-dialog", NULL);
793
794
795   GtkWidget *treeview =  get_widget_assert (xml, "treeview");
796   GtkWidget *entry =  get_widget_assert (xml, "entry1");
797
798
799   PsppireVarStore *vs = PSPPIRE_VAR_STORE (gtk_sheet_get_model (var_sheet));
800
801   PsppireVarSelect *select = psppire_var_select_new (treeview,
802                                                      entry, vs->dict);
803
804
805   PsppireDialog *dialog = create_weight_dialog (select, xml);
806
807   response = psppire_dialog_run (dialog);
808
809   g_object_unref (xml);
810
811   switch (response)
812     {
813     case GTK_RESPONSE_OK:
814     {
815       struct getl_interface *sss ;
816       const GList *list = psppire_var_select_get_variables (select);
817
818       g_assert ( g_list_length ((GList *)list) <= 1 );
819
820       if ( list == NULL)
821           {
822             sss = create_syntax_string_source ("WEIGHT OFF.");
823           }
824       else
825         {
826           struct variable *var = list->data;
827
828             sss = create_syntax_string_source ("WEIGHT BY %s.\n",
829                                                var_get_name (var));
830           }
831
832         execute_syntax (sss);
833         }
834       break;
835     case PSPPIRE_RESPONSE_PASTE:
836       {
837         struct syntax_editor *se =  (struct syntax_editor *) window_create (WINDOW_SYNTAX, NULL);
838
839         const GList *list = psppire_var_select_get_variables (select);
840
841         g_assert ( g_list_length ((GList *)list) <= 1 );
842
843         if ( list == NULL)
844           {
845             gtk_text_buffer_insert_at_cursor (se->buffer, "WEIGHT OFF.", -1);
846           }
847         else
848           {
849             struct variable *var = list->data;
850
851             gchar *text = g_strdup_printf ("WEIGHT BY %s.",
852                                            var_get_name (var));
853
854             gtk_text_buffer_insert_at_cursor (se->buffer,
855                                               text, -1);
856
857             g_free (text);
858           }
859       }
860       break;
861     default:
862       break;
863     }
864 }
865
866