X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fpsppire-data-sheet.c;h=e1ecbbb924a005bd0646c62a3558765965814fa1;hb=refs%2Fbuilds%2F20130116032122%2Fpspp;hp=b6bf67c265933bab22a28b70d23131ae20ae1a00;hpb=f481fd69631024bcdc7dc2369bbc1592d7a43ac7;p=pspp diff --git a/src/ui/gui/psppire-data-sheet.c b/src/ui/gui/psppire-data-sheet.c index b6bf67c265..e1ecbbb924 100644 --- a/src/ui/gui/psppire-data-sheet.c +++ b/src/ui/gui/psppire-data-sheet.c @@ -51,9 +51,12 @@ 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_set_clip (PsppireDataSheet *); +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); @@ -223,7 +226,10 @@ make_row_number_column (PsppireDataSheet *data_sheet, column = pspp_sheet_view_column_new_with_attributes (_("Case"), renderer, NULL); - g_object_set (column, "selectable", FALSE, "row-head", TRUE, 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); @@ -752,6 +758,7 @@ make_new_variable_column (PsppireDataSheet *data_sheet, 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", @@ -1040,7 +1047,7 @@ psppire_data_sheet_find_column_for_variable (PsppireDataSheet *data_sheet, } void -psppire_data_sheet_show_variable (PsppireDataSheet *data_sheet, +psppire_data_sheet_goto_variable (PsppireDataSheet *data_sheet, gint dict_index) { PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet); @@ -1049,8 +1056,17 @@ psppire_data_sheet_show_variable (PsppireDataSheet *data_sheet, column = psppire_data_sheet_find_column_for_variable (data_sheet, dict_index); if (column != NULL) - pspp_sheet_view_scroll_to_cell (sheet_view, NULL, column, - FALSE, 0.0, 0.0); + { + 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 * @@ -1200,17 +1216,33 @@ psppire_data_sheet_dispose (GObject *object) G_OBJECT_CLASS (psppire_data_sheet_parent_class)->dispose (object); } +static void +psppire_data_sheet_map (GtkWidget *widget) +{ + GtkClipboard *clip; + + GTK_WIDGET_CLASS (psppire_data_sheet_parent_class)->map (widget); + + clip = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD); + g_signal_connect (clip, "owner-change", G_CALLBACK (on_owner_change), + widget); + on_owner_change (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, @@ -1613,7 +1645,26 @@ on_edit_find (GtkAction *action, PsppireDataSheet *data_sheet) void on_edit_copy (GtkAction *action, PsppireDataSheet *data_sheet) { - psppire_data_sheet_set_clip (data_sheet); + psppire_data_sheet_set_clip (data_sheet, FALSE); +} + +void +on_edit_cut (GtkAction *action, PsppireDataSheet *data_sheet) +{ + psppire_data_sheet_set_clip (data_sheet, TRUE); +} + +void +on_edit_paste (GtkAction *action, 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 @@ -1675,6 +1726,12 @@ psppire_data_sheet_init (PsppireDataSheet *obj) action = get_action_assert (obj->builder, "edit_copy"); g_signal_connect (action, "activate", G_CALLBACK (on_edit_copy), obj); + action = get_action_assert (obj->builder, "edit_cut"); + g_signal_connect (action, "activate", G_CALLBACK (on_edit_cut), obj); + + action = get_action_assert (obj->builder, "edit_paste"); + g_signal_connect (action, "activate", G_CALLBACK (on_edit_paste), obj); + action = get_action_assert (obj->builder, "edit_clear-variables"); g_signal_connect (action, "activate", G_CALLBACK (on_edit_clear_variables), obj); @@ -1982,10 +2039,12 @@ static struct dictionary *clip_dict = NULL; static void psppire_data_sheet_update_clipboard (PsppireDataSheet *); -/* Set the clip according to the currently - selected range in the data sheet */ +/* 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) +psppire_data_sheet_set_clip (PsppireDataSheet *data_sheet, + gboolean cut) { struct casewriter *writer ; PsppireDataStore *ds = psppire_data_sheet_get_data_store (data_sheet); @@ -2041,6 +2100,35 @@ psppire_data_sheet_set_clip (PsppireDataSheet *data_sheet) } 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); @@ -2246,4 +2334,90 @@ psppire_data_sheet_update_clip_actions (PsppireDataSheet *data_sheet) action = get_action_assert (data_sheet->builder, "edit_cut"); gtk_action_set_sensitive (action, enable); } + +/* 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 ( sd->length < 0 ) + return; + + if ( sd->type != gdk_atom_intern ("UTF8_STRING", FALSE)) + return; + + c = (char *) sd->data; + + /* 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 < sd->length) + { + gint row = next_row; + gint column = next_column; + struct variable *var; + char *s = c; + + while (*c != '\t' && *c != '\n' && count < sd->length) + { + 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 +on_owner_change (GtkClipboard *clip, GdkEventOwnerChange *event, gpointer data) +{ + PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (data); + gboolean compatible_target = FALSE; + GtkAction *action; + gint i; + + for (i = 0; i < G_N_ELEMENTS (targets); i++) + { + GdkAtom atom = gdk_atom_intern (targets[i].target, TRUE); + if (gtk_clipboard_wait_is_target_available (clip, atom)) + { + compatible_target = TRUE; + break; + } + } + + action = get_action_assert (data_sheet->builder, "edit_paste"); + gtk_action_set_sensitive (action, compatible_target); +}