1 /*
2 * gretl -- Gnu Regression, Econometrics and Time-series Library
3 * Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include "gretl.h"
21 #include "dlgutils.h"
22 #include "dialogs.h"
23 #include "ssheet.h"
24 #include "menustate.h"
25 #include "obsbutton.h"
26 #include "session.h"
27 #include "toolbar.h"
28 #include "datawiz.h"
29
30 #include "gretl_panel.h"
31
32 /* The code here answers to (1) the "/Data/Dataset structure" menu item
33 in the main gretl window; (2) finalize_data_open() in gui_utils.c;
34 and (3) the "/File/New data set" main-window menu item.
35
36 In the first two cases we have a dataset loaded and we're offering
37 the user the chance to impose time-series or panel structure.
38
39 In the third case the dataset will be empty (dataset->n = 0) and
40 we're determining both the size and the stucture of the dataset
41 the user wants to create.
42 */
43
44 #define DWDEBUG 0
45
46 #define PD_SPECIAL -1
47
48 #define known_panel(p) (p->structure == STACKED_CROSS_SECTION || \
49 p->structure == STACKED_TIME_SERIES)
50
51 #define any_panel(p) (p->structure == STACKED_CROSS_SECTION || \
52 p->structure == STACKED_TIME_SERIES || \
53 p->structure == PANEL_UNKNOWN)
54
55 #define time_series(p) (p->structure == TIME_SERIES || \
56 p->structure == SPECIAL_TIME_SERIES)
57
58 /* identifiers for steps in the process of setting
59 dataset structure */
60 enum {
61 DW_SET_TYPE = 0,
62 DW_TS_FREQUENCY,
63 DW_WEEKLY_SELECT,
64 DW_STARTING_OBS,
65 DW_PANEL_MODE,
66 DW_PANEL_SIZE,
67 DW_PANEL_VARS,
68 DW_CONFIRM
69 };
70
71 enum {
72 DW_FORWARD = 0,
73 DW_BACK = 1
74 };
75
76 /* flags that may be set on the dataset options structure */
77 enum {
78 DW_CREATE = 1 << 0,
79 DW_DROPMISS = 1 << 1,
80 DW_N_PRIME = 1 << 2,
81 DW_VLIST_DONE = 1 << 3,
82 DW_NP_DONE = 1 << 4,
83 DW_NO_PANEL = 1 << 5,
84 DW_SSHEET = 1 << 6
85 };
86
87 #define dw_n_is_prime(o) (o->flags & DW_N_PRIME)
88 #define dw_vlist_done(o) (o->flags & DW_VLIST_DONE)
89
90 typedef struct dw_opts_ dw_opts;
91
92 struct dw_opts_ {
93 gretlopt flags; /* state bit-flags */
94 int n_radios; /* number of radio-button options */
95 int deflt; /* default setting for current radio variable */
96 int plf; /* panel: least factor > 1 of # of observations */
97 int uid; /* panel: ID number of "unit" variable */
98 int tid; /* panel: ID number of "period" variable */
99 int *setvar; /* pointer to variable currently being set */
100 int *extra; /* additional pointer to int variable */
101 GtkWidget *pdspin; /* used for setting custom time-series frequency */
102 GList *vlist; /* panel: list of candidates for uid, tid */
103 GtkWidget *dspin[4]; /* dataset dimension setters (new dataset) */
104 int dvals[4]; /* dataset dimension values (new dataset) */
105 };
106
wizcode_string(int code)107 static const char *wizcode_string (int code)
108 {
109 const char *titles[] = {
110 N_("Structure of dataset"),
111 N_("Time series frequency"),
112 N_("Daily date to represent week"),
113 N_("Starting observation"),
114 N_("Panel data organization"),
115 N_("Panel structure"),
116 N_("Panel index variables"),
117 N_("Confirm dataset structure")
118 };
119
120 if (code <= DW_CONFIRM) {
121 return titles[code];
122 } else {
123 return "";
124 }
125 }
126
127 static int translate_panel_vars (dw_opts *opts, int *uv, int *tv);
128
129 /* Initialize the "dummy" DATASET structure @dwinfo, based
130 on the current data info. This will just be a cross-section
131 unless the user has decided to modify an already-structured
132 dataset under /Data/Dataset structure.
133 */
134
dwinfo_init(DATASET * dwinfo)135 static void dwinfo_init (DATASET *dwinfo)
136 {
137 dwinfo->pd = dataset->pd;
138 dwinfo->structure = dataset->structure;
139
140 dwinfo->n = dataset->n;
141 strcpy(dwinfo->stobs, dataset->stobs);
142 strcpy(dwinfo->endobs, dataset->endobs);
143 dwinfo->sd0 = dataset->sd0;
144
145 #if DWDEBUG
146 fprintf(stderr, "dwinfo_init:\n"
147 " pd=%d, structure=%d, sd0=%g, stobs='%s', endobs='%s'\n",
148 dwinfo->pd, dwinfo->structure, dwinfo->sd0,
149 dwinfo->stobs, dwinfo->endobs);
150 #endif
151 }
152
153 /* For the case where the structure wizard is being used
154 to create a new dataset, and the user has chosen to type
155 in some values.
156 */
157
prep_spreadsheet(GtkWidget * widget,dialog_t * dlg)158 static void prep_spreadsheet (GtkWidget *widget, dialog_t *dlg)
159 {
160 GtkWidget *parent = edit_dialog_get_window(dlg);
161 const gchar *buf = edit_dialog_get_text(dlg);
162 int t;
163
164 if (buf == NULL || gui_validate_varname(buf,
165 GRETL_TYPE_SERIES,
166 parent)) {
167 edit_dialog_reset(dlg);
168 return;
169 }
170
171 dataset->varname[1][0] = '\0';
172 strncat(dataset->varname[1], buf, VNAMELEN - 1);
173 edit_dialog_close(dlg);
174
175 /* blank out the auto "index" variable */
176 for (t=0; t<dataset->n; t++) {
177 dataset->Z[1][t] = NADBL;
178 }
179 series_set_label(dataset, 1, "");
180
181 show_spreadsheet(SHEET_NEW_DATASET);
182 }
183
maybe_start_editing(void)184 static void maybe_start_editing (void)
185 {
186 int cancel = 0;
187 gchar *msg;
188
189 msg = g_strdup_printf(_("Enter name for first variable\n"
190 "(max. %d characters)"),
191 VNAMELEN - 1);
192
193 blocking_edit_dialog(CREATE_DATASET, _("gretl: name variable"),
194 msg, NULL, prep_spreadsheet, NULL,
195 VARCLICK_NONE, NULL, &cancel);
196 g_free(msg);
197
198 if (cancel) {
199 /* accept the default blank dataset */
200 register_data(NULLDATA_STARTED);
201 }
202 }
203
204 /* for balanced panel checking */
205
least_factor(int n)206 static int least_factor (int n)
207 {
208 int flim = n;
209 int prime = 1;
210 int factor;
211
212 if (n % 2 == 0) {
213 return 2;
214 }
215
216 for (factor = 3; factor < flim; factor += 2) {
217 if (n % factor == 0) {
218 prime = 0;
219 break;
220 } else {
221 flim = n / factor;
222 }
223 }
224
225 #if DWDEBUG
226 fprintf(stderr, "least factor: prime = %d, factor = %d\n",
227 prime, factor);
228 #endif
229
230 return (prime)? 1 : factor;
231 }
232
233 /* figure out if the dataset contains a prime number of
234 observations */
235
eval_n_is_prime(dw_opts * opts)236 static void eval_n_is_prime (dw_opts *opts)
237 {
238 if (opts->flags & DW_NP_DONE) {
239 return;
240 }
241
242 opts->plf = least_factor(dataset->n);
243
244 if (opts->plf == 1) {
245 opts->flags |= DW_N_PRIME;
246 } else {
247 opts->flags &= ~DW_N_PRIME;
248 }
249
250 opts->flags |= DW_NP_DONE;
251 }
252
maybe_unrestrict_dataset(void)253 static void maybe_unrestrict_dataset (void)
254 {
255 if (complex_subsampled()) {
256 maybe_free_full_dataset(dataset);
257 if (dataset->t1 == 0 &&
258 dataset->t2 == dataset->n - 1) {
259 restore_sample_state(FALSE);
260 }
261 }
262 }
263
264 /* respond to the "Apply" button in the wizard */
265
dwiz_make_changes(DATASET * dwinfo,dw_opts * opts,GtkWidget * dlg)266 static int dwiz_make_changes (DATASET *dwinfo, dw_opts *opts,
267 GtkWidget *dlg)
268 {
269 gchar *setobs_cmd = NULL;
270 gretlopt opt = OPT_NONE;
271 int delmiss = (opts->flags & DW_DROPMISS);
272 int delete_markers = 0;
273 int err = 0;
274
275 #if DWDEBUG
276 fprintf(stderr, "dwiz_make_changes\n");
277 #endif
278
279 /* preliminaries */
280 if (time_series(dwinfo)) {
281 ntolabel(dwinfo->stobs, dwinfo->t1, dwinfo);
282 } else if (known_panel(dwinfo)) {
283 if (!dataset_is_panel(dataset)) {
284 /* Turning a subset of a non-panel dataset into a panel:
285 this change will be irreversible */
286 maybe_unrestrict_dataset();
287 }
288 }
289
290 /* special: reorganizing dataset based on panel index vars */
291 if (dwinfo->structure == PANEL_UNKNOWN) {
292 int uv, tv;
293
294 err = translate_panel_vars(opts, &uv, &tv);
295 if (!err) {
296 err = set_panel_structure_from_vars(uv, tv, dataset);
297 }
298 if (!err) {
299 setobs_cmd = g_strdup_printf("setobs %s %s --panel-vars",
300 dataset->varname[uv],
301 dataset->varname[tv]);
302 }
303 goto finalize;
304 }
305
306 /* check for nothing to be done */
307 if (dwinfo->structure == dataset->structure &&
308 dwinfo->pd == dataset->pd &&
309 strcmp(dwinfo->stobs, dataset->stobs) == 0) {
310 if (delmiss) {
311 /* recording? */
312 goto finalize;
313 } else {
314 infobox(_("No changes were made"));
315 return 0;
316 }
317 }
318
319 /* if converting to time series, we probably don't want to
320 retain any original observation-marker strings */
321 if (dwinfo->structure == TIME_SERIES &&
322 dataset->markers && !delmiss) {
323 delete_markers = 1;
324 }
325
326 /* handle panel structure */
327 if (known_panel(dwinfo)) {
328 int nunits = dwinfo->t1;
329 int nperiods = dataset->n / nunits;
330
331 /* we don't offer a choice of "starting obs" */
332 dwinfo->pd = (dwinfo->structure == STACKED_TIME_SERIES)?
333 nperiods : nunits;
334 strcpy(dwinfo->stobs, "1:1");
335 }
336
337 /* handle conversion to cross-section */
338 if (dwinfo->structure == CROSS_SECTION) {
339 strcpy(dwinfo->stobs, "1");
340 }
341
342 if (dwinfo->structure == TIME_SERIES) {
343 opt = OPT_T;
344 } else if (dwinfo->structure == STACKED_TIME_SERIES) {
345 opt = OPT_S;
346 } else if (dwinfo->structure == STACKED_CROSS_SECTION) {
347 opt = OPT_C;
348 } else if (dwinfo->structure == CROSS_SECTION) {
349 opt = OPT_X;
350 } else if (dwinfo->structure == SPECIAL_TIME_SERIES) {
351 opt = OPT_N;
352 }
353
354 err = simple_set_obs(dataset, dwinfo->pd, dwinfo->stobs, opt);
355
356 #if DWDEBUG
357 fprintf(stderr, "pd=%d, stobs='%s', opt=%d; set_obs returned %d\n",
358 dwinfo->pd, dwinfo->stobs, opt, err);
359 #endif
360
361 if (!err && setobs_cmd == NULL) {
362 setobs_cmd = g_strdup_printf("setobs %d %s%s",
363 dwinfo->pd, dwinfo->stobs,
364 print_flags(opt, SETOBS));
365 }
366
367 finalize:
368
369 if (!err && delmiss) {
370 err = dataset_purge_missing_rows(dataset);
371 }
372
373 if (err) {
374 gui_errmsg(err);
375 } else {
376 if (delete_markers) {
377 dataset_destroy_obs_markers(dataset);
378 }
379 mark_dataset_as_modified();
380 }
381
382 if (!err && setobs_cmd != NULL) {
383 lib_command_strcpy(setobs_cmd);
384 record_command_verbatim();
385 }
386
387 g_free(setobs_cmd);
388
389 #if DWDEBUG
390 fprintf(stderr, "dwiz_make_changes: returning %d\n", err);
391 #endif
392
393 return err;
394 }
395
newdata_nobs(DATASET * dwinfo,dw_opts * opts)396 static int newdata_nobs (DATASET *dwinfo, dw_opts *opts)
397 {
398 if (dwinfo->structure == CROSS_SECTION) {
399 return opts->dvals[0];
400 } else if (dataset_is_time_series(dwinfo)) {
401 return opts->dvals[1];
402 } else {
403 return opts->dvals[2] * opts->dvals[3];
404 }
405 }
406
407 /* alternative to dwiz_make_changes() for use when the existing
408 dataset is empty
409 */
410
dwiz_replace_dataset(DATASET * dwinfo,dw_opts * opts,GtkWidget * dlg)411 static int dwiz_replace_dataset (DATASET *dwinfo, dw_opts *opts,
412 GtkWidget *dlg)
413 {
414 int err, n = newdata_nobs(dwinfo, opts);
415 gretlopt opt = OPT_NONE;
416
417 err = open_nulldata(dataset, data_status, n, OPT_NONE, NULL);
418 if (err) {
419 errbox(_("Failed to create empty data set"));
420 return err;
421 }
422
423 if (time_series(dwinfo)) {
424 ntolabel(dwinfo->stobs, dwinfo->t1, dwinfo);
425 }
426
427 if (dwinfo->structure == TIME_SERIES) {
428 opt = OPT_T;
429 } else if (dwinfo->structure == STACKED_TIME_SERIES) {
430 strcpy(dwinfo->stobs, "1:1");
431 dwinfo->pd = opts->dvals[3];
432 opt = OPT_S;
433 } else if (dwinfo->structure == CROSS_SECTION) {
434 opt = OPT_X;
435 } else if (dwinfo->structure == SPECIAL_TIME_SERIES) {
436 opt = OPT_N;
437 }
438
439 err = simple_set_obs(dataset, dwinfo->pd, dwinfo->stobs, opt);
440
441 if (opts->flags & DW_SSHEET) {
442 gtk_widget_hide(dlg);
443 maybe_start_editing();
444 } else {
445 register_data(NULLDATA_STARTED);
446 lib_command_sprintf("nulldata %d", dataset->n);
447 record_command_verbatim();
448 lib_command_sprintf("setobs %d %s%s", dwinfo->pd,
449 dwinfo->stobs, print_flags(opt, SETOBS));
450 record_command_verbatim();
451 }
452
453 return err;
454 }
455
456 #define TS_INFO_MAX 10
457 #define PANEL_INFO_MAX 3
458
459 struct freq_info {
460 int pd;
461 const char *label;
462 };
463
464 struct freq_info ts_info[] = {
465 { 1, N_("Annual") },
466 { 4, N_("Quarterly") },
467 { 12, N_("Monthly") },
468 { 52, N_("Weekly") },
469 { 5, N_("Daily (5 days)") },
470 { 6, N_("Daily (6 days)") },
471 { 7, N_("Daily (7 days)") },
472 { 24, N_("Hourly") },
473 { 10, N_("Decennial") },
474 { PD_SPECIAL, N_("Other") },
475 };
476
477 struct panel_info {
478 int code;
479 const char *label;
480 };
481
482 struct panel_info pan_info[] = {
483 { STACKED_TIME_SERIES, N_("Stacked time series") },
484 { STACKED_CROSS_SECTION, N_("Stacked cross sections") },
485 { PANEL_UNKNOWN, N_("Use index variables") }
486 };
487
ts_frequency_string(const DATASET * dwinfo)488 static const char *ts_frequency_string (const DATASET *dwinfo)
489 {
490 int i, pd = dwinfo->pd;
491
492 if (pd == PD_SPECIAL) {
493 return N_("Other");
494 } else if (dwinfo->structure == SPECIAL_TIME_SERIES) {
495 return N_("Time series");
496 } else {
497 for (i=0; i<TS_INFO_MAX; i++) {
498 if (ts_info[i].pd == pd) {
499 return ts_info[i].label;
500 }
501 }
502 }
503
504 return N_("Non-standard frequency");
505 }
506
507 /* For a step that involves a radio-button choice, figure
508 out the default value */
509
dwiz_radio_default(DATASET * dwinfo,int step)510 static int dwiz_radio_default (DATASET *dwinfo, int step)
511 {
512 int deflt = 1;
513
514 #if DWDEBUG
515 fprintf(stderr, "radio_default: step=%d, dwinfo->pd=%d, dwinfo->structure=%d\n",
516 step, dwinfo->pd, dwinfo->structure);
517 #endif
518
519 if (step == DW_SET_TYPE) {
520 deflt = dwinfo->structure;
521 } else if (step == DW_TS_FREQUENCY) {
522 if (dwinfo->structure == SPECIAL_TIME_SERIES) {
523 deflt = PD_SPECIAL;
524 } else if (dwinfo->pd == 4 || dwinfo->pd == 5 ||
525 dwinfo->pd == 6 || dwinfo->pd == 7 ||
526 dwinfo->pd == 10 || dwinfo->pd == 12 ||
527 dwinfo->pd == 52) {
528 deflt = dwinfo->pd;
529 }
530 } else if (step == DW_WEEKLY_SELECT) {
531 deflt = dwinfo->v;
532 } else if (step == DW_PANEL_MODE) {
533 deflt = dwinfo->structure;
534 }
535
536 #if DWDEBUG
537 fprintf(stderr, " returning deflt = %d\n", deflt);
538 #endif
539
540 return deflt;
541 }
542
543 /* For step @step of the process, figure out the value that
544 should be set by clicking radio button i.
545 */
546
dwiz_i_to_setval(DATASET * dwinfo,int step,int i)547 static int dwiz_i_to_setval (DATASET *dwinfo, int step, int i)
548 {
549 int setval;
550
551 if (step == DW_SET_TYPE &&
552 dwinfo->structure == SPECIAL_TIME_SERIES &&
553 i == TIME_SERIES) {
554 setval = SPECIAL_TIME_SERIES;
555 } else if (step == DW_TS_FREQUENCY) {
556 setval = (i < TS_INFO_MAX)? ts_info[i].pd : 0;
557 } else if (step == DW_PANEL_MODE) {
558 setval = (i < PANEL_INFO_MAX)? pan_info[i].code : 0;
559 } else {
560 setval = i;
561 }
562
563 return setval;
564 }
565
566 /* For step @step of the process, figure out the label that
567 should be shown alongside radio button i.
568 */
569
dwiz_radio_strings(int step,int i)570 static const char *dwiz_radio_strings (int step, int i)
571 {
572 if (step == DW_SET_TYPE) {
573 if (i == 0) return N_("Cross-sectional");
574 if (i == 1) return N_("Time series");
575 if (i == 2) return N_("Panel");
576 } else if (step == DW_WEEKLY_SELECT) {
577 if (i == 0) return N_("Monday");
578 if (i == 1) return N_("Tuesday");
579 if (i == 2) return N_("Wednesday");
580 if (i == 3) return N_("Thursday");
581 if (i == 4) return N_("Friday");
582 if (i == 5) return N_("Saturday");
583 if (i == 6) return N_("Sunday");
584 if (i == 7) return N_("None (don't use dates)");
585 } else if (step == DW_TS_FREQUENCY) {
586 return ts_info[i].label;
587 } else if (step == DW_PANEL_MODE) {
588 return pan_info[i].label;
589 }
590
591 return "";
592 }
593
dwiz_set_radio_opt(GtkWidget * w,dw_opts * opts)594 static void dwiz_set_radio_opt (GtkWidget *w, dw_opts *opts)
595 {
596 int val = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "setval"));
597
598 if (opts->pdspin != NULL) {
599 if (val == PD_SPECIAL) {
600 GtkAdjustment *adj =
601 gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(opts->pdspin));
602
603 gtk_widget_set_sensitive(opts->pdspin, TRUE);
604 val = (int) gtk_adjustment_get_value(adj);
605 if (opts->extra != NULL) {
606 *opts->extra = SPECIAL_TIME_SERIES;
607 }
608 } else {
609 gtk_widget_set_sensitive(opts->pdspin, FALSE);
610 if (opts->extra != NULL) {
611 *opts->extra = TIME_SERIES;
612 }
613 }
614 }
615
616 #if DWDEBUG
617 fprintf(stderr, "dwiz_set_radio_opt: setting setvar to %d\n", val);
618 if (opts->extra != NULL) {
619 fprintf(stderr, "dwiz_set_radio_opt: extra now = %d\n", *opts->extra);
620 }
621 #endif
622
623 *opts->setvar = val;
624 }
625
dw_nobs(DATASET * dwinfo,dw_opts * opts)626 static int dw_nobs (DATASET *dwinfo, dw_opts *opts)
627 {
628 if (dataset->n > 0) {
629 return dataset->n;
630 } else {
631 return newdata_nobs(dwinfo, opts);
632 }
633 }
634
make_confirmation_text(DATASET * dwinfo,dw_opts * opts)635 static gchar *make_confirmation_text (DATASET *dwinfo, dw_opts *opts)
636 {
637 int nobs = dw_nobs(dwinfo, opts);
638 gchar *ret = NULL;
639
640 if (dwinfo->structure == CROSS_SECTION) {
641 ret = g_strdup_printf(_("%s, observations 1 to %d"), _("Cross-sectional data"),
642 nobs);
643 } else if (time_series(dwinfo)) {
644 const char *tslabel = ts_frequency_string(dwinfo);
645 int lastobs = dwinfo->t1 + nobs - 1;
646 char stobs[OBSLEN];
647 char endobs[OBSLEN];
648
649 if (lastobs > dwinfo->n - 1) {
650 dwinfo->n = lastobs + 1;
651 }
652 ntolabel(stobs, dwinfo->t1, dwinfo);
653 ntolabel(endobs, lastobs, dwinfo);
654 ret = g_strdup_printf(_("%s, %s to %s"), _(tslabel), stobs, endobs);
655 if (opts->flags & DW_CREATE) {
656 GString *gs = g_string_new(ret);
657
658 g_string_append_printf(gs, ", T = %d", nobs);
659 g_free(ret);
660 ret = g_string_free(gs, FALSE);
661 }
662 } else if (dwinfo->structure == PANEL_UNKNOWN) {
663 ret = g_strdup_printf(_("Panel data (%s)\n"
664 "%d cross-sectional units observed over %d periods"),
665 _("stacked time series"), dwinfo->n, dwinfo->pd);
666 } else if (known_panel(dwinfo)) {
667 int nunits, nperiods;
668
669 if (opts->flags & DW_CREATE) {
670 nunits = opts->dvals[2];
671 nperiods = opts->dvals[3];
672 } else {
673 nunits = dwinfo->t1;
674 nperiods = nobs / nunits;
675 }
676
677 ret = g_strdup_printf(_("Panel data (%s)\n"
678 "%d cross-sectional units observed over %d periods"),
679 (dwinfo->structure == STACKED_TIME_SERIES)?
680 _("stacked time series") : _("stacked cross sections"),
681 nunits, nperiods);
682 }
683
684 if (opts->flags & DW_DROPMISS) {
685 gchar *s;
686
687 s = g_strdup_printf("%s\n%s", ret, _("(dropping missing observations)"));
688 g_free(ret);
689 ret = s;
690 }
691
692 return ret;
693 }
694
make_weekly_stobs(DATASET * dwinfo)695 static void make_weekly_stobs (DATASET *dwinfo)
696 {
697 int start_days[] = { 6, 7, 1, 2, 3, 4, 5 };
698
699 sprintf(dwinfo->stobs, "1800-01-0%d", start_days[dwinfo->v]);
700 }
701
default_start_decade(void)702 static int default_start_decade (void)
703 {
704 int d = 1700;
705
706 if (dataset->S != NULL) {
707 d = positive_int_from_string(dataset->S[0]);
708 }
709
710 if (d < 0) {
711 d = 1700;
712 }
713
714 return d;
715 }
716
compute_default_ts_info(DATASET * dwinfo)717 static void compute_default_ts_info (DATASET *dwinfo)
718 {
719 #if DWDEBUG
720 char obsstr[OBSLEN];
721
722 fprintf(stderr, "compute_ts_info() called: pd=%d, structure=%d\n",
723 dwinfo->pd, dwinfo->structure);
724 if (dwinfo->pd == PD_SPECIAL) {
725 fprintf(stderr, "breakage: pd = PD_SPECIAL\n");
726 }
727 #endif
728
729 if (dwinfo->pd < 0) {
730 dwinfo->pd = 1;
731 }
732
733 if (dwinfo->structure == SPECIAL_TIME_SERIES) {
734 /* non-standard time series */
735 dwinfo->n = 9999 * dwinfo->pd;
736 dwinfo->t1 = 0;
737 if (dwinfo->pd > 1) {
738 int p = dwinfo->pd;
739
740 strcpy(dwinfo->stobs, "1:");
741 while ((p = p / 10) > 0) {
742 strcat(dwinfo->stobs, "0");
743 }
744 strcat(dwinfo->stobs, "1");
745 } else {
746 strcpy(dwinfo->stobs, "1");
747 }
748 } else if (dwinfo->pd == 1) {
749 strcpy(dwinfo->stobs, "1");
750 dwinfo->n = 2100;
751 dwinfo->t1 = 1959; /* 1960 */
752 } else if (dwinfo->pd == 10) {
753 int dd = default_start_decade();
754
755 sprintf(dwinfo->stobs, "%d", dd);
756 if (dd > 1700) {
757 dwinfo->n = 30;
758 dwinfo->t1 = 0;
759 } else {
760 dwinfo->n = 40;
761 dwinfo->t1 = 25;
762 }
763 } else if (dwinfo->pd == 4) {
764 strcpy(dwinfo->stobs, "1300:1");
765 dwinfo->n = 1600 + 1400;
766 dwinfo->t1 = 1600 + 1040; /* 1960:1 */
767 } else if (dwinfo->pd == 12) {
768 strcpy(dwinfo->stobs, "1300:01");
769 dwinfo->n = 4800 + 4200;
770 dwinfo->t1 = 4800 + 3120; /* 1960:01 */
771 } else if (dwinfo->pd == 24) {
772 strcpy(dwinfo->stobs, "1:01");
773 dwinfo->n = 1500;
774 dwinfo->t1 = 0;
775 } else if (dwinfo->pd == 52) {
776 if (dwinfo->v >= 7) {
777 dwinfo->n = 500;
778 dwinfo->t1 = 0;
779 strcpy(dwinfo->stobs, "1");
780 } else {
781 make_weekly_stobs(dwinfo);
782 dwinfo->n = 13000;
783 dwinfo->t1 = 7826;
784 }
785 } else if (dwinfo->pd == 5 ||
786 dwinfo->pd == 6 ||
787 dwinfo->pd == 7) {
788 strcpy(dwinfo->stobs, "1900-01-01");
789 dwinfo->n = 50000;
790 /* set default start to 1960-01-01 (a Friday) */
791 if (dwinfo->pd == 5) {
792 dwinfo->t1 = 15654;
793 } else if (dwinfo->pd == 6) {
794 dwinfo->t1 = 18784;
795 } else {
796 dwinfo->t1 = 21914;
797 }
798 }
799
800 dwinfo->sd0 = get_date_x(dwinfo->pd, dwinfo->stobs);
801
802 if (dataset->structure == TIME_SERIES &&
803 dataset->pd == dwinfo->pd) {
804 /* make the current start the default */
805 dwinfo->t1 = dateton(dataset->stobs, dwinfo);
806 }
807
808 ntolabel(dwinfo->endobs, dwinfo->n - 1, dwinfo);
809
810 #if DWDEBUG
811 ntolabel(obsstr, dwinfo->t1, dwinfo);
812 fprintf(stderr, "dwinfo: v=%d, pd=%d, stobs='%s', endobs='%s', sd0=%g, t1=%d (%s)\n",
813 dwinfo->v, dwinfo->pd, dwinfo->stobs, dwinfo->endobs, dwinfo->sd0,
814 dwinfo->t1, obsstr);
815
816 ntolabel(obsstr, dataset->t1, dataset);
817 fprintf(stderr, "dataset: pd=%d, stobs='%s', sd0=%g, t1=%d (%s)\n",
818 dataset->pd, dataset->stobs, dataset->sd0, dataset->t1, obsstr);
819 #endif
820 }
821
default_panel_size(dw_opts * opts,DATASET * dwinfo)822 static int default_panel_size (dw_opts *opts, DATASET *dwinfo)
823 {
824 int sz = opts->plf;
825
826 if (dwinfo->pd > 1 && dwinfo->n % dwinfo->pd == 0) {
827 if (dwinfo->structure == STACKED_TIME_SERIES) {
828 sz = dwinfo->n / dwinfo->pd;
829 } else {
830 sz = dwinfo->pd;
831 }
832 }
833
834 dwinfo->t1 = sz;
835 dwinfo->t2 = dwinfo->n / sz;
836
837 return sz;
838 }
839
840 /* translate from the 0-based indexing in the GtkComboBox to
841 dataset indexing, for the unit and period variables */
842
translate_panel_vars(dw_opts * opts,int * uv,int * tv)843 static int translate_panel_vars (dw_opts *opts, int *uv, int *tv)
844 {
845 GList *list = opts->vlist;
846 int i, vi;
847 int err = 0;
848
849 *uv = *tv = 0;
850
851 for (i=0; list != NULL && !err; i++) {
852 if (i == opts->uid || i == opts->tid) {
853 vi = series_index(dataset, (const char *) list->data);
854 if (vi == dataset->v) {
855 err = E_DATA;
856 } else if (i == opts->uid) {
857 *uv = vi;
858 } else {
859 *tv = vi;
860 }
861 }
862 if (*uv > 0 && *tv > 0) {
863 break;
864 }
865 list = list->next;
866 }
867
868 #if DWDEBUG
869 fprintf(stderr, "translate_panel_vars: uid: %d -> %d, tid: %d -> %d\n",
870 opts->uid, *uv, opts->tid, *tv);
871 #endif
872
873 return err;
874 }
875
diagnose_panel_problem(DATASET * dset,int uv,int tv,int known_problem)876 static int diagnose_panel_problem (DATASET *dset, int uv, int tv,
877 int known_problem)
878 {
879 gchar *msg = NULL;
880 double ui, ti;
881 double uj, tj;
882 int i, j;
883 int found = 0;
884
885 for (i=1; i<dset->n && !found; i++) {
886 ui = dset->Z[uv][i];
887 ti = dset->Z[tv][i];
888 for (j=0; j<i; j++) {
889 uj = dset->Z[uv][j];
890 tj = dset->Z[tv][j];
891 if (uj == ui && tj == ti) {
892 msg = g_strdup_printf("%s = %g and %s = %g duplicated on "
893 "rows %d and %d", dset->varname[uv],
894 ui, dset->varname[tv], ti, i+1, j+1);
895 found = 1;
896 break;
897 }
898 }
899 }
900
901 if (!known_problem && !found) {
902 return 0; /* nothing amiss */
903 }
904
905 if (msg != NULL) {
906 errbox(msg);
907 g_free(msg);
908 } else {
909 errbox(_("The selected index variables do not represent "
910 "a panel structure"));
911 }
912
913 return E_DATA;
914 }
915
916 /* Given two user-selected variables that supposedly represent the
917 panel unit and period respectively, check that the selection makes
918 sense.
919 */
920
process_panel_vars(DATASET * dwinfo,dw_opts * opts)921 static int process_panel_vars (DATASET *dwinfo, dw_opts *opts)
922 {
923 int n = dataset->n;
924 double *uid = NULL;
925 double *tid = NULL;
926 int uv, tv;
927 int nunits = 0;
928 int nperiods = 0;
929 int err = 0;
930
931 /* FIXME sub-sampled dataset? */
932
933 err = translate_panel_vars(opts, &uv, &tv);
934 if (err) {
935 return err;
936 }
937
938 if (uv == tv) {
939 /* "can't happen" */
940 errbox(_("The unit and time index variables must be distinct"));
941 return E_DATA;
942 }
943
944 uid = copyvec(dataset->Z[uv], n);
945 tid = copyvec(dataset->Z[tv], n);
946
947 if (uid == NULL || tid == NULL) {
948 nomem();
949 err = E_ALLOC;
950 }
951
952 if (!err) {
953 qsort(uid, n, sizeof *uid, gretl_compare_doubles);
954 nunits = count_distinct_values(uid, n);
955
956 qsort(tid, n, sizeof *tid, gretl_compare_doubles);
957 nperiods = count_distinct_values(tid, n);
958
959 /* Heuristic: if a variable represents either the panel
960 unit or period, it must have at least two distinct
961 values, and must have fewer values than the total
962 number of observations. Further, the product of
963 the number of distinct values for the unit and time
964 variables must be at least equal to the number of
965 observations, otherwise there will be duplicated
966 rows (i.e. more than one row claiming to represent
967 unit i, period t, for some i, t).
968
969 Note that the product (nunits * nperiods) may be
970 _greater_ than total n: this may mean that we have
971 some implicit missing observations.
972 */
973
974 if (nunits == 1 || nperiods == 1 ||
975 nunits == n || nperiods == n) {
976 errbox(_("The selected index variables do not represent "
977 "a panel structure"));
978 fprintf(stderr, "nunits=%d, nperiods=%d, n=%d\n",
979 nunits, nperiods, n);
980 err = E_DATA;
981 } else {
982 int known_problem = nunits * nperiods < n;
983
984 err = diagnose_panel_problem(dataset, uv, tv, known_problem);
985 }
986
987 if (!err) {
988 dwinfo->n = nunits;
989 dwinfo->pd = nperiods;
990 }
991 }
992
993 free(uid);
994 free(tid);
995
996 return err;
997 }
998
999 /* Try to assemble a list of at least two potential panel index
1000 variables. These variables must have nothing but non-negative
1001 integer values, and they must have at least two distinct values
1002 (i.e. cannot be constants).
1003 */
1004
panelvars_list_ok(dw_opts * opts)1005 static int panelvars_list_ok (dw_opts *opts)
1006 {
1007 GList *vlist = NULL;
1008 int i, t, ok;
1009 double xt;
1010 int err = 0;
1011
1012 if (opts->flags & DW_VLIST_DONE) {
1013 return (opts->vlist != NULL);
1014 }
1015
1016 for (i=1; i<dataset->v; i++) {
1017 ok = 1;
1018 for (t=dataset->t1; t<=dataset->t2; t++) {
1019 xt = dataset->Z[i][t];
1020 if (na(xt) || xt < 0 || xt != floor(xt)) {
1021 ok = 0;
1022 break;
1023 }
1024 }
1025 if (ok) {
1026 ok = !gretl_isconst(dataset->t1, dataset->t2, dataset->Z[i]);
1027 }
1028 if (ok) {
1029 vlist = g_list_append(vlist, dataset->varname[i]);
1030 }
1031 }
1032
1033 if (vlist == NULL) {
1034 err = 1;
1035 } else if (g_list_length(vlist) < 2) {
1036 g_list_free(vlist);
1037 vlist = NULL;
1038 err = 1;
1039 }
1040
1041 opts->vlist = vlist;
1042 opts->flags |= DW_VLIST_DONE;
1043
1044 #if DWDEBUG
1045 fprintf(stderr, "panelvars_list_ok: returning %d\n", !err);
1046 #endif
1047
1048 return !err;
1049 }
1050
1051 /* Check whether or not it's feasible to offer a panel interpretation
1052 of the current dataset. This is impossible if the total number of
1053 observations is prime (cannot be factored as n * T) and the dataset
1054 contains no variables that might plausibly represent panel unit and
1055 period respectively.
1056 */
1057
panel_possible(dw_opts * opts)1058 static int panel_possible (dw_opts *opts)
1059 {
1060 int ok = 1;
1061
1062 if (opts->flags & DW_NO_PANEL) {
1063 return 0;
1064 }
1065
1066 eval_n_is_prime(opts);
1067
1068 if (opts->flags & DW_N_PRIME) {
1069 /* are there feasible index vars? */
1070 ok = panelvars_list_ok(opts);
1071 }
1072
1073 if (!ok) {
1074 opts->flags |= DW_NO_PANEL;
1075 warnbox(_("This dataset cannot be interpreted as a panel"));
1076 }
1077
1078 return ok;
1079 }
1080
1081 /* callback from combo: update the panel unit or time variable,
1082 building in a guard against selecting the same variable in
1083 both roles
1084 */
1085
update_panel_var(GtkWidget * box,dw_opts * opts)1086 static gboolean update_panel_var (GtkWidget *box, dw_opts *opts)
1087 {
1088 gint v = gtk_combo_box_get_active(GTK_COMBO_BOX(box));
1089 int i = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(box), "index"));
1090 GtkWidget *other = g_object_get_data(G_OBJECT(box), "other");
1091
1092 if (i == 0) {
1093 opts->uid = v;
1094 } else {
1095 opts->tid = v;
1096 }
1097
1098 if (other != NULL) {
1099 gint v2 = gtk_combo_box_get_active(GTK_COMBO_BOX(other));
1100
1101 if (v == v2) {
1102 /* we have a conflict: fix it */
1103 if (v > 0) {
1104 gtk_combo_box_set_active(GTK_COMBO_BOX(other), 0);
1105 } else {
1106 gtk_combo_box_set_active(GTK_COMBO_BOX(other), 1);
1107 }
1108 }
1109 }
1110
1111 #if DWDEBUG
1112 fprintf(stderr, "update_panel_var: i=%d, uid = %d, tid = %d\n",
1113 i, opts->uid, opts->tid);
1114 #endif
1115
1116 return FALSE;
1117 }
1118
1119 /* Try to find the most likely candidates for the unit (uid) and time
1120 (tid) index variables, given a list of variables that might
1121 perhaps be acceptable.
1122 */
1123
panelvar_candidates(GList * vlist,int * uid,int * tid)1124 static void panelvar_candidates (GList *vlist, int *uid, int *tid)
1125 {
1126 GList *list = vlist;
1127 const char *vname;
1128 char vtest[VNAMELEN];
1129 int i;
1130
1131 *uid = *tid = -1;
1132
1133 for (i=0; list != NULL; i++) {
1134 vname = (const char *) list->data;
1135 strcpy(vtest, vname);
1136 gretl_lower(vtest);
1137 if (*tid < 0) {
1138 if (!strcmp(vtest, "time") ||
1139 !strcmp(vtest, "year") ||
1140 !strcmp(vtest, "period")) {
1141 *tid = i;
1142 }
1143 }
1144 if (*uid < 0) {
1145 if (!strcmp(vtest, "unit") ||
1146 !strcmp(vtest, "group") ||
1147 !strcmp(vtest, "country") ||
1148 !strcmp(vtest, "id")) {
1149 *uid = i;
1150 }
1151 }
1152 if (*uid >= 0 && *tid >= 0) {
1153 break;
1154 }
1155 list = list->next;
1156 }
1157
1158 /* if we didn't succeed above, just ensure a non-conflicting
1159 assignment to uidx and tidx */
1160
1161 if (*uid < 0) {
1162 if (*tid < 0) {
1163 *uid = 0;
1164 *tid = 1;
1165 } else {
1166 *uid = (*tid == 0)? 1 : 0;
1167 }
1168 } else if (*tid < 0) {
1169 *tid = (*uid == 0)? 1 : 0;
1170 }
1171 }
1172
1173 /* combo box selector for variables possibly representing the
1174 panel unit and time-period */
1175
dwiz_combo(GList * vlist,dw_opts * opts)1176 static GtkWidget *dwiz_combo (GList *vlist, dw_opts *opts)
1177 {
1178 const char *strs[] = {
1179 N_("Unit or group index variable"),
1180 N_("Time index variable")
1181 };
1182 GtkWidget *w;
1183 GtkWidget *table;
1184 GtkWidget *combo[2];
1185 int i;
1186
1187 panelvar_candidates(vlist, &opts->uid, &opts->tid);
1188
1189 #if DWDEBUG
1190 fprintf(stderr, "dwiz_combo: uid = %d, tid = %d\n",
1191 opts->uid, opts->tid);
1192 #endif
1193
1194 table = gtk_table_new(2, 2, FALSE);
1195 gtk_table_set_col_spacings(GTK_TABLE(table), 5);
1196 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
1197
1198 for (i=0; i<2; i++) {
1199 GList *list = vlist;
1200
1201 w = gtk_label_new(_(strs[i]));
1202 gtk_misc_set_alignment(GTK_MISC(w), 1.0, 0.5);
1203 gtk_table_attach_defaults(GTK_TABLE(table), w, 0, 1, i, i+1);
1204
1205 combo[i] = gtk_combo_box_text_new();
1206 gtk_table_attach_defaults(GTK_TABLE(table), combo[i], 1, 2, i, i+1);
1207
1208 while (list != NULL) {
1209 combo_box_append_text(combo[i], list->data);
1210 list = list->next;
1211 }
1212
1213 gtk_combo_box_set_active(GTK_COMBO_BOX(combo[i]), (i == 0)? opts->uid : opts->tid);
1214 g_object_set_data(G_OBJECT(combo[i]), "index", GINT_TO_POINTER(i));
1215 g_signal_connect(G_OBJECT(combo[i]), "changed",
1216 G_CALLBACK(update_panel_var), opts);
1217 }
1218
1219 /* cross-connect the selectors */
1220 g_object_set_data(G_OBJECT(combo[0]), "other", combo[1]);
1221 g_object_set_data(G_OBJECT(combo[1]), "other", combo[0]);
1222
1223 return table;
1224 }
1225
dw_set_custom_frequency(GtkWidget * w,DATASET * dwinfo)1226 static void dw_set_custom_frequency (GtkWidget *w, DATASET *dwinfo)
1227 {
1228 dwinfo->pd = (int) gtk_adjustment_get_value(GTK_ADJUSTMENT(w));
1229 #if DWDEBUG
1230 fprintf(stderr, "dw_set_custom_frequency: set dwinfo->pd = %d\n", dwinfo->pd);
1231 #endif
1232 }
1233
dw_set_t1(GtkWidget * w,DATASET * dwinfo)1234 static void dw_set_t1 (GtkWidget *w, DATASET *dwinfo)
1235 {
1236 dwinfo->t1 = (int) gtk_adjustment_get_value(GTK_ADJUSTMENT(w));
1237 #if DWDEBUG
1238 fprintf(stderr, "dw_set_t1: set dwinfo->t1 = %d\n", dwinfo->t1);
1239 fprintf(stderr, "(memo: dwinfo->n = %d)\n", dwinfo->n);
1240 #endif
1241 }
1242
1243 /* spinner for time-series starting observation */
1244
add_startobs_spinner(GtkWidget * vbox,DATASET * dwinfo,int direction)1245 static void add_startobs_spinner (GtkWidget *vbox,
1246 DATASET *dwinfo,
1247 int direction)
1248 {
1249 GtkWidget *hbox, *label, *spin;
1250 GtkAdjustment *adj;
1251
1252 if (direction == DW_FORWARD) {
1253 compute_default_ts_info(dwinfo);
1254 }
1255
1256 adj = (GtkAdjustment *) gtk_adjustment_new(dwinfo->t1,
1257 0, dwinfo->n - 1,
1258 1, 10, 0);
1259 g_signal_connect(G_OBJECT(adj), "value-changed",
1260 G_CALLBACK(dw_set_t1), dwinfo);
1261 spin = data_start_button(adj, dwinfo);
1262 gtk_entry_set_activates_default(GTK_ENTRY(spin), TRUE);
1263
1264 hbox = gtk_hbox_new(FALSE, 5);
1265 label = gtk_label_new(_(ts_frequency_string(dwinfo)));
1266 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
1267 gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0);
1268 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1269 gtk_widget_show_all(hbox);
1270 }
1271
1272 /* spinner for selecting custom time-series frequency */
1273
frequency_spinner(GtkWidget * hbox,DATASET * dwinfo)1274 static GtkWidget *frequency_spinner (GtkWidget *hbox, DATASET *dwinfo)
1275 {
1276 GtkAdjustment *adj;
1277 GtkWidget *spin;
1278 int pdmax = 1000; /* arbitrary */
1279
1280 adj = (GtkAdjustment *) gtk_adjustment_new(dwinfo->pd, 1, pdmax,
1281 1, 10, 0);
1282
1283 g_signal_connect(G_OBJECT(adj), "value-changed",
1284 G_CALLBACK(dw_set_custom_frequency), dwinfo);
1285 spin = gtk_spin_button_new(adj, 1, 0);
1286
1287 gtk_entry_set_activates_default(GTK_ENTRY(spin), TRUE);
1288 gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0);
1289 gtk_widget_show(spin);
1290
1291 return spin;
1292 }
1293
1294 /* Panel: callback for setting the number of cross-sectional units, n,
1295 and the number of time periods, T, via spin buttons. We allow the
1296 user to vary either n or T, subject to the constraint that n * T
1297 equals the total number of observations.
1298 */
1299
dw_set_panel_dims(GtkSpinButton * w,DATASET * dwinfo)1300 static void dw_set_panel_dims (GtkSpinButton *w, DATASET *dwinfo)
1301 {
1302 int idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "idx"));
1303 int plf = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "plf"));
1304 GtkSpinButton *nspin = NULL, *Tspin = NULL;
1305 int oldn = dwinfo->t1;
1306 int oldT = dwinfo->t2;
1307 int n = 0, T = 0;
1308
1309 if (idx == 0) {
1310 nspin = w;
1311 Tspin = g_object_get_data(G_OBJECT(w), "Tspin");
1312 } else {
1313 Tspin = w;
1314 nspin = g_object_get_data(G_OBJECT(w), "nspin");
1315 }
1316
1317 if (nspin != NULL) {
1318 n = gtk_spin_button_get_value_as_int(nspin);
1319 }
1320
1321 if (Tspin != NULL) {
1322 T = gtk_spin_button_get_value_as_int(Tspin);
1323 }
1324
1325 if (nspin != NULL && Tspin != NULL) {
1326 int nTmax = dataset->n / plf;
1327
1328 if (n != oldn) {
1329 if (n > oldn) {
1330 while (dataset->n % n && n <= nTmax) {
1331 n++;
1332 }
1333 } else if (n < oldn) {
1334 while (dataset->n % n && n >= plf) {
1335 n--;
1336 }
1337 }
1338 if (dataset->n % n) {
1339 n = oldn;
1340 }
1341 T = dataset->n / n;
1342 } else if (T != oldT) {
1343 if (T > oldT) {
1344 while (dataset->n % T && T <= nTmax) {
1345 T++;
1346 }
1347 } else if (T < oldT) {
1348 while (dataset->n % T && T >= plf) {
1349 T--;
1350 }
1351 }
1352 if (dataset->n % T) {
1353 T = oldT;
1354 }
1355 n = dataset->n / T;
1356 }
1357
1358 gtk_spin_button_set_value(nspin, (double) n);
1359 gtk_spin_button_set_value(Tspin, (double) T);
1360 }
1361
1362 dwinfo->t1 = n;
1363 dwinfo->t2 = T;
1364
1365 #if DWDEBUG
1366 fprintf(stderr, "dw_set_panel_dims: n: %d -> %d, T: %d -> %d\n",
1367 oldn, n, oldT, T);
1368 #endif
1369 }
1370
dwiz_make_panel_spinners(dw_opts * opts,DATASET * dwinfo,GtkWidget * vbox)1371 static void dwiz_make_panel_spinners (dw_opts *opts,
1372 DATASET *dwinfo,
1373 GtkWidget *vbox)
1374 {
1375 const char *labels[] = {
1376 N_("Number of cross-sectional units"),
1377 N_("Number of time periods")
1378 };
1379 GtkWidget *label;
1380 GtkWidget *table;
1381 GtkAdjustment *adj;
1382 GtkWidget *pspin[2];
1383 int spinmin, spinmax, spinstart;
1384 int i;
1385
1386 spinmin = opts->plf;
1387 spinmax = dataset->n / opts->plf;
1388 spinstart = default_panel_size(opts, dwinfo);
1389
1390 table = gtk_table_new(2, 2, FALSE);
1391 gtk_table_set_col_spacings(GTK_TABLE(table), 5);
1392 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
1393
1394 for (i=0; i<2; i++) {
1395 label = gtk_label_new(_(labels[i]));
1396 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
1397 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, i, i+1);
1398
1399 if (i == 1) {
1400 spinstart = dataset->n / spinstart;
1401 }
1402
1403 adj = (GtkAdjustment *) gtk_adjustment_new(spinstart, spinmin, spinmax,
1404 1, 10, 0);
1405 pspin[i] = gtk_spin_button_new(adj, 1, 0);
1406 g_object_set_data(G_OBJECT(pspin[i]), "idx", GINT_TO_POINTER(i));
1407 g_object_set_data(G_OBJECT(pspin[i]), "plf", GINT_TO_POINTER(opts->plf));
1408 g_signal_connect(G_OBJECT(pspin[i]), "value-changed",
1409 G_CALLBACK(dw_set_panel_dims), dwinfo);
1410 gtk_entry_set_activates_default(GTK_ENTRY(pspin[i]), TRUE);
1411 gtk_table_attach_defaults(GTK_TABLE(table), pspin[i], 1, 2, i, i+1);
1412 }
1413
1414 g_object_set_data(G_OBJECT(pspin[0]), "Tspin", pspin[1]);
1415 g_object_set_data(G_OBJECT(pspin[1]), "nspin", pspin[0]);
1416
1417 gtk_widget_show_all(table);
1418 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 5);
1419 }
1420
maybe_add_missobs_purger(GtkWidget * vbox,gretlopt * flags)1421 static void maybe_add_missobs_purger (GtkWidget *vbox, gretlopt *flags)
1422 {
1423 double missfrac = 0.0;
1424 int active = 0;
1425
1426 if (*flags & DW_DROPMISS) {
1427 active = 1;
1428 } else {
1429 missfrac = missing_obs_fraction(dataset);
1430 }
1431
1432 if (active || (missfrac > 0 && missfrac < 0.12)) {
1433 GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
1434 GtkWidget *chk;
1435
1436 chk = gretl_option_check_button(_("purge missing observations"),
1437 flags, (gretlopt) DW_DROPMISS);
1438 gtk_box_pack_start(GTK_BOX(hbox), chk, FALSE, FALSE, 5);
1439 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1440 if (active) {
1441 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk), TRUE);
1442 }
1443 gtk_widget_show_all(hbox);
1444 }
1445 }
1446
1447 /* Calculate the options set-up for a given step of the wizard
1448 process: How many radio-button options should we show (if any)?
1449 What variable are we setting? What should be the default value for
1450 this variable?
1451 */
1452
set_up_dw_opts(dw_opts * opts,int step,DATASET * dwinfo)1453 static void set_up_dw_opts (dw_opts *opts, int step,
1454 DATASET *dwinfo)
1455 {
1456 opts->setvar = NULL;
1457 opts->extra = NULL;
1458 opts->pdspin = NULL;
1459 opts->n_radios = 0;
1460
1461 opts->deflt = dwiz_radio_default(dwinfo, step);
1462
1463 if (step == DW_SET_TYPE) {
1464 if (opts->flags & DW_NO_PANEL) {
1465 opts->n_radios = 2;
1466 } else {
1467 opts->n_radios = 3;
1468 }
1469 opts->setvar = &dwinfo->structure;
1470 } else if (step == DW_TS_FREQUENCY) {
1471 opts->n_radios = TS_INFO_MAX;
1472 opts->setvar = &dwinfo->pd;
1473 opts->extra = &dwinfo->structure;
1474 } else if (step == DW_WEEKLY_SELECT) {
1475 opts->n_radios = 8;
1476 opts->setvar = &dwinfo->v;
1477 } else if (step == DW_PANEL_MODE) {
1478 opts->n_radios = PANEL_INFO_MAX;
1479 opts->setvar = &dwinfo->structure;
1480 eval_n_is_prime(opts);
1481 } else if (step == DW_PANEL_SIZE) {
1482 opts->setvar = &dwinfo->pd;
1483 }
1484 }
1485
get_dimensions(int s,dw_opts * opts,int * dmax,int * d)1486 static void get_dimensions (int s, dw_opts *opts,
1487 int *dmax, int *d)
1488 {
1489 int k = opts->dvals[s];
1490
1491 if (s >= STACKED_TIME_SERIES) {
1492 *d = (k == 0)? 10 : k;
1493 *dmax = 10000;
1494 } else {
1495 *d = (k == 0)? 100 : k;
1496 *dmax = 1000000;
1497 }
1498 }
1499
sensitize_obs_spinners(GtkToggleButton * button,dw_opts * opts)1500 static void sensitize_obs_spinners (GtkToggleButton *button,
1501 dw_opts *opts)
1502 {
1503 if (button_is_active(button)) {
1504 int i, s, sv = widget_get_int(button, "setval");
1505
1506 for (i=0; i<4; i++) {
1507 s = (i == sv || (sv == 2 && i == 3));
1508 gtk_widget_set_sensitive(opts->dspin[i], s);
1509 }
1510 }
1511 }
1512
set_initial_obs_sensitivities(DATASET * dwinfo,dw_opts * opts)1513 static void set_initial_obs_sensitivities (DATASET *dwinfo,
1514 dw_opts *opts)
1515 {
1516 int i, s[4] = {0};
1517
1518 if (dwinfo->structure == CROSS_SECTION) {
1519 s[0] = 1;
1520 } else if (dataset_is_time_series(dwinfo)) {
1521 s[1] = 1;
1522 } else {
1523 s[2] = s[3] = 1;
1524 }
1525
1526 for (i=0; i<4; i++) {
1527 gtk_widget_set_sensitive(opts->dspin[i], s[i]);
1528 }
1529 }
1530
dwiz_new_dataset_combo(DATASET * dwinfo,dw_opts * opts,GtkWidget * vbox)1531 static void dwiz_new_dataset_combo (DATASET *dwinfo,
1532 dw_opts *opts,
1533 GtkWidget *vbox)
1534 {
1535 const gchar *strs[] = {"n =", "T ="};
1536 GSList *group = NULL;
1537 GtkWidget *button = NULL;
1538 GtkWidget *buttons[3];
1539 GtkWidget *label;
1540 GtkWidget *hbox, *table;
1541 int dmax, dval = 0;
1542 int i, j;
1543
1544 table = gtk_table_new(4, 2, FALSE);
1545 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
1546 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
1547 gtk_widget_show(table);
1548
1549 for (i=0; i<3; i++) {
1550 const char *s = dwiz_radio_strings(DW_SET_TYPE, i);
1551 int setval = dwiz_i_to_setval(dwinfo, DW_SET_TYPE, i);
1552
1553 if (button != NULL) {
1554 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1555 } else {
1556 group = NULL;
1557 }
1558
1559 /* dataset structure selector */
1560 buttons[i] = button = gtk_radio_button_new_with_label(group, _(s));
1561 gtk_table_attach_defaults(GTK_TABLE(table), button, 0, 1, i, i+1);
1562 g_signal_connect(G_OBJECT(button), "clicked",
1563 G_CALLBACK(dwiz_set_radio_opt), opts);
1564 g_object_set_data(G_OBJECT(button), "setval", GINT_TO_POINTER(setval));
1565 gtk_widget_show(button);
1566
1567 /* dimension (n or T) selector(s) */
1568 hbox = gtk_hbox_new(FALSE, 5);
1569 j = (i == 2)? 0 : i;
1570 label = gtk_label_new(strs[j]);
1571 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
1572 get_dimensions(i, opts, &dmax, &dval);
1573 opts->dspin[i] = gtk_spin_button_new_with_range(2, dmax, 1);
1574 gtk_spin_button_set_value(GTK_SPIN_BUTTON(opts->dspin[i]), dval);
1575 gtk_box_pack_start(GTK_BOX(hbox), opts->dspin[i], FALSE, FALSE, 5);
1576 gtk_table_attach_defaults(GTK_TABLE(table), hbox, 1, 2, i, i+1);
1577 gtk_widget_show_all(hbox);
1578
1579 if (i == 2) {
1580 /* panel: we need a setter for T as well as n */
1581 hbox = gtk_hbox_new(FALSE, 5);
1582 label = gtk_label_new(strs[j+1]);
1583 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
1584 get_dimensions(i+1, opts, &dmax, &dval);
1585 opts->dspin[i+1] = gtk_spin_button_new_with_range(2, dmax, 1);
1586 gtk_spin_button_set_value(GTK_SPIN_BUTTON(opts->dspin[i+1]), dval);
1587 gtk_box_pack_start(GTK_BOX(hbox), opts->dspin[i+1], FALSE, FALSE, 5);
1588 gtk_table_attach_defaults(GTK_TABLE(table), hbox, 1, 2, i+1, i+2);
1589 gtk_widget_show_all(hbox);
1590 }
1591
1592 if (opts->deflt == setval) {
1593 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
1594 if (opts->setvar != NULL && setval >= 0) {
1595 /* preset the variable to its default value */
1596 *opts->setvar = setval;
1597 }
1598 }
1599
1600 }
1601
1602 for (i=0; i<3; i++) {
1603 /* we defer this hook-up until all the spinners are created */
1604 g_signal_connect(G_OBJECT(buttons[i]), "toggled",
1605 G_CALLBACK(sensitize_obs_spinners), opts);
1606 }
1607
1608 set_initial_obs_sensitivities(dwinfo, opts);
1609 }
1610
1611 /* make two or more radio buttons based on the current settings in
1612 the @opts structure
1613 */
1614
dwiz_build_radios(int step,DATASET * dwinfo,dw_opts * opts,GtkWidget * vbox)1615 static void dwiz_build_radios (int step, DATASET *dwinfo,
1616 dw_opts *opts, GtkWidget *vbox)
1617 {
1618 GSList *group = NULL;
1619 GtkWidget *button = NULL;
1620 int i;
1621
1622 for (i=0; i<opts->n_radios; i++) {
1623 /* determine the value to be set by button i */
1624 int setval = dwiz_i_to_setval(dwinfo, step, i);
1625 GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
1626
1627 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1628 gtk_widget_show(hbox);
1629
1630 if (button != NULL) {
1631 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1632 } else {
1633 group = NULL;
1634 }
1635 button = gtk_radio_button_new_with_label(group,
1636 _(dwiz_radio_strings(step, i)));
1637 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
1638
1639 if (step == DW_TS_FREQUENCY && i == opts->n_radios - 1) {
1640 /* time series, "other" (custom) frequency: need spinner */
1641 opts->pdspin = frequency_spinner(hbox, dwinfo);
1642 gtk_widget_set_sensitive(opts->pdspin, FALSE);
1643 }
1644
1645 g_signal_connect(G_OBJECT(button), "clicked",
1646 G_CALLBACK(dwiz_set_radio_opt), opts);
1647 g_object_set_data(G_OBJECT(button), "setval", GINT_TO_POINTER(setval));
1648
1649 if (step == DW_PANEL_MODE && dw_n_is_prime(opts)) {
1650 /* only the "index variables" option should be active */
1651 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
1652 setval == PANEL_UNKNOWN);
1653 gtk_widget_set_sensitive(button, setval == PANEL_UNKNOWN);
1654 } else if (opts->deflt == setval) {
1655 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
1656 if (opts->setvar != NULL && setval >= 0) {
1657 /* preset the variable to its default value */
1658 *opts->setvar = setval;
1659 }
1660 }
1661
1662 if (step == DW_PANEL_MODE && i == opts->n_radios - 1) {
1663 if (!panelvars_list_ok(opts)) {
1664 /* disable the "index variables" option */
1665 gtk_widget_set_sensitive(button, FALSE);
1666 gretl_tooltips_add(button,
1667 _("The data set contains no suitable index variables"));
1668 }
1669 }
1670
1671 gtk_widget_show(button);
1672 }
1673 }
1674
dwiz_panelvars_selector(dw_opts * opts,DATASET * dwinfo,GtkWidget * vbox)1675 static void dwiz_panelvars_selector (dw_opts *opts,
1676 DATASET *dwinfo,
1677 GtkWidget *vbox)
1678 {
1679 GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
1680 GtkWidget *table = dwiz_combo(opts->vlist, opts);
1681
1682 gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 5);
1683 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1684 gtk_widget_show_all(hbox);
1685 }
1686
1687 /* Where should we be going, when the Forward or Back button
1688 is clicked? */
1689
dwiz_compute_step(int prevstep,int direction,DATASET * dwinfo,dw_opts * opts)1690 static int dwiz_compute_step (int prevstep, int direction, DATASET *dwinfo,
1691 dw_opts *opts)
1692 {
1693 int create = opts->flags & DW_CREATE;
1694 int step = 0;
1695
1696 #if DWDEBUG
1697 fprintf(stderr, "dwiz_compute_step: incoming step = %d\n", prevstep);
1698 #endif
1699
1700 if (direction == DW_FORWARD) {
1701 if (prevstep == DW_SET_TYPE) {
1702 if (time_series(dwinfo)) {
1703 step = DW_TS_FREQUENCY;
1704 } else if (known_panel(dwinfo)) {
1705 if (create) {
1706 dwinfo->structure = STACKED_TIME_SERIES;
1707 step = DW_CONFIRM;
1708 } else {
1709 step = DW_PANEL_MODE;
1710 }
1711 } else if (dwinfo->structure == PANEL_UNKNOWN) {
1712 step = DW_PANEL_MODE;
1713 } else {
1714 /* cross section */
1715 dwinfo->pd = 1;
1716 step = DW_CONFIRM;
1717 }
1718 } else if (prevstep == DW_TS_FREQUENCY) {
1719 if (dwinfo->structure != SPECIAL_TIME_SERIES) {
1720 if (dwinfo->pd == 52) {
1721 step = DW_WEEKLY_SELECT;
1722 } else {
1723 step = DW_STARTING_OBS;
1724 }
1725 } else {
1726 step = DW_STARTING_OBS;
1727 }
1728 } else if (prevstep == DW_WEEKLY_SELECT) {
1729 step = DW_STARTING_OBS;
1730 } else if (prevstep == DW_PANEL_MODE) {
1731 if (dwinfo->structure == PANEL_UNKNOWN) {
1732 step = DW_PANEL_VARS;
1733 } else {
1734 step = DW_PANEL_SIZE;
1735 }
1736 } else if (prevstep == DW_PANEL_VARS) {
1737 if (process_panel_vars(dwinfo, opts)) {
1738 /* error: don't proceed */
1739 step = DW_PANEL_VARS;
1740 } else {
1741 step = DW_CONFIRM;
1742 }
1743 } else if (prevstep == DW_STARTING_OBS ||
1744 prevstep == DW_PANEL_SIZE) {
1745 if (prevstep == DW_PANEL_SIZE &&
1746 dwinfo->structure == STACKED_TIME_SERIES) {
1747 dwinfo->pd = dwinfo->t2;
1748 }
1749 step = DW_CONFIRM;
1750 }
1751 } else if (direction == DW_BACK) {
1752 if (prevstep == DW_CONFIRM && create) {
1753 if (dwinfo->structure == CROSS_SECTION ||
1754 dwinfo->structure == STACKED_TIME_SERIES) {
1755 return DW_SET_TYPE;
1756 }
1757 }
1758 if (prevstep == DW_TS_FREQUENCY || prevstep == DW_PANEL_MODE) {
1759 step = DW_SET_TYPE;
1760 } else if (prevstep == DW_STARTING_OBS) {
1761 if (dwinfo->pd == 52) {
1762 step = DW_WEEKLY_SELECT;
1763 } else {
1764 step = DW_TS_FREQUENCY;
1765 }
1766 } else if (prevstep == DW_WEEKLY_SELECT) {
1767 step = DW_TS_FREQUENCY;
1768 } else if (prevstep == DW_PANEL_SIZE) {
1769 step = (create)? DW_SET_TYPE : DW_PANEL_MODE;
1770 } else if (prevstep == DW_PANEL_VARS) {
1771 step = DW_PANEL_MODE;
1772 } else if (prevstep == DW_CONFIRM) {
1773 if (dwinfo->structure == TIME_SERIES ||
1774 dwinfo->structure == SPECIAL_TIME_SERIES) {
1775 step = DW_STARTING_OBS;
1776 } else if (dwinfo->structure == STACKED_TIME_SERIES ||
1777 dwinfo->structure == STACKED_CROSS_SECTION) {
1778 step = DW_PANEL_SIZE;
1779 } else {
1780 step = DW_SET_TYPE;
1781 }
1782 }
1783 }
1784
1785 #if DWDEBUG
1786 fprintf(stderr, "dwiz_compute_step: returning step = %d\n", step);
1787 #endif
1788
1789 return step;
1790 }
1791
1792 /* clear a given notebook page, but leave the title string
1793 unchanged */
1794
kill_dwiz_child(GtkWidget * w,gpointer p)1795 static void kill_dwiz_child (GtkWidget *w, gpointer p)
1796 {
1797 int t = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "title"));
1798
1799 if (!t) {
1800 gtk_widget_destroy(w);
1801 }
1802 }
1803
clear_dwiz_page(GtkWidget * page)1804 static void clear_dwiz_page (GtkWidget *page)
1805 {
1806 gtk_container_foreach(GTK_CONTAINER(page),
1807 (GtkCallback) kill_dwiz_child,
1808 NULL);
1809 }
1810
1811 /* select the appropriate buttons to show, depending on the
1812 step */
1813
dwiz_button_visibility(GtkWidget * dlg,int step)1814 static void dwiz_button_visibility (GtkWidget *dlg, int step)
1815 {
1816 GtkWidget *cancel = g_object_get_data(G_OBJECT(dlg), "cancel");
1817 GtkWidget *back = g_object_get_data(G_OBJECT(dlg), "back");
1818 GtkWidget *forward = g_object_get_data(G_OBJECT(dlg), "forward");
1819 GtkWidget *apply = g_object_get_data(G_OBJECT(dlg), "apply");
1820 GtkWidget *help = g_object_get_data(G_OBJECT(dlg), "help");
1821
1822 if (step == DW_SET_TYPE) {
1823 gtk_widget_show(cancel);
1824 gtk_widget_hide(back);
1825 gtk_widget_show(forward);
1826 gtk_widget_hide(apply);
1827 } else if (step == DW_CONFIRM) {
1828 gtk_widget_show(cancel);
1829 gtk_widget_show(back);
1830 gtk_widget_hide(forward);
1831 gtk_widget_show(apply);
1832 } else {
1833 gtk_widget_show(cancel);
1834 gtk_widget_show(back);
1835 gtk_widget_show(forward);
1836 gtk_widget_hide(apply);
1837 }
1838
1839 if (step == DW_PANEL_MODE) {
1840 gtk_widget_show(help);
1841 } else {
1842 gtk_widget_hide(help);
1843 }
1844 }
1845
add_editing_option(GtkWidget * vbox,gretlopt * flags)1846 static void add_editing_option (GtkWidget *vbox, gretlopt *flags)
1847 {
1848 if (g_object_get_data(G_OBJECT(vbox), "edbutton") == NULL) {
1849 GtkWidget *hbox, *b;
1850
1851 hbox = gtk_hbox_new(FALSE, 5);
1852 b = gretl_option_check_button(_("start entering data values"),
1853 flags, (gretlopt) DW_SSHEET);
1854 gtk_box_pack_start(GTK_BOX(hbox), b, FALSE, FALSE, 5);
1855 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
1856 g_object_set_data(G_OBJECT(vbox), "edbutton", b);
1857 }
1858 }
1859
1860 /* build the appropriate notebook page for the given step */
1861
dwiz_prepare_page(GtkNotebook * nb,gint step,gint direction,DATASET * dwinfo)1862 static void dwiz_prepare_page (GtkNotebook *nb,
1863 gint step,
1864 gint direction,
1865 DATASET *dwinfo)
1866 {
1867 GtkWidget *page = gtk_notebook_get_nth_page(nb, step);
1868 GtkWidget *dlg = g_object_get_data(G_OBJECT(nb), "dlg");
1869 dw_opts *opts = g_object_get_data(G_OBJECT(dlg), "opts");
1870
1871 #if DWDEBUG
1872 fprintf(stderr, "Got Prepare, step = %d\n", step);
1873 #endif
1874
1875 if (step == DW_CONFIRM) {
1876 /* the final page */
1877 GtkWidget *w = g_object_get_data(G_OBJECT(page), "label");
1878 gchar *ctxt;
1879
1880 ctxt = make_confirmation_text(dwinfo, opts);
1881 gtk_label_set_text(GTK_LABEL(w), ctxt);
1882 g_free(ctxt);
1883 if (opts->flags & DW_CREATE) {
1884 if (newdata_nobs(dwinfo, opts) <= 100) {
1885 add_editing_option(page, &opts->flags);
1886 }
1887 }
1888 } else {
1889 /* all other pages */
1890 set_up_dw_opts(opts, step, dwinfo);
1891 clear_dwiz_page(page);
1892
1893 if (opts->n_radios > 0) {
1894 if (step == DW_SET_TYPE && (opts->flags & DW_CREATE)) {
1895 dwiz_new_dataset_combo(dwinfo, opts, page);
1896 } else {
1897 dwiz_build_radios(step, dwinfo, opts, page);
1898 }
1899 }
1900
1901 if (step == DW_STARTING_OBS) {
1902 add_startobs_spinner(page, dwinfo, direction);
1903 if (dataset != NULL && dataset->Z != NULL &&
1904 dataset_is_daily(dwinfo)) {
1905 maybe_add_missobs_purger(page, &opts->flags);
1906 }
1907 } else if (step == DW_PANEL_SIZE) {
1908 dwiz_make_panel_spinners(opts, dwinfo, page);
1909 } else if (step == DW_PANEL_VARS) {
1910 dwiz_panelvars_selector(opts, dwinfo, page);
1911 }
1912 }
1913
1914 gtk_widget_show_all(page);
1915 dwiz_button_visibility(dlg, step);
1916 }
1917
dwiz_finalize(GtkWidget * dlg,DATASET * dwinfo,int cancel)1918 static void dwiz_finalize (GtkWidget *dlg, DATASET *dwinfo,
1919 int cancel)
1920 {
1921 dw_opts *opts = g_object_get_data(G_OBJECT(dlg), "opts");
1922
1923 if (!cancel) {
1924 if (opts->flags & DW_CREATE) {
1925 dwiz_replace_dataset(dwinfo, opts, dlg);
1926 } else {
1927 dwiz_make_changes(dwinfo, opts, dlg);
1928 }
1929 } else if (opts->flags & DW_CREATE) {
1930 /* aborting creation of new dataset */
1931 gui_clear_dataset();
1932 }
1933
1934 gtk_widget_destroy(dlg);
1935 }
1936
1937 /* callback for the Cancel button */
1938
dwiz_cancel(GtkWidget * b,DATASET * dwinfo)1939 static void dwiz_cancel (GtkWidget *b, DATASET *dwinfo)
1940 {
1941 GtkWidget *dlg = g_object_get_data(G_OBJECT(b), "dlg");
1942
1943 dwiz_finalize(dlg, dwinfo, 1);
1944 }
1945
1946 /* callback for the Apply button */
1947
dwiz_apply(GtkWidget * b,DATASET * dwinfo)1948 static void dwiz_apply (GtkWidget *b, DATASET *dwinfo)
1949 {
1950 GtkWidget *dlg = g_object_get_data(G_OBJECT(b), "dlg");
1951
1952 dwiz_finalize(dlg, dwinfo, 0);
1953 }
1954
1955 /* callback for the Back button */
1956
dwiz_back(GtkWidget * b,GtkWidget * dlg)1957 static void dwiz_back (GtkWidget *b, GtkWidget *dlg)
1958 {
1959 GtkNotebook *nb = g_object_get_data(G_OBJECT(dlg), "nb");
1960 int pg = gtk_notebook_get_current_page(nb);
1961 DATASET *dwinfo = g_object_get_data(G_OBJECT(dlg), "dwinfo");
1962 dw_opts *opts = g_object_get_data(G_OBJECT(dlg), "opts");
1963
1964 pg = dwiz_compute_step(pg, DW_BACK, dwinfo, opts);
1965 dwiz_prepare_page(nb, pg, DW_BACK, dwinfo);
1966 gtk_notebook_set_current_page(nb, pg);
1967 }
1968
1969 /* callback for the Forward button */
1970
dwiz_forward(GtkWidget * b,GtkWidget * dlg)1971 static void dwiz_forward (GtkWidget *b, GtkWidget *dlg)
1972 {
1973 GtkNotebook *nb = g_object_get_data(G_OBJECT(dlg), "nb");
1974 int pg = gtk_notebook_get_current_page(nb);
1975 DATASET *dwinfo = g_object_get_data(G_OBJECT(dlg), "dwinfo");
1976 dw_opts *opts = g_object_get_data(G_OBJECT(dlg), "opts");
1977 int newpg;
1978
1979 if (pg == DW_SET_TYPE) {
1980 if (any_panel(dwinfo) && !panel_possible(opts)) {
1981 /* special case: called for panel but it won't work */
1982 dwinfo->structure = dataset->structure;
1983 dwiz_prepare_page(nb, DW_SET_TYPE, DW_BACK, dwinfo);
1984 gtk_notebook_set_current_page(nb, DW_SET_TYPE);
1985 return;
1986 }
1987 if (opts->flags & DW_CREATE) {
1988 int i;
1989
1990 for (i=0; i<4; i++) {
1991 opts->dvals[i] = spinner_get_int(opts->dspin[i]);
1992 }
1993 }
1994 }
1995
1996 newpg = dwiz_compute_step(pg, DW_FORWARD, dwinfo, opts);
1997 if (newpg != pg) {
1998 dwiz_prepare_page(nb, newpg, DW_FORWARD, dwinfo);
1999 gtk_notebook_set_current_page(nb, newpg);
2000 }
2001 }
2002
2003 /* initial setup for the final conformation text */
2004
dwiz_confirm_label(GtkWidget * page)2005 static void dwiz_confirm_label (GtkWidget *page)
2006 {
2007 GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
2008 GtkWidget *label = gtk_label_new("");
2009
2010 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
2011 gtk_box_pack_start(GTK_BOX(page), hbox, FALSE, FALSE, 5);
2012 g_object_set_data(G_OBJECT(page), "label", label);
2013 }
2014
free_dwinfo(GtkWidget * w,DATASET * dwinfo)2015 static void free_dwinfo (GtkWidget *w, DATASET *dwinfo)
2016 {
2017 free(dwinfo);
2018 }
2019
free_dw_opts(GtkWidget * w,dw_opts * opts)2020 static void free_dw_opts (GtkWidget *w, dw_opts *opts)
2021 {
2022 if (opts->vlist != NULL) {
2023 g_list_free(opts->vlist);
2024 }
2025 free(opts);
2026 }
2027
2028 /* Create all the buttons that we'll need. Which of these will
2029 actually be shown depends on the step */
2030
build_dwiz_buttons(GtkWidget * dlg,DATASET * dwinfo)2031 static void build_dwiz_buttons (GtkWidget *dlg, DATASET *dwinfo)
2032 {
2033 GtkWidget *hbox = gtk_dialog_get_action_area(GTK_DIALOG(dlg));
2034 GtkWidget *b;
2035
2036 /* "Cancel" button */
2037 b = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
2038 g_object_set_data(G_OBJECT(b), "dlg", dlg);
2039 g_signal_connect(G_OBJECT(b), "clicked",
2040 G_CALLBACK(dwiz_cancel),
2041 dwinfo);
2042 gtk_container_add(GTK_CONTAINER(hbox), b);
2043 g_object_set_data(G_OBJECT(dlg), "cancel", b);
2044
2045 /* "Back" button */
2046 b = gtk_button_new_from_stock(GTK_STOCK_GO_BACK);
2047 g_object_set_data(G_OBJECT(b), "dlg", dlg);
2048 g_signal_connect(G_OBJECT(b), "clicked",
2049 G_CALLBACK(dwiz_back),
2050 dlg);
2051 gtk_container_add(GTK_CONTAINER(hbox), b);
2052 g_object_set_data(G_OBJECT(dlg), "back", b);
2053
2054 /* "Forward" button */
2055 b = gtk_button_new_from_stock(GTK_STOCK_GO_FORWARD);
2056 g_object_set_data(G_OBJECT(b), "dlg", dlg);
2057 g_signal_connect(G_OBJECT(b), "clicked",
2058 G_CALLBACK(dwiz_forward),
2059 dlg);
2060 gtk_container_add(GTK_CONTAINER(hbox), b);
2061 g_object_set_data(G_OBJECT(dlg), "forward", b);
2062
2063 /* "Apply" button */
2064 b = gtk_button_new_from_stock(GTK_STOCK_APPLY);
2065 g_object_set_data(G_OBJECT(b), "dlg", dlg);
2066 g_signal_connect(G_OBJECT(b), "clicked",
2067 G_CALLBACK(dwiz_apply),
2068 dwinfo);
2069 gtk_container_add(GTK_CONTAINER(hbox), b);
2070 g_object_set_data(G_OBJECT(dlg), "apply", b);
2071
2072 /* Help button for panel mode selection */
2073 b = context_help_button(hbox, PANEL_MODE);
2074 g_object_set_data(G_OBJECT(dlg), "help", b);
2075 }
2076
2077 /* the title for the top of a given notebook page */
2078
dwiz_page_add_title(GtkWidget * vbox,int i,int smax)2079 static void dwiz_page_add_title (GtkWidget *vbox, int i, int smax)
2080 {
2081 GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
2082 GtkWidget *label= gtk_label_new(NULL);
2083 gchar *buf;
2084
2085 buf = g_markup_printf_escaped("<span face=\"sans\" "
2086 "weight=\"bold\" "
2087 "color=\"white\" "
2088 "background=\"#6C7B8A\" "
2089 "size=\"x-large\"> %-*s </span>",
2090 smax, _(wizcode_string(i)));
2091 gtk_label_set_markup(GTK_LABEL(label), buf);
2092 g_free(buf);
2093 g_object_set_data(G_OBJECT(hbox), "title", GINT_TO_POINTER(1));
2094 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
2095 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2096 }
2097
dw_opts_new(int create)2098 static dw_opts *dw_opts_new (int create)
2099 {
2100 dw_opts *opts = mymalloc(sizeof *opts);
2101
2102 if (opts != NULL) {
2103 opts->flags = (create)? DW_CREATE : 0;
2104 opts->vlist = NULL;
2105 opts->uid = opts->tid = 0;
2106 if (create) {
2107 int i;
2108
2109 for (i=0; i<4; i++) {
2110 opts->dvals[i] = 0;
2111 }
2112 }
2113 }
2114
2115 return opts;
2116 }
2117
2118 /* The main driver for the "wizard". If "create" is non-zero that
2119 means we're setting the structure for a newly created dataset,
2120 otherwise we're modifying the structure of an existing dataset.
2121 */
2122
data_structure_wizard(int create)2123 static void data_structure_wizard (int create)
2124 {
2125 GtkWidget *dialog;
2126 GtkWidget *vbox;
2127 GtkWidget *nb;
2128 GtkWidget *page;
2129 DATASET *dwinfo;
2130 dw_opts *opts;
2131 int i, n, smax = 0;
2132
2133 dwinfo = datainfo_new();
2134 if (dwinfo == NULL) {
2135 nomem();
2136 return;
2137 }
2138
2139 opts = dw_opts_new(create);
2140 if (opts == NULL) {
2141 free(dwinfo);
2142 return;
2143 }
2144
2145 /* copy current relevant info */
2146 dwinfo_init(dwinfo);
2147
2148 /* GTK dialog wrapper */
2149 dialog = gretl_dialog_new(_("Data structure wizard"), mdata->main,
2150 GRETL_DLG_QUASI_MODAL);
2151 g_object_set_data(G_OBJECT(dialog), "dwinfo", dwinfo);
2152 g_object_set_data(G_OBJECT(dialog), "opts", opts);
2153 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
2154
2155 /* notebook to hold the steps */
2156 nb = gtk_notebook_new();
2157 g_object_set_data(G_OBJECT(nb), "dlg", dialog);
2158 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(nb), FALSE);
2159 gtk_notebook_set_show_border(GTK_NOTEBOOK(nb), FALSE);
2160 gtk_container_add(GTK_CONTAINER(vbox), nb);
2161
2162 g_object_set_data(G_OBJECT(dialog), "nb", nb);
2163
2164 /* free allocated memory on exit */
2165 g_signal_connect(G_OBJECT(dialog), "destroy",
2166 G_CALLBACK(free_dwinfo),
2167 dwinfo);
2168 g_signal_connect(G_OBJECT(dialog), "destroy",
2169 G_CALLBACK(free_dw_opts),
2170 opts);
2171
2172 for (i=0; i<=DW_CONFIRM; i++) {
2173 n = g_utf8_strlen(_(wizcode_string(i)), -1);
2174 if (n > smax) {
2175 smax = n;
2176 }
2177 }
2178
2179 /* make all the notebook pages */
2180 for (i=0; i<=DW_CONFIRM; i++) {
2181 page = gtk_vbox_new(FALSE, 5);
2182 gtk_container_set_border_width(GTK_CONTAINER(page), 5);
2183 dwiz_page_add_title(page, i, smax);
2184 gtk_notebook_append_page(GTK_NOTEBOOK(nb), page, NULL);
2185 if (i == DW_CONFIRM) {
2186 dwiz_confirm_label(page);
2187 }
2188 gtk_widget_show(page);
2189 }
2190
2191 build_dwiz_buttons(dialog, dwinfo);
2192 gtk_widget_show(nb);
2193
2194 dwiz_prepare_page(GTK_NOTEBOOK(nb), 0, DW_FORWARD, dwinfo);
2195 gtk_notebook_set_current_page(GTK_NOTEBOOK(nb), 0);
2196
2197 /* note: we can't use gtk_widget_show_all() here
2198 because component widgets may be displayed
2199 selectively */
2200 gtk_widget_show(dialog);
2201 }
2202
2203 /* public interface */
2204
2205 /* Take the user through a series of dialogs to define the structure
2206 of the data set, either when creating a new data set or by way of
2207 restructuring an existing data set.
2208 */
2209
data_structure_dialog(void)2210 void data_structure_dialog (void)
2211 {
2212 data_structure_wizard(0);
2213 }
2214
new_data_structure_dialog(void)2215 void new_data_structure_dialog (void)
2216 {
2217 data_structure_wizard(1);
2218 }
2219