X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fui%2Fgui%2Fpsppire-variable-sheet.c;h=486d85c4ca2dd0aa37f1cf6526cc2dbd9ad5bb05;hb=e7913c62251710319b06c50702c5db9afb612be5;hp=2adef3f4d56d28ed021a8b4bc28170d2ca32b75b;hpb=e1c4d5d0f0c63ef20927ac2cd7f9ff4e7e4cf5c5;p=pspp diff --git a/src/ui/gui/psppire-variable-sheet.c b/src/ui/gui/psppire-variable-sheet.c index 2adef3f4d5..486d85c4ca 100644 --- a/src/ui/gui/psppire-variable-sheet.c +++ b/src/ui/gui/psppire-variable-sheet.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2017 John Darrington + Copyright (C) 2017, 2020 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 @@ -37,12 +37,8 @@ G_DEFINE_TYPE (PsppireVariableSheet, psppire_variable_sheet, SSW_TYPE_SHEET) static void -set_var_type (GtkCellRenderer *renderer, - GtkCellEditable *editable, - gchar *path, - gpointer user_data) +set_var_type (PsppireVariableSheet *sheet) { - PsppireVariableSheet *sheet = PSPPIRE_VARIABLE_SHEET (user_data); gint row = -1, col = -1; ssw_sheet_get_active_cell (SSW_SHEET (sheet), &col, &row); @@ -52,6 +48,9 @@ set_var_type (GtkCellRenderer *renderer, struct variable *var = psppire_dict_get_variable (PSPPIRE_DICT (dict), row); + if (var == NULL) + return; + const struct fmt_spec *format = var_get_write_format (var); struct fmt_spec fmt = *format; GtkWindow *win = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sheet))); @@ -62,12 +61,8 @@ set_var_type (GtkCellRenderer *renderer, } static void -set_missing_values (GtkCellRenderer *renderer, - GtkCellEditable *editable, - gchar *path, - gpointer user_data) +set_missing_values (PsppireVariableSheet *sheet) { - PsppireVariableSheet *sheet = PSPPIRE_VARIABLE_SHEET (user_data); gint row = -1, col = -1; ssw_sheet_get_active_cell (SSW_SHEET (sheet), &col, &row); @@ -77,6 +72,9 @@ set_missing_values (GtkCellRenderer *renderer, struct variable *var = psppire_dict_get_variable (PSPPIRE_DICT (dict), row); + if (var == NULL) + return; + struct missing_values mv; if (GTK_RESPONSE_OK == psppire_missing_val_dialog_run (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sheet))), @@ -89,12 +87,8 @@ set_missing_values (GtkCellRenderer *renderer, } static void -set_value_labels (GtkCellRenderer *renderer, - GtkCellEditable *editable, - gchar *path, - gpointer user_data) +set_value_labels (PsppireVariableSheet *sheet) { - PsppireVariableSheet *sheet = PSPPIRE_VARIABLE_SHEET (user_data); gint row = -1, col = -1; ssw_sheet_get_active_cell (SSW_SHEET (sheet), &col, &row); @@ -104,6 +98,9 @@ set_value_labels (GtkCellRenderer *renderer, struct variable *var = psppire_dict_get_variable (PSPPIRE_DICT (dict), row); + if (var == NULL) + return; + struct val_labs *vls = psppire_val_labs_dialog_run (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sheet))), var); @@ -213,8 +210,8 @@ select_renderer_func (PsppireVariableSheet *sheet, gint col, gint row, GType typ static void -show_variables_row_popup (SswSheet *sheet, int row, uint button, - uint state, gpointer p) +show_variables_row_popup (SswSheet *sheet, int row, guint button, + guint state, gpointer p) { PsppireVariableSheet *var_sheet = PSPPIRE_VARIABLE_SHEET (sheet); GListModel *vmodel = NULL; @@ -260,6 +257,13 @@ delete_variables (SswSheet *sheet) PsppireDict *dict = NULL; g_object_get (sheet, "data-model", &dict, NULL); + if (range->start_x > range->end_x) + { + gint temp = range->start_x; + range->start_x = range->end_x; + range->end_x = temp; + } + psppire_dict_delete_variables (dict, range->start_y, (range->end_y - range->start_y + 1)); @@ -271,6 +275,10 @@ create_var_row_header_popup_menu (PsppireVariableSheet *var_sheet) { GtkWidget *menu = gtk_menu_new (); + /* gtk_menu_shell_append does not sink/ref this object, + so we must do it ourselves (and remember to unref it). */ + g_object_ref_sink (menu); + GtkWidget *item = gtk_menu_item_new_with_mnemonic (_("_Insert Variable")); g_signal_connect_swapped (item, "activate", G_CALLBACK (insert_new_variable_var), @@ -317,12 +325,18 @@ change_var_property (PsppireVariableSheet *var_sheet, gint col, gint row, const PsppireDict *dict = NULL; g_object_get (var_sheet, "data-model", &dict, NULL); + int n_rows = psppire_dict_get_n_vars (dict); + if (row > n_rows) + return; + /* Return the IDXth variable */ struct variable *var = psppire_dict_get_variable (dict, row); if (NULL == var) var = psppire_dict_insert_variable (dict, row, NULL); + g_return_if_fail (var); + switch (col) { case DICT_TVM_COL_NAME: @@ -433,34 +447,61 @@ psppire_variable_sheet_dispose (GObject *obj) g_object_unref (sheet->value_label_renderer); g_object_unref (sheet->missing_values_renderer); g_object_unref (sheet->var_type_renderer); + g_object_unref (sheet->row_popup); /* Chain up to the parent class */ G_OBJECT_CLASS (parent_class)->dispose (obj); } +static void +psppire_variable_sheet_finalize (GObject *object) +{ + PsppireVariableSheet *sheet = PSPPIRE_VARIABLE_SHEET (object); + + g_free (sheet->value_label_dispatch); + g_free (sheet->missing_values_dispatch); + g_free (sheet->var_type_dispatch); + + if (G_OBJECT_CLASS (parent_class)->finalize) + (*G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +static void +psppire_variable_sheet_realize (GtkWidget *widget) +{ + /* This is a kludge. These are properties from the parent class. + They should really be set immediately after initialisation, but there is no + simple way to do that. */ + g_object_set (widget, + "editable", TRUE, + "select-renderer-func", select_renderer_func, + "vertical-draggable", TRUE, + "forward-conversion", var_sheet_data_to_string, + NULL); + + if (GTK_WIDGET_CLASS (parent_class)->realize) + (*GTK_WIDGET_CLASS (parent_class)->realize) (widget); +} + + static void psppire_variable_sheet_class_init (PsppireVariableSheetClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + object_class->dispose = psppire_variable_sheet_dispose; parent_class = g_type_class_peek_parent (class); + + widget_class->realize = psppire_variable_sheet_realize; + object_class->finalize = psppire_variable_sheet_finalize; } GtkWidget* psppire_variable_sheet_new (void) { - PsppireVarSheetHeader *vsh = - g_object_new (PSPPIRE_TYPE_VAR_SHEET_HEADER, NULL); - - GObject *obj = - g_object_new (PSPPIRE_TYPE_VARIABLE_SHEET, - "select-renderer-func", select_renderer_func, - "hmodel", vsh, - "forward-conversion", var_sheet_data_to_string, - NULL); - - return GTK_WIDGET (obj); + return g_object_new (PSPPIRE_TYPE_VARIABLE_SHEET, NULL); } static void @@ -485,29 +526,98 @@ move_variable (PsppireVariableSheet *sheet, gint from, gint to, gpointer ud) dict_reorder_var (dict->dict, var, new_pos); } + +static gboolean +is_printable_key (gint keyval) +{ + switch (keyval) + { + case GDK_KEY_Return: + case GDK_KEY_ISO_Left_Tab: + case GDK_KEY_Tab: + return FALSE; + break; + } + + return (0 != gdk_keyval_to_unicode (keyval)); +} + +struct dispatch +{ + PsppireVariableSheet *sheet; + void (*payload) (PsppireVariableSheet *); +}; + + +static gboolean +on_key_press (GtkWidget *w, GdkEventKey *e, gpointer user_data) +{ + const struct dispatch *d = user_data; + if (is_printable_key (e->keyval)) + { + d->payload (d->sheet); + return TRUE; + } + + return FALSE; +} + +static gboolean +on_button_press (GtkWidget *w, GdkEventButton *e, gpointer user_data) +{ + const struct dispatch *d = user_data; + if (e->button != 1) + return TRUE; + + d->payload (d->sheet); + return TRUE; +} + +static void +on_edit_start (GtkCellRenderer *renderer, + GtkCellEditable *editable, + gchar *path, + gpointer user_data) +{ + gtk_widget_grab_focus (GTK_WIDGET (editable)); + g_signal_connect (editable, "key-press-event", + G_CALLBACK (on_key_press), user_data); + g_signal_connect (editable, "button-press-event", + G_CALLBACK (on_button_press), user_data); + +} + static void psppire_variable_sheet_init (PsppireVariableSheet *sheet) { sheet->dispose_has_run = FALSE; sheet->value_label_renderer = gtk_cell_renderer_text_new (); - g_signal_connect (sheet->value_label_renderer, - "editing-started", G_CALLBACK (set_value_labels), - sheet); + sheet->value_label_dispatch = g_malloc (sizeof *sheet->value_label_dispatch); + sheet->value_label_dispatch->sheet = sheet; + sheet->value_label_dispatch->payload = set_value_labels; + g_signal_connect_after (sheet->value_label_renderer, + "editing-started", G_CALLBACK (on_edit_start), + sheet->value_label_dispatch); sheet->missing_values_renderer = gtk_cell_renderer_text_new (); - g_signal_connect (sheet->missing_values_renderer, - "editing-started", G_CALLBACK (set_missing_values), - sheet); + sheet->missing_values_dispatch = g_malloc (sizeof *sheet->missing_values_dispatch); + sheet->missing_values_dispatch->sheet = sheet; + sheet->missing_values_dispatch->payload = set_missing_values; + g_signal_connect_after (sheet->missing_values_renderer, + "editing-started", G_CALLBACK (on_edit_start), + sheet->missing_values_dispatch); sheet->var_type_renderer = gtk_cell_renderer_text_new (); - g_signal_connect (sheet->var_type_renderer, - "editing-started", G_CALLBACK (set_var_type), - sheet); + sheet->var_type_dispatch = g_malloc (sizeof *sheet->var_type_dispatch); + sheet->var_type_dispatch->sheet = sheet; + sheet->var_type_dispatch->payload = set_var_type; + g_signal_connect_after (sheet->var_type_renderer, + "editing-started", G_CALLBACK (on_edit_start), + sheet->var_type_dispatch); sheet->row_popup = create_var_row_header_popup_menu (sheet); - g_signal_connect (sheet, "selection-changed", G_CALLBACK (set_var_popup_sensitivity), sheet); @@ -519,4 +629,11 @@ psppire_variable_sheet_init (PsppireVariableSheet *sheet) g_signal_connect (sheet, "row-moved", G_CALLBACK (move_variable), NULL); + + PsppireVarSheetHeader *vsh = + g_object_new (PSPPIRE_TYPE_VAR_SHEET_HEADER, NULL); + + g_object_set (sheet, + "hmodel", vsh, + NULL); }