-static void
-psppire_data_sheet_class_init (PsppireDataSheetClass *class)
-{
- GObjectClass *gobject_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;
-
- 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));
-
- g_object_class_install_property (
- gobject_class,
- PROP_UI_MANAGER,
- g_param_spec_object ("ui-manager",
- "UI Manager",
- "UI manager for the data sheet. The client should merge this UI manager with the active UI manager to obtain data sheet specific menu items and tool bar items.",
- GTK_TYPE_UI_MANAGER,
- G_PARAM_READABLE));
-}
-
-static void
-do_popup_menu (GtkWidget *widget, guint button, guint32 time)
-{
- PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget);
- GtkWidget *menu;
-
- menu = get_widget_assert (data_sheet->builder, "datasheet-cases-popup");
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, button, time);
-}
-
-static void
-on_popup_menu (GtkWidget *widget, gpointer user_data UNUSED)
-{
- do_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_popup_menu (widget, event->button, event->time);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-on_edit_clear_cases (GtkAction *action, 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);
- gint n_selected_rows;
- gboolean may_delete_cases, may_delete_vars, may_insert_vars;
- GList *list, *iter;
- GtkTreePath *path;
- GtkAction *action;
-
- n_selected_rows = pspp_sheet_selection_count_selected_rows (selection);
-
- action = get_action_assert (data_sheet->builder, "edit_insert-case");
- gtk_action_set_sensitive (action, 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;
- }
- action = get_action_assert (data_sheet->builder, "edit_clear-cases");
- gtk_action_set_sensitive (action, may_delete_cases);
-
- 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;
- 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;
-
- action = get_action_assert (data_sheet->builder, "edit_insert-variable");
- gtk_action_set_sensitive (action, may_insert_vars);
-
- action = get_action_assert (data_sheet->builder, "edit_clear-variables");
- gtk_action_set_sensitive (action, may_delete_vars);
-
- action = get_action_assert (data_sheet->builder, "sort-up");
- gtk_action_set_sensitive (action, may_delete_vars);
-
- action = get_action_assert (data_sheet->builder, "sort-down");
- gtk_action_set_sensitive (action, may_delete_vars);
-
- psppire_data_sheet_update_clip_actions (data_sheet);
-}
-
-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;
-}
-
-static void
-on_edit_insert_case (GtkAction *action, 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;
- unsigned long row;
-
- selected = pspp_sheet_selection_get_range_set (selection);
- 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);
-}
-
-static void
-on_edit_insert_variable (GtkAction *action, 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);
-}
-
-static void
-on_edit_clear_variables (GtkAction *action, 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 *list, *iter;
-
- 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;
-
- 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);
-}
-
-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);
-}
-
-void
-on_sort_up (GtkAction *action, PsppireDataSheet *data_sheet)
-{
- do_sort (data_sheet, SORT_ASCEND);
-}
-
-void
-on_sort_down (GtkAction *action, PsppireDataSheet *data_sheet)
-{
- do_sort (data_sheet, SORT_DESCEND);
-}
-
-void
-on_edit_goto_case (GtkAction *action, PsppireDataSheet *data_sheet)
-{
- goto_case_dialog (data_sheet);
-}
-
-void
-on_edit_find (GtkAction *action, PsppireDataSheet *data_sheet)
-{
- PsppireDataWindow *pdw;
-
- pdw = psppire_data_window_for_data_store (data_sheet->data_store);
- g_return_if_fail (pdw != NULL);
-
- find_dialog (pdw);
-}
-
-void
-on_edit_copy (GtkAction *action, PsppireDataSheet *data_sheet)
-{
- psppire_data_sheet_set_clip (data_sheet);
-}
-
-static void
-psppire_data_sheet_init (PsppireDataSheet *obj)
-{
- PsppSheetView *sheet_view = PSPP_SHEET_VIEW (obj);
- GtkAction *action;
-
- obj->show_value_labels = FALSE;
- obj->show_case_numbers = TRUE;
- obj->may_create_vars = TRUE;
- obj->may_delete_vars = TRUE;
-
- obj->scroll_to_bottom_signal = 0;
- obj->scroll_to_right_signal = 0;
- obj->new_variable_column = NULL;
- obj->container = NULL;
-
- obj->uim = NULL;
- obj->dispose_has_run = FALSE;
-
- pspp_sheet_view_set_special_cells (sheet_view, PSPP_SHEET_VIEW_SPECIAL_CELLS_YES);
-
- 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);
-
- obj->builder = builder_new ("data-sheet.ui");
-
- action = get_action_assert (obj->builder, "edit_clear-cases");
- g_signal_connect (action, "activate", G_CALLBACK (on_edit_clear_cases),
- 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-case");
- g_signal_connect (action, "activate", G_CALLBACK (on_edit_insert_case),
- obj);
-
- action = get_action_assert (obj->builder, "edit_insert-variable");
- g_signal_connect (action, "activate", G_CALLBACK (on_edit_insert_variable),
- obj);
-
- action = get_action_assert (obj->builder, "edit_goto-case");
- g_signal_connect (action, "activate", G_CALLBACK (on_edit_goto_case),
- 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_clear-variables");
- g_signal_connect (action, "activate", G_CALLBACK (on_edit_clear_variables),
- obj);
-
- action = get_action_assert (obj->builder, "edit_find");
- g_signal_connect (action, "activate", G_CALLBACK (on_edit_find), obj);
-
- action = get_action_assert (obj->builder, "sort-up");
- g_signal_connect (action, "activate", G_CALLBACK (on_sort_up), obj);
-
- action = get_action_assert (obj->builder, "sort-down");
- g_signal_connect (action, "activate", G_CALLBACK (on_sort_down), obj);
-
-}
-
-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)
- {
- PsppireEmptyListStore *model;
- GtkAction *action;
- int n_rows;
-
- n_rows = psppire_data_store_get_case_count (data_sheet->data_store) + 1;
- 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);
-
- action = get_action_assert (data_sheet->builder, "edit_copy");
- g_signal_connect (action, "activate", G_CALLBACK (on_edit_copy),
- data_sheet);
- }
-}
-
-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);
- }