X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fui%2Fgui%2Fvar-type-dialog.c;h=c6e0ca24d2ec9965b6bdd25d797bddbe2cecc166;hb=514d9af1f690c316a5ad501aa0083ba6c1e00e56;hp=f5533b46115e8503c90a42bd40c2600ca25c56ea;hpb=d331e87bf86af44e0bda66a12dd33670c30e7b50;p=pspp diff --git a/src/ui/gui/var-type-dialog.c b/src/ui/gui/var-type-dialog.c index f5533b4611..c6e0ca24d2 100644 --- a/src/ui/gui/var-type-dialog.c +++ b/src/ui/gui/var-type-dialog.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2005, 2006, 2010, 2011, 2012 Free Software Foundation + Copyright (C) 2005, 2006, 2010, 2011, 2012, 2015, 2020 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 @@ -29,8 +29,13 @@ #include "data/variable.h" #include "libpspp/message.h" #include "ui/gui/builder-wrapper.h" +#include "ui/gui/psppire-format.h" #include "ui/gui/var-type-dialog.h" +#include +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + static const struct fmt_spec date_format[] = { {FMT_DATE, 11, 0}, @@ -50,7 +55,9 @@ static const struct fmt_spec date_format[] = {FMT_WKYR, 10, 0}, {FMT_WKYR, 8, 0}, {FMT_DATETIME, 17, 0}, - {FMT_DATETIME, 20, 0} + {FMT_DATETIME, 20, 0}, + {FMT_YMDHMS, 16, 0}, + {FMT_YMDHMS, 20, 0} }; @@ -79,6 +86,12 @@ static const int cc_format[] = FMT_CCE, }; +static GObject *psppire_var_type_dialog_constructor (GType type, guint, + GObjectConstructParam *); +static void psppire_var_type_dialog_set_state (PsppireVarTypeDialog *); + +static void psppire_var_type_dialog_set_format (PsppireVarTypeDialog *dialog, + const struct fmt_spec *format); static int find_format (const struct fmt_spec *target, const struct fmt_spec formats[], int n_formats); @@ -86,25 +99,147 @@ static int find_format_type (int target, const int types[], int n_types); static void select_treeview_at_index (GtkTreeView *, int index); -static void update_width_decimals (const struct var_type_dialog *); -static void refresh_active_button (struct var_type_dialog *); +static void update_width_decimals (const PsppireVarTypeDialog *); +static void refresh_active_button (PsppireVarTypeDialog *); static void on_active_button_change (GtkToggleButton *, - struct var_type_dialog *); -static void on_width_changed (GtkEntry *, struct var_type_dialog *); -static void on_decimals_changed (GtkEntry *, struct var_type_dialog *); + PsppireVarTypeDialog *); +static void on_width_changed (GtkEntry *, PsppireVarTypeDialog *); +static void on_decimals_changed (GtkEntry *, PsppireVarTypeDialog *); + +G_DEFINE_TYPE (PsppireVarTypeDialog, + psppire_var_type_dialog, + PSPPIRE_TYPE_DIALOG); + +enum + { + PROP_0, + PROP_FORMAT + }; + +static void +psppire_var_type_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + PsppireVarTypeDialog *obj = PSPPIRE_VAR_TYPE_DIALOG (object); + + switch (prop_id) + { + case PROP_FORMAT: + psppire_var_type_dialog_set_format (obj, g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +psppire_var_type_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + PsppireVarTypeDialog *obj = PSPPIRE_VAR_TYPE_DIALOG (object); + + switch (prop_id) + { + case PROP_FORMAT: + g_value_set_boxed (value, &obj->fmt_l); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +psppire_var_type_dialog_set_format (PsppireVarTypeDialog *dialog, + const struct fmt_spec *format) +{ + dialog->base_format = *format; + psppire_var_type_dialog_set_state (dialog); +} + +static const struct fmt_spec * +psppire_var_type_dialog_get_format (const PsppireVarTypeDialog *dialog) +{ + return &dialog->fmt_l; +} + +static void +psppire_var_type_dialog_init (PsppireVarTypeDialog *obj) +{ + /* We do all of our work on widgets in the constructor function, because that + runs after the construction properties have been set. Otherwise + PsppireDialog's "orientation" property hasn't been set and therefore we + have no box to populate. */ + obj->base_format = F_8_0; + obj->fmt_l = F_8_0; +} + +static void +psppire_var_type_dialog_class_init (PsppireVarTypeDialogClass *class) +{ + GObjectClass *gobject_class; + gobject_class = G_OBJECT_CLASS (class); + + gobject_class->constructor = psppire_var_type_dialog_constructor; + gobject_class->set_property = psppire_var_type_dialog_set_property; + gobject_class->get_property = psppire_var_type_dialog_get_property; + + g_object_class_install_property ( + gobject_class, PROP_FORMAT, + g_param_spec_boxed ("format", + "Format", + "The format being edited.", + PSPPIRE_TYPE_FORMAT, + G_PARAM_READABLE | G_PARAM_WRITABLE)); +} + +PsppireVarTypeDialog * +psppire_var_type_dialog_new (const struct fmt_spec *format) +{ + return PSPPIRE_VAR_TYPE_DIALOG ( + g_object_new (PSPPIRE_TYPE_VAR_TYPE_DIALOG, + "format", format, + NULL)); +} + +gint +psppire_var_type_dialog_run (GtkWindow *parent_window, + struct fmt_spec *format) +{ + PsppireVarTypeDialog *dialog; + + dialog = psppire_var_type_dialog_new (format); + gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + gtk_widget_show (GTK_WIDGET (dialog)); + + gint result = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); + if (result == GTK_RESPONSE_OK) + *format = *psppire_var_type_dialog_get_format (dialog); + + gtk_widget_destroy (GTK_WIDGET (dialog)); + + return result; +} + /* callback for when any of the radio buttons are toggled */ static void on_toggle (GtkToggleButton *togglebutton, gpointer dialog_) { - struct var_type_dialog *dialog = dialog_; + PsppireVarTypeDialog *dialog = dialog_; - if ( gtk_toggle_button_get_active (togglebutton) == TRUE) + if (gtk_toggle_button_get_active (togglebutton) == TRUE) refresh_active_button (dialog); } static void -refresh_active_button (struct var_type_dialog *dialog) +refresh_active_button (PsppireVarTypeDialog *dialog) { int i; @@ -127,7 +262,7 @@ refresh_active_button (struct var_type_dialog *dialog) } static void -update_adj_ranges (struct var_type_dialog *dialog) +update_adj_ranges (PsppireVarTypeDialog *dialog) { enum fmt_type type = dialog->fmt_l.type; const enum fmt_use use = FMT_FOR_OUTPUT; @@ -149,7 +284,7 @@ update_adj_ranges (struct var_type_dialog *dialog) /* callback for when any of the radio buttons are toggled */ static void on_active_button_change (GtkToggleButton *togglebutton, - struct var_type_dialog *dialog) + PsppireVarTypeDialog *dialog) { enum widgets { W_WIDTH = 1 << 0, @@ -203,7 +338,7 @@ on_active_button_change (GtkToggleButton *togglebutton, gtk_widget_set_visible (dialog->dollar_window, (widgets & W_DOLLAR_FORMATS) != 0); - dialog->fmt_l = *var_get_print_format (dialog->pv); + dialog->fmt_l = dialog->base_format; switch (dialog->active_button) { @@ -247,12 +382,6 @@ on_active_button_change (GtkToggleButton *togglebutton, update_width_decimals (dialog); } - - -static gint on_var_type_ok_clicked (GtkWidget *w, gpointer data); -static gint hide_dialog (GtkWidget *w, gpointer data); - - static void add_to_group (GtkWidget *w, gpointer data) { @@ -263,14 +392,14 @@ add_to_group (GtkWidget *w, gpointer data) /* Set the local width and decimals entry boxes to reflec the local format */ static void -update_width_decimals (const struct var_type_dialog *dialog) +update_width_decimals (const PsppireVarTypeDialog *dialog) { gtk_adjustment_set_value (dialog->adj_width, dialog->fmt_l.w); gtk_adjustment_set_value (dialog->adj_decimals, dialog->fmt_l.d); } static void -on_width_changed (GtkEntry *entry, struct var_type_dialog *dialog) +on_width_changed (GtkEntry *entry, PsppireVarTypeDialog *dialog) { int w = atoi (gtk_entry_get_text (GTK_ENTRY (dialog->entry_width))); fmt_change_width (&dialog->fmt_l, w, FMT_FOR_OUTPUT); @@ -278,7 +407,7 @@ on_width_changed (GtkEntry *entry, struct var_type_dialog *dialog) } static void -on_decimals_changed (GtkEntry *entry, struct var_type_dialog *dialog) +on_decimals_changed (GtkEntry *entry, PsppireVarTypeDialog *dialog) { int d = atoi (gtk_entry_get_text (GTK_ENTRY (dialog->entry_decimals))); fmt_change_decimals (&dialog->fmt_l, d, FMT_FOR_OUTPUT); @@ -292,9 +421,9 @@ preview_custom (GtkWidget *w, gpointer data) { const gchar *text ; - struct var_type_dialog *dialog = data; + PsppireVarTypeDialog *dialog = data; - if ( dialog->active_button != BUTTON_CUSTOM ) + if (dialog->active_button != BUTTON_CUSTOM) return; text = gtk_entry_get_text (GTK_ENTRY (dialog->entry_decimals)); @@ -304,7 +433,7 @@ preview_custom (GtkWidget *w, gpointer data) dialog->fmt_l.w = atoi (text); msg_disable (); - if ( ! fmt_check_output (&dialog->fmt_l)) + if (! fmt_check_output (&dialog->fmt_l)) { gtk_label_set_text (GTK_LABEL (dialog->label_psample), "---"); gtk_label_set_text (GTK_LABEL (dialog->label_nsample), "---"); @@ -336,6 +465,9 @@ get_index_from_treeview (GtkTreeView *treeview) GtkTreeIter iter; gint index; + if (selection == NULL) + return -1; + gtk_tree_selection_get_selected (selection, &model, &iter); path = gtk_tree_model_get_path (model, &iter); if (!path || gtk_tree_path_get_depth (path) < 1) @@ -351,50 +483,73 @@ get_index_from_treeview (GtkTreeView *treeview) It sets the fmt_l_spec to reflect the selected format */ static void set_date_format_from_treeview (GtkTreeView *treeview, - struct var_type_dialog *dialog) + PsppireVarTypeDialog *dialog) { - dialog->fmt_l = date_format[get_index_from_treeview (treeview)]; + gint idx = get_index_from_treeview (treeview); + if (idx < 0) + return; + + dialog->fmt_l = date_format[idx]; } /* Callback for when a dollar treeview row is changed. It sets the fmt_l_spec to reflect the selected format */ static void set_dollar_format_from_treeview (GtkTreeView *treeview, - struct var_type_dialog *dialog) + PsppireVarTypeDialog *dialog) { - dialog->fmt_l = dollar_format[get_index_from_treeview (treeview)]; + gint idx = get_index_from_treeview (treeview); + if (idx < 0) + return; + + dialog->fmt_l = dollar_format[idx]; } /* Callback for when a treeview row is changed. It sets the type of the fmt_l to reflect the selected type */ static void set_custom_format_from_treeview (GtkTreeView *treeview, - struct var_type_dialog *dialog) + PsppireVarTypeDialog *dialog) { - dialog->fmt_l.type = cc_format[get_index_from_treeview (treeview)]; + gint idx = get_index_from_treeview (treeview); + if (idx < 0) + return; + + dialog->fmt_l.type = cc_format[idx]; update_adj_ranges (dialog); fmt_fix_output (&dialog->fmt_l); update_width_decimals (dialog); } /* Create the structure */ -struct var_type_dialog * -var_type_dialog_create (GtkWindow *toplevel) +static GObject * +psppire_var_type_dialog_constructor (GType type, + guint n_properties, + GObjectConstructParam *properties) { + PsppireVarTypeDialog *dialog; + GtkContainer *content_area; + GtkBuilder *xml; + GObject *obj; gint i; - struct var_type_dialog *dialog = g_malloc (sizeof (struct var_type_dialog)); - GtkBuilder *xml = builder_new ("var-type-dialog.ui"); + obj = G_OBJECT_CLASS (psppire_var_type_dialog_parent_class)->constructor ( + type, n_properties, properties); + dialog = PSPPIRE_VAR_TYPE_DIALOG (obj); - dialog->window = get_widget_assert (xml,"var_type_dialog"); - dialog->active_button = -1; + g_object_set (dialog, "help-page", "Input-and-Output-Formats", + "title", _("Variable Type and Format"), NULL); + xml = builder_new ("var-type-dialog.ui"); - g_signal_connect (dialog->window, "delete-event", - G_CALLBACK (gtk_widget_hide_on_delete), NULL); + content_area = GTK_CONTAINER (PSPPIRE_DIALOG (dialog)); + gtk_container_add (GTK_CONTAINER (content_area), + get_widget_assert (xml, "var-type-dialog")); + + dialog->active_button = -1; - gtk_window_set_transient_for (GTK_WINDOW (dialog->window), - toplevel); + g_signal_connect (dialog, "delete-event", + G_CALLBACK (gtk_widget_hide_on_delete), NULL); dialog->radioButton[BUTTON_NUMERIC] = get_widget_assert (xml,"radiobutton1"); @@ -439,8 +594,6 @@ var_type_dialog_create (GtkWindow *toplevel) GTK_TREE_VIEW (get_widget_assert (xml, "custom_treeview")); - dialog->ok = get_widget_assert (xml,"var_type_ok"); - { GtkTreeIter iter; @@ -459,7 +612,7 @@ var_type_dialog_create (GtkWindow *toplevel) add_to_group, sizeGroup); - for (i = 0 ; i < num_BUTTONS; ++i ) + for (i = 0 ; i < num_BUTTONS; ++i) g_signal_connect (dialog->radioButton[i], "toggled", G_CALLBACK (on_toggle), dialog); @@ -481,7 +634,7 @@ var_type_dialog_create (GtkWindow *toplevel) list_store = gtk_list_store_new (1, G_TYPE_STRING); - for ( i = 0 ; i < sizeof (date_format) / sizeof (date_format[0]) ; ++i ) + for (i = 0 ; i < sizeof (date_format) / sizeof (date_format[0]) ; ++i) { const struct fmt_spec *f = &date_format[i]; gtk_list_store_append (list_store, &iter); @@ -515,7 +668,7 @@ var_type_dialog_create (GtkWindow *toplevel) list_store = gtk_list_store_new (1, G_TYPE_STRING); - for ( i = 0 ; i < sizeof (dollar_format)/sizeof (dollar_format[0]) ; ++i ) + for (i = 0 ; i < sizeof (dollar_format)/sizeof (dollar_format[0]) ; ++i) { char *template = settings_dollar_template (&dollar_format[i]); gtk_list_store_append (list_store, &iter); @@ -555,7 +708,7 @@ var_type_dialog_create (GtkWindow *toplevel) list_store = gtk_list_store_new (1, G_TYPE_STRING); - for ( i = 0 ; i < 5 ; ++i ) + for (i = 0 ; i < 5 ; ++i) { enum fmt_type cc_fmts[5] = {FMT_CCA, FMT_CCB, FMT_CCC, FMT_CCD, FMT_CCE}; gtk_list_store_append (list_store, &iter); @@ -594,27 +747,19 @@ var_type_dialog_create (GtkWindow *toplevel) "changed", G_CALLBACK (preview_custom), dialog); - - /* Connect to the OK button */ - g_signal_connect (dialog->ok, "clicked", G_CALLBACK (on_var_type_ok_clicked), - dialog); - - - /* And the cancel button */ - g_signal_connect (get_widget_assert (xml, "var_type_cancel") , "clicked", - G_CALLBACK (hide_dialog), - dialog); } g_object_unref (xml); - return dialog; + psppire_var_type_dialog_set_state (dialog); + + return obj; } /* Set a particular button to be active */ -void -var_type_dialog_set_active_button (struct var_type_dialog *dialog, gint b) +static void +var_type_dialog_set_active_button (PsppireVarTypeDialog *dialog, gint b) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->radioButton[b]), TRUE); @@ -659,15 +804,14 @@ find_format_type (int target, const int types[], int n_types) /* Set up the state of the dialog box to match the variable VAR */ static void -var_type_dialog_set_state (struct var_type_dialog *dialog) +psppire_var_type_dialog_set_state (PsppireVarTypeDialog *dialog) { int button; - g_assert (dialog); - g_assert (dialog->pv); + g_return_if_fail (dialog != NULL); /* Populate the radio button states */ - switch (var_get_print_format (dialog->pv)->type) + switch (dialog->base_format.type) { default: case FMT_F: @@ -694,6 +838,8 @@ var_type_dialog_set_state (struct var_type_dialog *dialog) case FMT_MOYR: case FMT_WKYR: case FMT_DATETIME: + case FMT_YMDHMS: + case FMT_MTIME: case FMT_TIME: case FMT_DTIME: case FMT_WKDAY: @@ -714,43 +860,3 @@ var_type_dialog_set_state (struct var_type_dialog *dialog) on_active_button_change (GTK_TOGGLE_BUTTON (dialog->radioButton[button]), dialog); } - - -/* Popup the dialog box */ -void -var_type_dialog_show (struct var_type_dialog *dialog) -{ - var_type_dialog_set_state (dialog); - - gtk_widget_show (dialog->window); -} - -/* Callbacks for the Variable Type Dialog Box */ - -/* Callback for when the var type dialog is closed using the OK button. - It sets the appropriate variable accordingly. */ -static gint -on_var_type_ok_clicked (GtkWidget *w, gpointer data) -{ - struct var_type_dialog *dialog = data; - - var_set_width (dialog->pv, fmt_var_width (&dialog->fmt_l)); - var_set_both_formats (dialog->pv, &dialog->fmt_l); - - gtk_widget_hide (dialog->window); - - return FALSE; -} - - - -static gint -hide_dialog (GtkWidget *w, gpointer data) -{ - struct var_type_dialog *dialog = data; - - gtk_widget_hide (dialog->window); - - return FALSE; -} -