treewide: Use struct fmt_spec by value instead of pointer in most cases.
[pspp] / src / ui / gui / psppire-var-info.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2020, 2021 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <gtk/gtk.h>
19
20 #include "psppire-var-info.h"
21 #include "data/value-labels.h"
22 #include "data/variable.h"
23
24 #include "gettext.h"
25 #define _(msgid) gettext (msgid)
26 #define N_(msgid) msgid
27
28 G_DEFINE_TYPE (PsppireVarInfo, psppire_var_info, GTK_TYPE_GRID);
29
30 static void
31 psppire_var_info_dispose (GObject *obj)
32 {
33   PsppireVarInfo *var_info = PSPPIRE_VAR_INFO (obj);
34
35   if (var_info->dispose_has_run)
36     return;
37   var_info->dispose_has_run = TRUE;
38
39   G_OBJECT_CLASS (psppire_var_info_parent_class)->dispose (obj);
40 }
41
42 static const char *field_labels[n_VAR_INFO] =
43   {
44    N_("Name"),
45    N_("Label"),
46    N_("Position"),
47    N_("Measurement Level"),
48    N_("Role"),
49    N_("Width"),
50    N_("Alignment"),
51    N_("Print Format"),
52    N_("Write Format"),
53    N_("Missing Values"),
54    N_("Value Labels")
55   };
56
57
58 void
59 psppire_var_info_init (PsppireVarInfo *var_info)
60 {
61   g_object_set (var_info,
62                 "row-spacing", 3,
63                 "column-spacing", 3,
64                 "margin", 5,
65                 NULL);
66
67   for (int r = 0; r < n_VAR_INFO; ++r)
68     {
69       GtkWidget *label = gtk_label_new (gettext (field_labels[r]));
70       g_object_set (label,
71                     "halign", GTK_ALIGN_START,
72                     NULL);
73
74       gtk_grid_attach (GTK_GRID (var_info), label, 0, r, 1, 1);
75       gtk_widget_show (label);
76
77       if (r >= n_VAR_INFO - 1)
78         break;
79
80       var_info->entry[r] = gtk_entry_new ();
81
82       g_object_set (var_info->entry[r],
83                     "visible", TRUE,
84                     "double-buffered", FALSE,
85                     "hexpand", TRUE,
86                     "editable", FALSE,
87                     NULL);
88
89       gtk_grid_attach (GTK_GRID (var_info), var_info->entry[r], 1, r, 1, 1);
90     }
91
92   var_info->combo = gtk_combo_box_text_new_with_entry ();
93   GtkWidget *entry = gtk_bin_get_child (GTK_BIN (var_info->combo));
94   g_object_set (entry, "editable", FALSE, NULL);
95   gtk_widget_show (var_info->combo);
96
97   gtk_grid_attach (GTK_GRID (var_info), var_info->combo, 1, n_VAR_INFO - 1, 1, 1);
98 }
99
100 GtkWidget*
101 psppire_var_info_new (void)
102 {
103   return GTK_WIDGET (g_object_new (psppire_var_info_get_type (), NULL));
104 }
105
106
107 enum
108   {
109     PROP_0,
110     PROP_VARIABLE,
111   };
112
113 static void
114 __set_property (GObject      *object,
115                 guint         prop_id,
116                 const GValue *value,
117                 GParamSpec   *pspec)
118 {
119   PsppireVarInfo *var_info = PSPPIRE_VAR_INFO (object);
120
121   switch (prop_id)
122     {
123     case PROP_VARIABLE:
124       {
125         gtk_combo_box_text_remove_all (GTK_COMBO_BOX_TEXT (var_info->combo));
126         gtk_combo_box_set_active  (GTK_COMBO_BOX (var_info->combo), 0);
127         GtkWidget *entry = gtk_bin_get_child (GTK_BIN (var_info->combo));
128         gtk_entry_set_text (GTK_ENTRY (entry), "");
129
130         const struct variable *var = g_value_get_pointer (value);
131         if (var == NULL)
132           {
133             for (int i = 0; i < n_VAR_INFO - 1; ++i)
134               {
135                 gtk_entry_set_text (GTK_ENTRY (var_info->entry[i]), "");
136               }
137             gtk_combo_box_set_active  (GTK_COMBO_BOX (var_info->combo), -1);
138             return;
139           }
140
141         char *str = NULL;
142         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_NAME]),
143                             var_get_name (var));
144
145         str = g_strdup_printf ("%ld", var_get_dict_index (var));
146         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_POSITION]),
147                             str);
148         g_free (str);
149
150         const char *label = var_get_label (var);
151         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_LABEL]),
152                             label ? label : "");
153
154         str = g_strdup_printf ("%d", var_get_width (var));
155         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_WIDTH]),
156                             str);
157         g_free (str);
158
159         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_MEASUREMENT_LEVEL]),
160                             measure_to_string (var_get_measure (var)));
161
162         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_ROLE]),
163                             var_role_to_string (var_get_role (var)));
164
165         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_ALIGNMENT]),
166                             alignment_to_string (var_get_alignment (var)));
167
168         struct fmt_spec pf = var_get_print_format (var);
169         char xx[FMT_STRING_LEN_MAX + 1];
170         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_PRINT_FORMAT]),
171                             fmt_to_string (pf, xx));
172
173         struct fmt_spec wf = var_get_write_format (var);
174         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_WRITE_FORMAT]),
175                             fmt_to_string (wf, xx));
176
177         const struct missing_values *mv = var_get_missing_values (var);
178         str = mv_to_string (mv, "UTF-8");
179         gtk_entry_set_text (GTK_ENTRY (var_info->entry[VAR_INFO_MISSING_VALUES]),
180                             str ? str : "");
181         g_free (str);
182
183         const struct val_labs *vls = var_get_value_labels (var);
184         if (vls)
185           {
186             for (const struct val_lab *vl = val_labs_first (vls);
187                  vl;
188                  vl = val_labs_next (vls, vl))
189               {
190                 struct string text;
191                 ds_init_empty (&text);
192
193                 const char *l = val_lab_get_label (vl);
194                 const union value *v = val_lab_get_value (vl);
195
196                 var_append_value_name__ (var, v, SETTINGS_VALUE_SHOW_VALUE, &text);
197                 ds_put_cstr (&text, ": ");
198                 ds_put_cstr (&text, l);
199
200                 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (var_info->combo), ds_cstr (&text));
201                 gtk_combo_box_set_active  (GTK_COMBO_BOX (var_info->combo), 0);
202               }
203           }
204       }
205       break;
206
207     default:
208       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
209       break;
210     }
211 }
212
213 static void
214 __get_property (GObject      *object,
215                 guint         prop_id,
216                 GValue       *value,
217                 GParamSpec   *pspec)
218 {
219   switch (prop_id)
220     {
221     default:
222       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
223       break;
224     }
225 }
226
227
228 static void
229 psppire_var_info_class_init (PsppireVarInfoClass *class)
230 {
231
232   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
233
234
235   gobject_class->set_property = __set_property;
236   gobject_class->get_property = __get_property;
237   gobject_class->dispose = psppire_var_info_dispose;
238
239   g_object_class_install_property (gobject_class, PROP_VARIABLE,
240                                    g_param_spec_pointer
241                                    ("variable",
242                                     "Variable",
243                                     "The variable whose parameters are to be displayed",
244                                     G_PARAM_WRITABLE));
245 }