From: Ben Pfaff Date: Sun, 19 Aug 2012 20:16:05 +0000 (-0700) Subject: Merge 'master' into 'psppsheet'. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f481fd69631024bcdc7dc2369bbc1592d7a43ac7;p=pspp Merge 'master' into 'psppsheet'. --- f481fd69631024bcdc7dc2369bbc1592d7a43ac7 diff --cc src/ui/gui/automake.mk index 14beeb9a1e,405671095f..87795d8dd3 --- a/src/ui/gui/automake.mk +++ b/src/ui/gui/automake.mk @@@ -42,7 -44,7 +43,8 @@@ UI_FILES = src/ui/gui/data-editor.ui \ src/ui/gui/output-viewer.ui \ src/ui/gui/syntax-editor.ui \ - src/ui/gui/var-sheet.ui ++ src/ui/gui/var-sheet.ui \ + src/ui/gui/var-type-dialog.ui EXTRA_DIST += \ src/ui/gui/OChangeLog \ diff --cc src/ui/gui/psppire-var-sheet.c index 03d43dd9c2,b02a0a03ec..dfd5ce1c4c --- a/src/ui/gui/psppire-var-sheet.c +++ b/src/ui/gui/psppire-var-sheet.c @@@ -15,27 -15,18 +15,28 @@@ along with this program. If not, see . */ #include -#include "psppire-var-sheet.h" -#include -#include "builder-wrapper.h" -#include "helper.h" +#include "ui/gui/psppire-var-sheet.h" -#include "customentry.h" -#include +#include "data/format.h" #include "data/value-labels.h" -#include "psppire-var-store.h" +#include "libpspp/range-set.h" +#include "ui/gui/builder-wrapper.h" +#include "ui/gui/helper.h" +#include "ui/gui/missing-val-dialog.h" +#include "ui/gui/pspp-sheet-selection.h" +#include "ui/gui/psppire-cell-renderer-button.h" +#include "ui/gui/psppire-data-editor.h" +#include "ui/gui/psppire-data-window.h" +#include "ui/gui/psppire-dialog-action-var-info.h" +#include "ui/gui/psppire-empty-list-store.h" +#include "ui/gui/psppire-marshal.h" #include "ui/gui/val-labs-dialog.h" + #include "ui/gui/var-type-dialog.h" +#include "ui/gui/var-display.h" +#include "ui/gui/var-type-dialog.h" + +#include "gl/intprops.h" #include #define _(msgid) gettext (msgid) @@@ -445,255 -287,95 +446,281 @@@ path_string_to_variable (PsppireVarShee } static void -var_sheet_show_var_type_dialog (PsppireVarSheet *vs) +on_type_click (PsppireCellRendererButton *cell, + gchar *path, + PsppireVarSheet *var_sheet) { - var_sheet->var_type_dialog->pv = path_string_to_variable (var_sheet, path); - var_type_dialog_show (var_sheet->var_type_dialog); - PsppireVarStore *var_store; ++ GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (var_sheet)); + struct fmt_spec format; + struct variable *var; - gint row; + - var_store = PSPPIRE_VAR_STORE (psppire_sheet_get_model (PSPPIRE_SHEET (vs))); - - psppire_sheet_get_active_cell (PSPPIRE_SHEET (vs), &row, NULL); - var = psppire_var_store_get_var (var_store, row); ++ var = path_string_to_variable (var_sheet, path); + g_return_if_fail (var != NULL); + + format = *var_get_print_format (var); - psppire_var_type_dialog_run (GTK_WINDOW (gtk_widget_get_toplevel ( - GTK_WIDGET (vs))), &format); ++ psppire_var_type_dialog_run (GTK_WINDOW (toplevel), &format); + var_set_width (var, fmt_var_width (&format)); + var_set_both_formats (var, &format); } static void -var_sheet_show_val_labs_dialog (PsppireVarSheet *vs) +on_value_labels_click (PsppireCellRendererButton *cell, + gchar *path, + PsppireVarSheet *var_sheet) { - struct variable *var = path_string_to_variable (var_sheet, path); - val_labs_dialog_set_target_variable (var_sheet->val_labs_dialog, var); - val_labs_dialog_show (var_sheet->val_labs_dialog); - PsppireVarStore *var_store; ++ GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (var_sheet)); + struct val_labs *labels; + struct variable *var; - gint row; - - var_store = PSPPIRE_VAR_STORE (psppire_sheet_get_model (PSPPIRE_SHEET (vs))); + - psppire_sheet_get_active_cell (PSPPIRE_SHEET (vs), &row, NULL); - var = psppire_var_store_get_var (var_store, row); ++ var = path_string_to_variable (var_sheet, path); + g_return_if_fail (var != NULL); + - labels = psppire_val_labs_dialog_run (GTK_WINDOW (gtk_widget_get_toplevel ( - GTK_WIDGET (vs))), var); ++ labels = psppire_val_labs_dialog_run (GTK_WINDOW (toplevel), var); + if (labels) + { + var_set_value_labels (var, labels); + val_labs_destroy (labels); + } } static void -var_sheet_show_miss_vals_dialog (PsppireVarSheet *vs) +on_missing_values_click (PsppireCellRendererButton *cell, + gchar *path, + PsppireVarSheet *var_sheet) { - var_sheet->missing_val_dialog->pv = path_string_to_variable (var_sheet, - path); - missing_val_dialog_show (var_sheet->missing_val_dialog); - PsppireVarStore *var_store; ++ GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (var_sheet)); + struct missing_values mv; + struct variable *var; - gint row; - - var_store = PSPPIRE_VAR_STORE (psppire_sheet_get_model (PSPPIRE_SHEET (vs))); + - psppire_sheet_get_active_cell (PSPPIRE_SHEET (vs), &row, NULL); - var = psppire_var_store_get_var (var_store, row); ++ var = path_string_to_variable (var_sheet, path); + g_return_if_fail (var != NULL); + - psppire_missing_val_dialog_run (GTK_WINDOW (gtk_widget_get_toplevel ( - GTK_WIDGET (vs))), var, &mv); ++ psppire_missing_val_dialog_run (GTK_WINDOW (toplevel), var, &mv); + var_set_missing_values (var, &mv); + mv_destroy (&mv); } -/* - Callback whenever the active cell changes on the var sheet. -*/ +static gint +get_string_width (PsppSheetView *treeview, GtkCellRenderer *renderer, + const char *string) +{ + gint width; + g_object_set (G_OBJECT (renderer), + PSPPIRE_IS_CELL_RENDERER_BUTTON (renderer) ? "label" : "text", + string, (void *) NULL); + gtk_cell_renderer_get_size (renderer, GTK_WIDGET (treeview), + NULL, NULL, NULL, &width, NULL); + return width; +} + +static gint +get_monospace_width (PsppSheetView *treeview, GtkCellRenderer *renderer, + size_t char_cnt) +{ + struct string s; + gint width; + + ds_init_empty (&s); + ds_put_byte_multiple (&s, '0', char_cnt); + ds_put_byte (&s, ' '); + width = get_string_width (treeview, renderer, ds_cstr (&s)); + ds_destroy (&s); + + return width; +} + +static PsppSheetViewColumn * +add_var_sheet_column (PsppireVarSheet *var_sheet, GtkCellRenderer *renderer, + enum vs_column column_id, + const char *title, int width) +{ + PsppSheetView *sheet_view = PSPP_SHEET_VIEW (var_sheet); + int title_width, content_width; + PsppSheetViewColumn *column; + + column = pspp_sheet_view_column_new_with_attributes (title, renderer, NULL); + g_object_set_data (G_OBJECT (column), "column-number", + GINT_TO_POINTER (column_id) + 1); + + pspp_sheet_view_column_set_cell_data_func ( + column, renderer, render_var_cell, var_sheet, NULL); + + title_width = get_string_width (sheet_view, renderer, title); + content_width = get_monospace_width (sheet_view, renderer, width); + g_object_set_data (G_OBJECT (column), "content-width", + GINT_TO_POINTER (content_width)); + + pspp_sheet_view_column_set_fixed_width (column, + MAX (title_width, content_width)); + pspp_sheet_view_column_set_resizable (column, TRUE); + + pspp_sheet_view_append_column (sheet_view, column); + + g_signal_connect (renderer, "edited", + G_CALLBACK (on_var_column_edited), + var_sheet); + g_object_set_data (G_OBJECT (renderer), "column-id", + GINT_TO_POINTER (column_id)); + g_object_set_data (G_OBJECT (renderer), "var-sheet", var_sheet); + + return column; +} + +static PsppSheetViewColumn * +add_text_column (PsppireVarSheet *var_sheet, enum vs_column column_id, + const char *title, int width) +{ + return add_var_sheet_column (var_sheet, gtk_cell_renderer_text_new (), + column_id, title, width); +} + +static PsppSheetViewColumn * +add_spin_column (PsppireVarSheet *var_sheet, enum vs_column column_id, + const char *title, int width) +{ + return add_var_sheet_column (var_sheet, gtk_cell_renderer_spin_new (), + column_id, title, width); +} + +static PsppSheetViewColumn * +add_combo_column (PsppireVarSheet *var_sheet, enum vs_column column_id, + const char *title, int width, + ...) +{ + GtkCellRenderer *cell; + GtkListStore *store; + const char *name; + va_list args; + + store = gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING); + va_start (args, width); + while ((name = va_arg (args, const char *)) != NULL) + { + int value = va_arg (args, int); + gtk_list_store_insert_with_values (store, NULL, G_MAXINT, + 0, value, + 1, name, + -1); + } + va_end (args); + + cell = gtk_cell_renderer_combo_new (); + g_object_set (cell, + "has-entry", FALSE, + "model", GTK_TREE_MODEL (store), + "text-column", 1, + NULL); + + return add_var_sheet_column (var_sheet, cell, column_id, title, width); + +} + static void -var_sheet_change_active_cell (PsppireVarSheet *vs, - gint row, gint column, - gint oldrow, gint oldcolumn, - gpointer data) +add_popup_menu (PsppireVarSheet *var_sheet, + PsppSheetViewColumn *column, + void (*on_click) (PsppireCellRendererButton *, + gchar *path, + PsppireVarSheet *var_sheet)) { - PsppireVarStore *var_store; - PsppireVarSheetClass *vs_class = - PSPPIRE_VAR_SHEET_CLASS(G_OBJECT_GET_CLASS (vs)); + PsppSheetView *sheet_view = PSPP_SHEET_VIEW (var_sheet); + const char *button_label = "..."; + GtkCellRenderer *button_renderer; + gint content_width; + + button_renderer = psppire_cell_renderer_button_new (); + g_object_set (button_renderer, + "label", button_label, + "editable", TRUE, + NULL); + g_signal_connect (button_renderer, "clicked", G_CALLBACK (on_click), + var_sheet); + pspp_sheet_view_column_pack_start (column, button_renderer, FALSE); + pspp_sheet_view_column_set_cell_data_func ( + column, button_renderer, render_popup_cell, var_sheet, NULL); + + content_width = GPOINTER_TO_INT (g_object_get_data ( + G_OBJECT (column), "content-width")); + content_width += get_string_width (sheet_view, button_renderer, + button_label); + if (content_width > pspp_sheet_view_column_get_fixed_width (column)) + pspp_sheet_view_column_set_fixed_width (column, content_width); +} - struct variable *var ; - PsppireSheet *sheet = PSPPIRE_SHEET (vs); +static gboolean +get_tooltip_location (GtkWidget *widget, GtkTooltip *tooltip, + gint wx, gint wy, size_t *row, size_t *column) +{ + PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget); + gint bx, by; + GtkTreePath *path; + GtkTreeIter iter; + PsppSheetViewColumn *tree_column; + GtkTreeModel *tree_model; + gpointer column_ptr; + bool ok; + + /* Check that WIDGET is really visible on the screen before we + do anything else. This is a bug fix for a sticky situation: + when text_data_import_assistant() returns, it frees the data + necessary to compose the tool tip message, but there may be + a tool tip under preparation at that point (even if there is + no visible tool tip) that will call back into us a little + bit later. Perhaps the correct solution to this problem is + to make the data related to the tool tips part of a GObject + that only gets destroyed when all references are released, + but this solution appears to be effective too. */ + if (!gtk_widget_get_mapped (widget)) + return FALSE; + + pspp_sheet_view_convert_widget_to_bin_window_coords (tree_view, + wx, wy, &bx, &by); + if (!pspp_sheet_view_get_path_at_pos (tree_view, bx, by, + &path, &tree_column, NULL, NULL)) + return FALSE; + + column_ptr = g_object_get_data (G_OBJECT (tree_column), "column-number"); + if (column_ptr == NULL) + return FALSE; + *column = GPOINTER_TO_INT (column_ptr) - 1; + + pspp_sheet_view_set_tooltip_cell (tree_view, tooltip, path, tree_column, + NULL); + + tree_model = pspp_sheet_view_get_model (tree_view); + ok = gtk_tree_model_get_iter (tree_model, &iter, path); + gtk_tree_path_free (path); + if (!ok) + return FALSE; + + *row = GPOINTER_TO_INT (iter.user_data); + return TRUE; +} - g_return_if_fail (sheet != NULL); +static gboolean +on_query_var_tooltip (GtkWidget *widget, gint wx, gint wy, + gboolean keyboard_mode UNUSED, + GtkTooltip *tooltip, gpointer *user_data UNUSED) +{ + PsppireVarSheet *var_sheet = PSPPIRE_VAR_SHEET (widget); + PsppireDict *dict; + struct variable *var; + size_t row, column; - var_store = PSPPIRE_VAR_STORE (psppire_sheet_get_model (sheet)); + if (!get_tooltip_location (widget, tooltip, wx, wy, &row, &column)) + return FALSE; - g_assert (var_store); + dict = psppire_var_sheet_get_dictionary (var_sheet); + g_return_val_if_fail (dict != NULL, FALSE); - g_return_if_fail (oldcolumn == PSPPIRE_VAR_STORE_COL_NAME || - row < psppire_var_store_get_var_cnt (var_store)); + if (row >= psppire_dict_get_var_cnt (dict)) + { + gtk_tooltip_set_text (tooltip, _("Enter a variable name to add a " + "new variable.")); + return TRUE; + } - var = psppire_var_store_get_var (var_store, row); + var = psppire_dict_get_variable (dict, row); + g_return_val_if_fail (var != NULL, FALSE); switch (column) { @@@ -895,560 -525,64 +922,543 @@@ psppire_var_sheet_get_property (GObjec } } - static void - psppire_var_sheet_realize (GtkWidget *w) - { - PsppireVarSheet *var_sheet = PSPPIRE_VAR_SHEET (w); - GtkWindow *toplevel; - - GTK_WIDGET_CLASS (psppire_var_sheet_parent_class)->realize (w); - - toplevel = GTK_WINDOW (gtk_widget_get_toplevel (w)); - var_sheet->val_labs_dialog = val_labs_dialog_create (toplevel); - var_sheet->missing_val_dialog = missing_val_dialog_create (toplevel); - var_sheet->var_type_dialog = var_type_dialog_create (toplevel); - } - +static void +psppire_var_sheet_dispose (GObject *obj) +{ + PsppireVarSheet *var_sheet = PSPPIRE_VAR_SHEET (obj); + int i; + + if (var_sheet->dispose_has_run) + return; + + var_sheet->dispose_has_run = TRUE; + + for (i = 0; i < PSPPIRE_VAR_SHEET_N_SIGNALS; i++) + if ( var_sheet->dict_signals[i]) + g_signal_handler_disconnect (var_sheet->dict, + var_sheet->dict_signals[i]); + + if (var_sheet->dict) + g_object_unref (var_sheet->dict); + + if (var_sheet->uim) + g_object_unref (var_sheet->uim); + + /* These dialogs are not GObjects (although they should be!) + But for now, unreffing them only causes a GCritical Error + so comment them out for now. (and accept the memory leakage) + + g_object_unref (var_sheet->val_labs_dialog); + g_object_unref (var_sheet->missing_val_dialog); + g_object_unref (var_sheet->var_type_dialog); + */ + + G_OBJECT_CLASS (psppire_var_sheet_parent_class)->dispose (obj); +} static void -psppire_var_sheet_init (PsppireVarSheet *vs) +psppire_var_sheet_class_init (PsppireVarSheetClass *class) { - GtkBuilder *builder = builder_new ("data-editor.ui"); + GObjectClass *gobject_class = G_OBJECT_CLASS (class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + GParamSpec *pspec; - connect_help (builder); + gobject_class->set_property = psppire_var_sheet_set_property; + gobject_class->get_property = psppire_var_sheet_get_property; + gobject_class->dispose = psppire_var_sheet_dispose; + - widget_class->realize = psppire_var_sheet_realize; - + g_signal_new ("var-double-clicked", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_true_handled, NULL, + psppire_marshal_BOOLEAN__INT, + G_TYPE_BOOLEAN, 1, G_TYPE_INT); + + pspec = g_param_spec_object ("dictionary", + "Dictionary displayed by the sheet", + "The PsppireDict that the sheet displays " + "may allow the user to edit", + PSPPIRE_TYPE_DICT, + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_DICTIONARY, pspec); - g_object_unref (builder); + pspec = g_param_spec_boolean ("may-create-vars", + "May create variables", + "Whether the user may create more variables", + TRUE, + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_MAY_CREATE_VARS, pspec); - vs->dispose_has_run = FALSE; - vs->may_create_vars = TRUE; + pspec = g_param_spec_boolean ("may-delete-vars", + "May delete variables", + "Whether the user may delete variables", + TRUE, + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_MAY_DELETE_VARS, pspec); + + pspec = g_param_spec_enum ("format-use", + "Use of variable format", + ("Whether variables have input or output " + "formats"), + PSPPIRE_TYPE_FMT_USE, + FMT_FOR_OUTPUT, + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_FORMAT_TYPE, pspec); + + pspec = g_param_spec_object ("ui-manager", + "UI Manager", + "UI manager for the variable sheet. The client should merge this UI manager with the active UI manager to obtain variable sheet specific menu items and tool bar items.", + GTK_TYPE_UI_MANAGER, + G_PARAM_READABLE); + g_object_class_install_property (gobject_class, PROP_UI_MANAGER, pspec); +} - g_signal_connect (vs, "activate", - G_CALLBACK (var_sheet_change_active_cell), - NULL); +static void +render_row_number_cell (PsppSheetViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data) +{ + PsppireVarSheet *var_sheet = user_data; + GValue gvalue = { 0, }; + gint row; + + row = GPOINTER_TO_INT (iter->user_data); + + g_value_init (&gvalue, G_TYPE_INT); + g_value_set_int (&gvalue, row + 1); + g_object_set_property (G_OBJECT (cell), "label", &gvalue); + g_value_unset (&gvalue); + + if (!var_sheet->dict || row < psppire_dict_get_var_cnt (var_sheet->dict)) + g_object_set (cell, "editable", TRUE, NULL); + else + g_object_set (cell, "editable", FALSE, NULL); +} + +static void +psppire_var_sheet_row_number_double_clicked (PsppireCellRendererButton *button, + gchar *path_string, + PsppireVarSheet *var_sheet) +{ + GtkTreePath *path; + + g_return_if_fail (var_sheet->dict != NULL); + + path = gtk_tree_path_new_from_string (path_string); + if (gtk_tree_path_get_depth (path) == 1) + { + gint *indices = gtk_tree_path_get_indices (path); + if (indices[0] < psppire_dict_get_var_cnt (var_sheet->dict)) + { + gboolean handled; + g_signal_emit_by_name (var_sheet, "var-double-clicked", + indices[0], &handled); + } + } + gtk_tree_path_free (path); +} + +static PsppSheetViewColumn * +make_row_number_column (PsppireVarSheet *var_sheet) +{ + PsppSheetViewColumn *column; + GtkCellRenderer *renderer; + + renderer = psppire_cell_renderer_button_new (); + g_object_set (renderer, "xalign", 1.0, NULL); + g_signal_connect (renderer, "double-clicked", + G_CALLBACK (psppire_var_sheet_row_number_double_clicked), + var_sheet); + + column = pspp_sheet_view_column_new_with_attributes (_("Variable"), + renderer, NULL); + pspp_sheet_view_column_set_cell_data_func ( + column, renderer, render_row_number_cell, var_sheet, NULL); + pspp_sheet_view_column_set_fixed_width (column, 50); + return column; +} + +static void +on_edit_clear_variables (GtkAction *action, PsppireVarSheet *var_sheet) +{ + PsppSheetView *sheet_view = PSPP_SHEET_VIEW (var_sheet); + PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view); + PsppireDict *dict = var_sheet->dict; + const struct range_set_node *node; + struct range_set *selected; + + selected = pspp_sheet_selection_get_range_set (selection); + for (node = range_set_last (selected); node != NULL; + node = range_set_prev (selected, node)) + { + int i; + + for (i = 1; i <= range_set_node_get_width (node); i++) + { + unsigned long row = range_set_node_get_end (node) - i; + if (row >= 0 && row < psppire_dict_get_var_cnt (dict)) + psppire_dict_delete_variables (dict, row, 1); + } + } + range_set_destroy (selected); +} + +static void +on_selection_changed (PsppSheetSelection *selection, + gpointer user_data UNUSED) +{ + PsppSheetView *sheet_view = pspp_sheet_selection_get_tree_view (selection); + PsppireVarSheet *var_sheet = PSPPIRE_VAR_SHEET (sheet_view); + gint n_selected_rows; + gboolean may_delete; + GtkTreePath *path; + GtkAction *action; + + n_selected_rows = pspp_sheet_selection_count_selected_rows (selection); + + action = get_action_assert (var_sheet->builder, "edit_insert-variable"); + gtk_action_set_sensitive (action, (var_sheet->may_create_vars + && n_selected_rows > 0)); + + switch (n_selected_rows) + { + case 0: + may_delete = FALSE; + break; + + case 1: + /* The row used for inserting new variables cannot be deleted. */ + path = gtk_tree_path_new_from_indices ( + psppire_dict_get_var_cnt (var_sheet->dict), -1); + may_delete = !pspp_sheet_selection_path_is_selected (selection, path); + gtk_tree_path_free (path); + break; - g_signal_connect (vs, "traverse", - G_CALLBACK (traverse_cell_callback), NULL); + default: + may_delete = TRUE; + break; + } + action = get_action_assert (var_sheet->builder, "edit_clear-variables"); + gtk_action_set_sensitive (action, var_sheet->may_delete_vars && may_delete); } +static void +on_edit_insert_variable (GtkAction *action, PsppireVarSheet *var_sheet) +{ + PsppSheetView *sheet_view = PSPP_SHEET_VIEW (var_sheet); + PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view); + PsppireDict *dict = var_sheet->dict; + struct range_set *selected; + unsigned long row; + + selected = pspp_sheet_selection_get_range_set (selection); + row = range_set_scan (selected, 0); + range_set_destroy (selected); + + if (row <= psppire_dict_get_var_cnt (dict)) + { + gchar name[64];; + if (psppire_dict_generate_name (dict, name, sizeof name)) + psppire_dict_insert_variable (dict, row, name); + } +} + +static void +psppire_var_sheet_init (PsppireVarSheet *obj) +{ + PsppSheetView *sheet_view = PSPP_SHEET_VIEW (obj); + PsppSheetViewColumn *column; + GtkAction *action; + GList *list; + + obj->dict = NULL; + obj->format_use = FMT_FOR_OUTPUT; + obj->may_create_vars = TRUE; + obj->may_delete_vars = TRUE; -static const struct column_parameters column_def[] = { - { N_("Name"), 80}, - { N_("Type"), 100}, - { N_("Width"), 57}, - { N_("Decimals"),91}, - { N_("Label"), 95}, - { N_("Values"), 103}, - { N_("Missing"), 95}, - { N_("Columns"), 80}, - { N_("Align"), 69}, - { N_("Measure"), 99}, -}; + obj->scroll_to_bottom_signal = 0; -GtkWidget* + obj->container = NULL; + obj->dispose_has_run = FALSE; + obj->uim = NULL; + + pspp_sheet_view_append_column (sheet_view, make_row_number_column (obj)); + + column = add_text_column (obj, VS_NAME, _("Name"), 12); + list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column)); + g_signal_connect (list->data, "editing-started", + G_CALLBACK (on_name_column_editing_started), NULL); + g_list_free (list); + + column = add_text_column (obj, VS_TYPE, _("Type"), 8); + add_popup_menu (obj, column, on_type_click); + + add_spin_column (obj, VS_WIDTH, _("Width"), 5); + + add_spin_column (obj, VS_DECIMALS, _("Decimals"), 2); + + add_text_column (obj, VS_LABEL, _("Label"), 20); + + column = add_text_column (obj, VS_VALUES, _("Value Labels"), 20); + add_popup_menu (obj, column, on_value_labels_click); + + column = add_text_column (obj, VS_MISSING, _("Missing Values"), 20); + add_popup_menu (obj, column, on_missing_values_click); + + add_spin_column (obj, VS_COLUMNS, _("Columns"), 3); + + add_combo_column (obj, VS_ALIGN, _("Align"), 6, + alignment_to_string (ALIGN_LEFT), ALIGN_LEFT, + alignment_to_string (ALIGN_CENTRE), ALIGN_CENTRE, + alignment_to_string (ALIGN_RIGHT), ALIGN_RIGHT, + NULL); + + add_combo_column (obj, VS_MEASURE, _("Measure"), 10, + measure_to_string (MEASURE_NOMINAL), MEASURE_NOMINAL, + measure_to_string (MEASURE_ORDINAL), MEASURE_ORDINAL, + measure_to_string (MEASURE_SCALE), MEASURE_SCALE, + NULL); + + pspp_sheet_view_set_rubber_banding (sheet_view, TRUE); + pspp_sheet_selection_set_mode (pspp_sheet_view_get_selection (sheet_view), + PSPP_SHEET_SELECTION_MULTIPLE); + + g_object_set (G_OBJECT (obj), "has-tooltip", TRUE, NULL); + g_signal_connect (obj, "query-tooltip", + G_CALLBACK (on_query_var_tooltip), NULL); + g_signal_connect (obj, "button-press-event", + G_CALLBACK (on_button_pressed), NULL); + g_signal_connect (obj, "popup-menu", G_CALLBACK (on_popup_menu), NULL); + + obj->builder = builder_new ("var-sheet.ui"); + + action = get_action_assert (obj->builder, "edit_clear-variables"); + g_signal_connect (action, "activate", G_CALLBACK (on_edit_clear_variables), + obj); + gtk_action_set_sensitive (action, FALSE); + g_signal_connect (pspp_sheet_view_get_selection (sheet_view), + "changed", G_CALLBACK (on_selection_changed), NULL); + + action = get_action_assert (obj->builder, "edit_insert-variable"); + gtk_action_set_sensitive (action, FALSE); + g_signal_connect (action, "activate", G_CALLBACK (on_edit_insert_variable), + obj); +} + +GtkWidget * psppire_var_sheet_new (void) { - gint i; - PsppireAxis *ha = psppire_axis_new (); - PsppireAxis *va = psppire_axis_new (); + return g_object_new (PSPPIRE_VAR_SHEET_TYPE, NULL); +} - GtkWidget *w = g_object_new (psppire_var_sheet_get_type (), NULL); +PsppireDict * +psppire_var_sheet_get_dictionary (PsppireVarSheet *var_sheet) +{ + return var_sheet->dict; +} - for (i = 0 ; i < 10 ; ++i) - psppire_axis_append (ha, column_def[i].width); +static void +refresh_model (PsppireVarSheet *var_sheet) +{ + pspp_sheet_view_set_model (PSPP_SHEET_VIEW (var_sheet), NULL); - g_object_set (va, - "default-size", 25, - NULL); + if (var_sheet->dict != NULL) + { + PsppireEmptyListStore *store; + int n_rows; + + n_rows = (psppire_dict_get_var_cnt (var_sheet->dict) + + var_sheet->may_create_vars); + store = psppire_empty_list_store_new (n_rows); + pspp_sheet_view_set_model (PSPP_SHEET_VIEW (var_sheet), + GTK_TREE_MODEL (store)); + g_object_unref (store); + } +} + +static void +on_var_changed (PsppireDict *dict, glong row, PsppireVarSheet *var_sheet) +{ + PsppireEmptyListStore *store; + + g_return_if_fail (dict == var_sheet->dict); + + store = PSPPIRE_EMPTY_LIST_STORE (pspp_sheet_view_get_model ( + PSPP_SHEET_VIEW (var_sheet))); + g_return_if_fail (store != NULL); + + psppire_empty_list_store_row_changed (store, row); +} + +static void +on_var_inserted (PsppireDict *dict, glong row, PsppireVarSheet *var_sheet) +{ + PsppireEmptyListStore *store; + int n_rows; - g_object_set (ha, "minimum-extent", 0, - NULL); + g_return_if_fail (dict == var_sheet->dict); - g_object_set (w, - "horizontal-axis", ha, - "vertical-axis", va, - NULL); + store = PSPPIRE_EMPTY_LIST_STORE (pspp_sheet_view_get_model ( + PSPP_SHEET_VIEW (var_sheet))); + g_return_if_fail (store != NULL); - return w; + n_rows = (psppire_dict_get_var_cnt (var_sheet->dict) + + var_sheet->may_create_vars); + psppire_empty_list_store_set_n_rows (store, n_rows); + psppire_empty_list_store_row_inserted (store, row); +} + +static void +on_var_deleted (PsppireDict *dict, + const struct variable *var, int dict_idx, int case_idx, + PsppireVarSheet *var_sheet) +{ + PsppireEmptyListStore *store; + int n_rows; + + g_return_if_fail (dict == var_sheet->dict); + + store = PSPPIRE_EMPTY_LIST_STORE (pspp_sheet_view_get_model ( + PSPP_SHEET_VIEW (var_sheet))); + g_return_if_fail (store != NULL); + + n_rows = (psppire_dict_get_var_cnt (var_sheet->dict) + + var_sheet->may_create_vars); + psppire_empty_list_store_set_n_rows (store, n_rows); + psppire_empty_list_store_row_deleted (store, dict_idx); +} + +static void +on_backend_changed (PsppireDict *dict, PsppireVarSheet *var_sheet) +{ + g_return_if_fail (dict == var_sheet->dict); + refresh_model (var_sheet); } + +void +psppire_var_sheet_set_dictionary (PsppireVarSheet *var_sheet, + PsppireDict *dict) +{ + if (var_sheet->dict != NULL) + { + int i; + + for (i = 0; i < PSPPIRE_VAR_SHEET_N_SIGNALS; i++) + { + if (var_sheet->dict_signals[i]) + g_signal_handler_disconnect (var_sheet->dict, + var_sheet->dict_signals[i]); + + var_sheet->dict_signals[i] = 0; + } + + g_object_unref (var_sheet->dict); + } + + var_sheet->dict = dict; + + if (dict != NULL) + { + g_object_ref (dict); + + var_sheet->dict_signals[PSPPIRE_VAR_SHEET_BACKEND_CHANGED] + = g_signal_connect (dict, "backend-changed", + G_CALLBACK (on_backend_changed), var_sheet); + + var_sheet->dict_signals[PSPPIRE_VAR_SHEET_VARIABLE_CHANGED] + = g_signal_connect (dict, "variable-changed", + G_CALLBACK (on_var_changed), var_sheet); + + var_sheet->dict_signals[PSPPIRE_VAR_SHEET_VARIABLE_DELETED] + = g_signal_connect (dict, "variable-inserted", + G_CALLBACK (on_var_inserted), var_sheet); + + var_sheet->dict_signals[PSPPIRE_VAR_SHEET_VARIABLE_INSERTED] + = g_signal_connect (dict, "variable-deleted", + G_CALLBACK (on_var_deleted), var_sheet); + } + + refresh_model (var_sheet); +} + +gboolean +psppire_var_sheet_get_may_create_vars (PsppireVarSheet *var_sheet) +{ + return var_sheet->may_create_vars; +} + +void +psppire_var_sheet_set_may_create_vars (PsppireVarSheet *var_sheet, + gboolean may_create_vars) +{ + if (var_sheet->may_create_vars != may_create_vars) + { + PsppireEmptyListStore *store; + gint n_rows; + + var_sheet->may_create_vars = may_create_vars; + + store = PSPPIRE_EMPTY_LIST_STORE (pspp_sheet_view_get_model ( + PSPP_SHEET_VIEW (var_sheet))); + g_return_if_fail (store != NULL); + + n_rows = (psppire_dict_get_var_cnt (var_sheet->dict) + + var_sheet->may_create_vars); + psppire_empty_list_store_set_n_rows (store, n_rows); + + if (may_create_vars) + psppire_empty_list_store_row_inserted (store, n_rows - 1); + else + psppire_empty_list_store_row_deleted (store, n_rows); + + on_selection_changed (pspp_sheet_view_get_selection ( + PSPP_SHEET_VIEW (var_sheet)), NULL); + } +} + +gboolean +psppire_var_sheet_get_may_delete_vars (PsppireVarSheet *var_sheet) +{ + return var_sheet->may_delete_vars; +} + +void +psppire_var_sheet_set_may_delete_vars (PsppireVarSheet *var_sheet, + gboolean may_delete_vars) +{ + if (var_sheet->may_delete_vars != may_delete_vars) + { + var_sheet->may_delete_vars = may_delete_vars; + on_selection_changed (pspp_sheet_view_get_selection ( + PSPP_SHEET_VIEW (var_sheet)), NULL); + } +} + +void +psppire_var_sheet_goto_variable (PsppireVarSheet *var_sheet, int dict_index) +{ + PsppSheetView *sheet_view = PSPP_SHEET_VIEW (var_sheet); + GtkTreePath *path; + + path = gtk_tree_path_new_from_indices (dict_index, -1); + pspp_sheet_view_scroll_to_cell (sheet_view, path, NULL, FALSE, 0.0, 0.0); + pspp_sheet_view_set_cursor (sheet_view, path, NULL, FALSE); + gtk_tree_path_free (path); +} + +GtkUIManager * +psppire_var_sheet_get_ui_manager (PsppireVarSheet *var_sheet) +{ + if (var_sheet->uim == NULL) + { + var_sheet->uim = GTK_UI_MANAGER (get_object_assert (var_sheet->builder, + "var_sheet_uim", + GTK_TYPE_UI_MANAGER)); + g_object_ref (var_sheet->uim); + } + + return var_sheet->uim; +} + diff --cc src/ui/gui/psppire-var-sheet.h index cd4bd20b3b,058821b7b3..e8db83e12a --- a/src/ui/gui/psppire-var-sheet.h +++ b/src/ui/gui/psppire-var-sheet.h @@@ -44,45 -36,25 +44,42 @@@ GType psppire_fmt_use_get_type (void) G typedef struct _PsppireVarSheet PsppireVarSheet; typedef struct _PsppireVarSheetClass PsppireVarSheetClass; +enum +{ + PSPPIRE_VAR_SHEET_BACKEND_CHANGED, + PSPPIRE_VAR_SHEET_VARIABLE_CHANGED, + PSPPIRE_VAR_SHEET_VARIABLE_INSERTED, + PSPPIRE_VAR_SHEET_VARIABLE_DELETED, + PSPPIRE_VAR_SHEET_N_SIGNALS + }; + struct _PsppireVarSheet { - PsppireSheet parent; + PsppSheetView parent; - gboolean dispose_has_run; gboolean may_create_vars; -}; + gboolean may_delete_vars; + enum fmt_use format_use; + struct _PsppireDict *dict; - struct val_labs_dialog *val_labs_dialog; - struct missing_val_dialog *missing_val_dialog; - struct var_type_dialog *var_type_dialog; -struct _PsppireVarSheetClass -{ - PsppireSheetClass parent_class; + gulong scroll_to_bottom_signal; + gulong dict_signals[PSPPIRE_VAR_SHEET_N_SIGNALS]; + + GtkBuilder *builder; - GtkListStore *alignment_list; - GtkListStore *measure_list; + GtkWidget *container; + gulong on_switch_page_handler; - void (*var_sheet)(PsppireVarSheet*); + GtkUIManager *uim; + + gboolean dispose_has_run; }; +struct _PsppireVarSheetClass +{ + PsppSheetViewClass parent_class; +}; GType psppire_var_sheet_get_type (void); GtkWidget* psppire_var_sheet_new (void); diff --cc src/ui/gui/val-labs-dialog.h index 89b85d073e,379a5eeb3e..74b752e142 --- a/src/ui/gui/val-labs-dialog.h +++ b/src/ui/gui/val-labs-dialog.h @@@ -23,16 -23,61 +23,60 @@@ #include - #include + #include "data/format.h" + #include "data/variable.h" + #include "ui/gui/psppire-dialog.h" -#include "ui/gui/psppire-var-store.h" - struct val_labs; + G_BEGIN_DECLS + #define PSPPIRE_TYPE_VAL_LABS_DIALOG (psppire_val_labs_dialog_get_type()) + #define PSPPIRE_VAL_LABS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),PSPPIRE_TYPE_VAL_LABS_DIALOG,PsppireValLabsDialog)) + #define PSPPIRE_VAL_LABS_DIALOG_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class),PSPPIRE_TYPE_VAL_LABS_DIALOG,PsppireValLabsDialogClass)) + #define PSPPIRE_IS_VAL_LABS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PSPPIRE_TYPE_VAL_LABS_DIALOG)) + #define PSPPIRE_IS_VAL_LABS_DIALOG_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),PSPPIRE_TYPE_VAL_LABS_DIALOG)) + #define PSPPIRE_VAL_LABS_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),PSPPIRE_TYPE_VAL_LABS_DIALOG,PsppireValLabsDialogClass)) - struct val_labs_dialog * val_labs_dialog_create (GtkWindow *); + typedef struct _PsppireValLabsDialog PsppireValLabsDialog; + typedef struct _PsppireValLabsDialogClass PsppireValLabsDialogClass; - void val_labs_dialog_show (struct val_labs_dialog *); + struct _PsppireValLabsDialog { + PsppireDialog parent; - void val_labs_dialog_set_target_variable (struct val_labs_dialog *, - struct variable *); + struct val_labs *labs; + gchar *encoding; + struct fmt_spec format; - #endif + /* Actions */ + GtkWidget *add_button; + GtkWidget *remove_button; + GtkWidget *change_button; + + /* Entry Boxes */ + GtkWidget *value_entry; + GtkWidget *label_entry; + + /* Signal handler ids */ + gint change_handler_id; + gint value_handler_id; + + GtkWidget *treeview; + }; + + struct _PsppireValLabsDialogClass { + PsppireDialogClass parent_class; + }; + + GType psppire_val_labs_dialog_get_type (void) G_GNUC_CONST; + PsppireValLabsDialog* psppire_val_labs_dialog_new (const struct variable *); + + void psppire_val_labs_dialog_set_variable (PsppireValLabsDialog *, + const struct variable *); + const struct val_labs *psppire_val_labs_dialog_get_value_labels ( + const PsppireValLabsDialog *); + + struct val_labs *psppire_val_labs_dialog_run (GtkWindow *parent_window, + const struct variable *); + + G_END_DECLS + + #endif /* psppire-val-labs-dialog.h */ diff --cc src/ui/gui/var-type-dialog.h index 8e11160e3e,0251cbe519..b2d58d2a73 --- a/src/ui/gui/var-type-dialog.h +++ b/src/ui/gui/var-type-dialog.h @@@ -15,10 -15,24 +15,23 @@@ along with this program. If not, see . */ - #ifndef __PSPPIRE_VAR_TYPE_DIALOG_H - #define __PSPPIRE_VAR_TYPE_DIALOG_H + #ifndef PSPPIRE_VAR_TYPE_DIALOG_H + #define PSPPIRE_VAR_TYPE_DIALOG_H 1 - #include + #include "data/format.h" + #include "psppire-dialog.h" -#include "psppire-var-store.h" + + G_BEGIN_DECLS + + #define PSPPIRE_TYPE_VAR_TYPE_DIALOG (psppire_var_type_dialog_get_type()) + #define PSPPIRE_VAR_TYPE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),PSPPIRE_TYPE_VAR_TYPE_DIALOG,PsppireVarTypeDialog)) + #define PSPPIRE_VAR_TYPE_DIALOG_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class),PSPPIRE_TYPE_VAR_TYPE_DIALOG,PsppireVarTypeDialogClass)) + #define PSPPIRE_IS_VAR_TYPE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PSPPIRE_TYPE_VAR_TYPE_DIALOG)) + #define PSPPIRE_IS_VAR_TYPE_DIALOG_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),PSPPIRE_TYPE_VAR_TYPE_DIALOG)) + #define PSPPIRE_VAR_TYPE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),PSPPIRE_TYPE_VAR_TYPE_DIALOG,PsppireVarTypeDialogClass)) + + typedef struct _PsppireVarTypeDialog PsppireVarTypeDialog; + typedef struct _PsppireVarTypeDialogClass PsppireVarTypeDialogClass; /* This module describes the behaviour of the Variable Type dialog box, used for input of the variable type parameter in the var sheet */