X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fsort-cases-dialog.c;h=4e7ac61f5ca94ddd2670ccd8baadfeb65c0529e7;hb=66153a44d861ccddf6a176ec5a94ffb959232ad6;hp=40795a205112c57b60ca4e5b12ff380a3a67b164;hpb=72147c12357446b304264b6944b8a1d92c45f53c;p=pspp-builds.git diff --git a/src/ui/gui/sort-cases-dialog.c b/src/ui/gui/sort-cases-dialog.c index 40795a20..4e7ac61f 100644 --- a/src/ui/gui/sort-cases-dialog.c +++ b/src/ui/gui/sort-cases-dialog.c @@ -1,482 +1,166 @@ -/* - PSPPIRE --- A Graphical User Interface for PSPP - Copyright (C) 2006 Free Software Foundation - Written by John Darrington +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2007 Free Software Foundation - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ - -/* This module describes the behaviour of the Sort Cases dialog box. */ - - -/* This code is rather quick and dirty. Some of the issues are: - - 1. Character set conversion when displaying dictionary tree view. - - 2. The interaction between the dictionary treeview, the criteria - list treeview and the button, needs to be abstracted and made - available as an external interface. - - 3. There's no destroy function for this dialog. - - 4. Some of the functionality might be better implemented with - GtkAction. - - 5. Double clicking the tree view rows should insert/delete them - from the criteria list. - - 6. Changing the Ascending/Descending flag ought to be possible for - a criteria already in the criteria tree view. - - 7. Variables which are in the criteria tree view should not be - shown in the dictionary treeview. - - 8. The dialog box structure itself ought to be a GtkWindow and - abstracted better. -*/ + 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 "helper.h" +#include #include "sort-cases-dialog.h" -#include "psppire-dict.h" -#include - -#include -#define _(msgid) gettext (msgid) -#define N_(msgid) msgid - - -enum {CRIT_TVM_IDX = 0, CRIT_TVM_DIR}; +#include "executor.h" +#include "psppire-dialog.h" +#include "psppire-data-window.h" +#include "psppire-var-store.h" +#include "dialog-common.h" +#include "psppire-selector.h" +#include "dict-display.h" + +#include +#include "helper.h" -/* Occurs when the dictionary tree view selection changes */ static void -dictionary_selection_changed (GtkTreeSelection *selection, - gpointer data) +refresh (PsppireDialog *dialog, GtkTreeView *dest) { - GtkTreeSelection *otherselection ; - struct sort_cases_dialog *dialog = (struct sort_cases_dialog*) data; + GtkTreeModel *liststore = gtk_tree_view_get_model (dest); - if ( 0 == gtk_tree_selection_count_selected_rows(selection) ) - return ; - gtk_arrow_set(dialog->arrow, GTK_ARROW_RIGHT, GTK_SHADOW_OUT); - dialog->button_state = VAR_SELECT; - - otherselection = gtk_tree_view_get_selection(dialog->criteria_view); - - gtk_tree_selection_unselect_all(otherselection); + gtk_list_store_clear (GTK_LIST_STORE (liststore)); } -/* Occurs when the sort criteria tree view selection changes */ -static void -criteria_selection_changed (GtkTreeSelection *selection, - gpointer data) +struct sort_cases_dialog { - GtkTreeSelection *otherselection ; - struct sort_cases_dialog *dialog = (struct sort_cases_dialog*) data; + GtkTreeView *tv; + PsppireDict *dict; + GtkToggleButton *ascending; +}; - if ( 0 == gtk_tree_selection_count_selected_rows(selection) ) - return ; - - otherselection = gtk_tree_view_get_selection(dialog->dict_view); - - gtk_arrow_set(dialog->arrow, GTK_ARROW_LEFT, GTK_SHADOW_OUT); - dialog->button_state = VAR_DESELECT; - - gtk_tree_selection_unselect_all(otherselection); -} - -/* Occurs when the dialog box is deleted (eg: closed via the title bar) */ -static gint -delete_event_callback(GtkWidget *widget, - GdkEvent *event, - gpointer data) +static gboolean +dialog_state_valid (gpointer data) { - struct sort_cases_dialog *dialog = (struct sort_cases_dialog*) data; - - g_main_loop_quit(dialog->loop); + struct sort_cases_dialog *scd = data; + GtkTreeModel *model = gtk_tree_view_get_model (scd->tv); - gtk_widget_hide_on_delete(widget); + gint n_rows = gtk_tree_model_iter_n_children (model, NULL); - dialog->response = GTK_RESPONSE_DELETE_EVENT; + if ( n_rows == 0 ) + return FALSE; return TRUE; } -/* Occurs when the cancel button is clicked */ -static void -sort_cases_cancel_callback(GObject *obj, gpointer data) -{ - struct sort_cases_dialog *dialog = (struct sort_cases_dialog*) data; - - gtk_widget_hide(dialog->window); - - g_main_loop_quit(dialog->loop); - - dialog->response = GTK_RESPONSE_CANCEL; -} - -/* Occurs when the reset button is clicked */ -static void -sort_cases_reset_callback(GObject *obj, gpointer data) -{ - struct sort_cases_dialog *dialog = (struct sort_cases_dialog*) data; - - gtk_arrow_set(dialog->arrow, GTK_ARROW_RIGHT, GTK_SHADOW_OUT); - dialog->button_state = VAR_SELECT; - - gtk_list_store_clear(dialog->criteria_list); -} - - -/* Add variables currently selected in the dictionary tree view to the - list of criteria */ -static void -select_criteria(GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, gpointer data) -{ - GtkTreeIter new_iter; - gint index; - gint dir; - struct variable *variable; - struct sort_cases_dialog *dialog = (struct sort_cases_dialog*) data; - - /* Get the variable from the dictionary */ - gtk_tree_model_get (model, iter, - DICT_TVM_COL_VAR, &variable, - -1); - - index = var_get_dict_index (variable); - - dir = gtk_toggle_button_get_active (dialog->ascending_button) ? - SRT_ASCEND:SRT_DESCEND; - - /* Append to the list of criteria */ - gtk_list_store_append(dialog->criteria_list, &new_iter); - gtk_list_store_set(dialog->criteria_list, - &new_iter, CRIT_TVM_IDX, index, -1); - gtk_list_store_set(dialog->criteria_list, - &new_iter, CRIT_TVM_DIR, dir, -1); -} - -/* Create a list of the RowRefs which are to be removed from the - criteria list */ -static void -path_to_row_ref(GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, gpointer data) -{ - GList **rrlist = data; - GtkTreeRowReference *rowref = gtk_tree_row_reference_new(model, path); - - *rrlist = g_list_append(*rrlist, rowref); -} - - -/* Remove a row from the list of criteria */ -static void -deselect_criteria(gpointer data, - gpointer user_data) -{ - GtkTreeIter iter; - GtkTreeRowReference *row_ref = data; - GtkTreePath *path; - struct sort_cases_dialog *dialog = (struct sort_cases_dialog*) user_data; - - path = gtk_tree_row_reference_get_path(row_ref); - - gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->criteria_list), &iter, path); - - gtk_list_store_remove(dialog->criteria_list, &iter); - - gtk_tree_row_reference_free(row_ref); -} - - - -/* Callback which occurs when the button to remove variables from the list - of criteria is clicked. */ -static void -sort_cases_button_callback(GObject *obj, gpointer data) +static char * +generate_syntax (const struct sort_cases_dialog *scd) { - struct sort_cases_dialog *dialog = (struct sort_cases_dialog*) data; + gchar *text; + GString *string = g_string_new ("SORT CASES BY "); + gint n_vars = append_variable_names (string, + scd->dict, GTK_TREE_VIEW (scd->tv), 0); - if ( dialog->button_state == VAR_SELECT) /* Right facing arrow */ + if ( n_vars == 0 ) + g_string_assign (string, ""); + else { - GtkTreeSelection *selection = - gtk_tree_view_get_selection(dialog->dict_view); - - gtk_tree_selection_selected_foreach(selection, select_criteria, dialog); + const char up_down = + gtk_toggle_button_get_active (scd->ascending) ? 'A' : 'D'; + g_string_append_printf (string, "(%c)", up_down); + g_string_append (string, "."); } - else /* Left facing arrow */ - { - GList *selectedRows = NULL; - GtkTreeSelection *selection = - gtk_tree_view_get_selection(dialog->criteria_view); - - /* Make a list of rows to be deleted */ - gtk_tree_selection_selected_foreach(selection, path_to_row_ref, - &selectedRows); - /* ... and delete them */ - g_list_foreach(selectedRows, deselect_criteria, dialog); - g_list_free(selectedRows); - } -} + text = string->str; + g_string_free (string, FALSE); -/* Callback which occurs when the OK button is clicked */ -static void -sort_cases_ok_callback(GObject *obj, gpointer data) -{ - struct sort_cases_dialog *dialog = (struct sort_cases_dialog*) data; - - gtk_widget_hide(dialog->window); - g_main_loop_quit(dialog->loop); - - dialog->response = GTK_RESPONSE_OK; + return text; } -/* This function is responsible for rendering a criterion in the - criteria list */ -static void -criteria_render_func(GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *model, GtkTreeIter *iter, - gpointer data) +/* Pops up the Sort Cases dialog box */ +void +sort_cases_dialog (GObject *o, gpointer data) { - gint var_index; - struct variable *variable ; - gint direction; - gchar *buf; - gchar *varname; - PsppireDict *dict = data; - - gtk_tree_model_get(model, iter, - CRIT_TVM_IDX, &var_index, - CRIT_TVM_DIR, &direction, -1); - - variable = psppire_dict_get_variable(dict, var_index); - - varname = pspp_locale_to_utf8 (var_get_name(variable), - -1, 0); - - if ( direction == SRT_ASCEND) - buf = g_strdup_printf("%s: %s", varname, _("Ascending")); - else - buf = g_strdup_printf("%s: %s", varname, _("Descending")); - - g_free(varname); - - g_object_set(renderer, "text", buf, NULL); - - g_free(buf); -} - - -/* Create the dialog */ -struct sort_cases_dialog * -sort_cases_dialog_create(GladeXML *xml) -{ - struct sort_cases_dialog *dialog = g_malloc(sizeof(*dialog)); - - dialog->loop = g_main_loop_new(NULL, FALSE); - - dialog->window = get_widget_assert(xml, "sort-cases-dialog"); - - dialog->dict_view = GTK_TREE_VIEW(get_widget_assert - (xml, "sort-cases-treeview-dict")); - dialog->criteria_view = GTK_TREE_VIEW(get_widget_assert - (xml, "sort-cases-treeview-criteria")); - - dialog->arrow = GTK_ARROW(get_widget_assert(xml, "sort-cases-arrow")); - dialog->button = GTK_BUTTON(get_widget_assert(xml, "sort-cases-button")); - - dialog->ascending_button = - GTK_TOGGLE_BUTTON(get_widget_assert(xml, "sort-cases-button-ascending")); - - g_signal_connect(dialog->window, "delete-event", - G_CALLBACK(delete_event_callback), dialog); - - g_signal_connect(get_widget_assert(xml, "sort-cases-cancel"), - "clicked", G_CALLBACK(sort_cases_cancel_callback), dialog); - - g_signal_connect(get_widget_assert(xml, "sort-cases-ok"), - "clicked", G_CALLBACK(sort_cases_ok_callback), dialog); + gint response; + PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data); + struct sort_cases_dialog scd; - g_signal_connect(get_widget_assert(xml, "sort-cases-reset"), - "clicked", G_CALLBACK(sort_cases_reset_callback), dialog); + GtkBuilder *xml = builder_new ("psppire.ui"); + GtkWidget *dialog = get_widget_assert (xml, "sort-cases-dialog"); - g_signal_connect(get_widget_assert(xml, "sort-cases-button"), - "clicked", G_CALLBACK(sort_cases_button_callback), dialog); + GtkWidget *source = get_widget_assert (xml, "sort-cases-treeview1"); + GtkWidget *selector = get_widget_assert (xml, "sort-cases-selector"); + GtkWidget *dest = get_widget_assert (xml, "sort-cases-treeview2"); - { - /* Set up the dictionary treeview */ - GtkTreeViewColumn *col; + PsppireVarStore *vs = NULL; - GtkTreeSelection *selection = - gtk_tree_view_get_selection(dialog->dict_view); + g_object_get (de->data_editor, "var-store", &vs, NULL); - GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); + gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de)); - col = gtk_tree_view_column_new_with_attributes(_("Var"), - renderer, - "text", - 0, - NULL); + g_object_get (vs, "dictionary", &scd.dict, NULL); + g_object_set (source, "dictionary", scd.dict, NULL); - /* FIXME: make this a value in terms of character widths */ - g_object_set(col, "min-width", 100, NULL); + set_dest_model (GTK_TREE_VIEW (dest), scd.dict); - gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED); + psppire_selector_set_subjects (PSPPIRE_SELECTOR (selector), + source, + dest, + insert_source_row_into_tree_view, + NULL, + NULL); - gtk_tree_view_append_column(dialog->dict_view, col); + g_signal_connect (dialog, "refresh", G_CALLBACK (refresh), dest); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); + scd.tv = GTK_TREE_VIEW (dest); + scd.ascending = + GTK_TOGGLE_BUTTON (get_widget_assert (xml, "sort-cases-radiobutton0")); - g_signal_connect(selection, "changed", - G_CALLBACK(dictionary_selection_changed), dialog); - } - { - /* Set up the variable list treeview */ - GtkTreeSelection *selection = - gtk_tree_view_get_selection(dialog->criteria_view); + psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog), + dialog_state_valid, &scd); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); - dialog->crit_renderer = gtk_cell_renderer_text_new(); + response = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); - dialog->crit_col = gtk_tree_view_column_new_with_attributes(_("Criteria"), - dialog->crit_renderer, - "text", - 0, - NULL); - gtk_tree_view_column_set_sizing (dialog->crit_col, GTK_TREE_VIEW_COLUMN_FIXED); - - gtk_tree_view_append_column(GTK_TREE_VIEW(dialog->criteria_view), - dialog->crit_col); - - g_signal_connect(selection, "changed", - G_CALLBACK(criteria_selection_changed), dialog); - } - - { - /* Create the list of criteria */ - dialog->criteria_list = gtk_list_store_new(2, - G_TYPE_INT, /* index of the variable */ - G_TYPE_INT /* Ascending/Descending */ - ); - - gtk_tree_view_set_model(dialog->criteria_view, - GTK_TREE_MODEL(dialog->criteria_list)); - } - - dialog->response = GTK_RESPONSE_NONE; - - return dialog; -} - - -static void -convert_list_store_to_criteria(GtkListStore *list, - PsppireDict *dict, - struct sort_criteria *criteria); - - -/* Run the dialog. - If the return value is GTK_RESPONSE_OK, then CRITERIA gets filled - with a valid sort criteria which can be used to sort the data. - This structure and its contents must be freed by the caller. */ -gint -sort_cases_dialog_run(struct sort_cases_dialog *dialog, - PsppireDict *dict, - struct sort_criteria *criteria - ) -{ - g_assert(! g_main_loop_is_running(dialog->loop)); - - gtk_tree_view_set_model(GTK_TREE_VIEW(dialog->dict_view), - GTK_TREE_MODEL(dict)); - - - gtk_tree_view_column_set_cell_data_func(dialog->crit_col, - dialog->crit_renderer, - criteria_render_func, dict, 0); - - gtk_list_store_clear(dialog->criteria_list); - - gtk_arrow_set(dialog->arrow, GTK_ARROW_RIGHT, GTK_SHADOW_OUT); - dialog->button_state = VAR_SELECT; - - gtk_widget_show(dialog->window); - - g_main_loop_run(dialog->loop); - - if ( GTK_RESPONSE_OK == dialog->response) - convert_list_store_to_criteria(dialog->criteria_list, - dict, criteria); - - return dialog->response; -} - - - -/* Convert the GtkListStore to a struct sort_criteria*/ -static void -convert_list_store_to_criteria(GtkListStore *list, - PsppireDict *dict, - struct sort_criteria *criteria) -{ - GtkTreeIter iter; - gboolean valid; - gint n = 0; - - GtkTreeModel *model = GTK_TREE_MODEL(list); - - criteria->crit_cnt = gtk_tree_model_iter_n_children (model, NULL); - - criteria->crits = g_malloc(sizeof(struct sort_criterion) * - criteria->crit_cnt); - - for(valid = gtk_tree_model_get_iter_first(model, &iter); - valid; - valid = gtk_tree_model_iter_next(model, &iter)) + switch (response) { - struct variable *variable; - gint index; - struct sort_criterion *scn = &criteria->crits[n]; - g_assert ( n < criteria->crit_cnt); - n++; - - gtk_tree_model_get(model, &iter, - CRIT_TVM_IDX, &index, - CRIT_TVM_DIR, &scn->dir, - -1); - - variable = psppire_dict_get_variable(dict, index); - - scn->fv = var_get_case_index (variable); - scn->width = var_get_width(variable); + case GTK_RESPONSE_OK: + { + gchar *syntax = generate_syntax (&scd); + + struct getl_interface *sss = create_syntax_string_source (syntax); + execute_syntax (sss); + + g_free (syntax); + } + break; + case PSPPIRE_RESPONSE_PASTE: + { + gchar *syntax = generate_syntax (&scd); + paste_syntax_in_new_window (syntax); + + g_free (syntax); + } + break; + default: + break; } + + g_object_unref (xml); }