Added psppire-dialog and psppire-buttonbox widgets.
[pspp-builds.git] / src / ui / gui / data-editor.c
index b35f3f1af8242961efbcf0a104a7ad0ddae6a83f..33d5a3e4c883840f6989c3a9e2fb981eb555e809 100644 (file)
@@ -1,6 +1,6 @@
 /*
     PSPPIRE --- A Graphical User Interface for PSPP
-    Copyright (C) 2006  Free Software Foundation
+    Copyright (C) 2006, 2007  Free Software Foundation
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include <glade/glade.h>
 #include <gtk/gtk.h>
 
-
+#include "window-manager.h"
 #include <gtksheet/gtksheet.h>
 
 #include "helper.h"
 #include "about.h"
+#include "psppire-dialog.h"
+#include "psppire-var-select.h"
 
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 #include "psppire-data-store.h"
 #include "psppire-var-store.h"
 
+#include "weight-cases-dialog.h"
+
+
+static void insert_variable (GtkCheckMenuItem *m, gpointer data);
+
+
 /* Switch between the VAR SHEET and the DATA SHEET */
 enum {PAGE_DATA_SHEET = 0, PAGE_VAR_SHEET};
 
@@ -51,6 +59,9 @@ static gboolean click2row (GtkWidget *w, gint row, gpointer data);
 static void select_sheet (struct data_editor *de, guint page_num);
 
 
+/* Callback for when the dictionary changes its weights */
+static void on_weight_change (GObject *, gint, gpointer);
+
 static void data_var_select (GtkNotebook *notebook,
                            GtkNotebookPage *page,
                            guint page_num,
@@ -72,6 +83,32 @@ static void value_labels_toggled (GtkToggleToolButton *, gpointer);
 
 static void file_quit (GtkCheckMenuItem *, gpointer );
 
+static void on_clear_activate (GtkMenuItem *, gpointer);
+
+static void
+enable_edit_clear (GtkWidget *w, gint row, gpointer data)
+{
+  struct data_editor *de = data;
+
+  GtkWidget *menuitem = get_widget_assert (de->xml, "edit_clear");
+
+  gtk_widget_set_sensitive (menuitem, TRUE);
+}
+
+static gboolean
+disable_edit_clear (GtkWidget *w, gint x, gint y, gpointer data)
+{
+  struct data_editor *de = data;
+
+  GtkWidget *menuitem = get_widget_assert (de->xml, "edit_clear");
+
+  gtk_widget_set_sensitive (menuitem, FALSE);
+
+  return FALSE;
+}
+
+static void weight_cases_dialog (GObject *o, gpointer data);
+
 
 /*
   Create a new data editor.
@@ -81,6 +118,8 @@ new_data_editor (void)
 {
   struct data_editor *de ;
   struct editor_window *e;
+  GtkSheet *var_sheet ;
+  PsppireVarStore *vs;
 
   de = g_malloc (sizeof (*de));
 
@@ -88,7 +127,28 @@ new_data_editor (void)
 
   de->xml = glade_xml_new (PKGDATADIR "/data-editor.glade", NULL, NULL);
 
-  e->window = get_widget_assert (de->xml, "data_editor");
+
+  var_sheet = GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
+
+  vs = PSPPIRE_VAR_STORE (gtk_sheet_get_model (var_sheet));
+
+  g_signal_connect (vs->dict, "weight-changed",
+                   G_CALLBACK (on_weight_change),
+                   de);
+
+  connect_help (de->xml);
+
+  de->invoke_weight_cases_dialog =
+    gtk_action_new ("weight-cases-dialog",
+                   _("Weights"),
+                   _("Weight cases by variable"),
+                   "pspp-weight-cases");
+
+
+  g_signal_connect (de->invoke_weight_cases_dialog, "activate",
+                   G_CALLBACK (weight_cases_dialog), de);
+
+  e->window = GTK_WINDOW (get_widget_assert (de->xml, "data_editor"));
 
   g_signal_connect (get_widget_assert (de->xml,"file_new_data"),
                    "activate",
@@ -110,12 +170,43 @@ new_data_editor (void)
                    G_CALLBACK (open_syntax_window),
                    e->window);
 
+
+  g_signal_connect (get_widget_assert (de->xml,"edit_clear"),
+                   "activate",
+                   G_CALLBACK (on_clear_activate),
+                   de);
+
+
+  g_signal_connect (get_widget_assert (de->xml,"data_insert-variable"),
+                   "activate",
+                   G_CALLBACK (insert_variable),
+                   de);
+
+  gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
+                           get_widget_assert (de->xml, "data_weight-cases")
+                           );
+
+  /* 
+  g_signal_connect (get_widget_assert (de->xml,"data_weight-cases"),
+                   "activate",
+                   G_CALLBACK (weight_cases_dialog),
+                   de);
+  */
+
+
   g_signal_connect (get_widget_assert (de->xml,"help_about"),
                    "activate",
                    G_CALLBACK (about_new),
                    e->window);
 
 
+  g_signal_connect (get_widget_assert (de->xml,"help_reference"),
+                   "activate",
+                   G_CALLBACK (reference_manual),
+                   e->window);
+
+
+
   g_signal_connect (get_widget_assert (de->xml,"data_sheet"),
                    "double-click-column",
                    G_CALLBACK (click2column),
@@ -128,6 +219,17 @@ new_data_editor (void)
                    de);
 
 
+  g_signal_connect (get_widget_assert (de->xml, "variable_sheet"),
+                   "select-row",
+                   GTK_SIGNAL_FUNC (enable_edit_clear),
+                   de);
+
+  g_signal_connect (get_widget_assert (de->xml, "variable_sheet"),
+                   "activate",
+                   GTK_SIGNAL_FUNC (disable_edit_clear),
+                   de);
+
+
   g_signal_connect (get_widget_assert (de->xml, "notebook"),
                    "switch-page",
                    G_CALLBACK (data_var_select), de);
@@ -171,11 +273,21 @@ new_data_editor (void)
                    G_CALLBACK (value_labels_toggled), de);
 
 
+  gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
+                           get_widget_assert (de->xml, "button-weight-cases")
+                           );
+
   g_signal_connect (get_widget_assert (de->xml, "file_quit"),
                    "activate",
                    G_CALLBACK (file_quit), de);
 
 
+  g_signal_connect (get_widget_assert (de->xml, "windows_minimise_all"),
+                   "activate",
+                   G_CALLBACK (minimise_all_windows), NULL);
+
+
+
   select_sheet (de, PAGE_DATA_SHEET);
 
   return de;
@@ -195,10 +307,10 @@ click2row (GtkWidget *w, gint row, gpointer data)
 
   data_editor_select_sheet (de, PAGE_DATA_SHEET);
 
-  gtk_sheet_get_active_cell (GTK_SHEET(data_sheet),
+  gtk_sheet_get_active_cell (GTK_SHEET (data_sheet),
                             &current_row, &current_column);
 
-  gtk_sheet_set_active_cell (GTK_SHEET(data_sheet), current_row, row);
+  gtk_sheet_set_active_cell (GTK_SHEET (data_sheet), current_row, row);
 
   return FALSE;
 }
@@ -217,10 +329,10 @@ click2column (GtkWidget *w, gint col, gpointer data)
 
   data_editor_select_sheet (de, PAGE_VAR_SHEET);
 
-  gtk_sheet_get_active_cell (GTK_SHEET(var_sheet),
+  gtk_sheet_get_active_cell (GTK_SHEET (var_sheet),
                             &current_row, &current_column);
 
-  gtk_sheet_set_active_cell (GTK_SHEET(var_sheet), col, current_column);
+  gtk_sheet_set_active_cell (GTK_SHEET (var_sheet), col, current_column);
 
   return FALSE;
 }
@@ -238,7 +350,7 @@ new_data_window (GtkMenuItem *menuitem, gpointer parent)
 static void
 select_sheet (struct data_editor *de, guint page_num)
 {
-  GtkWidget *insert_variable = get_widget_assert (de->xml, "insert-variable");
+  GtkWidget *insert_variable = get_widget_assert (de->xml, "data_insert-variable");
   GtkWidget *insert_cases = get_widget_assert (de->xml, "insert-cases");
 
   GtkWidget *view_data = get_widget_assert (de->xml, "view_data");
@@ -255,8 +367,9 @@ select_sheet (struct data_editor *de, guint page_num)
     case PAGE_DATA_SHEET:
       gtk_widget_show (view_variables);
       gtk_widget_hide (view_data);
-      gtk_widget_set_sensitive (insert_variable, FALSE);
+#if 0
       gtk_widget_set_sensitive (insert_cases, TRUE);
+#endif
       break;
     default:
       g_assert_not_reached ();
@@ -309,18 +422,18 @@ open_data_window (GtkMenuItem *menuitem, gpointer parent)
   gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
   gtk_file_filter_add_pattern (filter, "*.sav");
   gtk_file_filter_add_pattern (filter, "*.SAV");
-  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
 
   filter = gtk_file_filter_new ();
   gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
   gtk_file_filter_add_pattern (filter, "*.por");
   gtk_file_filter_add_pattern (filter, "*.POR");
-  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
 
   filter = gtk_file_filter_new ();
   gtk_file_filter_set_name (filter, _("All Files"));
   gtk_file_filter_add_pattern (filter, "*");
-  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
 
   do {
 
@@ -346,7 +459,7 @@ static void
 status_bar_activate (GtkCheckMenuItem *menuitem, gpointer data)
 {
   struct data_editor *de = data;
-  GtkWidget *statusbar = get_widget_assert (de->xml, "statusbar");
+  GtkWidget *statusbar = get_widget_assert (de->xml, "status-bar");
 
   if ( gtk_check_menu_item_get_active (menuitem) )
     gtk_widget_show (statusbar);
@@ -355,8 +468,6 @@ status_bar_activate (GtkCheckMenuItem *menuitem, gpointer data)
 }
 
 
-
-
 static void
 grid_lines_activate (GtkCheckMenuItem *menuitem, gpointer data)
 {
@@ -404,10 +515,10 @@ fonts_activate (GtkMenuItem *menuitem, gpointer data)
   if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
     {
       GtkSheet *data_sheet =
-       GTK_SHEET(get_widget_assert (de->xml, "data_sheet"));
+       GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
 
       GtkSheet *var_sheet =
-       GTK_SHEET(get_widget_assert (de->xml, "variable_sheet"));
+       GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
 
       PsppireDataStore *ds = PSPPIRE_DATA_STORE (gtk_sheet_get_model (data_sheet));
       PsppireVarStore *vs = PSPPIRE_VAR_STORE (gtk_sheet_get_model (var_sheet));
@@ -481,3 +592,163 @@ file_quit (GtkCheckMenuItem *menuitem, gpointer data)
   */
   gtk_main_quit ();
 }
+
+
+
+/* Callback for when the Clear item in the edit menu is activated */
+static void
+on_clear_activate (GtkMenuItem *menuitem, gpointer data)
+{
+  struct data_editor *de = data;
+
+  GtkNotebook *notebook = GTK_NOTEBOOK (get_widget_assert (de->xml,
+                                                          "notebook"));
+
+  switch ( gtk_notebook_get_current_page (notebook) )
+    {
+    case PAGE_VAR_SHEET:
+      {
+       GtkSheet *var_sheet =
+         GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
+
+       PsppireVarStore *vs = PSPPIRE_VAR_STORE
+         (gtk_sheet_get_model (var_sheet) );
+
+       /* This shouldn't be able to happen, because the menuitem
+          should be disabled */
+       g_return_if_fail (var_sheet->state  ==  GTK_SHEET_ROW_SELECTED );
+
+       psppire_dict_delete_variables (vs->dict,
+                                      var_sheet->range.row0,
+                                      1 +
+                                      var_sheet->range.rowi -
+                                      var_sheet->range.row0 );
+      }
+      break;
+      case PAGE_DATA_SHEET:
+       break;
+      default:
+       g_assert_not_reached ();
+    }
+}
+
+
+/* Insert a new variable before the current row in the variable sheet,
+   or before the current column in the data sheet, whichever is selected */
+static void
+insert_variable (GtkCheckMenuItem *m, gpointer data)
+{
+  struct data_editor *de = data;
+  gint posn;
+
+  GtkWidget *notebook = get_widget_assert (de->xml, "notebook");
+
+  GtkSheet *var_sheet =
+    GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
+
+  PsppireVarStore *vs = PSPPIRE_VAR_STORE
+    (gtk_sheet_get_model (var_sheet) );
+
+  switch ( gtk_notebook_get_current_page ( GTK_NOTEBOOK (notebook)) )
+    {
+    case PAGE_VAR_SHEET:
+      posn = var_sheet->active_cell.row;
+      break;
+    case PAGE_DATA_SHEET:
+      {
+       GtkSheet *data_sheet =
+         GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
+
+       if ( data_sheet->state == GTK_SHEET_COLUMN_SELECTED )
+         posn = data_sheet->range.col0;
+       else
+         posn = data_sheet->active_cell.col;
+      }
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  psppire_dict_insert_variable (vs->dict, posn, NULL);
+}
+
+
+/* Callback for when the dictionary changes its weights */
+static void
+on_weight_change (GObject *o, gint weight_index, gpointer data)
+{
+  struct data_editor *de = data;
+  GtkWidget *weight_status_area =
+    get_widget_assert (de->xml, "weight-status-area");
+
+  if ( weight_index == -1 )
+    {
+      gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
+    }
+  else
+    {
+      GtkSheet *var_sheet =
+       GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
+
+      PsppireVarStore *vs = PSPPIRE_VAR_STORE
+       (gtk_sheet_get_model (var_sheet) );
+
+      struct variable *var = psppire_dict_get_variable (vs->dict,
+                                                       weight_index);
+
+      gchar *text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
+
+      gtk_label_set_text (GTK_LABEL (weight_status_area), text);
+
+      g_free (text);
+    }
+}
+
+
+static void
+weight_cases_dialog (GObject *o, gpointer data)
+{
+  gint response;
+  struct data_editor *de = data;
+  GtkSheet *var_sheet =
+    GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
+
+
+  GladeXML *xml = glade_xml_new (PKGDATADIR "/psppire.glade",
+                                "weight-cases-dialog", NULL);
+
+
+  GtkWidget *treeview =  get_widget_assert (xml, "treeview");
+  GtkWidget *entry =  get_widget_assert (xml, "entry1");
+
+
+  PsppireVarStore *vs = PSPPIRE_VAR_STORE (gtk_sheet_get_model (var_sheet));
+
+  PsppireVarSelect *select = psppire_var_select_new (treeview,
+                                                    entry, vs->dict);
+
+
+  PsppireDialog *dialog = create_weight_dialog (select, xml);
+
+  response = psppire_dialog_run (dialog);
+
+  g_object_unref (xml);
+
+  if (response == GTK_RESPONSE_OK)
+    {
+      const GList *list = psppire_var_select_get_variables (select);
+
+      g_assert ( g_list_length (list) <= 1 );
+
+      if ( list == NULL)
+       psppire_dict_set_weight_variable (select->dict, NULL);
+      else
+       {
+         struct variable *var = list->data;
+
+         psppire_dict_set_weight_variable (select->dict, var);
+       }
+    }
+}
+
+