From 506f91ea69a719a5c4444102fcf73b188678c512 Mon Sep 17 00:00:00 2001 From: John Darrington Date: Sun, 7 Aug 2016 08:02:47 +0200 Subject: [PATCH] Remove obsolete file --- src/ui/gui/automake.mk | 2 - src/ui/gui/psppire-data-sheet.c | 2473 ------------------------------- src/ui/gui/psppire-data-sheet.h | 118 -- 3 files changed, 2593 deletions(-) delete mode 100644 src/ui/gui/psppire-data-sheet.c delete mode 100644 src/ui/gui/psppire-data-sheet.h diff --git a/src/ui/gui/automake.mk b/src/ui/gui/automake.mk index f4791522a4..762d37d7c5 100644 --- a/src/ui/gui/automake.mk +++ b/src/ui/gui/automake.mk @@ -162,8 +162,6 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/psppire-conf.h \ src/ui/gui/psppire-data-editor.c \ src/ui/gui/psppire-data-editor.h \ - src/ui/gui/psppire-data-sheet.c \ - src/ui/gui/psppire-data-sheet.h \ src/ui/gui/psppire-data-store.c \ src/ui/gui/psppire-data-store.h \ src/ui/gui/psppire-data-window.c \ diff --git a/src/ui/gui/psppire-data-sheet.c b/src/ui/gui/psppire-data-sheet.c deleted file mode 100644 index a0f4ad9169..0000000000 --- a/src/ui/gui/psppire-data-sheet.c +++ /dev/null @@ -1,2473 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc. - - 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 - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -// #include "ui/gui/psppire-data-sheet.h" - -#include "data/case-map.h" -#include "data/casereader.h" -#include "data/casewriter.h" -#include "data/data-out.h" -#include "data/datasheet.h" -#include "data/format.h" -#include "data/value-labels.h" -#include "libpspp/intern.h" -#include "libpspp/range-set.h" -#include "ui/gui/executor.h" -#include "ui/gui/find-dialog.h" -#include "ui/gui/goto-case-dialog.h" -#include "ui/gui/builder-wrapper.h" -#include "ui/gui/helper.h" -#include "ui/gui/psppire-data-store.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 "gl/intprops.h" -#include "gl/xalloc.h" - -#include -#define _(msgid) gettext (msgid) -#define N_(msgid) msgid - -#if 0 - -static void psppire_data_sheet_dispose (GObject *); -static void psppire_data_sheet_unset_data_store (PsppireDataSheet *); - -static void psppire_data_sheet_update_clip_actions (PsppireDataSheet *); -static void psppire_data_sheet_update_primary_selection (PsppireDataSheet *, - gboolean should_own); -static void psppire_data_sheet_set_clip (PsppireDataSheet *, gboolean cut); - -static void on_selection_changed (PsppSheetSelection *, gpointer); -static void on_owner_change (GtkClipboard *, GdkEventOwnerChange *, gpointer); -static void psppire_data_sheet_clip_received_cb (GtkClipboard *, - GtkSelectionData *, gpointer); - -G_DEFINE_TYPE (PsppireDataSheet, psppire_data_sheet, PSPP_TYPE_SHEET_VIEW); - -static gboolean -get_tooltip_location (GtkWidget *widget, GtkTooltip *tooltip, - gint wx, gint wy, - size_t *row, PsppSheetViewColumn **columnp) -{ - PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget); - gint bx, by; - GtkTreePath *path; - GtkTreeIter iter; - PsppSheetViewColumn *tree_column; - GtkTreeModel *tree_model; - 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; - - *columnp = tree_column; - - 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; -} - -static gboolean -on_query_tooltip (GtkWidget *widget, gint wx, gint wy, - gboolean keyboard_mode UNUSED, - GtkTooltip *tooltip, gpointer data UNUSED) -{ - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget); - PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet); - PsppSheetViewColumn *column; - struct variable *var; - const char *label; - union value v; - size_t row; - int width; - - g_return_val_if_fail (data_store != NULL, FALSE); - g_return_val_if_fail (data_store->datasheet != NULL, FALSE); - - if (!get_tooltip_location (widget, tooltip, wx, wy, &row, &column)) - return FALSE; - - var = g_object_get_data (G_OBJECT (column), "variable"); - if (var == NULL) - { - if (g_object_get_data (G_OBJECT (column), "new-var-column") == NULL) - return FALSE; - - gtk_tooltip_set_text (tooltip, - _("Enter a number to add a new variable.")); - return TRUE; - } - else if (row >= datasheet_get_n_rows (data_store->datasheet)) - { - gtk_tooltip_set_text (tooltip, _("Enter a number to add a new case.")); - return TRUE; - } - - width = var_get_width (var); - - value_init (&v, width); - datasheet_get_value (data_store->datasheet, row, var_get_case_index (var), - &v); - - label = var_lookup_value_label (var, &v); - if (label != NULL) - { - if (data_sheet->show_value_labels) - { - char *s = value_to_text (v, var); - gtk_tooltip_set_text (tooltip, s); - free (s); - } - else - gtk_tooltip_set_text (tooltip, label); - } - value_destroy (&v, width); - - return label != NULL; -} - -static void -render_row_number_cell (PsppSheetViewColumn *tree_column, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer store_) -{ - PsppireDataStore *store = store_; - GValue gvalue = { 0, }; - gint row = GPOINTER_TO_INT (iter->user_data); - - g_return_if_fail (store->datasheet); - - 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 (row < datasheet_get_n_rows (store->datasheet)) - g_object_set (cell, "editable", TRUE, NULL); - else - g_object_set (cell, "editable", FALSE, NULL); - - g_object_set (cell, - "slash", psppire_data_store_filtered (store, row), - NULL); -} - -static void -on_row_number_clicked (PsppireCellRendererButton *button, - gchar *path_string, - PsppSheetView *sheet_view) -{ - PsppSheetSelection *selection; - GtkTreePath *path; - - path = gtk_tree_path_new_from_string (path_string); - - selection = pspp_sheet_view_get_selection (sheet_view); - pspp_sheet_selection_unselect_all (selection); - pspp_sheet_selection_select_path (selection, path); - pspp_sheet_selection_select_all_columns (selection); - - gtk_tree_path_free (path); -} - -static void -make_row_number_column (PsppireDataSheet *data_sheet, - PsppireDataStore *ds) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppSheetViewColumn *column; - GtkCellRenderer *renderer; - - renderer = psppire_cell_renderer_button_new (); - g_object_set (renderer, "xalign", 1.0, NULL); - g_signal_connect (renderer, "clicked", G_CALLBACK (on_row_number_clicked), - sheet_view); - - column = pspp_sheet_view_column_new_with_attributes (_("Case"), - renderer, NULL); - pspp_sheet_view_column_set_selectable (column, TRUE); - pspp_sheet_view_column_set_row_head (column, TRUE); - pspp_sheet_view_column_set_tabbable (column, FALSE); - pspp_sheet_view_column_set_clickable (column, TRUE); - pspp_sheet_view_column_set_cell_data_func ( - column, renderer, render_row_number_cell, ds, NULL); - pspp_sheet_view_column_set_fixed_width (column, 50); - pspp_sheet_view_column_set_visible (column, data_sheet->show_case_numbers); - pspp_sheet_view_append_column (sheet_view, column); -} - -static void -render_data_cell (PsppSheetViewColumn *tree_column, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer data_sheet_) -{ - PsppireDataSheet *data_sheet = data_sheet_; - PsppireDataStore *store = psppire_data_sheet_get_data_store (data_sheet); - struct variable *var; - gchar *string; - gint row; - - double xalign; - - row = GPOINTER_TO_INT (iter->user_data); - var = g_object_get_data (G_OBJECT (tree_column), "variable"); - - string = psppire_data_store_get_string (store, row, var, - data_sheet->show_value_labels); - if (string != NULL) - { - GValue gvalue = { 0 }; - - g_value_init (&gvalue, G_TYPE_STRING); - g_value_take_string (&gvalue, string); - g_object_set_property (G_OBJECT (cell), "text", &gvalue); - g_value_unset (&gvalue); - } - else - g_object_set (G_OBJECT (cell), "text", "", NULL); - - switch (var_get_alignment (var)) - { - case ALIGN_LEFT: xalign = 0.0; break; - case ALIGN_RIGHT: xalign = 1.0; break; - case ALIGN_CENTRE: xalign = 0.5; break; - default: xalign = 0.0; break; - } - g_object_set (cell, - "xalign", xalign, - "editable", TRUE, - NULL); -} - -static gint -get_string_width (PsppSheetView *treeview, GtkCellRenderer *renderer, - const char *string) -{ - gint width; - g_object_set (G_OBJECT (renderer), "text", string, (void *) NULL); - gtk_cell_renderer_get_preferred_width (renderer, GTK_WIDGET (treeview), - NULL, &width); - - 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 void -on_data_column_editing_started (GtkCellRenderer *cell, - GtkCellEditable *editable, - const gchar *path, - gpointer user_data) -{ - PsppSheetViewColumn *column = g_object_get_data (G_OBJECT (cell), "column"); - PsppireDataSheet *data_sheet = g_object_get_data (G_OBJECT (cell), "data-sheet"); - PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet); - struct variable *var; - - g_return_if_fail (column); - g_return_if_fail (data_sheet); - g_return_if_fail (data_store); - - - g_object_ref (editable); - g_object_set_data_full (G_OBJECT (cell), "data-sheet-editable", - editable, g_object_unref); - - var = g_object_get_data (G_OBJECT (column), "variable"); - g_return_if_fail (var); - - if (var_has_value_labels (var) && GTK_IS_COMBO_BOX (editable)) - { - const struct val_labs *labels = var_get_value_labels (var); - const struct val_lab **vls = val_labs_sorted (labels); - size_t n_vls = val_labs_count (labels); - GtkListStore *list_store; - int i; - - list_store = gtk_list_store_new (1, G_TYPE_STRING); - for (i = 0; i < n_vls; ++i) - { - const struct val_lab *vl = vls[i]; - GtkTreeIter iter; - - gtk_list_store_append (list_store, &iter); - gtk_list_store_set (list_store, &iter, - 0, val_lab_get_label (vl), - -1); - } - free (vls); - - gtk_combo_box_set_model (GTK_COMBO_BOX (editable), - GTK_TREE_MODEL (list_store)); - g_object_unref (list_store); - } -} - -static void -scroll_to_bottom (GtkWidget *widget, - GtkRequisition *requisition, - gpointer unused UNUSED) -{ - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget); - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (widget); - GtkAdjustment *vadjust; - - vadjust = pspp_sheet_view_get_vadjustment (sheet_view); - gtk_adjustment_set_value (vadjust, gtk_adjustment_get_upper (vadjust)); - - if (data_sheet->scroll_to_bottom_signal) - { - g_signal_handler_disconnect (data_sheet, - data_sheet->scroll_to_bottom_signal); - data_sheet->scroll_to_bottom_signal = 0; - } -} - -static void -on_data_column_edited (GtkCellRendererText *cell, - gchar *path_string, - gchar *new_text, - gpointer user_data) -{ - PsppSheetViewColumn *column = g_object_get_data (G_OBJECT (cell), "column"); - PsppireDataSheet *data_sheet = g_object_get_data (G_OBJECT (cell), "data-sheet"); - PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet); - GtkEditable *editable; - struct variable *var; - GtkTreePath *path; - gboolean is_val_lab; - gboolean new_row; - gint row; - - path = gtk_tree_path_new_from_string (path_string); - row = gtk_tree_path_get_indices (path)[0]; - gtk_tree_path_free (path); - - var = g_object_get_data (G_OBJECT (column), "variable"); - - new_row = row == psppire_data_store_get_case_count (data_store); - if (new_row && new_text[0] == '\0') - return; - - editable = g_object_steal_data (G_OBJECT (cell), "data-sheet-editable"); - g_return_if_fail (editable != NULL); - is_val_lab = (GTK_IS_COMBO_BOX (editable) - && gtk_combo_box_get_active (GTK_COMBO_BOX (editable)) >= 0); - g_object_unref (editable); - - psppire_data_store_set_string (data_store, new_text, row, var, is_val_lab); - - if (new_row && !data_sheet->scroll_to_bottom_signal) - { - gtk_widget_queue_resize (GTK_WIDGET (data_sheet)); - data_sheet->scroll_to_bottom_signal = - g_signal_connect (data_sheet, "size-allocate", - G_CALLBACK (scroll_to_bottom), NULL); - } - else - { - /* We could be more specific about what to redraw, if it seems - important for performance. */ - gtk_widget_queue_draw (GTK_WIDGET (data_sheet)); - } -} - -static void -scroll_to_right (GtkWidget *widget, - PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppSheetViewColumn *column, *prev; - GList *columns, *iter; - - column = NULL; - prev = NULL; - columns = pspp_sheet_view_get_columns (sheet_view); - for (iter = columns; iter; iter = iter->next) - { - PsppSheetViewColumn *c = iter->data; - if (g_object_get_data (G_OBJECT (c), "new-var-column")) - { - column = c; - break; - } - prev = c; - } - g_list_free (columns); - - if (column == NULL) - return; - - pspp_sheet_view_scroll_to_cell (sheet_view, NULL, column, FALSE, 0, 0); - - if (prev) - { - GtkTreePath *path; - - pspp_sheet_view_get_cursor (sheet_view, &path, NULL); - if (path) - { - pspp_sheet_view_set_cursor (sheet_view, path, prev, TRUE); - gtk_tree_path_free (path); - } - } - - if (data_sheet->scroll_to_right_signal) - { - g_signal_handler_disconnect (widget, data_sheet->scroll_to_right_signal); - data_sheet->scroll_to_right_signal = 0; - } -} - -static void -on_new_variable_column_edited (GtkCellRendererText *cell, - gchar *path_string, - gchar *new_text, - gpointer user_data) -{ - PsppireDataSheet *data_sheet = g_object_get_data (G_OBJECT (cell), "data-sheet"); - PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet); - PsppireDict *dict = data_store->dict; - struct variable *var; - GtkTreePath *path; - char name[64]; - gint row; - - if (new_text[0] == '\0') - { - /* User didn't enter anything so don't create a variable. */ - return; - } - - path = gtk_tree_path_new_from_string (path_string); - row = gtk_tree_path_get_indices (path)[0]; - gtk_tree_path_free (path); - - if (!psppire_dict_generate_name (dict, name, sizeof name)) - return; - - var = psppire_dict_insert_variable (dict, psppire_dict_get_var_cnt (dict), - name); - g_return_if_fail (var != NULL); - - psppire_data_store_set_string (data_store, new_text, row, var, FALSE); - - if (!data_sheet->scroll_to_right_signal) - { - gtk_widget_queue_resize (GTK_WIDGET (data_sheet)); - data_sheet->scroll_to_right_signal = - g_signal_connect_after (gtk_widget_get_toplevel (GTK_WIDGET (data_sheet)), "check-resize", - G_CALLBACK (scroll_to_right), data_sheet); - } - else - { - /* We could be more specific about what to redraw, if it seems - important for performance. */ - gtk_widget_queue_draw (GTK_WIDGET (data_sheet)); - } -} - -static void -calc_width_conversion (PsppireDataSheet *data_sheet, - gint *base_width, gint *incr_width) -{ - GtkCellRenderer *cell; - gint w1, w10; - - cell = gtk_cell_renderer_text_new (); - w1 = get_monospace_width (PSPP_SHEET_VIEW (data_sheet), cell, 1); - w10 = get_monospace_width (PSPP_SHEET_VIEW (data_sheet), cell, 10); - *incr_width = MAX (1, (w10 - w1) / 9); - *base_width = MAX (0, w10 - *incr_width * 10); - g_object_ref_sink (cell); - g_object_unref (cell); -} - -static gint -display_width_from_pixel_width (PsppireDataSheet *data_sheet, - gint pixel_width) -{ - gint base_width, incr_width; - - calc_width_conversion (data_sheet, &base_width, &incr_width); - return MAX ((pixel_width - base_width + incr_width / 2) / incr_width, 1); -} - -static gint -display_width_to_pixel_width (PsppireDataSheet *data_sheet, - gint display_width, - gint base_width, - gint incr_width) -{ - return base_width + incr_width * display_width; -} - -static void -on_data_column_resized (GObject *gobject, - GParamSpec *pspec, - gpointer user_data) -{ - PsppireDataSheet *data_sheet = user_data; - PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet); - PsppSheetViewColumn *column = PSPP_SHEET_VIEW_COLUMN (gobject); - struct variable *var; - gint pixel_width; - int display_width; - - if (data_store == NULL) - return; - - pixel_width = pspp_sheet_view_column_get_width (column); - if (pixel_width == pspp_sheet_view_column_get_fixed_width (column)) - { - /* Short-circuit the expensive display_width_from_pixel_width() - calculation, to make loading .sav files with 2000 columns visibly - faster. */ - return; - } - - var = g_object_get_data (G_OBJECT (column), "variable"); - display_width = display_width_from_pixel_width (data_sheet, pixel_width); - var_set_display_width (var, display_width); -} - -enum sort_order - { - SORT_ASCEND, - SORT_DESCEND - }; - -static void -do_sort (PsppireDataSheet *data_sheet, enum sort_order order) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view); - PsppireDataWindow *pdw; - GList *list, *iter; - GString *syntax; - int n_vars; - - pdw = psppire_data_window_for_data_store (data_sheet->data_store); - g_return_if_fail (pdw != NULL); - - list = pspp_sheet_selection_get_selected_columns (selection); - - syntax = g_string_new ("SORT CASES BY"); - n_vars = 0; - for (iter = list; iter; iter = iter->next) - { - PsppSheetViewColumn *column = iter->data; - struct variable *var; - - var = g_object_get_data (G_OBJECT (column), "variable"); - if (var != NULL) - { - g_string_append_printf (syntax, " %s", var_get_name (var)); - n_vars++; - } - } - if (n_vars > 0) - { - if (order == SORT_DESCEND) - g_string_append (syntax, " (DOWN)"); - g_string_append_c (syntax, '.'); - execute_const_syntax_string (pdw, syntax->str); - } - g_string_free (syntax, TRUE); -} - -static void -on_sort_up (PsppireDataSheet *data_sheet) -{ - do_sort (data_sheet, SORT_ASCEND); -} - -static void -on_sort_down (PsppireDataSheet *data_sheet) -{ - do_sort (data_sheet, SORT_DESCEND); -} - -static void -do_data_column_popup_menu (PsppSheetViewColumn *column, - guint button, guint32 time) -{ - GtkWidget *sheet_view = pspp_sheet_view_column_get_tree_view (column); - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (sheet_view); - - gtk_menu_popup (GTK_MENU (data_sheet->column_popup_menu), NULL, NULL, NULL, NULL, button, time); -} - -static void -on_data_column_popup_menu (PsppSheetViewColumn *column, - gpointer user_data UNUSED) -{ - do_data_column_popup_menu (column, 0, gtk_get_current_event_time ()); -} - -static gboolean -on_column_button_press_event (PsppSheetViewColumn *column, - GdkEventButton *event, - gpointer user_data UNUSED) -{ - PsppSheetSelection *selection; - PsppSheetView *sheet_view; - - sheet_view = PSPP_SHEET_VIEW (pspp_sheet_view_column_get_tree_view ( - column)); - g_return_val_if_fail (sheet_view != NULL, FALSE); - - selection = pspp_sheet_view_get_selection (sheet_view); - g_return_val_if_fail (selection != NULL, FALSE); - - if (event->type == GDK_BUTTON_PRESS && event->button == 3) - { - do_data_column_popup_menu (column, event->button, event->time); - return TRUE; - } - else if (event->type == GDK_2BUTTON_PRESS && event->button == 1) - { - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (sheet_view); - struct variable *var; - - var = g_object_get_data (G_OBJECT (column), "variable"); - if (var != NULL) - { - gboolean handled; - - g_signal_emit_by_name (data_sheet, "var-double-clicked", - var_get_dict_index (var), &handled); - return handled; - } - } - - return FALSE; -} - -static gboolean -on_data_column_query_tooltip (PsppSheetViewColumn *column, - GtkTooltip *tooltip, - gpointer user_data UNUSED) -{ - struct variable *var; - const char *text; - - var = g_object_get_data (G_OBJECT (column), "variable"); - g_return_val_if_fail (var != NULL, FALSE); - - text = var_has_label (var) ? var_get_label (var) : var_get_name (var); - gtk_tooltip_set_text (tooltip, text); - - return TRUE; -} - -static void -add_data_column_cell_renderer (PsppireDataSheet *data_sheet, - PsppSheetViewColumn *column) -{ - GtkCellRenderer *cell; - struct variable *var; - - var = g_object_get_data (G_OBJECT (column), "variable"); - g_return_if_fail (var != NULL); - - if (data_sheet->show_value_labels && var_has_value_labels (var)) - { - cell = gtk_cell_renderer_combo_new (); - g_object_set (G_OBJECT (cell), - "has-entry", TRUE, - "text-column", 0, - NULL); - } - else - cell = gtk_cell_renderer_text_new (); - - g_signal_connect (cell, "editing-started", - G_CALLBACK (on_data_column_editing_started), NULL); - g_signal_connect (cell, "edited", G_CALLBACK (on_data_column_edited), NULL); - - g_object_set_data (G_OBJECT (cell), "column", column); - g_object_set_data (G_OBJECT (cell), "data-sheet", data_sheet); - - pspp_sheet_view_column_clear (column); - pspp_sheet_view_column_pack_start (column, cell, TRUE); - - pspp_sheet_view_column_set_cell_data_func ( - column, cell, render_data_cell, data_sheet, NULL); -} - -static PsppSheetViewColumn * -make_data_column (PsppireDataSheet *data_sheet, gint dict_idx, - gint base_width, gint incr_width) -{ - PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet); - struct variable *var; - PsppSheetViewColumn *column; - char *name; - int width; - - var = psppire_dict_get_variable (data_store->dict, dict_idx); - - column = pspp_sheet_view_column_new (); - - name = escape_underscores (var_get_name (var)); - pspp_sheet_view_column_set_title (column, name); - free (name); - - g_object_set_data (G_OBJECT (column), "variable", var); - - width = display_width_to_pixel_width (data_sheet, - var_get_display_width (var), - base_width, incr_width); - pspp_sheet_view_column_set_min_width (column, 10); - pspp_sheet_view_column_set_fixed_width (column, width); - pspp_sheet_view_column_set_resizable (column, TRUE); - - pspp_sheet_view_column_set_clickable (column, TRUE); - g_signal_connect (column, "notify::width", - G_CALLBACK (on_data_column_resized), data_sheet); - - g_signal_connect (column, "button-press-event", - G_CALLBACK (on_column_button_press_event), - data_sheet); - g_signal_connect (column, "query-tooltip", - G_CALLBACK (on_data_column_query_tooltip), NULL); - g_signal_connect (column, "popup-menu", - G_CALLBACK (on_data_column_popup_menu), data_sheet); - - add_data_column_cell_renderer (data_sheet, column); - - return column; -} - -static void -make_new_variable_column (PsppireDataSheet *data_sheet, - gint base_width, gint incr_width) -{ - PsppSheetViewColumn *column; - GtkCellRenderer *cell; - int width; - - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, "editable", TRUE, NULL); - - g_signal_connect (cell, "edited", G_CALLBACK (on_new_variable_column_edited), - NULL); - - column = pspp_sheet_view_column_new_with_attributes ("", cell, NULL); - g_object_set_data (G_OBJECT (column), "new-var-column", column); - - width = display_width_to_pixel_width (data_sheet, 8, base_width, incr_width); - pspp_sheet_view_column_set_min_width (column, 10); - pspp_sheet_view_column_set_fixed_width (column, width); - pspp_sheet_view_column_set_tabbable (column, FALSE); - - g_object_set_data (G_OBJECT (cell), "data-sheet", data_sheet); - g_signal_connect (column, "button-press-event", - G_CALLBACK (on_column_button_press_event), - data_sheet); - g_signal_connect (column, "popup-menu", - G_CALLBACK (on_data_column_popup_menu), data_sheet); - - pspp_sheet_view_column_set_visible (column, data_sheet->may_create_vars); - - pspp_sheet_view_append_column (PSPP_SHEET_VIEW (data_sheet), column); - data_sheet->new_variable_column = column; -} - -static void -psppire_data_sheet_model_changed (GObject *gobject, - GParamSpec *pspec, - gpointer user_data) -{ - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (gobject); - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppireDataStore *data_store; - - /* Remove old columns. */ - for (;;) - { - PsppSheetViewColumn *column = pspp_sheet_view_get_column (sheet_view, 0); - if (column == NULL) - break; - - pspp_sheet_view_remove_column (sheet_view, column); - } - data_sheet->new_variable_column = NULL; - - if (pspp_sheet_view_get_model (sheet_view) == NULL) - { - /* Don't create any columns at all if there's no model. Otherwise we'll - create some columns as part of the "dispose" callback for the sheet - view, which sets the model to NULL. That causes warnings to be - logged and is obviously undesirable in any case. */ - return; - } - - /* Add new columns. */ - data_store = psppire_data_sheet_get_data_store (data_sheet); - if (data_store != NULL) - { - gint base_width, incr_width; - int i; - - calc_width_conversion (data_sheet, &base_width, &incr_width); - - make_row_number_column (data_sheet, data_store); - for (i = 0; i < psppire_dict_get_var_cnt (data_store->dict); i++) - { - PsppSheetViewColumn *column; - - column = make_data_column (data_sheet, i, base_width, incr_width); - pspp_sheet_view_append_column (sheet_view, column); - } - make_new_variable_column (data_sheet, base_width, incr_width); - } -} - -enum - { - PROP_0, - PROP_DATA_STORE, - PROP_VALUE_LABELS, - PROP_CASE_NUMBERS, - PROP_CURRENT_CASE, - PROP_MAY_CREATE_VARS, - PROP_MAY_DELETE_VARS - }; - -static void -psppire_data_sheet_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PsppireDataSheet *obj = PSPPIRE_DATA_SHEET (object); - - switch (prop_id) - { - case PROP_DATA_STORE: - psppire_data_sheet_set_data_store ( - obj, PSPPIRE_DATA_STORE (g_value_get_object (value))); - break; - - case PROP_VALUE_LABELS: - psppire_data_sheet_set_value_labels (obj, g_value_get_boolean (value)); - break; - - case PROP_CASE_NUMBERS: - psppire_data_sheet_set_case_numbers (obj, g_value_get_boolean (value)); - break; - - case PROP_CURRENT_CASE: - psppire_data_sheet_goto_case (obj, g_value_get_long (value)); - break; - - case PROP_MAY_CREATE_VARS: - psppire_data_sheet_set_may_create_vars (obj, - g_value_get_boolean (value)); - break; - - case PROP_MAY_DELETE_VARS: - psppire_data_sheet_set_may_delete_vars (obj, - g_value_get_boolean (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -psppire_data_sheet_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PsppireDataSheet *obj = PSPPIRE_DATA_SHEET (object); - - switch (prop_id) - { - case PROP_DATA_STORE: - g_value_set_object (value, psppire_data_sheet_get_data_store (obj)); - break; - - case PROP_VALUE_LABELS: - g_value_set_boolean (value, psppire_data_sheet_get_value_labels (obj)); - break; - - case PROP_CASE_NUMBERS: - g_value_set_boolean (value, psppire_data_sheet_get_case_numbers (obj)); - break; - - case PROP_CURRENT_CASE: - g_value_set_long (value, psppire_data_sheet_get_selected_case (obj)); - break; - - case PROP_MAY_CREATE_VARS: - g_value_set_boolean (value, obj->may_create_vars); - break; - - case PROP_MAY_DELETE_VARS: - g_value_set_boolean (value, obj->may_delete_vars); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -gboolean -psppire_data_sheet_get_value_labels (const PsppireDataSheet *ds) -{ - return ds->show_value_labels; -} - -void -psppire_data_sheet_set_value_labels (PsppireDataSheet *ds, - gboolean show_value_labels) -{ - show_value_labels = !!show_value_labels; - if (show_value_labels != ds->show_value_labels) - { - ds->show_value_labels = show_value_labels; - g_object_notify (G_OBJECT (ds), "value-labels"); - - /* Pretend the model changed, to force the columns to be rebuilt. - Otherwise cell renderers won't get changed from combo boxes to text - entries or vice versa. */ - g_object_notify (G_OBJECT (ds), "model"); - } -} - -gboolean -psppire_data_sheet_get_case_numbers (const PsppireDataSheet *ds) -{ - return ds->show_case_numbers; -} - -void -psppire_data_sheet_set_case_numbers (PsppireDataSheet *ds, - gboolean show_case_numbers) -{ - show_case_numbers = !!show_case_numbers; - if (show_case_numbers != ds->show_case_numbers) - { - PsppSheetViewColumn *column; - - ds->show_case_numbers = show_case_numbers; - column = pspp_sheet_view_get_column (PSPP_SHEET_VIEW (ds), 0); - if (column) - pspp_sheet_view_column_set_visible (column, show_case_numbers); - - g_object_notify (G_OBJECT (ds), "case-numbers"); - gtk_widget_queue_draw (GTK_WIDGET (ds)); - } -} - -gboolean -psppire_data_sheet_get_may_create_vars (PsppireDataSheet *data_sheet) -{ - return data_sheet->may_create_vars; -} - -void -psppire_data_sheet_set_may_create_vars (PsppireDataSheet *data_sheet, - gboolean may_create_vars) -{ - if (data_sheet->may_create_vars != may_create_vars) - { - data_sheet->may_create_vars = may_create_vars; - if (data_sheet->new_variable_column) - pspp_sheet_view_column_set_visible (data_sheet->new_variable_column, - may_create_vars); - - on_selection_changed (pspp_sheet_view_get_selection ( - PSPP_SHEET_VIEW (data_sheet)), NULL); - } -} - -gboolean -psppire_data_sheet_get_may_delete_vars (PsppireDataSheet *data_sheet) -{ - return data_sheet->may_delete_vars; -} - -void -psppire_data_sheet_set_may_delete_vars (PsppireDataSheet *data_sheet, - gboolean may_delete_vars) -{ - if (data_sheet->may_delete_vars != may_delete_vars) - { - data_sheet->may_delete_vars = may_delete_vars; - on_selection_changed (pspp_sheet_view_get_selection ( - PSPP_SHEET_VIEW (data_sheet)), NULL); - } -} - -static PsppSheetViewColumn * -psppire_data_sheet_find_column_for_variable (PsppireDataSheet *data_sheet, - gint dict_index) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppireDataStore *data_store; - PsppSheetViewColumn *column; - struct variable *var; - GList *list, *iter; - - data_store = psppire_data_sheet_get_data_store (data_sheet); - g_return_val_if_fail (data_store != NULL, NULL); - g_return_val_if_fail (data_store->dict != NULL, NULL); - - var = psppire_dict_get_variable (data_store->dict, dict_index); - g_return_val_if_fail (var != NULL, NULL); - - column = NULL; - list = pspp_sheet_view_get_columns (sheet_view); - for (iter = list; iter != NULL; iter = iter->next) - { - PsppSheetViewColumn *c = iter->data; - struct variable *v; - - v = g_object_get_data (G_OBJECT (c), "variable"); - if (v == var) - { - column = c; - break; - } - } - g_list_free (list); - - return column; -} - -void -psppire_data_sheet_goto_variable (PsppireDataSheet *data_sheet, - gint dict_index) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppSheetViewColumn *column; - - column = psppire_data_sheet_find_column_for_variable (data_sheet, - dict_index); - if (column != NULL) - { - GtkTreePath *path; - - gint row = psppire_data_sheet_get_current_case (data_sheet); - path = gtk_tree_path_new_from_indices (row >= 0 ? row : 0, -1); - - pspp_sheet_view_scroll_to_cell (sheet_view, path, column, - FALSE, 0.0, 0.0); - pspp_sheet_view_set_cursor (sheet_view, path, column, FALSE); - gtk_tree_path_free (path); - } -} - -struct variable * -psppire_data_sheet_get_current_variable (const PsppireDataSheet *data_sheet) -{ - PsppSheetSelection *selection; - struct variable *var; - GList *selected_columns; - GList *iter; - - selection = pspp_sheet_view_get_selection (PSPP_SHEET_VIEW (data_sheet)); - selected_columns = pspp_sheet_selection_get_selected_columns (selection); - - var = NULL; - for (iter = selected_columns; iter != NULL; iter = iter->next) - { - PsppSheetViewColumn *column = iter->data; - struct variable *v = g_object_get_data (G_OBJECT (column), "variable"); - if (v != NULL) - { - if (var) - { - var = NULL; - break; - } - else - var = v; - } - } - - g_list_free (selected_columns); - - return var; - -} -void -psppire_data_sheet_goto_case (PsppireDataSheet *data_sheet, gint case_index) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppireDataStore *store = data_sheet->data_store; - PsppSheetSelection *selection; - GtkTreePath *path; - - g_return_if_fail (case_index >= 0); - g_return_if_fail (case_index < psppire_data_store_get_case_count (store)); - - path = gtk_tree_path_new_from_indices (case_index, -1); - - /* Select the case. */ - selection = pspp_sheet_view_get_selection (sheet_view); - pspp_sheet_selection_unselect_all (selection); - pspp_sheet_selection_select_path (selection, path); - pspp_sheet_selection_select_all_columns (selection); - - /* Scroll so that the case is visible. */ - pspp_sheet_view_scroll_to_cell (sheet_view, path, NULL, FALSE, 0.0, 0.0); - - gtk_tree_path_free (path); -} - -/* Returns the 0-based index of a selected case, if there is at least one, and - -1 otherwise. - - If more than one case is selected, returns the one with the smallest index, - that is, the index of the case closest to the beginning of the file. The - row that can be used to insert a new case is not considered a case. */ -gint -psppire_data_sheet_get_selected_case (const PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppireDataStore *store = data_sheet->data_store; - const struct range_set_node *node; - PsppSheetSelection *selection; - struct range_set *rows; - gint row; - - selection = pspp_sheet_view_get_selection (sheet_view); - rows = pspp_sheet_selection_get_range_set (selection); - node = range_set_first (rows); - row = (node && node->start < psppire_data_store_get_case_count (store) - ? node->start - : -1); - range_set_destroy (rows); - - return row; -} - -/* Returns the 0-based index of a selected case, if exactly one case is - selected, and -1 otherwise. Returns -1 if the row that can be used to - insert a new case is selected. */ -gint -psppire_data_sheet_get_current_case (const PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppireDataStore *store = data_sheet->data_store; - const struct range_set_node *node; - PsppSheetSelection *selection; - struct range_set *rows; - gint row; - - selection = pspp_sheet_view_get_selection (sheet_view); - if (pspp_sheet_selection_count_selected_rows (selection) != 1) - return -1; - - rows = pspp_sheet_selection_get_range_set (selection); - node = range_set_first (rows); - row = (node && node->start < psppire_data_store_get_case_count (store) - ? node->start - : -1); - range_set_destroy (rows); - - return row; -} - - -static void -psppire_data_sheet_dispose (GObject *object) -{ - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (object); - - if (data_sheet->clip != NULL && data_sheet->on_owner_change_signal != 0) - { - g_signal_handler_disconnect (data_sheet->clip, - data_sheet->on_owner_change_signal); - data_sheet->on_owner_change_signal = 0; - } - - if (data_sheet->dispose_has_run) - return; - - data_sheet->dispose_has_run = TRUE; - - psppire_data_sheet_unset_data_store (data_sheet); - - G_OBJECT_CLASS (psppire_data_sheet_parent_class)->dispose (object); -} - -static void -psppire_data_sheet_map (GtkWidget *widget) -{ - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget); - - GTK_WIDGET_CLASS (psppire_data_sheet_parent_class)->map (widget); - - data_sheet->clip = gtk_widget_get_clipboard (widget, - GDK_SELECTION_CLIPBOARD); - if (data_sheet->on_owner_change_signal) - g_signal_handler_disconnect (data_sheet->clip, - data_sheet->on_owner_change_signal); - data_sheet->on_owner_change_signal - = g_signal_connect (data_sheet->clip, "owner-change", - G_CALLBACK (on_owner_change), widget); - on_owner_change (data_sheet->clip, NULL, widget); -} - -static void -psppire_data_sheet_class_init (PsppireDataSheetClass *class) -{ - GObjectClass *gobject_class; - GtkWidgetClass *widget_class; - - gobject_class = G_OBJECT_CLASS (class); - gobject_class->set_property = psppire_data_sheet_set_property; - gobject_class->get_property = psppire_data_sheet_get_property; - gobject_class->dispose = psppire_data_sheet_dispose; - - widget_class = GTK_WIDGET_CLASS (class); - widget_class->map = psppire_data_sheet_map; - - 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); - - g_object_class_install_property ( - gobject_class, PROP_DATA_STORE, - g_param_spec_object ("data-store", - "Data Store", - "The data store for the data sheet to display.", - PSPPIRE_TYPE_DATA_STORE, - G_PARAM_WRITABLE | G_PARAM_READABLE)); - - g_object_class_install_property ( - gobject_class, PROP_VALUE_LABELS, - g_param_spec_boolean ("value-labels", - "Value Labels", - "Whether or not the data sheet should display labels instead of values", - FALSE, - G_PARAM_WRITABLE | G_PARAM_READABLE)); - - g_object_class_install_property ( - gobject_class, PROP_CASE_NUMBERS, - g_param_spec_boolean ("case-numbers", - "Case Numbers", - "Whether or not the data sheet should display case numbers", - FALSE, - G_PARAM_WRITABLE | G_PARAM_READABLE)); - - g_object_class_install_property ( - gobject_class, - PROP_CURRENT_CASE, - g_param_spec_long ("current-case", - "Current Case", - "Zero based number of the selected case", - 0, CASENUMBER_MAX, - 0, - G_PARAM_WRITABLE | G_PARAM_READABLE)); - - g_object_class_install_property ( - gobject_class, - PROP_MAY_CREATE_VARS, - 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_DELETE_VARS, - g_param_spec_boolean ("may-delete-vars", - "May delete variables", - "Whether the user may delete variables", - TRUE, - G_PARAM_READWRITE)); -} - -static void -do_row_popup_menu (GtkWidget *widget, guint button, guint32 time) -{ - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget); - - - gtk_menu_popup (GTK_MENU (data_sheet->row_popup_menu), NULL, NULL, NULL, NULL, button, time); -} - -static void -on_popup_menu (GtkWidget *widget, gpointer user_data UNUSED) -{ - do_row_popup_menu (widget, 0, gtk_get_current_event_time ()); -} - -static gboolean -on_button_pressed (GtkWidget *widget, GdkEventButton *event, - gpointer user_data UNUSED) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (widget); - - if (event->type == GDK_BUTTON_PRESS && event->button == 3) - { - PsppSheetSelection *selection; - - selection = pspp_sheet_view_get_selection (sheet_view); - if (pspp_sheet_selection_count_selected_rows (selection) <= 1) - { - GtkTreePath *path; - - if (pspp_sheet_view_get_path_at_pos (sheet_view, event->x, event->y, - &path, NULL, NULL, NULL)) - { - pspp_sheet_selection_unselect_all (selection); - pspp_sheet_selection_select_path (selection, path); - pspp_sheet_selection_select_all_columns (selection); - gtk_tree_path_free (path); - } - } - - do_row_popup_menu (widget, event->button, event->time); - - return TRUE; - } - - return FALSE; -} - -void -psppire_data_sheet_edit_clear_cases (PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view); - 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)) - { - unsigned long int start = range_set_node_get_start (node); - unsigned long int count = range_set_node_get_width (node); - - psppire_data_store_delete_cases (data_sheet->data_store, start, count); - } - 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); - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (sheet_view); - gboolean any_variables_selected; - gboolean may_delete_cases, may_delete_vars, may_insert_vars; - GList *list, *iter; - GtkTreePath *path; - - GtkWidget *top = gtk_widget_get_toplevel (GTK_WIDGET (data_sheet)); - if (! PSPPIRE_IS_DATA_WINDOW (top)) - return; - - PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (top); - - gint n_selected_rows = pspp_sheet_selection_count_selected_rows (selection); - - gtk_widget_set_sensitive (dw->mi_insert_case, n_selected_rows > 0); - - switch (n_selected_rows) - { - case 0: - may_delete_cases = FALSE; - break; - - case 1: - /* The row used for inserting new cases cannot be deleted. */ - path = gtk_tree_path_new_from_indices ( - psppire_data_store_get_case_count (data_sheet->data_store), -1); - may_delete_cases = !pspp_sheet_selection_path_is_selected (selection, - path); - gtk_tree_path_free (path); - break; - - default: - may_delete_cases = TRUE; - break; - } - - gtk_widget_set_sensitive (dw->mi_clear_cases, may_delete_cases); - - any_variables_selected = FALSE; - may_delete_vars = may_insert_vars = FALSE; - list = pspp_sheet_selection_get_selected_columns (selection); - - for (iter = list; iter != NULL; iter = iter->next) - { - PsppSheetViewColumn *column = iter->data; - struct variable *var = g_object_get_data (G_OBJECT (column), "variable"); - - if (var != NULL) - { - may_delete_vars = may_insert_vars = TRUE; - any_variables_selected = TRUE; - break; - } - if (g_object_get_data (G_OBJECT (column), "new-var-column") != NULL) - may_insert_vars = TRUE; - } - g_list_free (list); - - may_insert_vars = may_insert_vars && data_sheet->may_create_vars; - may_delete_vars = may_delete_vars && data_sheet->may_delete_vars; - - gtk_widget_set_sensitive (dw->mi_insert_var, may_insert_vars); - gtk_widget_set_sensitive (dw->mi_clear_variables, may_delete_vars); - gtk_widget_set_sensitive (data_sheet->pu_sort_up, may_delete_vars); - gtk_widget_set_sensitive (data_sheet->pu_sort_down, may_delete_vars); - - psppire_data_sheet_update_clip_actions (data_sheet); - psppire_data_sheet_update_primary_selection (data_sheet, - (n_selected_rows > 0 - && any_variables_selected)); -} - -static gboolean -psppire_data_sheet_get_selected_range (PsppireDataSheet *data_sheet, - struct range_set **rowsp, - struct range_set **colsp) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppireDataStore *data_store = data_sheet->data_store; - PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view); - unsigned long n_cases; - struct range_set *rows, *cols; - GList *list, *iter; - - if (data_store == NULL) - return FALSE; - n_cases = psppire_data_store_get_case_count (data_store); - - rows = pspp_sheet_selection_get_range_set (selection); - range_set_set0 (rows, n_cases, ULONG_MAX - n_cases); - if (range_set_is_empty (rows)) - { - range_set_destroy (rows); - return FALSE; - } - - cols = range_set_create (); - list = pspp_sheet_selection_get_selected_columns (selection); - for (iter = list; iter != NULL; iter = iter->next) - { - PsppSheetViewColumn *column = iter->data; - struct variable *var = g_object_get_data (G_OBJECT (column), "variable"); - - if (var != NULL) - range_set_set1 (cols, var_get_dict_index (var), 1); - } - g_list_free (list); - if (range_set_is_empty (cols)) - { - range_set_destroy (rows); - range_set_destroy (cols); - return FALSE; - } - - *rowsp = rows; - *colsp = cols; - return TRUE; -} - -/* Insert a case at the selected row */ -void -psppire_data_sheet_insert_case (PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view); - PsppireDataStore *data_store = data_sheet->data_store; - struct range_set *selected = pspp_sheet_selection_get_range_set (selection); - unsigned long row = range_set_scan (selected, 0); - range_set_destroy (selected); - - if (row <= psppire_data_store_get_case_count (data_store)) - psppire_data_store_insert_new_case (data_store, row); -} - -void -psppire_data_sheet_insert_variable (PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view); - PsppireDict *dict = data_sheet->data_store->dict; - PsppSheetViewColumn *column; - struct variable *var; - gchar name[64]; - GList *list; - gint index; - - list = pspp_sheet_selection_get_selected_columns (selection); - if (list == NULL) - return; - column = list->data; - g_list_free (list); - - var = g_object_get_data (G_OBJECT (column), "variable"); - index = var ? var_get_dict_index (var) : psppire_dict_get_var_cnt (dict); - if (psppire_dict_generate_name (dict, name, sizeof name)) - psppire_dict_insert_variable (dict, index, name); -} - -void -psppire_data_sheet_edit_clear_variables (PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view); - PsppireDict *dict = data_sheet->data_store->dict; - GList *iter; - GList *list = pspp_sheet_selection_get_selected_columns (selection); - - if (list == NULL) - return; - list = g_list_reverse (list); - for (iter = list; iter; iter = iter->next) - { - PsppSheetViewColumn *column = iter->data; - struct variable *var = g_object_get_data (G_OBJECT (column), "variable"); - if (var != NULL) - psppire_dict_delete_variables (dict, var_get_dict_index (var), 1); - } - g_list_free (list); -} - -void -psppire_data_sheet_edit_copy (PsppireDataSheet *data_sheet) -{ - psppire_data_sheet_set_clip (data_sheet, FALSE); -} - -void -psppire_data_sheet_edit_cut (PsppireDataSheet *data_sheet) -{ - psppire_data_sheet_set_clip (data_sheet, TRUE); -} - -void -psppire_data_sheet_edit_paste (PsppireDataSheet *data_sheet) -{ - GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (data_sheet)); - GtkClipboard *clipboard = - gtk_clipboard_get_for_display (display, GDK_SELECTION_CLIPBOARD); - - gtk_clipboard_request_contents (clipboard, - gdk_atom_intern ("UTF8_STRING", TRUE), - psppire_data_sheet_clip_received_cb, - data_sheet); -} - -static void -psppire_data_sheet_init (PsppireDataSheet *obj) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (obj); - - obj->show_value_labels = FALSE; - obj->show_case_numbers = TRUE; - obj->may_create_vars = TRUE; - obj->may_delete_vars = TRUE; - - obj->owns_primary_selection = FALSE; - - obj->scroll_to_bottom_signal = 0; - obj->scroll_to_right_signal = 0; - obj->on_owner_change_signal = 0; - obj->new_variable_column = NULL; - obj->container = NULL; - - obj->dispose_has_run = FALSE; - - pspp_sheet_view_set_special_cells (sheet_view, PSPP_SHEET_VIEW_SPECIAL_CELLS_YES); - - { - obj->row_popup_menu = gtk_menu_new (); - int i = 0; - - GtkWidget *insert_case = gtk_menu_item_new_with_mnemonic (_("_Insert Case")); - GtkWidget *clear_cases = gtk_menu_item_new_with_mnemonic (_("Cl_ear Cases")); - - gtk_menu_attach (GTK_MENU (obj->row_popup_menu), insert_case, 0, 1, i, i + 1); ++i; - gtk_menu_attach (GTK_MENU (obj->row_popup_menu), clear_cases, 0, 1, i, i + 1); ++i; - - g_signal_connect_swapped (clear_cases, "activate", G_CALLBACK (psppire_data_sheet_edit_clear_cases), obj); - g_signal_connect_swapped (insert_case, "activate", G_CALLBACK (psppire_data_sheet_insert_case), obj); - - gtk_widget_show_all (obj->row_popup_menu); - } - - { - obj->column_popup_menu = gtk_menu_new (); - int i = 0; - - GtkWidget *insert_variable = gtk_menu_item_new_with_mnemonic (_("_Insert Variable")); - GtkWidget *clear_variables = gtk_menu_item_new_with_mnemonic (_("Cl_ear Variables")); - obj->pu_sort_up = gtk_menu_item_new_with_mnemonic (_("Sort _Ascending")); - obj->pu_sort_down = gtk_menu_item_new_with_mnemonic (_("Sort _Descending")); - - g_signal_connect_swapped (clear_variables, "activate", G_CALLBACK (psppire_data_sheet_edit_clear_variables), obj); - g_signal_connect_swapped (insert_variable, "activate", G_CALLBACK (psppire_data_sheet_insert_variable), obj); - - g_signal_connect_swapped (obj->pu_sort_up, "activate", G_CALLBACK (on_sort_up), obj); - g_signal_connect_swapped (obj->pu_sort_down, "activate", G_CALLBACK (on_sort_down), obj); - - gtk_menu_attach (GTK_MENU (obj->column_popup_menu), insert_variable, 0, 1, i, i + 1); ++i; - gtk_menu_attach (GTK_MENU (obj->column_popup_menu), clear_variables, 0, 1, i, i + 1); ++i; - - gtk_menu_attach (GTK_MENU (obj->column_popup_menu), gtk_separator_menu_item_new (), 0, 1, i, i + 1); ++i; - - gtk_menu_attach (GTK_MENU (obj->column_popup_menu), obj->pu_sort_up, 0, 1, i, i + 1); ++i; - gtk_menu_attach (GTK_MENU (obj->column_popup_menu), obj->pu_sort_down, 0, 1, i, i + 1); ++i; - - gtk_widget_show_all (obj->column_popup_menu); - } - - - g_signal_connect (obj, "notify::model", - G_CALLBACK (psppire_data_sheet_model_changed), 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_RECTANGLE); - - g_object_set (G_OBJECT (obj), "has-tooltip", TRUE, (void *) NULL); - g_signal_connect (obj, "query-tooltip", - G_CALLBACK (on_query_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); - - g_signal_connect (pspp_sheet_view_get_selection (sheet_view), - "changed", G_CALLBACK (on_selection_changed), NULL); -} - -GtkWidget * -psppire_data_sheet_new (void) -{ - return g_object_new (PSPP_TYPE_DATA_SHEET, NULL); -} - -PsppireDataStore * -psppire_data_sheet_get_data_store (PsppireDataSheet *data_sheet) -{ - return data_sheet->data_store; -} - -static void -refresh_model (PsppireDataSheet *data_sheet) -{ - pspp_sheet_view_set_model (PSPP_SHEET_VIEW (data_sheet), NULL); - - if (data_sheet->data_store != NULL) - { - int n_rows = psppire_data_store_get_case_count (data_sheet->data_store) + 1; - PsppireEmptyListStore *model = psppire_empty_list_store_new (n_rows); - pspp_sheet_view_set_model (PSPP_SHEET_VIEW (data_sheet), - GTK_TREE_MODEL (model)); - g_object_unref (model); - } -} - -static void -on_case_inserted (PsppireDataStore *data_store, gint row, - PsppireDataSheet *data_sheet) -{ - PsppireEmptyListStore *empty_list_store; - GtkTreeModel *tree_model; - gint n_rows; - - g_return_if_fail (data_store == data_sheet->data_store); - - n_rows = psppire_data_store_get_case_count (data_store) + 1; - if (row == n_rows - 1) - row++; - - tree_model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (data_sheet)); - empty_list_store = PSPPIRE_EMPTY_LIST_STORE (tree_model); - psppire_empty_list_store_set_n_rows (empty_list_store, n_rows); - psppire_empty_list_store_row_inserted (empty_list_store, row); -} - -static void -on_cases_deleted (PsppireDataStore *data_store, gint first, gint n_cases, - PsppireDataSheet *data_sheet) -{ - - g_return_if_fail (data_store == data_sheet->data_store); - - if (n_cases > 1) - { - /* This is a bit of a cop-out. We could do better, if it ever turns out - that this performs too poorly. */ - refresh_model (data_sheet); - } - else - { - PsppireEmptyListStore *empty_list_store; - GtkTreeModel *tree_model; - gint n_rows = psppire_data_store_get_case_count (data_store) + 1; - - tree_model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (data_sheet)); - empty_list_store = PSPPIRE_EMPTY_LIST_STORE (tree_model); - psppire_empty_list_store_set_n_rows (empty_list_store, n_rows); - psppire_empty_list_store_row_deleted (empty_list_store, first); - } -} - -static void -on_case_change (PsppireDataStore *data_store, gint row, - PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - - pspp_sheet_view_stop_editing (sheet_view, TRUE); - gtk_widget_queue_draw (GTK_WIDGET (data_sheet)); -} - -static void -on_backend_changed (PsppireDataStore *data_store, - PsppireDataSheet *data_sheet) -{ - g_return_if_fail (data_store == data_sheet->data_store); - refresh_model (data_sheet); -} - -static void -on_variable_display_width_changed (PsppireDict *dict, int dict_index, - PsppireDataSheet *data_sheet) -{ - PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet); - PsppSheetViewColumn *column; - struct variable *var; - int display_width; - gint pixel_width; - - g_return_if_fail (data_sheet->data_store != NULL); - g_return_if_fail (dict == data_sheet->data_store->dict); - - column = psppire_data_sheet_find_column_for_variable (data_sheet, - dict_index); - if (column == NULL) - return; - - var = psppire_dict_get_variable (data_store->dict, dict_index); - g_return_if_fail (var != NULL); - - pixel_width = pspp_sheet_view_column_get_fixed_width (column); - display_width = display_width_from_pixel_width (data_sheet, pixel_width); - if (display_width != var_get_display_width (var)) - { - gint base_width, incr_width; - - display_width = var_get_display_width (var); - calc_width_conversion (data_sheet, &base_width, &incr_width); - pixel_width = display_width_to_pixel_width (data_sheet, display_width, - base_width, incr_width); - pspp_sheet_view_column_set_fixed_width (column, pixel_width); - } -} - -static void -on_variable_changed (PsppireDict *dict, int dict_index, - guint what, const struct variable *oldvar, - PsppireDataSheet *data_sheet) -{ - PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet); - PsppSheetViewColumn *column; - GtkCellRenderer *cell; - struct variable *var; - GList *cells; - char *name; - - g_return_if_fail (data_sheet->data_store != NULL); - g_return_if_fail (dict == data_sheet->data_store->dict); - - - if (what & VAR_TRAIT_DISPLAY_WIDTH) - on_variable_display_width_changed (dict, dict_index, data_sheet); - - column = psppire_data_sheet_find_column_for_variable (data_sheet, - dict_index); - if (column == NULL) - return; - - - var = psppire_dict_get_variable (data_store->dict, dict_index); - g_return_if_fail (var != NULL); - - name = escape_underscores (var_get_name (var)); - if (strcmp (name, pspp_sheet_view_column_get_title (column))) - pspp_sheet_view_column_set_title (column, name); - free (name); - - cells = pspp_sheet_view_column_get_cell_renderers (column); - g_return_if_fail (cells); - cell = cells->data; - g_list_free (cells); - - if (var_has_value_labels (var) != GTK_IS_CELL_RENDERER_COMBO (cell)) - { - /* Stop editing before we delete and replace the cell renderers. - Otherwise if this column is currently being edited, an eventual call - to pspp_sheet_view_stop_editing() will obtain a NULL cell and pass - that to gtk_cell_renderer_stop_editing(), which causes a critical. - - It's possible that this is a bug in PsppSheetView, and it's possible - that PsppSheetView inherits that from GtkTreeView, but I haven't - investigated yet. */ - pspp_sheet_view_stop_editing (PSPP_SHEET_VIEW (data_sheet), TRUE); - - add_data_column_cell_renderer (data_sheet, column); - } -} - -static void -on_variable_inserted (PsppireDict *dict, int var_index, - PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - gint base_width, incr_width; - PsppSheetViewColumn *column; - - calc_width_conversion (data_sheet, &base_width, &incr_width); - column = make_data_column (data_sheet, var_index, base_width, incr_width); - pspp_sheet_view_insert_column (sheet_view, column, var_index + 1); -} - -static void -on_variable_deleted (PsppireDict *dict, - const struct variable *var, int case_idx, int width, - PsppireDataSheet *data_sheet) -{ - PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); - GList *columns, *iter; - - columns = pspp_sheet_view_get_columns (sheet_view); - for (iter = columns; iter != NULL; iter = iter->next) - { - PsppSheetViewColumn *column = iter->data; - const struct variable *column_var; - - column_var = g_object_get_data (G_OBJECT (column), "variable"); - if (column_var == var) - pspp_sheet_view_remove_column (sheet_view, column); - } - g_list_free (columns); -} - -static void -psppire_data_sheet_unset_data_store (PsppireDataSheet *data_sheet) -{ - PsppireDataStore *store = data_sheet->data_store; - - if (store == NULL) - return; - - data_sheet->data_store = NULL; - - g_signal_handlers_disconnect_by_func ( - store, G_CALLBACK (on_backend_changed), data_sheet); - g_signal_handlers_disconnect_by_func ( - store, G_CALLBACK (on_case_inserted), data_sheet); - g_signal_handlers_disconnect_by_func ( - store, G_CALLBACK (on_cases_deleted), data_sheet); - g_signal_handlers_disconnect_by_func ( - store, G_CALLBACK (on_case_change), data_sheet); - - g_signal_handlers_disconnect_by_func ( - store->dict, G_CALLBACK (on_variable_changed), data_sheet); - g_signal_handlers_disconnect_by_func ( - store->dict, G_CALLBACK (on_variable_display_width_changed), data_sheet); - g_signal_handlers_disconnect_by_func ( - store->dict, G_CALLBACK (on_variable_inserted), data_sheet); - g_signal_handlers_disconnect_by_func ( - store->dict, G_CALLBACK (on_variable_deleted), data_sheet); - - g_object_unref (store); -} - -void -psppire_data_sheet_set_data_store (PsppireDataSheet *data_sheet, - PsppireDataStore *data_store) -{ - psppire_data_sheet_unset_data_store (data_sheet); - - data_sheet->data_store = data_store; - if (data_store != NULL) - { - g_object_ref (data_store); - g_signal_connect (data_store, "backend-changed", - G_CALLBACK (on_backend_changed), data_sheet); - g_signal_connect (data_store, "case-inserted", - G_CALLBACK (on_case_inserted), data_sheet); - g_signal_connect (data_store, "cases-deleted", - G_CALLBACK (on_cases_deleted), data_sheet); - g_signal_connect (data_store, "case-changed", - G_CALLBACK (on_case_change), data_sheet); - - /* XXX it's unclean to hook into the dict this way--what if the dict - changes? As of this writing, though, nothing ever changes the - data_store's dict. */ - g_signal_connect (data_store->dict, "variable-changed", - G_CALLBACK (on_variable_changed), - data_sheet); - g_signal_connect (data_store->dict, "variable-inserted", - G_CALLBACK (on_variable_inserted), data_sheet); - g_signal_connect (data_store->dict, "variable-deleted", - G_CALLBACK (on_variable_deleted), data_sheet); - } - refresh_model (data_sheet); -} - -/* Clipboard stuff */ - -/* A casereader and dictionary holding the data currently in the clip */ -static struct casereader *clip_datasheet = NULL; -static struct dictionary *clip_dict = NULL; - - -static void psppire_data_sheet_update_clipboard (PsppireDataSheet *); - -static gboolean -psppire_data_sheet_fetch_clip (PsppireDataSheet *data_sheet, gboolean cut, - struct casereader **readerp, - struct dictionary **dictp) -{ - struct casewriter *writer ; - PsppireDataStore *ds = psppire_data_sheet_get_data_store (data_sheet); - struct case_map *map = NULL; - struct range_set *rows, *cols; - const struct range_set_node *node; - struct dictionary *dict; - - if (!psppire_data_sheet_get_selected_range (data_sheet, &rows, &cols)) - { - *readerp = NULL; - *dictp = NULL; - return FALSE; - } - - /* Construct clip dictionary. */ - *dictp = dict = dict_create (dict_get_encoding (ds->dict->dict)); - RANGE_SET_FOR_EACH (node, cols) - { - int dict_index; - - for (dict_index = node->start; dict_index < node->end; dict_index++) - { - struct variable *var = dict_get_var (ds->dict->dict, dict_index); - dict_clone_var_assert (dict, var); - } - } - - /* Construct clip data. */ - map = case_map_by_name (ds->dict->dict, dict); - writer = autopaging_writer_create (dict_get_proto (dict)); - RANGE_SET_FOR_EACH (node, rows) - { - unsigned long int row; - - for (row = node->start; row < node->end; row++) - { - struct ccase *old = psppire_data_store_get_case (ds, row); - if (old != NULL) - casewriter_write (writer, case_map_execute (map, old)); - else - casewriter_force_error (writer); - } - } - case_map_destroy (map); - - /* Clear data that we copied out, if we're doing a "cut". */ - if (cut && !casewriter_error (writer)) - { - RANGE_SET_FOR_EACH (node, rows) - { - unsigned long int row; - - for (row = node->start; row < node->end; row++) - { - const struct range_set_node *node2; - - RANGE_SET_FOR_EACH (node2, cols) - { - int dict_index; - - for (dict_index = node2->start; dict_index < node2->end; - dict_index++) - { - struct variable *var; - - var = dict_get_var (ds->dict->dict, dict_index); - psppire_data_store_set_string (ds, "", row, - var, false); - } - } - } - } - } - - range_set_destroy (rows); - range_set_destroy (cols); - - *readerp = casewriter_make_reader (writer); - - return TRUE; -} - -/* Set the clip from the currently selected range in DATA_SHEET. If CUT is - true, clears the original data from DATA_SHEET, otherwise leaves the - original data in-place. */ -static void -psppire_data_sheet_set_clip (PsppireDataSheet *data_sheet, - gboolean cut) -{ - struct casereader *reader; - struct dictionary *dict; - - if (psppire_data_sheet_fetch_clip (data_sheet, cut, &reader, &dict)) - { - casereader_destroy (clip_datasheet); - dict_destroy (clip_dict); - - clip_datasheet = reader; - clip_dict = dict; - - psppire_data_sheet_update_clipboard (data_sheet); - } -} - -enum { - SELECT_FMT_NULL, - SELECT_FMT_TEXT, - SELECT_FMT_HTML -}; - - -/* Perform data_out for case CC, variable V, appending to STRING */ -static void -data_out_g_string (GString *string, const struct variable *v, - const struct ccase *cc) -{ - const struct fmt_spec *fs = var_get_print_format (v); - const union value *val = case_data (cc, v); - - char *s = data_out (val, var_get_encoding (v), fs); - - g_string_append (string, s); - - g_free (s); -} - -static GString * -clip_to_text (struct casereader *datasheet, struct dictionary *dict) -{ - casenumber r; - GString *string; - - const size_t val_cnt = caseproto_get_n_widths (casereader_get_proto (datasheet)); - const casenumber case_cnt = casereader_get_case_cnt (datasheet); - const size_t var_cnt = dict_get_var_cnt (dict); - - string = g_string_sized_new (10 * val_cnt * case_cnt); - - for (r = 0 ; r < case_cnt ; ++r ) - { - int c; - struct ccase *cc; - - cc = casereader_peek (datasheet, r); - if (cc == NULL) - { - g_warning ("Clipboard seems to have inexplicably shrunk"); - break; - } - - for (c = 0 ; c < var_cnt ; ++c) - { - const struct variable *v = dict_get_var (dict, c); - data_out_g_string (string, v, cc); - if ( c < val_cnt - 1 ) - g_string_append (string, "\t"); - } - - if ( r < case_cnt) - g_string_append (string, "\n"); - - case_unref (cc); - } - - return string; -} - - -static GString * -clip_to_html (struct casereader *datasheet, struct dictionary *dict) -{ - casenumber r; - GString *string; - - const size_t val_cnt = caseproto_get_n_widths (casereader_get_proto (datasheet)); - const casenumber case_cnt = casereader_get_case_cnt (datasheet); - const size_t var_cnt = dict_get_var_cnt (dict); - - /* Guestimate the size needed */ - string = g_string_sized_new (80 + 20 * val_cnt * case_cnt); - - g_string_append (string, - "\n"); - - g_string_append (string, "\n"); - for (r = 0 ; r < case_cnt ; ++r ) - { - int c; - struct ccase *cc = casereader_peek (datasheet, r); - if (cc == NULL) - { - g_warning ("Clipboard seems to have inexplicably shrunk"); - break; - } - g_string_append (string, "\n"); - - for (c = 0 ; c < var_cnt ; ++c) - { - const struct variable *v = dict_get_var (dict, c); - g_string_append (string, "\n"); - } - - g_string_append (string, "\n"); - - case_unref (cc); - } - g_string_append (string, "
"); - data_out_g_string (string, v, cc); - g_string_append (string, "
\n"); - - return string; -} - - - -static void -psppire_data_sheet_clipboard_set (GtkSelectionData *selection_data, - guint info, - struct casereader *reader, - struct dictionary *dict) -{ - GString *string = NULL; - - switch (info) - { - case SELECT_FMT_TEXT: - string = clip_to_text (reader, dict); - break; - case SELECT_FMT_HTML: - string = clip_to_html (reader, dict); - break; - default: - g_assert_not_reached (); - } - - gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), - 8, - (const guchar *) string->str, string->len); - - g_string_free (string, TRUE); -} - -static void -psppire_data_sheet_clipboard_get_cb (GtkClipboard *clipboard, - GtkSelectionData *selection_data, - guint info, - gpointer data) -{ - psppire_data_sheet_clipboard_set (selection_data, info, - clip_datasheet, clip_dict); -} - -static void -psppire_data_sheet_clipboard_clear_cb (GtkClipboard *clipboard, - gpointer data) -{ - dict_destroy (clip_dict); - clip_dict = NULL; - - casereader_destroy (clip_datasheet); - clip_datasheet = NULL; -} - - -static const GtkTargetEntry targets[] = { - { "UTF8_STRING", 0, SELECT_FMT_TEXT }, - { "STRING", 0, SELECT_FMT_TEXT }, - { "TEXT", 0, SELECT_FMT_TEXT }, - { "COMPOUND_TEXT", 0, SELECT_FMT_TEXT }, - { "text/plain;charset=utf-8", 0, SELECT_FMT_TEXT }, - { "text/plain", 0, SELECT_FMT_TEXT }, - { "text/html", 0, SELECT_FMT_HTML } -}; - - - -static void -psppire_data_sheet_update_clipboard (PsppireDataSheet *sheet) -{ - GtkClipboard *clipboard = - gtk_widget_get_clipboard (GTK_WIDGET (sheet), - GDK_SELECTION_CLIPBOARD); - - if (!gtk_clipboard_set_with_owner (clipboard, targets, - G_N_ELEMENTS (targets), - psppire_data_sheet_clipboard_get_cb, - psppire_data_sheet_clipboard_clear_cb, - G_OBJECT (sheet))) - psppire_data_sheet_clipboard_clear_cb (clipboard, sheet); -} - -static void -psppire_data_sheet_update_clip_actions (PsppireDataSheet *data_sheet) -{ - struct range_set *rows, *cols; - GtkWidget *top = gtk_widget_get_toplevel (GTK_WIDGET (data_sheet)); - if (! PSPPIRE_IS_DATA_WINDOW (top)) - return; - - PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (top); - gboolean enable = - psppire_data_sheet_get_selected_range (data_sheet, &rows, &cols); - - if (enable) - { - range_set_destroy (rows); - range_set_destroy (cols); - } - - gtk_widget_set_sensitive (dw->mi_copy, enable); - gtk_widget_set_sensitive (dw->mi_cut, enable); -} - -static void -psppire_data_sheet_primary_get_cb (GtkClipboard *clipboard, - GtkSelectionData *selection_data, - guint info, - gpointer data) -{ - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (data); - struct casereader *reader; - struct dictionary *dict; - - if (psppire_data_sheet_fetch_clip (data_sheet, FALSE, &reader, &dict)) - { - psppire_data_sheet_clipboard_set (selection_data, info, - reader, dict); - casereader_destroy (reader); - dict_destroy (dict); - } -} - -static void -psppire_data_sheet_update_primary_selection (PsppireDataSheet *data_sheet, - gboolean should_own) -{ - GtkClipboard *clipboard; - GdkDisplay *display; - - display = gtk_widget_get_display (GTK_WIDGET (data_sheet)); - clipboard = gtk_clipboard_get_for_display (display, GDK_SELECTION_PRIMARY); - g_return_if_fail (clipboard != NULL); - - if (data_sheet->owns_primary_selection && !should_own) - { - data_sheet->owns_primary_selection = FALSE; - gtk_clipboard_clear (clipboard); - } - else if (should_own) - data_sheet->owns_primary_selection = - gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets), - psppire_data_sheet_primary_get_cb, - NULL, G_OBJECT (data_sheet)); -} - -/* A callback for when the clipboard contents have been received. */ -static void -psppire_data_sheet_clip_received_cb (GtkClipboard *clipboard, - GtkSelectionData *sd, - gpointer data) -{ - PsppireDataSheet *data_sheet = data; - PsppireDataStore *store = data_sheet->data_store; - struct range_set *rows, *cols; - gint count = 0; - gint next_row, next_column; - gint first_column; - char *c; - - if ( gtk_selection_data_get_length (sd) < 0 ) - return; - - if ( gtk_selection_data_get_data_type (sd) != gdk_atom_intern ("UTF8_STRING", FALSE)) - return; - - c = (char *) gtk_selection_data_get_data (sd); - - /* Get the starting selected position in the data sheet. (Possibly we should - only paste into the selected range if it's larger than one cell?) */ - if (!psppire_data_sheet_get_selected_range (data_sheet, &rows, &cols)) - return; - next_row = range_set_first (rows)->start; - first_column = next_column = range_set_first (cols)->start; - range_set_destroy (rows); - range_set_destroy (cols); - - g_return_if_fail (next_row >= 0); - g_return_if_fail (next_column >= 0); - - while (count < gtk_selection_data_get_length (sd)) - { - gint row = next_row; - gint column = next_column; - struct variable *var; - char *s = c; - - while (*c != '\t' && *c != '\n' && count < gtk_selection_data_get_length (sd)) - { - c++; - count++; - } - if ( *c == '\t') - { - next_row = row ; - next_column = column + 1; - } - else if ( *c == '\n') - { - next_row = row + 1; - next_column = first_column; - } - *c++ = '\0'; - count++; - - var = psppire_dict_get_variable (store->dict, column); - if (var != NULL) - psppire_data_store_set_string (store, s, row, var, FALSE); - } -} - -static void -psppire_data_sheet_targets_received_cb (GtkClipboard *clipboard, - GdkAtom *atoms, - gint n_atoms, - gpointer data) -{ - GtkWidget *mi = GTK_WIDGET (data); - gboolean compatible_target = FALSE; - gint i; - for (i = 0; i < G_N_ELEMENTS (targets); i++) - { - GdkAtom target = gdk_atom_intern (targets[i].target, TRUE); - gint j; - - for (j = 0; j < n_atoms; j++) - if (target == atoms[j]) - { - compatible_target = TRUE; - break; - } - } - - gtk_widget_set_sensitive (mi, compatible_target); -} - -static void -on_owner_change (GtkClipboard *clip, GdkEventOwnerChange *event, gpointer data) -{ - PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (data); - - GtkWidget *top = gtk_widget_get_toplevel (GTK_WIDGET (data_sheet)); - if (! PSPPIRE_IS_DATA_WINDOW (top)) - return; - - PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (top); - - gtk_clipboard_request_targets (clip, - psppire_data_sheet_targets_received_cb, - dw->mi_paste); -} - -#endif diff --git a/src/ui/gui/psppire-data-sheet.h b/src/ui/gui/psppire-data-sheet.h deleted file mode 100644 index 8e73b9e381..0000000000 --- a/src/ui/gui/psppire-data-sheet.h +++ /dev/null @@ -1,118 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc. - - 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 - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef PSPPIRE_DATA_SHEET_H -#define PSPPIRE_DATA_SHEET_H 1 - -#error "Do not include this file" - -/* PsppireDataSheet is a PsppSheetView that displays the data in a dataset, - with one column per variable and one row per case. - - PsppireDataSheet is usually a child of PsppireDataEditor in the widget - hierarchy. Other widgets can also use it. */ - -#include -#include "ui/gui/pspp-sheet-view.h" - -G_BEGIN_DECLS - -#define PSPP_TYPE_DATA_SHEET (psppire_data_sheet_get_type()) -#define PSPPIRE_DATA_SHEET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),PSPP_TYPE_DATA_SHEET,PsppireDataSheet)) -#define PSPPIRE_DATA_SHEET_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class),PSPP_TYPE_DATA_SHEET,PsppireDataSheetClass)) -#define PSPP_IS_DATA_SHEET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PSPP_TYPE_DATA_SHEET)) -#define PSPP_IS_DATA_SHEET_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),PSPP_TYPE_DATA_SHEET)) -#define PSPPIRE_DATA_SHEET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),PSPP_TYPE_DATA_SHEET,PsppireDataSheetClass)) - -typedef struct _PsppireDataSheet PsppireDataSheet; -typedef struct _PsppireDataSheetClass PsppireDataSheetClass; - -struct _PsppireDataSheet -{ - PsppSheetView parent; - - struct _PsppireDataStore *data_store; - gboolean show_value_labels; - gboolean show_case_numbers; - gboolean may_create_vars; - gboolean may_delete_vars; - - gboolean owns_primary_selection; - - guint scroll_to_bottom_signal; - guint scroll_to_right_signal; - - GtkClipboard *clip; - guint on_owner_change_signal; - - PsppSheetViewColumn *new_variable_column; - - GtkWidget *container; - gboolean dispose_has_run; - - GtkWidget *column_popup_menu; - GtkWidget *row_popup_menu; - - GtkWidget *pu_sort_up; - GtkWidget *pu_sort_down; -}; - -struct _PsppireDataSheetClass -{ - PsppSheetViewClass parent_class; -}; - -GType psppire_data_sheet_get_type (void) G_GNUC_CONST; -GtkWidget *psppire_data_sheet_new (void); - -struct _PsppireDataStore *psppire_data_sheet_get_data_store (PsppireDataSheet *); -void psppire_data_sheet_set_data_store (PsppireDataSheet *, - struct _PsppireDataStore *); - -gboolean psppire_data_sheet_get_value_labels (const PsppireDataSheet *); -void psppire_data_sheet_set_value_labels (PsppireDataSheet *, - gboolean show_value_labels); - -gboolean psppire_data_sheet_get_case_numbers (const PsppireDataSheet *); -void psppire_data_sheet_set_case_numbers (PsppireDataSheet *, - gboolean show_case_numbers); - -gboolean psppire_data_sheet_get_may_create_vars (PsppireDataSheet *); -void psppire_data_sheet_set_may_create_vars (PsppireDataSheet *, gboolean); - -gboolean psppire_data_sheet_get_may_delete_vars (PsppireDataSheet *); -void psppire_data_sheet_set_may_delete_vars (PsppireDataSheet *, gboolean); - -void psppire_data_sheet_goto_variable (PsppireDataSheet *, gint dict_index); -struct variable *psppire_data_sheet_get_current_variable (const PsppireDataSheet *); - -void psppire_data_sheet_goto_case (PsppireDataSheet *, gint case_index); -gint psppire_data_sheet_get_selected_case (const PsppireDataSheet *); -gint psppire_data_sheet_get_current_case (const PsppireDataSheet *); - -void psppire_data_sheet_insert_case (PsppireDataSheet *data_sheet); -void psppire_data_sheet_insert_variable (PsppireDataSheet *data_sheet); - -void psppire_data_sheet_edit_cut (PsppireDataSheet *data_sheet); -void psppire_data_sheet_edit_copy (PsppireDataSheet *data_sheet); -void psppire_data_sheet_edit_paste (PsppireDataSheet *data_sheet); - -void psppire_data_sheet_edit_clear_cases (PsppireDataSheet *data_sheet); -void psppire_data_sheet_edit_clear_variables (PsppireDataSheet *data_sheet); - -G_END_DECLS - -#endif /* PSPPIRE_DATA_SHEET_H */ -- 2.30.2