/* * Copyright (c) by Allin Cottrell * * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* selector.c for gretl */ #include "gretl.h" #include "selector.h" #include "dlgutils.h" #include "menustate.h" #include "fileselect.h" #include "fnsave.h" #include "treeutils.h" #include "var.h" #include "gretl_func.h" #include "libset.h" #if 0 #include "bootstrap.h" #endif #define VLDEBUG 0 enum { SR_LVARS = 1, SR_RVARS1, SR_RVARS2 }; #define N_EXTRA 6 #define N_RADIOS 2 struct _selector { GtkWidget *dlg; GtkWidget *vbox; GtkWidget *action_area; GtkWidget *lvars; GtkWidget *depvar; GtkWidget *rvars1; GtkWidget *rvars2; GtkWidget *default_check; GtkWidget *add_button; GtkWidget *lags_button; GtkWidget *extra[N_EXTRA]; GtkWidget *radios[N_RADIOS]; int code; int active_var; int error; gretlopt opts; char *cmdlist; gpointer data; int (*callback)(); }; #ifdef ENABLE_GMP #define MODEL_CODE(c) (c == OLS || c == CORC || c == HILU || c == WLS || \ c == HCCM || c == HSK || c == ARMA || c == ARCH || \ c == TSLS || c == LOGIT || c == PROBIT || c == GARCH || \ c == AR || c == MPOLS || c == LAD || c == LOGISTIC || \ c == TOBIT || c == PWE || c == POISSON || c == PANEL || \ c == PANEL_WLS || c == PANEL_B || c == ARBOND) #else #define MODEL_CODE(c) (c == OLS || c == CORC || c == HILU || c == WLS || \ c == HCCM || c == HSK || c == ARMA || c == ARCH || \ c == TSLS || c == LOGIT || c == PROBIT || c == GARCH || \ c == AR || c == LAD || c == LOGISTIC || \ c == TOBIT || c == PWE || c == POISSON || c == PANEL || \ c == PANEL_WLS || c == PANEL_B || c == ARBOND) #endif #define COINT_CODE(c) (c == COINT || c == COINT2) #define VEC_CODE(c) (c == COINT || c == COINT2 || c == VAR || \ c == VECM || c == VLAGSEL) #define VEC_MODEL_CODE(c) (c == VAR || c == VECM || c == VLAGSEL) #define ADDVAR_CODE(c) (c == LOGS || c == LAGS || c == SQUARE || \ c == DIFF || c == LDIFF) #define GRAPH_CODE(c) (c == GR_PLOT || c == GR_XY || c == GR_IMP || GR_DUMMY) #define TWO_VARS_CODE(c) (c == SPEARMAN || c == ELLIPSE || c == XCORRGM) #define WANT_TOGGLES(c) (c == ARBOND || \ c == ARMA || \ c == COINT || \ c == COINT2 || \ c == GARCH || \ c == HILU || \ c == LOGIT || \ c == OLS || \ c == PANEL || \ c == PANEL_WLS || \ c == PANEL_B || \ c == PROBIT || \ c == TOBIT || \ c == TSLS || \ c == VAR || \ c == VECM || \ c == VLAGSEL || \ c == WLS) #define WANT_RADIOS(c) (c == COINT2 || c == VECM || c == ARMA || c == PANEL || \ c == SCATTERS || c == COINT || c == ARBOND || c == OMIT) #define USE_VECXLIST(c) (c == VAR || c == VLAGSEL || c == VECM) #define AUX_LAST(c) (c == TSLS || \ c == VAR || \ c == VLAGSEL || \ c == VECM) #define dataset_lags_ok(d) ((d)->structure == TIME_SERIES || \ (d)->structure == SPECIAL_TIME_SERIES || \ (d)->structure == STACKED_TIME_SERIES) #define select_lags_primary(c) (MODEL_CODE(c)) #define select_lags_aux(c) (c == VAR || c == VECM || c == VLAGSEL || c == TSLS) #define select_lags_depvar(c) (MODEL_CODE(c) && c != ARMA && c != ARBOND) static int default_var = -1; static int want_seasonals; static int default_order; static int vartrend; static int lags_hidden; static int y_x_lags_enabled; static int y_w_lags_enabled; static int arma_p = 1; static int arma_P = 0; static int arima_d = 0; static int arima_D = 0; static int arma_q = 1; static int arma_Q = 0; static int garch_p = 1; static int garch_q = 1; static int arma_const = 1; static int arma_x12 = 0; static int *xlist; static int *instlist; static int *veclist; static int *vecxlist; static GtkWidget *multiplot_label; static GtkWidget *multiplot_menu; static selector *open_selector; static gint listvar_special_click (GtkWidget *widget, GdkEventButton *event, gpointer data); static gint lvars_right_click (GtkWidget *widget, GdkEventButton *event, selector *sr); static gboolean lags_dialog_driver (GtkWidget *w, selector *sr); static int list_show_var (int v, int code, int show_lags); static int selector_get_depvar_number(selector *sr); static int spinner_get_int (GtkWidget *w); static int functions_list (selector *sr); static void primary_rhs_varlist (selector *sr, GtkWidget *vbox); #include "lagpref.c" static int selection_at_max (selector *sr, int nsel) { int ret = 0; if (TWO_VARS_CODE(sr->code) && nsel == 2) { ret = 1; } return ret; } static int sr_get_lag_context (selector *sr, int locus) { int c = 0; if (sr == NULL || !dataset_lags_ok(datainfo)) { return 0; } if (locus == SR_RVARS1 && select_lags_primary(sr->code)) { c = LAG_X; } else if (locus == SR_RVARS2 && select_lags_aux(sr->code)) { c = (sr->code == TSLS)? LAG_W : LAG_X; } return c; } static int lag_context_from_widget (GtkWidget *w) { gint locus = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "locus")); selector *sr = g_object_get_data(G_OBJECT(w), "sr"); int context = 0; if (sr != NULL && locus) { context = sr_get_lag_context(sr, locus); } return context; } static int lags_button_relevant (selector *sr, int locus) { if (sr->lags_button != NULL) { if (locus == SR_RVARS1 && select_lags_primary(sr->code)) { return 1; } else if (locus == SR_RVARS2 && select_lags_aux(sr->code)) { return 1; } } return 0; } void clear_selector (void) { default_var = -1; default_order = 0; vartrend = 0; arma_p = 1; arima_d = 0; arma_q = 1; arma_P = 0; arima_D = 0; arma_Q = 0; arma_const = 1; garch_p = 1; garch_q = 1; free(xlist); xlist = NULL; free(instlist); instlist = NULL; free(veclist); veclist = NULL; free(vecxlist); vecxlist = NULL; destroy_lag_preferences(); } static int selector_get_depvar_number (selector *sr) { int ynum = -1; if (sr != NULL && sr->depvar != NULL) { const char *s = gtk_entry_get_text(GTK_ENTRY(sr->depvar)); if (s != NULL && *s != '\0') { if (sr->code == SAVE_FUNCTIONS) { ynum = user_function_index_by_name(s); } else { ynum = varindex(datainfo, s); if (ynum == datainfo->v) { ynum = -1; } } } } return ynum; } static gint dblclick_lvars_row (GtkWidget *w, GdkEventButton *event, selector *sr); static void real_varlist_set_var (int v, int lag, GtkListStore *store, GtkTreeIter *iter) { if (lag == 0) { gtk_list_store_set(store, iter, 0, v, 1, 0, 2, datainfo->varname[v], -1); } else { char vstr[VNAMELEN + 8]; sprintf(vstr, "%s(-%d)", datainfo->varname[v], lag); gtk_list_store_set(store, iter, 0, v, 1, lag, 2, vstr, -1); } } static int varlist_remove_var_full (int v, GtkTreeModel *mod, GtkTreeIter *iter) { GtkTreeIter *last = iter; int row = -1, ok = 1; int tv, i = 0; #if VLDEBUG fprintf(stderr, "\nvarlist_remove_var_full: looking for var %d (%s)\n", v, datainfo->varname[v]); #endif if (gtk_tree_model_get_iter_first(mod, iter)) { last = iter; while (1) { gtk_tree_model_get(mod, iter, 0, &tv, -1); #if VLDEBUG fprintf(stderr, "row %d: checking against %d\n", i, tv); #endif if (tv == v) { ok = gtk_list_store_remove(GTK_LIST_STORE(mod), iter); #if VLDEBUG fprintf(stderr, "removed at row %d, now ok = %d\n", i, ok); #endif if (row < 0) { row = i; } if (ok) { continue; } else { break; } } if (!gtk_tree_model_iter_next(mod, iter)) { /* iter is now invalid */ iter = last; break; } last = iter; i++; } } else { iter = last; } return row; } static void varlist_insert_var_full (int v, GtkTreeModel *mod, GtkTreeIter *iter, selector *sr, int locus) { int lcontext = 0; #if VLDEBUG fprintf(stderr, "varlist_insert_var_full: starting var %d\n", v); #endif if (v > 0 && dataset_lags_ok(datainfo)) { lcontext = sr_get_lag_context(sr, locus); } if (lcontext) { int *laglist = get_lag_pref_as_list(v, lcontext); if (laglist != NULL) { int i, row, append = 0; row = varlist_remove_var_full(v, mod, iter); if (row < 0) { append = 1; } #if VLDEBUG fprintf(stderr, "got laglist, done prior removal, row=%d, append=%d\n", row, append); #endif for (i=1; i<=laglist[0]; i++) { if (append) { gtk_list_store_append(GTK_LIST_STORE(mod), iter); } else { gtk_list_store_insert(GTK_LIST_STORE(mod), iter, row++); } #if VLDEBUG fprintf(stderr, "adding var %d, lag %d\n", v, laglist[i]); #endif real_varlist_set_var(v, laglist[i], GTK_LIST_STORE(mod), iter); } free(laglist); } else { lcontext = 0; } } if (lcontext == 0) { gtk_list_store_append(GTK_LIST_STORE(mod), iter); real_varlist_set_var(v, 0, GTK_LIST_STORE(mod), iter); } } static gboolean set_active_var (GtkWidget *widget, GdkEventButton *event, selector *sr) { GtkTreeView *view = GTK_TREE_VIEW(widget); GtkTreeModel *model = gtk_tree_view_get_model(view); GtkTreePath *path; if (gtk_tree_view_get_path_at_pos(view, event->x, event->y, &path, NULL, NULL, NULL)) { GtkTreeIter iter; gint varnum, row; gtk_tree_model_get_iter(model, &iter, path); gtk_tree_model_get(model, &iter, 0, &varnum, -1); if (sr != NULL) { sr->active_var = varnum; } row = tree_path_get_row_number(path); g_object_set_data(G_OBJECT(widget), "active_row", GINT_TO_POINTER(row)); gtk_tree_path_free(path); } return FALSE; } static void list_append_var_simple (GtkListStore *store, GtkTreeIter *iterp, int v) { const char *vname = datainfo->varname[v]; gtk_list_store_append(store, iterp); gtk_list_store_set(store, iterp, 0, v, 1, 0, 2, vname, -1); } static void list_append_var (GtkListStore *store, GtkTreeIter *iter, int v, selector *sr, int locus) { int i, lcontext = 0; if (v > 0 && dataset_lags_ok(datainfo)) { lcontext = sr_get_lag_context(sr, locus); } if (lcontext) { int *laglist = get_lag_pref_as_list(v, lcontext); if (laglist != NULL) { for (i=1; i<=laglist[0]; i++) { gtk_list_store_append(store, iter); real_varlist_set_var(v, laglist[i], store, iter); } free(laglist); } else { lcontext = 0; } } if (lcontext == 0) { gtk_list_store_append(store, iter); real_varlist_set_var(v, 0, store, iter); } } /* build a new liststore and associated tree view, and pack into the given box */ static GtkWidget *var_list_box_new (GtkBox *box, selector *sr, int locus) { GtkListStore *store; GtkWidget *view, *scroller; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection *select; int width = 120; int height = -1; store = gtk_list_store_new(3, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING); view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(G_OBJECT(store)); g_object_set_data(G_OBJECT(view), "sr", sr); g_object_set_data(G_OBJECT(view), "locus", GINT_TO_POINTER(locus)); renderer = gtk_cell_renderer_text_new(); g_object_set(renderer, "ypad", 0, NULL); column = gtk_tree_view_column_new_with_attributes(NULL, renderer, "text", 2, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); gtk_tree_view_set_reorderable(GTK_TREE_VIEW(view), FALSE); select = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); gtk_tree_selection_set_mode(select, GTK_SELECTION_EXTENDED); g_signal_connect(G_OBJECT(view), "motion_notify_event", G_CALLBACK(listbox_drag), NULL); if (locus == SR_LVARS) { /* left-hand box with the selectable vars */ g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(lvars_right_click), sr); g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(set_active_var), sr); g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(dblclick_lvars_row), sr); } else if (locus == SR_RVARS1 || locus == SR_RVARS2) { /* lists of selected items */ g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(set_active_var), NULL); g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(listvar_special_click), view); } scroller = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scroller), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(scroller), view); gtk_box_pack_start(box, scroller, TRUE, TRUE, 0); width *= gui_scale; gtk_widget_set_size_request(view, width, height); gtk_widget_show(view); gtk_widget_show(scroller); return view; } /* add to "extra" var slot the current selection from sr->lvars */ static void real_set_extra_var (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, selector *sr) { gint vnum; gchar *vname; gtk_tree_model_get(model, iter, 0, &vnum, 2, &vname, -1); gtk_entry_set_text(GTK_ENTRY(sr->extra[0]), vname); g_free(vname); g_object_set_data(G_OBJECT(sr->extra[0]), "data", GINT_TO_POINTER(vnum)); } static void set_extra_var_callback (GtkWidget *w, selector *sr) { GtkTreeSelection *selection; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sr->lvars)); gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) real_set_extra_var, sr); } static void real_set_factor (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, selector *sr) { gint vnum; gchar *vname; gtk_tree_model_get(model, iter, 0, &vnum, 2, &vname, -1); gtk_entry_set_text(GTK_ENTRY(sr->rvars1), vname); g_free(vname); g_object_set_data(G_OBJECT(sr->rvars1), "data", GINT_TO_POINTER(vnum)); } static void set_factor_callback (GtkWidget *w, selector *sr) { GtkTreeSelection *selection; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sr->lvars)); gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) real_set_factor, sr); } static void remove_as_indep_var (selector *sr, gint v) { GtkTreeView *view = GTK_TREE_VIEW(sr->rvars1); GtkTreeModel *model = gtk_tree_view_get_model(view); GtkTreeIter iter; gboolean ok; gint xnum; if (gtk_tree_model_get_iter_first(model, &iter)) { do { ok = TRUE; gtk_tree_model_get(model, &iter, 0, &xnum, -1); if (xnum == v) { ok = gtk_list_store_remove(GTK_LIST_STORE(model), &iter); } } while (ok && gtk_tree_model_iter_next(model, &iter)); } } static void maybe_insert_or_revise_depvar_lags (selector *sr, int v, int lcontext, int revise) { int *laglist = NULL; GtkWidget *w; GtkTreeModel *mod; GtkTreeIter iter; int append = 1; int modv, row = 0; int jmin = 0, jmax = 1; int i, j; if (lcontext == LAG_Y_X) { jmin = 0; jmax = 1; } else if (lcontext == LAG_Y_W) { /* instrument, not indep var */ jmin = 1; jmax = 2; } for (j=jmin; j 0)? sr->rvars2: sr->rvars1; if (w == NULL) { return; } mod = gtk_tree_view_get_model(GTK_TREE_VIEW(w)); if (lcontext == 0) { lcontext = (j > 0)? LAG_Y_W : LAG_Y_X; } laglist = get_lag_pref_as_list(v, lcontext); if (laglist == NULL) { if (revise) { varlist_remove_var_full(v, mod, &iter); } return; } varlist_remove_var_full(v, mod, &iter); if (gtk_tree_model_get_iter_first(mod, &iter)) { do { gtk_tree_model_get(mod, &iter, 0, &modv, -1); if (modv > 0) { append = 0; break; } row++; } while (gtk_tree_model_iter_next(mod, &iter)); } for (i=1; i<=laglist[0]; i++) { if (append) { gtk_list_store_append(GTK_LIST_STORE(mod), &iter); } else { gtk_list_store_insert(GTK_LIST_STORE(mod), &iter, row++); } #if VLDEBUG fprintf(stderr, "depvar_lags: adding var %d, lag %d\n", v, laglist[i]); #endif real_varlist_set_var(v, laglist[i], GTK_LIST_STORE(mod), &iter); } free(laglist); } } static void maybe_insert_depvar_lags (selector *sr, int v, int lcontext) { maybe_insert_or_revise_depvar_lags(sr, v, lcontext, 0); } static void maybe_revise_depvar_lags (selector *sr, int v, int lcontext) { maybe_insert_or_revise_depvar_lags(sr, v, lcontext, 1); } static void dependent_var_cleanup (selector *sr, int newy) { int oldy = selector_get_depvar_number(sr); if (oldy != newy) { if (oldy > 0) { remove_as_indep_var(sr, oldy); /* lags business */ } y_x_lags_enabled = 0; y_w_lags_enabled = 0; remove_as_indep_var(sr, newy); } } static void set_public_from_active (selector *sr) { gint v = sr->active_var; if (sr->depvar == NULL) { return; } dependent_var_cleanup(sr, v); gtk_entry_set_text(GTK_ENTRY(sr->depvar), user_function_name_by_index(v)); } static void set_dependent_var_from_active (selector *sr) { gint v = sr->active_var; if (sr->depvar == NULL) { return; } /* models: if we select foo as regressand, remove it from the list of regressors if need be; also remove lags associated with the previous dependent var, if any. */ if (MODEL_CODE(sr->code)) { dependent_var_cleanup(sr, v); } gtk_entry_set_text(GTK_ENTRY(sr->depvar), datainfo->varname[v]); if (select_lags_depvar(sr->code)) { maybe_insert_depvar_lags(sr, v, 0); } } static void real_set_dependent_var (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, selector *sr) { gchar *vname; gint v; gtk_tree_model_get(model, iter, 0, &v, 2, &vname, -1); if (MODEL_CODE(sr->code)) { dependent_var_cleanup(sr, v); } gtk_entry_set_text(GTK_ENTRY(sr->depvar), vname); if (select_lags_depvar(sr->code)) { maybe_insert_depvar_lags(sr, v, 0); } } static void set_dependent_var_callback (GtkWidget *w, selector *sr) { GtkTreeSelection *selection; if (sr->depvar == NULL) return; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(sr->lvars)); gtk_tree_selection_selected_foreach (selection, (GtkTreeSelectionForeachFunc) real_set_dependent_var, sr); } static void set_right_var_from_main (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, selector *sr) { GtkTreeModel *rmod; GtkTreeIter r_iter; gchar *vnum = NULL; int v; gtk_tree_model_get(model, iter, 0, &vnum, -1); rmod = gtk_tree_view_get_model(GTK_TREE_VIEW(sr->rvars1)); if (rmod == NULL) { g_free(vnum); return; } v = atoi(vnum); if (gtk_tree_model_get_iter_first(rmod, &r_iter)) { while (gtk_tree_model_iter_next(rmod, &r_iter)) { ; } } gtk_list_store_append(GTK_LIST_STORE(rmod), &r_iter); real_varlist_set_var(v, 0, GTK_LIST_STORE(rmod), &r_iter); g_free(vnum); } static void set_vars_from_main (selector *sr) { GtkTreeSelection *selection; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mdata->listbox)); gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) set_right_var_from_main, sr); } /* Append a specified variable in the SR_RVARS1 locus: used when saving data and there's only one variable to save. */ static void select_singleton (selector *sr) { GtkTreeModel *lmod, *rmod; GtkTreeIter iter; int v; lmod = gtk_tree_view_get_model(GTK_TREE_VIEW(sr->lvars)); if (lmod == NULL) { return; } rmod = gtk_tree_view_get_model(GTK_TREE_VIEW(sr->rvars1)); if (rmod == NULL) { return; } gtk_tree_model_get_iter_first(lmod, &iter); gtk_tree_model_get(lmod, &iter, 0, &v, -1); gtk_tree_model_get_iter_first(rmod, &iter); gtk_list_store_append(GTK_LIST_STORE(rmod), &iter); gtk_list_store_set(GTK_LIST_STORE(rmod), &iter, 0, v, 1, 0, 2, datainfo->varname[v], -1); } static void real_add_generic (GtkTreeModel *srcmodel, GtkTreeIter *srciter, selector *sr, int locus) { GtkWidget *list; GtkTreeModel *model; GtkTreeIter iter; gchar *vname = NULL; gint v, xnum; gint already_there = 0; gint at_max = 0; gint keep_names = 0; int nvars = 0; list = (locus == SR_RVARS2)? sr->rvars2 : sr->rvars1; if (!GTK_IS_TREE_VIEW(list)) { return; } model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); if (model == NULL) { return; } keep_names = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(sr->lvars), "keep_names")); if (keep_names) { gtk_tree_model_get(srcmodel, srciter, 0, &v, 2, &vname, -1); } else { gtk_tree_model_get(srcmodel, srciter, 0, &v, -1); } nvars = 0; if (gtk_tree_model_get_iter_first(model, &iter)) { do { nvars++; if (!at_max && selection_at_max(sr, nvars)) { at_max = 1; } if (!already_there) { gtk_tree_model_get(model, &iter, 0, &xnum, -1); if (xnum == v) { already_there = 1; } } } while (gtk_tree_model_iter_next(model, &iter)); } if (!already_there && !at_max) { if (vname != NULL) { gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, v, 1, 0, 2, vname, -1); g_free(vname); } else { #if VLDEBUG fprintf(stderr, "real_add_generic: calling varlist_insert_var_full\n"); #endif varlist_insert_var_full(v, model, &iter, sr, locus); } nvars++; } if (sr->add_button != NULL && at_max) { gtk_widget_set_sensitive(sr->add_button, FALSE); } if (nvars > 0 && lags_button_relevant(sr, locus)) { gtk_widget_set_sensitive(sr->lags_button, TRUE); } } static void add_to_rvars1 (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, selector *sr) { /* models: don't add the regressand to the list of regressors; functions: keep public and private interfaces distinct */ if (MODEL_CODE(sr->code) || sr->code == SAVE_FUNCTIONS) { gint xnum, ynum; gtk_tree_model_get(model, iter, 0, &xnum, -1); ynum = selector_get_depvar_number(sr); if (xnum == ynum) { return; } } real_add_generic(model, iter, sr, SR_RVARS1); } static void add_to_rvars2 (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, selector *sr) { real_add_generic(model, iter, sr, SR_RVARS2); } static void add_to_rvars2_callback (GtkWidget *w, selector *sr) { GtkTreeSelection *selection; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sr->lvars)); gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) add_to_rvars2, sr); } static void add_all_to_rvars1_callback (GtkWidget *w, selector *sr) { GtkTreeSelection *selection; if (!GTK_IS_TREE_VIEW(sr->lvars)) { return; } selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sr->lvars)); gtk_tree_selection_select_all(selection); gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) add_to_rvars1, sr); } static void add_to_rvars1_callback (GtkWidget *w, selector *sr) { GtkTreeSelection *selection; if (!GTK_IS_TREE_VIEW(sr->lvars)) { return; } selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sr->lvars)); gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) add_to_rvars1, sr); } static void remove_from_right_callback (GtkWidget *w, gpointer data) { GtkTreeView *view = GTK_TREE_VIEW(data); GtkTreeModel *model = gtk_tree_view_get_model(view); GtkTreeSelection *selection = gtk_tree_view_get_selection(view); GtkTreePath *path; GtkTreeIter iter, last; selector *sr; int context = 0; int nsel = 0; if (model == NULL || selection == NULL) { return; } /* get to the last row */ if (gtk_tree_model_get_iter_first(model, &iter)) { last = iter; nsel = 1; while (gtk_tree_model_iter_next(model, &iter)) { last = iter; nsel++; } } else { return; } context = lag_context_from_widget(GTK_WIDGET(view)); /* work back up, deleting selected rows */ path = gtk_tree_model_get_path(model, &last); while (1) { if (gtk_tree_model_get_iter(model, &last, path) && gtk_tree_selection_iter_is_selected(selection, &last)) { if (context) { gint v, lag; gtk_tree_model_get(model, &last, 0, &v, 1, &lag, -1); remove_specific_lag(v, lag, context); } gtk_list_store_remove(GTK_LIST_STORE(model), &last); nsel--; } if (!gtk_tree_path_prev(path)) { break; } } sr = g_object_get_data(G_OBJECT(data), "selector"); if (sr != NULL && sr->add_button != NULL && !GTK_WIDGET_SENSITIVE(sr->add_button) && !selection_at_max(sr, nsel)) { gtk_widget_set_sensitive(sr->add_button, TRUE); } if (context && sr != NULL && sr->lags_button != NULL) { if (nsel == 0) { gtk_widget_set_sensitive(sr->lags_button, FALSE); } } } /* callbacks from button presses in list boxes: double and right clicks do special stuff */ static gint dblclick_lvars_row (GtkWidget *w, GdkEventButton *event, selector *sr) { if (event != NULL && event->type == GDK_2BUTTON_PRESS) { if (sr->code == SAVE_FUNCTIONS) { set_public_from_active(sr); } else { set_dependent_var_from_active(sr); if (sr->default_check != NULL) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sr->default_check), TRUE); } } } return FALSE; } static gint listvar_special_click (GtkWidget *widget, GdkEventButton *event, gpointer data) { GdkWindow *topwin; GdkModifierType mods; topwin = gtk_widget_get_parent_window(GTK_WIDGET(data)); gdk_window_get_pointer(topwin, NULL, NULL, &mods); if (mods & GDK_BUTTON2_MASK) { gtk_tree_view_set_reorderable(GTK_TREE_VIEW(data), TRUE); } else { gtk_tree_view_set_reorderable(GTK_TREE_VIEW(data), FALSE); } if (mods & GDK_BUTTON3_MASK) { remove_from_right_callback(NULL, data); return TRUE; } return FALSE; } static gint lvars_right_click (GtkWidget *widget, GdkEventButton *event, selector *sr) { GdkWindow *topwin; GdkModifierType mods; topwin = gtk_widget_get_parent_window(sr->lvars); gdk_window_get_pointer(topwin, NULL, NULL, &mods); if (mods & GDK_BUTTON3_MASK) { add_to_rvars1_callback(NULL, sr); return TRUE; } return FALSE; } /* end special click callbacks */ static void varlist_insert_const (GtkWidget *w) { GtkTreeModel *mod = gtk_tree_view_get_model(GTK_TREE_VIEW(w)); GtkTreeIter iter; gtk_tree_model_get_iter_first(mod, &iter); gtk_list_store_append(GTK_LIST_STORE(mod), &iter); gtk_list_store_set(GTK_LIST_STORE(mod), &iter, 0, 0, 1, 0, 2, "const", -1); } static void clear_vars (GtkWidget *w, selector *sr) { GtkTreeSelection *selection; /* deselect all vars on left */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sr->lvars)); gtk_tree_selection_unselect_all(selection); /* clear dependent var slot */ if (sr->depvar != NULL) { gtk_entry_set_text(GTK_ENTRY(sr->depvar), ""); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sr->default_check), FALSE); default_var = -1; } if (sr->code == GR_DUMMY || sr->code == GR_3D) { /* clear special slot */ gtk_entry_set_text(GTK_ENTRY(sr->rvars1), ""); } else { /* empty lower right variable list */ clear_varlist(sr->rvars1); if (sr->add_button != NULL) { gtk_widget_set_sensitive(sr->add_button, TRUE); } } if (MODEL_CODE(sr->code) && sr->code != ARMA) { /* insert default const in regressors box */ varlist_insert_const(sr->rvars1); } if (sr->rvars2 != NULL) { /* empty lower right variable list */ clear_varlist(sr->rvars2); if (sr->code == TSLS) { varlist_insert_const(sr->rvars2); } } if (sr->lags_button != NULL) { gtk_widget_set_sensitive(sr->lags_button, FALSE); } clear_selector(); } static gint varlist_row_count (selector *sr, int locus, int *realrows) { int lcontext = 0; GtkWidget *w; GtkTreeModel *mod; GtkTreeIter iter; gint v, lag, n = 0; w = (locus == SR_RVARS1)? sr->rvars1 : sr->rvars2; if (realrows != NULL) { lcontext = sr_get_lag_context(sr, locus); *realrows = 0; } if (w != NULL) { mod = gtk_tree_view_get_model(GTK_TREE_VIEW(w)); if (GTK_IS_TREE_MODEL(mod) && gtk_tree_model_get_iter_first(mod, &iter)) { do { n++; if (lcontext) { gtk_tree_model_get(mod, &iter, 0, &v, 1, &lag, -1); if (!is_lag_dummy(v, lag, lcontext)) { *realrows += 1; } } } while (gtk_tree_model_iter_next(mod, &iter)); } } if (realrows != NULL && lcontext == 0) { *realrows = n; } return n; } static void topslot_empty (int code) { switch (code) { case GR_XY: case GR_3D: case GR_IMP: errbox(_("You must select an X-axis variable")); break; case SCATTERS: errbox(_("You must select a Y-axis variable")); break; case SAVE_FUNCTIONS: errbox(_("You must specify a public interface")); break; default: errbox(_("You must select a dependent variable")); } } static void reverse_list (char *list) { char *tmp, *p; char istr[8]; p = strchr(list, ';'); if (p == NULL) return; tmp = malloc(strlen(list) + 4); if (tmp == NULL) return; sscanf(list, "%7s", istr); strcpy(tmp, p + 2); strcat(tmp, " ; "); strcat(tmp, istr); strcpy(list, tmp); free(tmp); } enum cmdlist_codes { ADD_NOW, ADD_AT_END }; static int add_to_cmdlist (selector *sr, const char *add) { int n = strlen(sr->cmdlist); char *cmdlist = NULL; int err = 0; if (n % MAXLEN > MAXLEN - 32) { int blocks = 2 + n / MAXLEN; cmdlist = realloc(sr->cmdlist, blocks * MAXLEN); if (cmdlist == NULL) { err = 1; } else { sr->cmdlist = cmdlist; } } if (!err) { strcat(sr->cmdlist, add); } return err; } static void add_pdq_vals_to_cmdlist (selector *sr) { char s[32]; if (sr->code == GARCH) { garch_p = spinner_get_int(sr->extra[0]); garch_q = spinner_get_int(sr->extra[1]); sprintf(s, "%d %d ; ", garch_p, garch_q); add_to_cmdlist(sr, s); return; } if (sr->code == ARBOND) { int p = spinner_get_int(sr->extra[0]); sprintf(s, "%d ; ", p); add_to_cmdlist(sr, s); return; } if (sr->code == ARCH) { int p = spinner_get_int(sr->extra[0]); sprintf(s, "%d ", p); add_to_cmdlist(sr, s); return; } arma_p = spinner_get_int(sr->extra[0]); arima_d = spinner_get_int(sr->extra[1]); arma_q = spinner_get_int(sr->extra[2]); sprintf(s, "%d %d %d ; ", arma_p, arima_d, arma_q); add_to_cmdlist(sr, s); if (sr->extra[3] != NULL) { arma_P = spinner_get_int(sr->extra[3]); arima_D = spinner_get_int(sr->extra[4]); arma_Q = spinner_get_int(sr->extra[5]); if (arma_P > 0 || arima_D > 0 || arma_Q > 0) { sprintf(s, "%d %d %d ; ", arma_P, arima_D, arma_Q); add_to_cmdlist(sr, s); } } } /* Take the stored preferred laglist for a variable (if any) and convert to a string specification for adding to the regression command line. */ static char * discrete_lags_string (const char *vname, const int *laglist, char context) { int len = strlen(vname) + 4; gchar *tmp; char *s; int i, li; int err = 0; s = malloc(len + laglist[0] * 6); if (s != NULL) { sprintf(s, " %s(", vname); for (i=1; i<=laglist[0]; i++) { li = laglist[i]; if (li > 999) { err = 1; break; } tmp = g_strdup_printf("%s%d", (li > 0)? "-" : "", li); strcat(s, tmp); if (i < laglist[0]) { strcat(s, ", "); } else { strcat(s, ")"); } g_free(tmp); } if (err) { free(s); s = NULL; } } return s; } /* for use in constructing command list, possibly with embedded lags */ static char *get_lagpref_string (int v, char context) { const char *vname = datainfo->varname[v]; const int *laglist; int lmin, lmax; char *s = NULL; if (v == 0) { if (context == LAG_Y_X || context == LAG_Y_W) { /* const as dependent: empty lags string */ return g_strdup(""); } else { /* const as indep var: just return itself */ return g_strdup(" 0"); } } get_lag_preference(v, &lmin, &lmax, &laglist, context); if (laglist != NULL) { s = discrete_lags_string(vname, laglist, context); } else if (lmin != lmax) { s = g_strdup_printf(" %s(%s%d to -%d)", vname, (lmin > 0)? "-" : "", lmin, lmax); } else if (lmin != 0) { s = g_strdup_printf(" %s(%s%d)", vname, (lmin > 0)? "-" : "", lmin); } else if (context != LAG_Y_X && context != LAG_Y_W) { s = g_strdup_printf(" %d", v); } #if LDEBUG if (s != NULL) { fprintf(stderr, "get_lagpref_string (v=%d, context=%d):\n" " constructed s = '%s'\n", v, (int) context, s); } #endif return s; } static int maybe_resize_recorder_lists (selector *sr, int n) { int err = 0; if (MODEL_CODE(sr->code) || VEC_CODE(sr->code)) { int *newlist; if (MODEL_CODE(sr->code)) { newlist = gretl_list_resize(&xlist, n); } else { newlist = gretl_list_resize(&veclist, n); } if (newlist == NULL) { err = E_ALLOC; } } return err; } static int maybe_resize_exog_recorder_lists (selector *sr, int n) { int err = 0; if (sr->code == TSLS || USE_VECXLIST(sr->code)) { int *newlist; if (sr->code == TSLS) { newlist = gretl_list_resize(&instlist, n); } else { newlist = gretl_list_resize(&vecxlist, n); } if (newlist == NULL) { err = E_ALLOC; } } return err; } static void get_rvars1_data (selector *sr, int rows, int context) { GtkTreeModel *model; GtkTreeIter iter; gint rvar, lag; gchar *rvstr; int added = 0; int i, j = 1; model = gtk_tree_view_get_model(GTK_TREE_VIEW(sr->rvars1)); gtk_tree_model_get_iter_first(model, &iter); for (i=0; ierror = E_ALLOC; break; } else { add_to_cmdlist(sr, rvstr); g_free(rvstr); added++; } /* save for future reference */ if (MODEL_CODE(sr->code) && xlist != NULL) { xlist[j++] = rvar; } else if (VEC_CODE(sr->code) && veclist != NULL) { veclist[j++] = rvar; } gtk_tree_model_iter_next(model, &iter); } if (sr->code == ARMA && added && !(sr->opts & OPT_N)) { /* add const explicitly */ add_to_cmdlist(sr, " 0"); } } static int get_rvars2_data (selector *sr, int rows, int context) { GtkTreeModel *model; GtkTreeIter iter; gint exog, lag, ynum; int *reclist = NULL; gchar *tmp; int i, j = 1; int err = 0; model = gtk_tree_view_get_model(GTK_TREE_VIEW(sr->rvars2)); gtk_tree_model_get_iter_first(model, &iter); if (sr->code == TSLS) { reclist = instlist; } else if (USE_VECXLIST(sr->code)) { reclist = vecxlist; } ynum = selector_get_depvar_number(sr); for (i=0; icode == TSLS && exog == ynum && lag == 0) { errbox("You can't use the dependent variable as an instrument"); err = 1; break; } if (is_lag_dummy(exog, lag, context)) { gtk_tree_model_iter_next(model, &iter); continue; } if (context) { tmp = get_lagpref_string(exog, context); } else { tmp = g_strdup_printf(" %d", exog); } add_to_cmdlist(sr, tmp); g_free(tmp); if (reclist != NULL) { reclist[j++] = exog; } gtk_tree_model_iter_next(model, &iter); } return err; } static void parse_extra_widgets (selector *sr, char *endbit) { const gchar *txt = NULL; char numstr[8]; int k; if (sr->code == WLS || sr->code == POISSON || sr->code == AR || sr->code == GR_DUMMY || sr->code == GR_3D) { txt = gtk_entry_get_text(GTK_ENTRY(sr->extra[0])); if (txt == NULL || *txt == '\0') { if (sr->code == WLS) { errbox(_("You must select a weight variable")); sr->error = 1; } else if (sr->code == AR) { errbox(_("You must specify a list of lags")); sr->error = 1; } else if (sr->code == GR_DUMMY || sr->code == GR_3D) { errbox(("You must select a Y-axis variable")); sr->error = 1; } } } if (sr->error) { return; } if (sr->code == WLS || sr->code == GR_DUMMY || sr->code == GR_3D) { k = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(sr->extra[0]), "data")); sprintf(numstr, "%d ", k); add_to_cmdlist(sr, numstr); } else if (sr->code == POISSON) { if (txt != NULL && *txt != '\0') { k = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(sr->extra[0]), "data")); sprintf(endbit, " ; %d", k); } } else if (sr->code == AR) { add_to_cmdlist(sr, txt); add_to_cmdlist(sr, " ; "); } } static void vec_get_spinner_data (selector *sr, int *order) { GtkAdjustment *adj; char numstr[8]; int k; /* lag order */ adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(sr->extra[0])); *order = (int) adj->value; sprintf(numstr, "%d ", *order); add_to_cmdlist(sr, numstr); if (sr->code == VECM) { /* cointegration rank */ adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(sr->extra[1])); k = (int) adj->value; sprintf(numstr, "%d", k); add_to_cmdlist(sr, numstr); } } static void parse_depvar_widget (selector *sr, char *endbit, char **dvlags, char **idvlags) { int ynum = selector_get_depvar_number(sr); if (ynum < 0) { topslot_empty(sr->code); sr->error = 1; } else { char numstr[8]; if (sr->code == GR_XY || sr->code == GR_IMP) { sprintf(endbit, " %d", ynum); } else { sprintf(numstr, "%d", ynum); add_to_cmdlist(sr, numstr); } if (dataset_lags_ok(datainfo) && select_lags_depvar(sr->code)) { *dvlags = get_lagpref_string(ynum, LAG_Y_X); if (sr->code == TSLS) { *idvlags = get_lagpref_string(ynum, LAG_Y_W); } } if (sr->default_check != NULL && GTK_TOGGLE_BUTTON(sr->default_check)->active) { default_var = ynum; } } } static void parse_special_graph_data (selector *sr) { const gchar *txt = gtk_entry_get_text(GTK_ENTRY(sr->rvars1)); char numstr[8]; if (txt == NULL || !*txt) { if (sr->code == GR_3D) { errbox(_("You must select a Z-axis variable")); } else { errbox(_("You must select a factor variable")); } sr->error = 1; } else { int v = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(sr->rvars1), "data")); sprintf(numstr, " %d", v); add_to_cmdlist(sr, numstr); } } static void construct_cmdlist (selector *sr) { gint rows = 0, realrows = 0; gchar endbit[12] = {0}; char *dvlags = NULL; char *idvlags = NULL; int context = 0; int order = 0; sr->error = 0; sr->cmdlist = mymalloc(MAXLEN); if (sr->cmdlist == NULL) { return; } *sr->cmdlist = '\0'; /* deal with content of "extra" widgets */ if (sr->code == ARMA || sr->code == ARCH || sr->code == GARCH || sr->code == ARBOND) { add_pdq_vals_to_cmdlist(sr); } else if (VEC_CODE(sr->code)) { vec_get_spinner_data(sr, &order); } else { parse_extra_widgets(sr, endbit); } /* deal with the "depvar" widget */ if (!sr->error && sr->depvar != NULL) { parse_depvar_widget(sr, endbit, &dvlags, &idvlags); } /* bail out if things have gone wrong already */ if (sr->error) { return; } if (sr->code == GR_DUMMY || sr->code == GR_3D) { parse_special_graph_data(sr); return; } rows = varlist_row_count(sr, SR_RVARS1, &realrows); if (sr->code == SCATTERS) { if (rows > 0) { add_to_cmdlist(sr, " ;"); } else { sr->error = E_ARGS; gui_errmsg(sr->error); return; } } if (VEC_CODE(sr->code) && rows < 2) { errbox(_("You must select two or more endogenous variables")); sr->error = 1; return; } if (realrows > 0) { maybe_resize_recorder_lists(sr, realrows); } /* primary RHS varlist */ context = sr_get_lag_context(sr, SR_RVARS1); get_rvars1_data(sr, rows, context); /* cases with a (possibly optional) secondary RHS list */ if (sr->code == TSLS || USE_VECXLIST(sr->code)) { rows = varlist_row_count(sr, SR_RVARS2, &realrows); if (rows > 0) { if (realrows > 0) { maybe_resize_exog_recorder_lists(sr, realrows); } context = sr_get_lag_context(sr, SR_RVARS2); if (sr->code == TSLS && dvlags != NULL) { add_to_cmdlist(sr, dvlags); free(dvlags); dvlags = NULL; } if (*sr->cmdlist != '\0') { add_to_cmdlist(sr, " ;"); } sr->error = get_rvars2_data(sr, rows, context); } else if (sr->code == TSLS) { /* only tsls requires a "secondary" variable selection */ errbox(_("You must specify a set of instrumental variables")); sr->error = 1; } } /* deal with any trailing strings */ if (!sr->error) { if (endbit[0] != '\0') { add_to_cmdlist(sr, endbit); } else if (dvlags != NULL) { add_to_cmdlist(sr, dvlags); free(dvlags); } else if (idvlags != NULL) { add_to_cmdlist(sr, idvlags); free(idvlags); } } if ((sr->code == SCATTERS) && !sr->error) { GtkWidget *m; int xstate; m = GTK_OPTION_MENU(multiplot_menu)->menu_item; xstate = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(m), "x-axis-item")); if (xstate) { reverse_list(sr->cmdlist); } } if (!sr->error) { /* record some choices as defaults */ if (sr->code == VECM || sr->code == VAR || sr->code == VLAGSEL) { if (sr->opts & OPT_D) { want_seasonals = 1; } else { want_seasonals = 0; } } if (sr->code == VECM || sr->code == VAR) { default_order = order; } if ((sr->code == VAR || sr->code == VLAGSEL) && (sr->opts & OPT_T)) { vartrend = 1; } if (sr->code == ARMA) { if (sr->opts & OPT_N) { arma_const = 0; } if (sr->opts & OPT_X) { arma_x12 = 1; } } } } static void cancel_selector (GtkWidget *widget, selector *sr) { if (open_selector != NULL) { gtk_widget_destroy(sr->dlg); } } static void destroy_selector (GtkWidget *w, selector *sr) { if (SAVE_DATA_ACTION(sr->code) || sr->code == SAVE_FUNCTIONS || sr->code == DEFINE_MATRIX) { gtk_main_quit(); } free(sr->cmdlist); free(sr); open_selector = NULL; } static char *est_str (int cmdnum) { switch (cmdnum) { case OLS: return N_("OLS"); case HCCM: return N_("HCCM"); case HSK: return N_("Heteroskedasticity corrected"); case CORC: return N_("Cochrane-Orcutt"); case HILU: return N_("Hildreth-Lu"); case PWE: return N_("Prais-Winsten"); case LOGIT: return N_("Logit"); case PROBIT: return N_("Probit"); case TOBIT: return N_("Tobit"); case LOGISTIC: return N_("Logistic"); case POISSON: return N_("Poisson"); case PANEL: return N_("Panel model"); case PANEL_WLS: return N_("Groupwise WLS"); case PANEL_B: return N_("Between-groups model"); case ARBOND: return N_("Dynamic panel model"); case WLS: return N_("Weighted least squares"); case TSLS: return N_("Two-stage least squares"); case AR: return N_("Autoregressive model"); case ARMA: return N_("ARIMA"); case ARCH: return N_("ARCH"); case GARCH: return N_("GARCH"); case VAR: return N_("VAR"); case VLAGSEL: return N_("VAR lag selection"); case VECM: return N_("VECM"); case LAD: return N_("LAD"); case COINT: case COINT2: return N_("Cointegration"); #ifdef ENABLE_GMP case MPOLS: return N_("Multiple precision OLS"); #endif default: return ""; } } static char *extra_string (int ci) { switch (ci) { case WLS: return N_("Weight variable"); case POISSON: return N_("Offset variable"); case AR: return N_("List of AR lags"); case GR_DUMMY: case GR_3D: return N_("Y-axis variable"); default: return NULL; } } static gint flip_multiplot_axis (GtkMenuItem *m, GtkOptionMenu *popdown) { gint xstate = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(m), "x-axis-item")); if (xstate) { gtk_label_set_text(GTK_LABEL(multiplot_label), _("Y-axis variables")); } else { gtk_label_set_text(GTK_LABEL(multiplot_label), _("X-axis variables")); } return FALSE; } static GtkWidget *multiplot_popdown (int ci) { GtkWidget *popdown; GtkWidget *menu; GtkWidget *child; popdown = gtk_option_menu_new(); menu = gtk_menu_new(); child = gtk_menu_item_new_with_label(_("Y-axis variable")); g_signal_connect(G_OBJECT(child), "activate", G_CALLBACK(flip_multiplot_axis), popdown); gtk_menu_shell_append(GTK_MENU_SHELL(menu), child); child = gtk_menu_item_new_with_label(_("X-axis variable")); g_signal_connect(G_OBJECT(child), "activate", G_CALLBACK(flip_multiplot_axis), popdown); gtk_menu_shell_append(GTK_MENU_SHELL(menu), child); g_object_set_data(G_OBJECT(child), "x-axis-item", GINT_TO_POINTER(1)); gtk_option_menu_set_menu(GTK_OPTION_MENU(popdown), menu); multiplot_menu = popdown; return popdown; } static GtkWidget * entry_with_label_and_chooser (selector *sr, GtkWidget *vbox, gchar *label_string, int label_active, void (*clickfunc)()) { GtkWidget *tmp, *x_hbox; GtkWidget *entry; if (label_active) { tmp = multiplot_popdown(sr->code); gtk_box_pack_start(GTK_BOX(vbox), tmp, FALSE, FALSE, 0); gtk_widget_show_all(tmp); } else if (label_string != NULL) { tmp = gtk_label_new(label_string); gtk_box_pack_start(GTK_BOX(vbox), tmp, FALSE, FALSE, 0); gtk_widget_show(tmp); } x_hbox = gtk_hbox_new(FALSE, 5); tmp = gtk_button_new_with_label (_("Choose->")); gtk_box_pack_start(GTK_BOX(x_hbox), tmp, TRUE, TRUE, 0); g_signal_connect (G_OBJECT(tmp), "clicked", G_CALLBACK(clickfunc), sr); gtk_widget_show(tmp); entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry), VNAMELEN - 1); gtk_entry_set_width_chars(GTK_ENTRY(entry), VNAMELEN + 3); gtk_box_pack_start(GTK_BOX(x_hbox), entry, FALSE, FALSE, 0); gtk_widget_show(entry); gtk_box_pack_start(GTK_BOX(vbox), x_hbox, FALSE, FALSE, 0); gtk_widget_show(x_hbox); if (label_active || label_string != NULL) { vbox_add_hsep(vbox); } return entry; } static void build_x_axis_section (selector *sr, GtkWidget *right_vbox) { if (sr->code == SCATTERS) { sr->depvar = entry_with_label_and_chooser(sr, right_vbox, NULL, 1, set_dependent_var_callback); } else { sr->depvar = entry_with_label_and_chooser(sr, right_vbox, _("X-axis variable"), 0, set_dependent_var_callback); } } static void maybe_activate_depvar_lags (GtkWidget *w, selector *sr) { if (select_lags_depvar(sr->code) && sr->lags_button != NULL) { const gchar *txt = gtk_entry_get_text(GTK_ENTRY(w)); if (txt != NULL && *txt != 0) { gtk_widget_set_sensitive(sr->lags_button, TRUE); } } } /* returns ID number of variable pre-inserted as dependent, or -1 */ static int build_depvar_section (selector *sr, GtkWidget *right_vbox, int preselect) { GtkWidget *tmp, *depvar_hbox; int yvar = (preselect)? preselect : default_var; tmp = gtk_label_new(_("Dependent variable")); gtk_box_pack_start(GTK_BOX(right_vbox), tmp, FALSE, FALSE, 0); gtk_widget_show(tmp); depvar_hbox = gtk_hbox_new(FALSE, 5); tmp = gtk_button_new_with_label (_("Choose ->")); gtk_box_pack_start(GTK_BOX(depvar_hbox), tmp, TRUE, TRUE, 0); g_signal_connect (G_OBJECT(tmp), "clicked", G_CALLBACK(set_dependent_var_callback), sr); gtk_widget_show(tmp); sr->depvar = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(sr->depvar), VNAMELEN - 1); gtk_entry_set_width_chars(GTK_ENTRY(sr->depvar), VNAMELEN + 3); g_signal_connect(G_OBJECT(sr->depvar), "changed", G_CALLBACK(maybe_activate_depvar_lags), sr); if (yvar >= 0) { gtk_entry_set_text(GTK_ENTRY(sr->depvar), datainfo->varname[yvar]); } gtk_box_pack_start(GTK_BOX(depvar_hbox), sr->depvar, FALSE, FALSE, 0); gtk_widget_show(sr->depvar); gtk_box_pack_start(GTK_BOX(right_vbox), depvar_hbox, FALSE, FALSE, 0); gtk_widget_show(depvar_hbox); sr->default_check = gtk_check_button_new_with_label(_("Set as default")); gtk_box_pack_start(GTK_BOX(right_vbox), sr->default_check, FALSE, FALSE, 0); gtk_widget_show(sr->default_check); if (sr->code != ARBOND) { vbox_add_hsep(right_vbox); } return yvar; } static void build_public_iface_section (selector *sr, GtkWidget *right_vbox) { GtkWidget *tmp, *pub_hbox; tmp = gtk_label_new(_("Public interface")); gtk_box_pack_start(GTK_BOX(right_vbox), tmp, FALSE, FALSE, 0); gtk_widget_show(tmp); pub_hbox = gtk_hbox_new(FALSE, 5); tmp = gtk_button_new_with_label(_("Choose ->")); gtk_box_pack_start(GTK_BOX(pub_hbox), tmp, TRUE, TRUE, 0); g_signal_connect (G_OBJECT(tmp), "clicked", G_CALLBACK(set_dependent_var_callback), sr); gtk_widget_show(tmp); sr->depvar = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(sr->depvar), FN_NAMELEN - 1); gtk_entry_set_width_chars(GTK_ENTRY(sr->depvar), 18); gtk_box_pack_start(GTK_BOX(pub_hbox), sr->depvar, FALSE, FALSE, 0); gtk_widget_show(sr->depvar); gtk_box_pack_start(GTK_BOX(right_vbox), pub_hbox, FALSE, FALSE, 0); gtk_widget_show(pub_hbox); vbox_add_hsep(right_vbox); } enum { LAG_ONLY, LAG_AND_RANK }; static void lag_order_spin (selector *sr, GtkWidget *vbox, int code) { GtkWidget *tmp, *hbox; GtkObject *adj; gdouble lag; gdouble minlag; gdouble maxlag; const char *labels[] = { N_("lag order:"), N_("cointegration rank:") }; int i, nspin = (code == LAG_AND_RANK)? 2 : 1; maxlag = (datainfo->n < 72)? (datainfo->n / 2) : 36; minlag = 1; if (default_order > 0 && default_order <= maxlag) { lag = default_order; } else { lag = (datainfo->pd > 12)? 12 : datainfo->pd; } if (sr->code == VLAGSEL) { minlag = 2; lag *= 2; if (lag > maxlag) { lag = maxlag; } } for (i=0; icode == VLAGSEL) { tmp = gtk_label_new(_("maximum lag:")); } else { tmp = gtk_label_new(_(labels[i])); } gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5); gtk_widget_show(tmp); gtk_misc_set_alignment(GTK_MISC(tmp), 0.0, 0.5); if (i == 0) { adj = gtk_adjustment_new(lag, minlag, maxlag, 1, 1, 1); } else { adj = gtk_adjustment_new(1, 1, 10, 1, 1, 1); } sr->extra[i] = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0); gtk_box_pack_start(GTK_BOX(hbox), sr->extra[i], FALSE, FALSE, 5); gtk_widget_show(sr->extra[i]); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); } } static void AR_order_spin (selector *sr, GtkWidget *vbox) { GtkWidget *tmp, *hbox; GtkObject *adj; gdouble val, maxlag; hbox = gtk_hbox_new(FALSE, 5); if (sr->code == ARCH) { tmp = gtk_label_new(_("ARCH order:")); val = datainfo->pd; maxlag = 2 * datainfo->pd; } else { tmp = gtk_label_new(_("AR order:")); val = 1; maxlag = datainfo->pd; } gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5); gtk_widget_show(tmp); gtk_misc_set_alignment(GTK_MISC(tmp), 0.0, 0.5); adj = gtk_adjustment_new(val, 1, maxlag, 1, 1, 1); sr->extra[0] = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0); gtk_box_pack_start(GTK_BOX(hbox), sr->extra[0], FALSE, FALSE, 5); gtk_widget_show(sr->extra[0]); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); } static void dummy_box (selector *sr, GtkWidget *vbox) { sr->rvars1 = entry_with_label_and_chooser(sr, vbox, _("Factor (dummy)"), 0, set_factor_callback); } static void zvar_box (selector *sr, GtkWidget *vbox) { sr->rvars1 = entry_with_label_and_chooser(sr, vbox, _("Z-axis variable"), 0, set_factor_callback); } static void extra_var_box (selector *sr, GtkWidget *vbox) { sr->extra[0] = entry_with_label_and_chooser(sr, vbox, NULL, 0, set_extra_var_callback); } static void auxiliary_rhs_varlist (selector *sr, GtkWidget *vbox) { GtkListStore *store; GtkTreeIter iter; GtkWidget *remove, *hbox, *bvbox; GtkWidget *tmp = NULL; int *reclist = NULL; if (sr->code == VAR || sr->code == VLAGSEL) { tmp = gtk_label_new(_("Exogenous variables")); } else if (sr->code == VECM) { tmp = gtk_label_new(_("Exogenous variables")); } else if (sr->code == TSLS) { tmp = gtk_label_new(_("Instruments")); } if (tmp != NULL) { gtk_box_pack_start(GTK_BOX(vbox), tmp, FALSE, FALSE, 0); gtk_widget_show(tmp); } hbox = gtk_hbox_new(FALSE, 5); bvbox = gtk_vbox_new(TRUE, 0); tmp = gtk_button_new_with_label(_("Add ->")); gtk_box_pack_start(GTK_BOX(bvbox), tmp, TRUE, FALSE, 0); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(add_to_rvars2_callback), sr); remove = gtk_button_new_with_label(_("<- Remove")); gtk_box_pack_start(GTK_BOX(bvbox), remove, TRUE, FALSE, 0); if (sr->code == VAR || sr->code == VLAGSEL || sr->code == VECM) { sr->lags_button = gtk_button_new_with_label(_("lags...")); gtk_box_pack_start(GTK_BOX(bvbox), sr->lags_button, TRUE, FALSE, 0); g_signal_connect(G_OBJECT(sr->lags_button), "clicked", G_CALLBACK(lags_dialog_driver), sr); gtk_widget_set_sensitive(sr->lags_button, FALSE); } gtk_box_pack_start(GTK_BOX(hbox), bvbox, TRUE, TRUE, 0); gtk_widget_show_all(bvbox); /* then the listing */ sr->rvars2 = var_list_box_new(GTK_BOX(hbox), sr, SR_RVARS2); store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sr->rvars2))); gtk_list_store_clear(store); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); if (sr->code == TSLS) { reclist = instlist; } else if (sr->code == VAR || sr->code == VLAGSEL || sr->code == VECM) { reclist = vecxlist; } if (reclist != NULL) { int i; for (i=1; i<=reclist[0]; i++) { list_append_var(store, &iter, reclist[i], sr, SR_RVARS2); } if (reclist[0] > 0 && (sr->code == VAR || sr->code == VLAGSEL || sr->code == VECM)) { gtk_widget_set_sensitive(sr->lags_button, TRUE); } } else if (!VEC_CODE(sr->code)) { list_append_var(store, &iter, 0, sr, SR_RVARS2); } /* hook up remove button to list box */ g_signal_connect(G_OBJECT(remove), "clicked", G_CALLBACK(remove_from_right_callback), sr->rvars2); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); gtk_widget_show(hbox); } static void build_mid_section (selector *sr, GtkWidget *right_vbox) { GtkWidget *tmp; const char *str = _(extra_string(sr->code)); if (str != NULL) { tmp = gtk_label_new(str); gtk_box_pack_start(GTK_BOX(right_vbox), tmp, FALSE, FALSE, 0); gtk_widget_show(tmp); } if (sr->code == WLS || sr->code == POISSON || sr->code == GR_DUMMY || sr->code == GR_3D) { extra_var_box(sr, right_vbox); } else if (sr->code == TSLS) { primary_rhs_varlist(sr, right_vbox); } else if (sr->code == AR) { sr->extra[0] = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(right_vbox), sr->extra[0], FALSE, TRUE, 0); gtk_widget_show(sr->extra[0]); } else if (sr->code == VAR || sr->code == VLAGSEL) { lag_order_spin(sr, right_vbox, LAG_ONLY); vbox_add_hsep(right_vbox); primary_rhs_varlist(sr, right_vbox); } else if (sr->code == VECM) { lag_order_spin(sr, right_vbox, LAG_AND_RANK); vbox_add_hsep(right_vbox); primary_rhs_varlist(sr, right_vbox); } else if (VEC_CODE(sr->code)) { lag_order_spin(sr, right_vbox, LAG_ONLY); } else if (sr->code == ARBOND || sr->code == ARCH) { AR_order_spin(sr, right_vbox); } vbox_add_hsep(right_vbox); } static int screen_scalar (int i, int c) { if ((MODEL_CODE(c) || VEC_CODE(c) || GRAPH_CODE(c) || c == LAGS || c == DIFF || c == LDIFF) && var_is_scalar(datainfo, i)) { return 1; } else { return 0; } } static void selector_init (selector *sr, guint code, const char *title, gpointer p, int (*callback)()) { GtkWidget *base; double x; int dlgx = -1, dlgy = 340; int i; sr->code = code; sr->opts = (code == PANEL_WLS)? OPT_W : OPT_NONE; if (MODEL_CODE(code)) { if (datainfo->v > 9) { dlgy += 80; } else if (code == ARMA) { dlgy += 40; } } if (code == WLS || code == POISSON || code == AR) { dlgy += 30; } else if (code == TSLS) { dlgy += 40; } else if (VEC_CODE(code)) { dlgy = 450; if (code == VAR || code == VECM) { dlgy += 90; } else if (code == VLAGSEL) { dlgy += 40; } } if (WANT_TOGGLES(code) && code != COINT) { dlgy += 40; } if (WANT_RADIOS(code)) { dlgy += 60; } if (code == ARMA && datainfo->pd > 1) { /* seasonal spinners */ dlgy += 60; } if (dataset_lags_ok(datainfo)) { if (MODEL_CODE(code) && code != ARMA) { /* lag selector button at foot */ dlgy += 30; } } sr->lvars = NULL; sr->depvar = NULL; sr->rvars1 = NULL; sr->rvars2 = NULL; sr->default_check = NULL; sr->add_button = NULL; sr->lags_button = NULL; for (i=0; iextra[i] = NULL; } for (i=0; iradios[i] = NULL; } sr->cmdlist = NULL; sr->data = p; sr->callback = callback; sr->active_var = 0; sr->error = 0; sr->dlg = gtk_window_new(GTK_WINDOW_TOPLEVEL); open_selector = sr; gtk_window_set_title(GTK_WINDOW(sr->dlg), title); x = (double) dlgy * gui_scale; dlgy = x; if (code == SAVE_FUNCTIONS) { x = (double) 460 * gui_scale; dlgx = x; } gtk_window_set_default_size(GTK_WINDOW(sr->dlg), dlgx, dlgy); g_signal_connect(G_OBJECT(sr->dlg), "destroy", G_CALLBACK(destroy_selector), sr); /* create equivalent of gtkdialog structure */ base = gtk_vbox_new(FALSE, 5); gtk_container_add(GTK_CONTAINER(sr->dlg), base); gtk_widget_show(base); sr->vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(sr->vbox); /* make (upper) vbox expansible */ gtk_box_pack_start(GTK_BOX(base), sr->vbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(sr->vbox), 5); gtk_box_set_spacing(GTK_BOX(sr->vbox), 5); vbox_add_hsep(base); sr->action_area = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(sr->action_area), GTK_BUTTONBOX_END); gtk_button_box_set_spacing(GTK_BUTTON_BOX(sr->action_area), 10); gtk_widget_show(sr->action_area); gtk_box_pack_start(GTK_BOX(base), sr->action_area, FALSE, FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(sr->action_area), 5); } static void option_callback (GtkWidget *w, selector *sr) { gint i = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "opt")); gretlopt opt = i; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) { sr->opts |= opt; } else { sr->opts &= ~opt; } if (sr->code == PANEL) { GtkWidget *w = g_object_get_data(G_OBJECT(sr->dlg), "robust-button"); if (w != NULL) { gtk_widget_set_sensitive(w, !(sr->opts & OPT_U)); } } } static void reverse_option_callback (GtkWidget *w, selector *sr) { gint i = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "opt")); gretlopt opt = i; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) { sr->opts &= ~opt; } else { sr->opts |= opt; } } static void robust_config_button (GtkWidget *w, GtkWidget *b) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) { gtk_widget_set_sensitive(b, TRUE); } else { gtk_widget_set_sensitive(b, FALSE); } } static GtkWidget *spinner_aux_label (int i) { GtkWidget *hbox; GtkWidget *lbl; hbox = gtk_hbox_new(FALSE, 5); if (i == 0) { lbl = gtk_label_new(_("Non-seasonal")); } else { lbl = gtk_label_new(_("Seasonal")); } gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 5); gtk_widget_show(lbl); return hbox; } static GtkWidget *spinner_label (int i, int code) { const char *arma_strs[] = { N_("AR order:"), N_("Difference:"), N_("MA order:") }; const char *arch_strs[] = { N_("ARCH p:"), N_("ARCH q:") }; GtkWidget *lbl = NULL; if (code == ARMA) { lbl = gtk_label_new(_(arma_strs[i % 3])); } else { lbl = gtk_label_new(_(arch_strs[i])); } return lbl; } static void build_pdq_spinners (selector *sr) { GtkWidget *tmp, *hbox; GtkObject *adj; gdouble vmax, val; int i; if (sr->code == GARCH) { hbox = gtk_hbox_new(FALSE, 5); for (i=0; i<2; i++) { tmp = spinner_label(i, GARCH); gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 5); val = (i==0)? garch_p : garch_q; adj = gtk_adjustment_new(val, 0, 4, 1, 1, 1); sr->extra[i] = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0); gtk_box_pack_start(GTK_BOX(hbox), sr->extra[i], FALSE, FALSE, 5); } gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 5); gtk_widget_show_all(hbox); return; } if (datainfo->pd > 1) { tmp = spinner_aux_label(0); gtk_box_pack_start(GTK_BOX(sr->vbox), tmp, FALSE, FALSE, 0); gtk_widget_show(tmp); } hbox = gtk_hbox_new(FALSE, 5); for (i=0; i<3; i++) { tmp = spinner_label(i, ARMA); gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 0); val = (i==0)? arma_p : (i==1)? arima_d : arma_q; vmax = (i == 1)? 2 : 4; adj = gtk_adjustment_new(val, 0, vmax, 1, 1, 1); sr->extra[i] = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0); gtk_box_pack_start(GTK_BOX(hbox), sr->extra[i], FALSE, FALSE, 5); } gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 5); gtk_widget_show_all(hbox); if (datainfo->pd > 1) { tmp = spinner_aux_label(1); gtk_box_pack_start(GTK_BOX(sr->vbox), tmp, FALSE, FALSE, 0); gtk_widget_show(tmp); hbox = gtk_hbox_new(FALSE, 5); for (i=0; i<3; i++) { tmp = spinner_label(i, ARMA); gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 0); val = (i==0)? arma_P : (i==1)? arima_D : arma_Q; vmax = (i == 1)? 2 : 4; adj = gtk_adjustment_new(val, 0, vmax, 1, 1, 1); sr->extra[i+3] = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0); gtk_box_pack_start(GTK_BOX(hbox), sr->extra[i+3], FALSE, FALSE, 5); } gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 5); gtk_widget_show_all(hbox); } } static void hc_config (GtkWidget *w, gpointer p) { options_dialog(4); } static void pack_switch (GtkWidget *b, selector *sr, gboolean checked, gboolean reversed, gretlopt opt, int child) { GtkWidget *hbox = gtk_hbox_new(FALSE, 5); gint offset = (child)? 15 : 0; gint i = opt; g_object_set_data(G_OBJECT(b), "opt", GINT_TO_POINTER(i)); if (reversed) { g_signal_connect(G_OBJECT(b), "toggled", G_CALLBACK(reverse_option_callback), sr); if (checked) { sr->opts &= ~opt; } else { sr->opts |= opt; } } else { g_signal_connect(G_OBJECT(b), "toggled", G_CALLBACK(option_callback), sr); if (checked) { sr->opts |= opt; } else { sr->opts &= ~opt; } } gtk_box_pack_start(GTK_BOX(hbox), b, TRUE, TRUE, offset); gtk_widget_show(b); gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), checked); } #if 0 /* not ready yet */ static void call_iters_dialog (GtkWidget *w, selector *sr) { iterinfo iinfo; int canceled = 0; iinfo.ci = sr->code; /* FIXME need to figure out properly where to get the defaults from, given the command and possible options */ if (1) { iinfo.maxiters = get_bhhh_maxiter(); iinfo.tol = get_bhhh_toler(); } else if (sr->code == NLS || sr->code == MLE || sr->code == GMM) { iinfo.maxiters = 400; /* FIXME: 100*(n+1) or 200*(n+1) */ iinfo.tol = get_nls_toler(); } edit_dialog("Iterative estimation", "Tolerance for convergence", NULL, NULL, &iinfo, ITERATIONS, VARCLICK_NONE, &canceled); if (!canceled) { fprintf(stderr, "iters=%d, tol=%g\n", iinfo.maxiters, iinfo.tol); /* FIXME check and set values */ } } #endif #define robust_conf(c) (c != LOGIT && c != PROBIT) static void build_selector_switches (selector *sr) { GtkWidget *hbox, *tmp; if (sr->code == OLS || sr->code == WLS || sr->code == GARCH || sr->code == TSLS || sr->code == VAR || sr->code == LOGIT || sr->code == PROBIT || sr->code == PANEL) { GtkWidget *b1; /* FIXME arma robust variant? */ vbox_add_hsep(sr->vbox); b1 = gtk_check_button_new_with_label(_("Robust standard errors")); g_object_set_data(G_OBJECT(b1), "opt", GINT_TO_POINTER(OPT_R)); g_signal_connect(G_OBJECT(b1), "toggled", G_CALLBACK(option_callback), sr); if (robust_conf(sr->code) && using_hc_by_default()) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b1), TRUE); } if (sr->code == PANEL) { g_object_set_data(G_OBJECT(sr->dlg), "robust-button", b1); } hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), b1, FALSE, FALSE, 0); gtk_widget_show(b1); if (robust_conf(sr->code)) { GtkWidget *b2; b2 = gtk_button_new_with_label(_("configure")); g_signal_connect(G_OBJECT(b2), "clicked", G_CALLBACK(hc_config), sr); gtk_widget_set_sensitive(b2, using_hc_by_default()); g_signal_connect(G_OBJECT(b1), "toggled", G_CALLBACK(robust_config_button), b2); gtk_box_pack_start(GTK_BOX(hbox), b2, FALSE, FALSE, 0); gtk_widget_show(b2); } gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); } if (sr->code == TOBIT || sr->code == ARMA || sr->code == GARCH || sr->code == LOGIT || sr->code == PROBIT) { if (sr->code == ARMA) { vbox_add_hsep(sr->vbox); tmp = gtk_check_button_new_with_label(_("Include a constant")); pack_switch(tmp, sr, arma_const, TRUE, OPT_N, 0); } #if 0 /* testing */ hbox = gtk_hbox_new(FALSE, 5); tmp = gtk_button_new_with_label(_("Configure")); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(call_iters_dialog), sr); gtk_box_pack_start(GTK_BOX(hbox), tmp, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show_all(hbox); #else tmp = gtk_check_button_new_with_label(_("Show details of iterations")); pack_switch(tmp, sr, FALSE, FALSE, OPT_V, 0); #endif } else if (sr->code == COINT2 || sr->code == VECM || sr->code == VAR || sr->code == VLAGSEL) { if (sr->code == VAR || sr->code == VLAGSEL) { tmp = gtk_check_button_new_with_label(_("Include a constant")); pack_switch(tmp, sr, TRUE, TRUE, OPT_N, 0); tmp = gtk_check_button_new_with_label(_("Include a trend")); pack_switch(tmp, sr, vartrend, FALSE, OPT_T, 0); } else { tmp = gtk_check_button_new_with_label(_("Show details of regressions")); pack_switch(tmp, sr, FALSE, FALSE, OPT_V, 0); } tmp = gtk_check_button_new_with_label(_("Include seasonal dummies")); pack_switch(tmp, sr, want_seasonals && (datainfo->pd == 4 || datainfo->pd == 12), FALSE, OPT_D, 0); if (datainfo->pd != 4 && datainfo->pd != 12) { gtk_widget_set_sensitive(tmp, FALSE); } } else if (sr->code == HILU) { tmp = gtk_check_button_new_with_label(_("Fine-tune using Cochrane-Orcutt")); pack_switch(tmp, sr, TRUE, TRUE, OPT_B, 0); } else if (sr->code == COINT) { tmp = gtk_check_button_new_with_label(_("Test down from maximum lag order")); pack_switch(tmp, sr, FALSE, FALSE, OPT_A, 0); tmp = gtk_check_button_new_with_label(_("Skip initial DF tests")); pack_switch(tmp, sr, FALSE, FALSE, OPT_S, 0); } else if (sr->code == PANEL_WLS) { tmp = gtk_check_button_new_with_label(_("Iterated weighted least squares")); pack_switch(tmp, sr, FALSE, FALSE, OPT_T, 0); } else if (sr->code == PANEL || sr->code == ARBOND) { tmp = gtk_check_button_new_with_label(_("Include time dummies")); pack_switch(tmp, sr, FALSE, FALSE, OPT_D, 0); } #ifdef HAVE_X12A if (sr->code == ARMA) { tmp = gtk_check_button_new_with_label(_("Use X-12-ARIMA")); pack_switch(tmp, sr, arma_x12, FALSE, OPT_X, 0); } #endif } static void unhide_lags_callback (GtkWidget *w, selector *sr) { int i, show_lags = GTK_TOGGLE_BUTTON(w)->active; GtkListStore *store; GtkTreeIter iter; store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sr->lvars))); gtk_list_store_clear(store); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); for (i=1; iv; i++) { if (list_show_var(i, sr->code, show_lags)) { list_append_var_simple(store, &iter, i); } } } static void unhide_lags_switch (selector *sr) { GtkWidget *hbox; GtkWidget *b; vbox_add_hsep(sr->vbox); b = gtk_check_button_new_with_label(_("Show lagged variables")); g_signal_connect(G_OBJECT(b), "toggled", G_CALLBACK(unhide_lags_callback), sr); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), b, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show_all(hbox); } #if 0 /* not ready */ static void boot_switch_callback (GtkWidget *w, selector *sr) { if (GTK_TOGGLE_BUTTON(w)->active) { sr->opts |= OPT_P; } else { sr->opts &= ~OPT_P; } } static void test_boot_switch (selector *sr) { GtkWidget *hbox; GtkWidget *b; vbox_add_hsep(sr->vbox); b = gtk_check_button_new_with_label(_("Use bootstrap")); g_signal_connect(G_OBJECT(b), "toggled", G_CALLBACK(boot_switch_callback), sr); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), b, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show_all(hbox); } #endif static void build_scatters_radios (selector *sr) { GtkWidget *b1, *b2; GSList *group; b1 = gtk_radio_button_new_with_label(NULL, _("Use points")); pack_switch(b1, sr, TRUE, FALSE, OPT_NONE, 1); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1)); b2 = gtk_radio_button_new_with_label(group, _("Use lines")); pack_switch(b2, sr, FALSE, FALSE, OPT_L, 1); sr->radios[0] = b1; sr->radios[1] = b2; } static void build_omit_test_radios (selector *sr) { GtkWidget *b1, *b2; GSList *group; vbox_add_hsep(sr->vbox); b1 = gtk_radio_button_new_with_label(NULL, _("Estimate reduced model")); pack_switch(b1, sr, TRUE, FALSE, OPT_NONE, 0); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1)); b2 = gtk_radio_button_new_with_label(group, _("Wald test, based on covariance matrix")); pack_switch(b2, sr, FALSE, FALSE, OPT_W, 0); sr->radios[0] = b1; sr->radios[1] = b2; } static void build_arma_radios (selector *sr) { GtkWidget *b1, *b2; GSList *group; vbox_add_hsep(sr->vbox); b1 = gtk_radio_button_new_with_label(NULL, _("Exact Maximum Likelihood")); pack_switch(b1, sr, TRUE, FALSE, OPT_NONE, 0); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1)); b2 = gtk_radio_button_new_with_label(group, _("Conditional Maximum Likelihood")); pack_switch(b2, sr, FALSE, FALSE, OPT_C, 0); sr->radios[0] = b1; sr->radios[1] = b2; } static void build_panel_radios (selector *sr) { GtkWidget *b1, *b2; GSList *group; if (sr->opts & OPT_W) { /* panel weighted least squares */ return; } b1 = gtk_radio_button_new_with_label(NULL, _("Fixed effects")); pack_switch(b1, sr, TRUE, FALSE, OPT_NONE, 0); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1)); b2 = gtk_radio_button_new_with_label(group, _("Random effects")); pack_switch(b2, sr, FALSE, FALSE, OPT_U, 0); sr->radios[0] = b1; sr->radios[1] = b2; } static void build_arbond_radios (selector *sr) { GtkWidget *b1, *b2; GSList *group; b1 = gtk_radio_button_new_with_label(NULL, _("1-step estimation")); pack_switch(b1, sr, TRUE, FALSE, OPT_NONE, 0); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1)); b2 = gtk_radio_button_new_with_label(group, _("2-step estimation")); pack_switch(b2, sr, FALSE, FALSE, OPT_T, 0); sr->radios[0] = b1; sr->radios[1] = b2; } static void build_coint_radios (selector *sr) { GtkWidget *button = NULL; GSList *group = NULL; const char *opt_strs[] = { N_("test without constant"), N_("test with constant"), N_("with constant and trend"), N_("with constant and quadratic trend"), NULL }; gretlopt opts[] = { OPT_N, OPT_NONE, OPT_T, OPT_R, }; int i, deflt = 0; vbox_add_hsep(sr->vbox); for (i=0; opt_strs[i] != NULL; i++) { if (button != NULL) { group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)); } else { group = NULL; } button = gtk_radio_button_new_with_label(group, _(opt_strs[i])); pack_switch(button, sr, (opts[i] == deflt), FALSE, opts[i], 0); } } static void build_vec_radios (selector *sr) { GtkWidget *button = NULL; GSList *group = NULL; const char *opt_strs[] = { N_("No constant"), N_("Restricted constant"), N_("Unrestricted constant"), N_("Restricted trend"), N_("Unrestricted trend"), NULL }; gretlopt opts[] = { OPT_N, OPT_R, OPT_NONE, OPT_A, OPT_T }; int i, deflt = 0; vbox_add_hsep(sr->vbox); for (i=0; opt_strs[i] != NULL; i++) { if (button != NULL) { group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)); } else { group = NULL; } button = gtk_radio_button_new_with_label(group, _(opt_strs[i])); pack_switch(button, sr, (opts[i] == deflt), FALSE, opts[i], 0); } } static void build_selector_radios (selector *sr) { if (sr->code == ARMA) { build_arma_radios(sr); } else if (sr->code == PANEL) { build_panel_radios(sr); } else if (sr->code == ARBOND) { build_arbond_radios(sr); } else if (sr->code == SCATTERS) { build_scatters_radios(sr); } else if (sr->code == COINT) { build_coint_radios(sr); } else if (sr->code == OMIT) { build_omit_test_radios(sr); } else { build_vec_radios(sr); } } static void lag_selector_button (selector *sr) { GtkWidget *hbox = gtk_hbox_new(FALSE, 5); sr->lags_button = gtk_button_new_with_label(_("lags...")); g_signal_connect(G_OBJECT(sr->lags_button), "clicked", G_CALLBACK(lags_dialog_driver), sr); if (varlist_row_count(sr, SR_RVARS1, NULL) < 2) { gtk_widget_set_sensitive(sr->lags_button, FALSE); } gtk_box_pack_start(GTK_BOX(hbox), sr->lags_button, FALSE, FALSE, 0); gtk_widget_show(sr->lags_button); gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); } static void selector_doit (GtkWidget *w, selector *sr) { construct_cmdlist(sr); if (sr->error == 0) { int err = sr->callback(sr); if (!err && open_selector != NULL) { gtk_widget_destroy(sr->dlg); } } } static void build_selector_buttons (selector *sr) { GtkWidget *tmp; if (sr->code != PRINT && sr->code != SAVE_FUNCTIONS && sr->code != DEFINE_LIST && sr->code != DEFINE_MATRIX && !SAVE_DATA_ACTION(sr->code)) { tmp = gtk_button_new_from_stock(GTK_STOCK_HELP); GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT); gtk_container_add(GTK_CONTAINER(sr->action_area), tmp); gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(sr->action_area), tmp, TRUE); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(context_help), GINT_TO_POINTER(sr->code)); gtk_widget_show(tmp); } tmp = gtk_button_new_from_stock(GTK_STOCK_CLEAR); GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT); gtk_container_add(GTK_CONTAINER(sr->action_area), tmp); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(clear_vars), sr); gtk_widget_show(tmp); tmp = gtk_button_new_from_stock(GTK_STOCK_CANCEL); GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT); gtk_container_add(GTK_CONTAINER(sr->action_area), tmp); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(cancel_selector), sr); gtk_widget_show(tmp); tmp = gtk_button_new_from_stock(GTK_STOCK_OK); GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT); gtk_container_add(GTK_CONTAINER(sr->action_area), tmp); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(selector_doit), sr); gtk_widget_show(tmp); gtk_widget_grab_default(tmp); } static int list_show_var (int v, int code, int show_lags) { int ret = 1; lags_hidden = 0; if (v == 0 && (code == DEFINE_LIST || code == DEFINE_MATRIX)) { ; } else if (v == 0 && (!MODEL_CODE(code) || code == ARMA)) { ret = 0; } else if (var_is_hidden(datainfo, v)) { ret = 0; } else if (screen_scalar(v, code)) { ret = 0; } else if (!show_lags && is_standard_lag(v, datainfo, NULL)) { lags_hidden = 1; ret = 0; } return ret; } static GtkWidget *selection_dialog_top_label (int ci) { gchar *s; if (MODEL_CODE(ci) || VEC_CODE(ci)) s = _(est_str(ci)); else if (ci == GR_XY) s = _("XY scatterplot"); else if (ci == GR_IMP) s = _("plot with impulses"); else if (ci == GR_3D) s = _("3D plot"); else if (ci == SCATTERS) s = _("multiple scatterplots"); else if (ci == GR_DUMMY) s = _("factorized plot"); else if (ci == SAVE_FUNCTIONS) s = _("functions to package"); else s = "fixme need string"; return gtk_label_new(s); } static void primary_rhs_varlist (selector *sr, GtkWidget *vbox) { GtkListStore *store; GtkTreeIter iter; GtkWidget *remove; GtkWidget *hbox; GtkWidget *bvbox; GtkWidget *tmp = NULL; int i; if (COINT_CODE(sr->code)) { tmp = gtk_label_new(_("Variables to test")); } else if (VEC_CODE(sr->code)) { tmp = gtk_label_new(_("Endogenous variables")); } else if (MODEL_CODE(sr->code)) { tmp = gtk_label_new(_("Independent variables")); } else if (sr->code == GR_XY || sr->code == GR_IMP) { tmp = gtk_label_new(_("Y-axis variables")); } else if (sr->code == SCATTERS) { multiplot_label = tmp = gtk_label_new(_("X-axis variables")); } else if (sr->code == SAVE_FUNCTIONS) { tmp = gtk_label_new(_("Helper functions")); } if (tmp != NULL) { gtk_box_pack_start(GTK_BOX(vbox), tmp, FALSE, FALSE, 0); gtk_widget_show(tmp); } hbox = gtk_hbox_new(FALSE, 5); /* push/pull buttons first, in their own little vbox */ bvbox = gtk_vbox_new(TRUE, 0); tmp = gtk_button_new_with_label (_("Add ->")); gtk_box_pack_start(GTK_BOX(bvbox), tmp, TRUE, FALSE, 0); g_signal_connect (G_OBJECT(tmp), "clicked", G_CALLBACK(add_to_rvars1_callback), sr); remove = gtk_button_new_with_label (_("<- Remove")); gtk_box_pack_start(GTK_BOX(bvbox), remove, TRUE, FALSE, 0); if (sr->code == ARMA) { sr->lags_button = gtk_button_new_with_label(_("lags...")); gtk_box_pack_start(GTK_BOX(bvbox), sr->lags_button, TRUE, FALSE, 0); g_signal_connect(G_OBJECT(sr->lags_button), "clicked", G_CALLBACK(lags_dialog_driver), sr); gtk_widget_set_sensitive(sr->lags_button, FALSE); } gtk_box_pack_start(GTK_BOX(hbox), bvbox, TRUE, TRUE, 0); gtk_widget_show_all(bvbox); /* then the actual primary RHS listbox */ sr->rvars1 = var_list_box_new(GTK_BOX(hbox), sr, SR_RVARS1); store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sr->rvars1))); gtk_list_store_clear (store); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); if (MODEL_CODE(sr->code)) { if (sr->code != ARMA) { /* stick the constant in by default */ list_append_var(store, &iter, 0, sr, SR_RVARS1); } else { g_object_set_data(G_OBJECT(sr->rvars1), "selector", sr); } if (xlist != NULL) { int nx = 0; /* we have a saved list of regressors */ for (i=1; i<=xlist[0]; i++) { if (xlist[i] != 0) { list_append_var(store, &iter, xlist[i], sr, SR_RVARS1); nx++; } } if (nx > 0 && sr->code == ARMA) { gtk_widget_set_sensitive(sr->lags_button, TRUE); } } } else if (VEC_CODE(sr->code) && veclist != NULL) { for (i=1; i<=veclist[0]; i++) { list_append_var(store, &iter, veclist[i], sr, SR_RVARS1); } } /* hook remove button to listing */ g_signal_connect(G_OBJECT(remove), "clicked", G_CALLBACK(remove_from_right_callback), sr->rvars1); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); gtk_widget_show(hbox); } void selection_dialog (const char *title, int (*callback)(), guint ci, int preselect) { GtkListStore *store; GtkTreeIter iter; GtkWidget *right_vbox, *tmp; GtkWidget *big_hbox; selector *sr; int yvar = 0; int i; if (open_selector != NULL) { gdk_window_raise(open_selector->dlg->window); return; } sr = mymalloc(sizeof *sr); if (sr == NULL) return; selector_init(sr, ci, title, NULL, callback); tmp = selection_dialog_top_label(ci); gtk_box_pack_start(GTK_BOX(sr->vbox), tmp, FALSE, FALSE, 5); gtk_widget_show(tmp); /* the following encloses LHS lvars, depvar and indepvar stuff */ big_hbox = gtk_hbox_new(FALSE, 5); /* LHS: list of elements to choose from */ sr->lvars = var_list_box_new(GTK_BOX(big_hbox), sr, SR_LVARS); store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sr->lvars))); gtk_list_store_clear(store); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); if (ci == SAVE_FUNCTIONS) { functions_list(sr); } else { for (i=0; iv; i++) { if (list_show_var(i, ci, 0)) { list_append_var_simple(store, &iter, i); } } } /* RHS: vertical holder */ right_vbox = gtk_vbox_new(FALSE, 5); if (MODEL_CODE(ci)) { /* models: top right -> dependent variable */ yvar = build_depvar_section(sr, right_vbox, preselect); } else if (ci == GR_XY || ci == GR_IMP || ci == GR_DUMMY || ci == SCATTERS || ci == GR_3D) { /* graphs: top right -> x-axis variable */ build_x_axis_section(sr, right_vbox); } else if (ci == SAVE_FUNCTIONS) { build_public_iface_section(sr, right_vbox); } /* middle right: used for some estimators and factored plot */ if (ci == WLS || ci == AR || ci == TSLS || ci == ARCH || VEC_CODE(ci) || ci == POISSON || ci == ARBOND || ci == GR_DUMMY || ci == GR_3D) { build_mid_section(sr, right_vbox); } if (ci == GR_DUMMY) { /* special case: choose dummy var for factorized plot */ dummy_box(sr, right_vbox); } else if (ci == GR_3D) { /* special case: choose Z axis variable */ zvar_box(sr, right_vbox); } else if (AUX_LAST(ci)) { auxiliary_rhs_varlist(sr, right_vbox); } else { /* all other uses: list of vars */ primary_rhs_varlist(sr, right_vbox); } /* pack the whole RHS to the right of the LHS lvars */ gtk_box_pack_start(GTK_BOX(big_hbox), right_vbox, TRUE, TRUE, 0); gtk_widget_show(right_vbox); /* pack the whole central section into the dialog's vbox */ gtk_box_pack_start(GTK_BOX(sr->vbox), big_hbox, TRUE, TRUE, 0); gtk_widget_show(big_hbox); /* AR, D, MA spinners for ARIMA; P and Q for GARCH */ if (ci == ARMA || ci == GARCH) { build_pdq_spinners(sr); } /* toggle switches for some cases */ if (WANT_TOGGLES(ci)) { build_selector_switches(sr); } /* and radio buttons for some */ if (WANT_RADIOS(ci)) { build_selector_radios(sr); } /* plus lag selection stuff, if relevant */ if (dataset_lags_ok(datainfo)) { if (MODEL_CODE(ci) && ci != ARMA) { lag_selector_button(sr); } if (select_lags_depvar(ci) && yvar > 0) { maybe_activate_depvar_lags(sr->depvar, sr); maybe_insert_depvar_lags(sr, yvar, 0); } } /* buttons: Help, Clear, Cancel, OK */ build_selector_buttons(sr); gtk_widget_show(sr->dlg); } static char *get_topstr (int cmdnum) { switch (cmdnum) { case LOGS: return N_("Select variables for logging"); case LAGS: return N_("Select variables for lagging"); case SQUARE: return N_("Select variables to square"); case DIFF: return N_("Select variables to difference"); case LDIFF: return N_("Select variables to log-difference"); case ADD: return N_("Select variables to add"); case OMIT: case VAROMIT: return N_("Select variables to omit"); case COEFFSUM: return N_("Select coefficients to sum"); case SPEARMAN: case ELLIPSE: return N_("Select two variables"); case PRINT: return N_("Select variables to display"); case GR_PLOT: case GR_BOX: case GR_NBOX: return N_("Select variables to plot"); case SAVE_DATA: case SAVE_DATA_AS: case EXPORT_CSV: case EXPORT_R: case EXPORT_OCTAVE: case EXPORT_JM: case EXPORT_DAT: return N_("Select variables to save"); case COPY_CSV: return N_("Select variables to copy"); case DEFINE_LIST: return N_("Define named list"); default: return NULL; } } static int add_omit_list (gpointer p, selector *sr) { windata_t *vwin = (windata_t *) p; GRETL_VAR *var = NULL; MODEL *pmod = NULL; GtkListStore *store; GtkTreeIter iter; int *xlist = NULL; int i, nvars = 0; if (sr->code == VAROMIT) { var = (GRETL_VAR *) vwin->data; } else { pmod = (MODEL *) vwin->data; } store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sr->lvars))); gtk_list_store_clear(store); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); if (sr->code == ELLIPSE) { char pname[VNAMELEN]; for (i=0; incoeff; i++) { gretl_model_get_param_name(pmod, datainfo, i, pname); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, i, 1, 0, 2, pname, -1); nvars++; } g_object_set_data(G_OBJECT(sr->lvars), "keep_names", GINT_TO_POINTER(1)); } else if (sr->code == OMIT || sr->code == ADD || sr->code == COEFFSUM) { xlist = gretl_model_get_x_list(pmod); if (xlist == NULL) { return 0; } if (sr->code == ADD) { int dv = gretl_model_get_depvar(pmod); for (i=0; iv; i++) { if (!in_gretl_list(xlist, i) && i != dv && !var_is_hidden(datainfo, i)) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, i, 1, 0, 2, datainfo->varname[i], -1); nvars++; } } } else { for (i=1; i<=xlist[0]; i++) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, xlist[i], 1, 0, 2, datainfo->varname[xlist[i]], -1); nvars++; } } } else if (sr->code == VAROMIT) { int err; xlist = gretl_VAR_get_exo_list(var, &err); if (xlist != NULL) { for (i=1; i<=xlist[0]; i++) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, xlist[i], 1, 0, 2, datainfo->varname[xlist[i]], -1); nvars++; } } } free(xlist); return nvars; } static int functions_list (selector *sr) { GtkListStore *store; GtkTreeIter iter; const char *fnname; int n = 0; store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sr->lvars))); gtk_list_store_clear(store); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); function_names_init(); while ((fnname = next_free_function_name()) != NULL) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, n++, 1, 0, 2, fnname, -1); } g_object_set_data(G_OBJECT(sr->lvars), "keep_names", GINT_TO_POINTER(1)); return n; } static GtkWidget *simple_selection_top_label (int code) { GtkWidget *label = NULL; const char *str = get_topstr(code); if (str != NULL && *str != '\0') { label = gtk_label_new(_(str)); } return label; } static gboolean remove_busy_signal (GtkWidget *w, windata_t *vwin) { if (vwin != NULL) { unset_window_busy(vwin); } return FALSE; } static void add_to_rvars1_from_named_list (selector *sr, const int *list) { GtkTreeModel *mod; GtkTreeIter iter; int i, v; mod = gtk_tree_view_get_model(GTK_TREE_VIEW(sr->rvars1)); if (mod == NULL) { return; } gtk_tree_model_get_iter_first(mod, &iter); for (i=1; i<=list[0]; i++) { v = list[i]; gtk_list_store_append(GTK_LIST_STORE(mod), &iter); gtk_list_store_set(GTK_LIST_STORE(mod), &iter, 0, v, 1, 0, 2, datainfo->varname[v], -1); } } static void maybe_set_listdef_vars (selector *sr) { const char *lname = selector_entry_text(sr); if (lname != NULL && *lname != 0) { int *list = get_list_by_name(lname); if (list != NULL) { add_to_rvars1_from_named_list(sr, list); } } } static void maybe_set_tsplot_vars (selector *sr) { int mc = mdata_selection_count(); if (mc > 1 && mc < 7) { set_vars_from_main(sr); } } static void selector_add_top_entry (selector *sr) { GtkWidget *src; GtkWidget *hbox; GtkWidget *label; GtkWidget *entry; const char *lname; src = GTK_WIDGET(sr->data); lname = gtk_entry_get_text(GTK_ENTRY(src)); hbox = gtk_hbox_new(FALSE, 0); label = gtk_label_new("Name for list:"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); entry = gtk_entry_new_with_max_length(31); gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); if (lname != NULL && *lname != 0 && strcmp(lname, "null")) { gtk_entry_set_text(GTK_ENTRY(entry), lname); gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1); } gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(sr->vbox), hbox, FALSE, FALSE, 0); sr->extra[0] = entry; gtk_widget_show_all(hbox); } #if 0 /* not ready */ static int ols_omit_select (windata_t *vwin) { if (vwin->role == VIEW_MODEL) { MODEL *pmod = vwin->data; return bootstrap_ok(pmod->ci); } else { return 0; } } #endif void simple_selection (const char *title, int (*callback)(), guint ci, gpointer p) { GtkListStore *store; GtkTreeIter iter; GtkWidget *left_vbox, *button_vbox, *right_vbox, *tmp; GtkWidget *top_hbox, *big_hbox, *remove_button; selector *sr; int nleft = 0; int i; if (open_selector != NULL) { gdk_window_raise(open_selector->dlg->window); return; } sr = mymalloc(sizeof *sr); if (sr == NULL) { return; } selector_init(sr, ci, title, p, callback); tmp = simple_selection_top_label(ci); if (tmp != NULL) { gtk_box_pack_start(GTK_BOX(sr->vbox), tmp, FALSE, FALSE, 0); gtk_widget_show(tmp); } /* entry field for some uses */ if (ci == DEFINE_LIST) { selector_add_top_entry(sr); } /* for titles */ top_hbox = gtk_hbox_new(FALSE, 0); gtk_box_set_homogeneous(GTK_BOX(top_hbox), TRUE); tmp = gtk_label_new(_("Available vars")); gtk_box_pack_start(GTK_BOX(top_hbox), tmp, FALSE, FALSE, 5); gtk_widget_show(tmp); tmp = gtk_label_new(" "); gtk_box_pack_start(GTK_BOX(top_hbox), tmp, FALSE, FALSE, 5); gtk_widget_show(tmp); tmp = gtk_label_new(_("Selected vars")); gtk_box_pack_start(GTK_BOX(top_hbox), tmp, FALSE, FALSE, 5); gtk_widget_show(tmp); gtk_box_pack_start(GTK_BOX(sr->vbox), top_hbox, FALSE, FALSE, 5); gtk_widget_show(top_hbox); /* the following will enclose 3 or more vboxes */ big_hbox = gtk_hbox_new(FALSE, 5); /* holds list of elements available for selection */ left_vbox = gtk_vbox_new(FALSE, 5); sr->lvars = var_list_box_new(GTK_BOX(left_vbox), sr, SR_LVARS); store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sr->lvars))); gtk_list_store_clear(store); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); if (ci == OMIT || ci == ADD || ci == COEFFSUM || ci == ELLIPSE || ci == VAROMIT) { nleft = add_omit_list(p, sr); g_signal_connect(G_OBJECT(sr->dlg), "destroy", G_CALLBACK(remove_busy_signal), p); } else { int start = (ci == DEFINE_LIST || ci == DEFINE_MATRIX)? 0 : 1; for (i=start; iv; i++) { if (list_show_var(i, ci, 0)) { list_append_var_simple(store, &iter, i); nleft++; } } } gtk_box_pack_start(GTK_BOX(big_hbox), left_vbox, TRUE, TRUE, 0); gtk_widget_show(left_vbox); /* middle: vertical holder for push/pull buttons */ button_vbox = gtk_vbox_new(TRUE, 0); sr->add_button = gtk_button_new_with_label(_("Select ->")); gtk_box_pack_start(GTK_BOX(button_vbox), sr->add_button, TRUE, FALSE, 0); g_signal_connect(G_OBJECT(sr->add_button), "clicked", G_CALLBACK(add_to_rvars1_callback), sr); if (SAVE_DATA_ACTION(sr->code)) { tmp = gtk_button_new_with_label (_("All ->")); gtk_box_pack_start(GTK_BOX(button_vbox), tmp, TRUE, FALSE, 0); g_signal_connect (G_OBJECT(tmp), "clicked", G_CALLBACK(add_all_to_rvars1_callback), sr); } remove_button = gtk_button_new_with_label(_("<- Remove")); gtk_box_pack_start(GTK_BOX(button_vbox), remove_button, TRUE, FALSE, 0); gtk_box_pack_start(GTK_BOX(big_hbox), button_vbox, TRUE, TRUE, 0); gtk_widget_show_all(button_vbox); /* RHS: vertical holder for selected vars */ right_vbox = gtk_vbox_new(FALSE, 5); sr->rvars1 = var_list_box_new(GTK_BOX(right_vbox), sr, SR_RVARS1); g_object_set_data(G_OBJECT(sr->rvars1), "selector", sr); gtk_box_pack_start(GTK_BOX(big_hbox), right_vbox, TRUE, TRUE, 0); gtk_widget_show(right_vbox); /* connect removal from right signal */ g_signal_connect(G_OBJECT(remove_button), "clicked", G_CALLBACK(remove_from_right_callback), sr->rvars1); /* pack the whole central section into the dialog's vbox */ gtk_box_pack_start(GTK_BOX(sr->vbox), big_hbox, TRUE, TRUE, 0); gtk_widget_show(big_hbox); /* unhide lags check box? */ if (SAVE_DATA_ACTION(sr->code) && lags_hidden) { unhide_lags_switch(sr); } /* radio buttons? */ if (WANT_RADIOS(sr->code)) { build_selector_radios(sr); } #if 0 /* not ready */ /* bootstrap check box? */ if (ci == OMIT && ols_omit_select(p)) { test_boot_switch(sr); } #endif /* buttons: Help, Clear, Cancel, OK */ build_selector_buttons(sr); if (TWO_VARS_CODE(sr->code) && sr->code != ELLIPSE && mdata_selection_count() == 2) { set_vars_from_main(sr); } else if (nleft == 1) { select_singleton(sr); } else if (sr->code == DEFINE_LIST) { maybe_set_listdef_vars(sr); } else if (sr->code == TSPLOTS) { maybe_set_tsplot_vars(sr); } if (nleft == 0) { gtk_widget_destroy(sr->dlg); errbox(_("No variables are available")); } else if ((ci == COEFFSUM || ci == ELLIPSE) && nleft < 2) { gtk_widget_destroy(sr->dlg); errbox(_("No variables are available")); } else { gtk_widget_show(sr->dlg); } if (SAVE_DATA_ACTION(sr->code)) { gretl_set_window_modal(sr->dlg); } else if (sr->code == DEFINE_MATRIX) { gtk_main(); } } struct list_maker { char *liststr; int n_items; size_t len; int overflow; }; static void selection_add_item (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, struct list_maker *lmkr) { gchar *varnum = NULL; if (lmkr->len > MAXLEN - 12) { lmkr->overflow = 1; return; } gtk_tree_model_get (model, iter, 0, &varnum, -1); strcat(lmkr->liststr, " "); strcat(lmkr->liststr, varnum); lmkr->len += strlen(varnum) + 1; g_free(varnum); lmkr->n_items += 1; } char *main_window_selection_as_string (void) { GtkTreeSelection *select; struct list_maker lmkr; lmkr.liststr = mymalloc(MAXLEN); if (lmkr.liststr == NULL) { return NULL; } lmkr.liststr[0] = 0; lmkr.n_items = lmkr.overflow = 0; lmkr.len = 0; select = gtk_tree_view_get_selection(GTK_TREE_VIEW(mdata->listbox)); gtk_tree_selection_selected_foreach(select, (GtkTreeSelectionForeachFunc) selection_add_item, &lmkr); if (lmkr.overflow) { errbox(_("Too many items were selected")); lmkr.liststr[0] = 0; } return lmkr.liststr; } static const char *data_save_title (int code) { switch (code) { case EXPORT_CSV: return _("Save CSV data file"); case EXPORT_R: return _("Save R data file"); case EXPORT_OCTAVE: return _("Save octave data file"); default: return _("Save data file"); } return ""; } static int data_save_selection_callback (selector *sr) { gpointer data = sr->data; int code = sr->code; if (sr->cmdlist == NULL || *sr->cmdlist == 0) { return 0; } if (storelist != NULL) { free(storelist); storelist = NULL; } storelist = g_strdup(sr->cmdlist); gtk_widget_destroy(sr->dlg); if (code == SAVE_FUNCTIONS) { prepare_functions_save(); } else if (code != COPY_CSV) { file_selector(data_save_title(code), code, FSEL_DATA_MISC, data); } return 0; } void data_save_selection_wrapper (int file_code, gpointer p) { if (file_code == SAVE_FUNCTIONS) { if (n_free_functions() == 0) { #if 0 errbox(_("No user-defined functions are currently loaded.\n" "Please load or define some functions first.")); #else errbox(_("No user-defined functions are currently available\n" "for packaging.\n\nPlease load or define some " "functions first.")); #endif return; } selection_dialog(_("Save functions"), data_save_selection_callback, file_code, 0); } else { simple_selection((file_code == COPY_CSV)? _("Copy data") : _("Save data"), data_save_selection_callback, file_code, p); } gtk_main(); /* the corresponding gtk_main_quit() is in the function destroy_selector() */ } /* accessor functions */ int selector_code (const selector *sr) { return (sr->code == PANEL_WLS || sr->code == PANEL_B)? PANEL : sr->code; } const char *selector_list (const selector *sr) { const char *ret = NULL; if (sr->cmdlist != NULL && *sr->cmdlist != '\0') { ret = sr->cmdlist; } return ret; } int selector_list_hasconst (const selector *sr) { int hc = sr->cmdlist != NULL && strstr(sr->cmdlist, " 0") != NULL; return hc; } gpointer selector_get_data (const selector *sr) { return sr->data; } gretlopt selector_get_opts (const selector *sr) { if (sr->code == PANEL_B) { return sr->opts | OPT_B; } else { return sr->opts; } } const char *selector_entry_text (const selector *sr) { g_return_val_if_fail(GTK_IS_ENTRY(sr->extra[0]), NULL); return gtk_entry_get_text(GTK_ENTRY(sr->extra[0])); } int selector_error (const selector *sr) { return sr->error; } void maybe_clear_selector (const int *dlist) { int i, j; if (xlist != NULL) { for (i=1; i<=xlist[0]; i++) { for (j=1; j<=dlist[0]; j++) { if (xlist[i] >= dlist[j]) { clear_selector(); return; } } } } } /* ------------- lag selection apparatus -------------- */ #define NOT_LAG 6666 #define VDEFLT -1 typedef struct var_lag_info_ var_lag_info; struct var_lag_info_ { int v; int pos; int nvl; int lmin; int lmax; char context; char *lspec; GtkWidget *spin1; GtkWidget *spin2; GtkWidget *entry; GtkWidget *toggle; var_lag_info *vlp; }; #define depvar_row(c) (c == LAG_Y_X || c == LAG_Y_W) static void lag_entry_callback (GtkWidget *w, gpointer p) { const gchar *s = gtk_entry_get_text(GTK_ENTRY(w)); var_lag_info *vlinfo = (var_lag_info *) p; free(vlinfo->lspec); vlinfo->lspec = g_strdup(s); if (vlinfo->v == VDEFLT) { /* set the default for this context */ var_lag_info *vlset = vlinfo->vlp; GtkWidget *e; int i; for (i=vlinfo->pos+1; invl; i++) { if (vlset[i].context == vlinfo->context) { e = vlset[i].entry; if (e != NULL) { gtk_entry_set_text(GTK_ENTRY(vlset[i].entry), s); } } } } } static int spinner_get_int (GtkWidget *w) { return (int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)); } static void lag_set_callback (GtkWidget *w, gpointer p) { var_lag_info *vlinfo; double dlag; int *lag; vlinfo = (var_lag_info *) g_object_get_data(G_OBJECT(w), "vlinfo"); lag = (w == vlinfo->spin1)? &vlinfo->lmin : &vlinfo->lmax; *lag = spinner_get_int(w); dlag = *lag; /* fix-ups, if need be */ if (w == vlinfo->spin1 && vlinfo->spin2 != NULL) { int lmax = spinner_get_int(vlinfo->spin2); if (lmax < *lag) { gtk_spin_button_set_value(GTK_SPIN_BUTTON(vlinfo->spin2), dlag); } } else if (vlinfo->spin1 != NULL) { int lmin = spinner_get_int(vlinfo->spin1); if (lmin > *lag) { gtk_spin_button_set_value(GTK_SPIN_BUTTON(vlinfo->spin1), dlag); } } if (vlinfo->v == VDEFLT) { /* set the default for this context */ var_lag_info *vlset = vlinfo->vlp; GtkWidget *s; int i; for (i=vlinfo->pos+1; invl; i++) { if (vlset[i].context == vlinfo->context) { s = (w == vlinfo->spin1)? vlset[i].spin1 : vlset[i].spin2; if (s != NULL) { gtk_spin_button_set_value(GTK_SPIN_BUTTON(s), dlag); } } } } } static void activate_specific_lags (GtkWidget *w, var_lag_info *vlinfo) { gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); if (active) { gtk_widget_set_sensitive(vlinfo->entry, TRUE); gtk_widget_set_sensitive(vlinfo->spin1, FALSE); gtk_widget_set_sensitive(vlinfo->spin2, FALSE); } else { gtk_widget_set_sensitive(vlinfo->entry, FALSE); gtk_widget_set_sensitive(vlinfo->spin1, TRUE); gtk_widget_set_sensitive(vlinfo->spin2, TRUE); } if (vlinfo->v == VDEFLT) { /* set the default per context */ var_lag_info *vlset = vlinfo->vlp; int i; for (i=vlinfo->pos+1; invl; i++) { if (vlset[i].context == vlinfo->context) { if (vlset[i].toggle != NULL) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vlset[i].toggle), active); } } } } } static void lag_toggle_register (GtkWidget *w, var_lag_info *vlinfo) { var_lag_info *vlset = vlinfo->vlp; gboolean active; int i; if (vlset == NULL) return; for (i=0; invl; i++) { if (depvar_row(vlset[i].context)) { if (!GTK_WIDGET_SENSITIVE(vlset[i].spin1) && !GTK_WIDGET_SENSITIVE(vlset[i].entry)) { /* dependent var lags are disabled */ vlset[i].lmin = vlset[i].lmax = NOT_LAG; /* ?? */ free(vlset[i].lspec); vlset[i].lspec = NULL; continue; } } active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vlset[i].toggle)); if (active) { vlset[i].lmin = vlset[i].lmax = NOT_LAG; } else { free(vlset[i].lspec); vlset[i].lspec = NULL; } } } static void activate_y_lags (GtkWidget *w, var_lag_info *vlinfo) { gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); gtk_widget_set_sensitive(vlinfo->spin1, active); gtk_widget_set_sensitive(vlinfo->spin2, active); gtk_widget_set_sensitive(vlinfo->toggle, active); if (active) { vlinfo->lmin = spinner_get_int(vlinfo->spin1); vlinfo->lmax = spinner_get_int(vlinfo->spin2); } if (vlinfo->context == LAG_Y_X) { y_x_lags_enabled = active; } else { y_w_lags_enabled = active; } } static void lagsel_spin_connect (GtkWidget *button) { g_signal_connect(G_OBJECT(button), "value-changed", G_CALLBACK(lag_set_callback), NULL); } static void lags_set_OK (GtkWidget *w, gpointer p) { int *resp = (int *) p; *resp = GRETL_YES; } static void resensitive_selector (GtkWidget *w, gpointer p) { if (open_selector != NULL) { gtk_widget_set_sensitive(open_selector->dlg, TRUE); } } /* Below: we provide spinners for a lag range and also a free-form entry field for non-contiguous lags. In some circumstances we allow specification of lags for the dependent variable as well as the independent vars. */ static int lags_dialog (const int *list, var_lag_info *vlinfo, selector *sr) { GtkWidget *lbl, *dialog, *myvbox; GtkWidget *tbl, *tmp, *hbox; GtkWidget *y_check = NULL; gint tbl_len; double lmin, lmax, ldef; int i, j; int ret = GRETL_CANCEL; dialog = gretl_dialog_new(_("lag order"), sr->dlg, GRETL_DLG_BLOCK| GRETL_DLG_RESIZE); g_signal_connect(G_OBJECT(dialog), "destroy", G_CALLBACK(resensitive_selector), NULL); myvbox = gtk_vbox_new(FALSE, 5); /* allow for additional label row */ tbl_len = list[0] + 1; lmax = (datainfo->t2 - datainfo->t1) / list[0]; ldef = datainfo->pd; tbl = gtk_table_new(tbl_len, 7, FALSE); gtk_table_set_row_spacings(GTK_TABLE(tbl), 5); gtk_table_set_col_spacings(GTK_TABLE(tbl), 5); gtk_box_pack_start(GTK_BOX(myvbox), tbl, FALSE, FALSE, 0); /* row 0 of table: headings */ lbl = gtk_label_new(_("Variable")); gtk_table_attach_defaults(GTK_TABLE(tbl), lbl, 0, 1, 0, 1); lbl = gtk_label_new(_("lags")); gtk_table_attach_defaults(GTK_TABLE(tbl), lbl, 1, 4, 0, 1); lbl = gtk_label_new(" "); gtk_table_attach_defaults(GTK_TABLE(tbl), lbl, 4, 5, 0, 1); lbl = gtk_label_new(_("or")); gtk_table_attach_defaults(GTK_TABLE(tbl), lbl, 5, 6, 0, 1); lbl = gtk_label_new(_("specific lags")); gtk_table_attach_defaults(GTK_TABLE(tbl), lbl, 6, 7, 0, 1); j = 0; for (i=1; i<=list[0]; i++) { if (list[i] >= LISTSEP) { if (list[i] - LISTSEP == LAG_W) { tmp = gtk_label_new(_("Instruments")); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 7, i, i+1); } else if (depvar_row(list[i] - LISTSEP)) { y_check = gtk_check_button_new_with_label(_("Lags of dependent variable")); gtk_table_attach_defaults(GTK_TABLE(tbl), y_check, 0, 7, i, i+1); } else { tmp = gtk_hseparator_new(); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 7, i, i+1); } continue; } if (list[i] == VDEFLT) { lbl = gtk_label_new("default"); } else { lbl = gtk_label_new(datainfo->varname[list[i]]); } gtk_table_attach_defaults(GTK_TABLE(tbl), lbl, 0, 1, i, i+1); lmin = (depvar_row(vlinfo[j].context))? 1 : 0; /* min. lag spinner */ vlinfo[j].spin1 = gtk_spin_button_new_with_range(lmin, lmax, 1); gtk_table_attach_defaults(GTK_TABLE(tbl), vlinfo[j].spin1, 1, 2, i, i+1); g_object_set_data(G_OBJECT(vlinfo[j].spin1), "vlinfo", &vlinfo[j]); lagsel_spin_connect(vlinfo[j].spin1); gtk_spin_button_set_value(GTK_SPIN_BUTTON(vlinfo[j].spin1), vlinfo[j].lmin); lbl = gtk_label_new(_("to")); gtk_table_attach_defaults(GTK_TABLE(tbl), lbl, 2, 3, i, i+1); /* max. lag spinner */ vlinfo[j].spin2 = gtk_spin_button_new_with_range(lmin, lmax, 1); gtk_table_attach_defaults(GTK_TABLE(tbl), vlinfo[j].spin2, 3, 4, i, i+1); g_object_set_data(G_OBJECT(vlinfo[j].spin2), "vlinfo", &vlinfo[j]); lagsel_spin_connect(vlinfo[j].spin2); gtk_spin_button_set_value(GTK_SPIN_BUTTON(vlinfo[j].spin2), vlinfo[j].lmax); /* spacer column */ lbl = gtk_label_new(" "); gtk_table_attach_defaults(GTK_TABLE(tbl), lbl, 4, 5, 0, 1); /* toggle button for activating entry of specific lags */ vlinfo[j].toggle = gtk_check_button_new(); gtk_table_attach_defaults(GTK_TABLE(tbl), vlinfo[j].toggle, 5, 6, i, i+1); g_signal_connect(G_OBJECT(vlinfo[j].toggle), "toggled", G_CALLBACK(activate_specific_lags), &vlinfo[j]); /* entry widget for specific lags */ vlinfo[j].entry = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(vlinfo[j].entry), 16); gtk_table_attach_defaults(GTK_TABLE(tbl), vlinfo[j].entry, 6, 7, i, i+1); g_signal_connect(G_OBJECT(vlinfo[j].entry), "changed", G_CALLBACK(lag_entry_callback), &vlinfo[j]); if (vlinfo[j].lspec != NULL && vlinfo[j].lspec[0] != 0) { /* got a saved non-contiguous lag spec */ gtk_entry_set_text(GTK_ENTRY(vlinfo[j].entry), vlinfo[j].lspec); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vlinfo[j].toggle), TRUE); } else { gtk_widget_set_sensitive(vlinfo[j].entry, FALSE); } /* set sensitivity of dependent variable lags apparatus */ if (depvar_row(vlinfo[j].context)) { g_signal_connect(G_OBJECT(y_check), "toggled", G_CALLBACK(activate_y_lags), &vlinfo[j]); if ((vlinfo[j].context == LAG_Y_X && y_x_lags_enabled) || (vlinfo[j].context == LAG_Y_W && y_w_lags_enabled)) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(y_check), TRUE); } else { gtk_widget_set_sensitive(vlinfo[j].spin1, FALSE); gtk_widget_set_sensitive(vlinfo[j].spin2, FALSE); gtk_widget_set_sensitive(vlinfo[j].toggle, FALSE); gtk_widget_set_sensitive(vlinfo[j].entry, FALSE); } } j++; } hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), myvbox, TRUE, TRUE, 5); if (list[0] > 10) { GtkWidget *scroller = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroller), hbox); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scroller, TRUE, TRUE, 5); gtk_widget_show_all(scroller); gtk_widget_set_size_request(scroller, -1, 360); } else { gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 5); gtk_widget_show_all(hbox); } hbox = GTK_DIALOG(dialog)->action_area; /* "Cancel" button */ tmp = cancel_delete_button(hbox, dialog, NULL); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(delete_widget), dialog); /* "OK" button */ tmp = ok_button(hbox); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(lags_set_OK), &ret); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(lag_toggle_register), &vlinfo[0]); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(delete_widget), dialog); gtk_widget_grab_default(tmp); gtk_widget_show(tmp); /* "Help" button */ context_help_button(hbox, LAGS_DIALOG); gtk_widget_set_sensitive(sr->dlg, FALSE); gtk_widget_show(dialog); return ret; } static int laggable_var (int v, int lag, int context) { if (v == 0 || !strcmp(datainfo->varname[v], "time") || !strcmp(datainfo->varname[v], "timesq")) { return 0; } if (is_lag_dummy(v, lag, context)) { return 0; } return 1; } static void revise_var_string (var_lag_info *vlinfo, selector *sr, int locus) { GtkWidget *w; GtkTreeModel *mod; GtkTreeIter iter; int modv; w = (locus == SR_RVARS2)? sr->rvars2 : sr->rvars1; mod = gtk_tree_view_get_model(GTK_TREE_VIEW(w)); gtk_tree_model_get_iter_first(mod, &iter); do { gtk_tree_model_get(mod, &iter, 0, &modv, -1); if (modv == vlinfo->v) { #if VLDEBUG fprintf(stderr, "revise_var_string: calling varlist_insert_var_full\n"); #endif varlist_insert_var_full(vlinfo->v, mod, &iter, sr, locus); break; } } while (gtk_tree_model_iter_next(mod, &iter)); } /* go through a list box and find the vars that are candidates for lag selection: this excludes constant and trend, and also list entries that are themselves just dummy placeholders for already selected lags of a variable */ static int get_laggable_vars (GtkWidget *w, int context, int *list, int *i) { GtkTreeModel *model; GtkTreeIter iter; gint xnum, lag; int n = 0; if (!GTK_IS_TREE_VIEW(w)) { return 0; } model = gtk_tree_view_get_model(GTK_TREE_VIEW(w)); if (model == NULL) { return 0; } if (gtk_tree_model_get_iter_first(model, &iter)) { do { gtk_tree_model_get(model, &iter, 0, &xnum, 1, &lag, -1); if (laggable_var(xnum, lag, context)) { if (list != NULL) { list[*i] = xnum; *i += 1; } n++; } } while (gtk_tree_model_iter_next(model, &iter)); } return n; } static int *sr_get_stoch_list (selector *sr, int *nset, int *pcontext) { GtkWidget *list[2] = { NULL, NULL }; gint ynum = 0; int nv[2] = {0}; int llen, sep; int context; int i, j; int *slist = NULL; if (sr->code != ARMA && sr->code != VAR && sr->code != VECM && sr->code != VLAGSEL && sr->code != ARBOND) { ynum = selector_get_depvar_number(sr); } list[0] = (select_lags_primary(sr->code))? sr->rvars1 : sr->rvars2; if (sr->code == TSLS) { list[1] = sr->rvars2; } for (j=0; list[j] != NULL && j<2; j++) { context = (j == 1)? LAG_W : LAG_X; nv[j] = get_laggable_vars(list[j], context, NULL, NULL); } if (nv[0] == 0) { list[0] = NULL; } if (nv[1] == 0) { list[1] = NULL; } llen = sep = 0; if (ynum < 0 && nv[0] == 0 && nv[1] == 0) { /* no vars to deal with */ errbox("Please add some variables to the model first"); } else { if (nv[0] > 0) { *pcontext = LAG_X; llen += nv[0] + 1; /* xvars plus their defaults */ if (ynum > 0) { llen++; /* separator */ sep++; llen++; /* dep var row */ } } if (nv[1] > 0) { if (nv[0] > 0) { llen++; /* separator from X's */ sep++; } else { *pcontext = LAG_W; } llen++; /* "instruments" heading */ sep++; llen += nv[1] + 1; /* instruments plus their defaults */ if (ynum > 0) { llen++; /* separator */ sep++; llen++; /* dep var row */ } } if (nv[0] == 0 && nv[1] == 0) { /* only the dependent variable is present */ *pcontext = LAG_Y_X; llen++; /* "separator" */ sep++; llen++; /* dep var row */ } slist = gretl_list_new(llen); if (slist != NULL) { i = 1; for (j=0; j<2; j++) { if (list[j] == NULL) { continue; } context = (j == 1)? LAG_W : LAG_X; if (j == 1) { if (nv[0] > 0) { slist[i++] = LISTSEP; } slist[i++] = LISTSEP + LAG_W; } slist[i++] = VDEFLT; get_laggable_vars(list[j], context, slist, &i); if (ynum > 0) { slist[i++] = LISTSEP + ((j > 0)? LAG_Y_W : LAG_Y_X); slist[i++] = ynum; } } if (nv[0] == 0 && nv[1] == 0) { slist[i++] = LISTSEP + LAG_Y_X; slist[i++] = ynum; } } *nset = llen - sep; } return slist; } static void maybe_revise_var_string (var_lag_info *vlinfo, selector *sr) { int locus = 0; #if VLDEBUG fprintf(stderr, "maybe_revise_var_string: v = %d, context = %d\n", vlinfo->v, vlinfo->context); #endif if (vlinfo->context == LAG_X) { locus = (sr->code == VAR || sr->code == VECM || sr->code == VLAGSEL)? SR_RVARS2 : SR_RVARS1; } else if (vlinfo->context == LAG_W) { locus = SR_RVARS2; } else if (depvar_row(vlinfo->context)) { #if VLDEBUG fprintf(stderr, " calling maybe_revise_depvar_lags, context = %d\n", vlinfo->context); #endif maybe_revise_depvar_lags(sr, vlinfo->v, vlinfo->context); } if (locus > 0) { #if VLDEBUG fprintf(stderr, " calling revise_var_string, locus = %d\n", locus); #endif revise_var_string(vlinfo, sr, locus); } } /* return 1 if lags changed, else 0 */ static int set_lags_for_var (var_lag_info *vlinfo, int yxlags, int ywlags) { int *llist = NULL; int changed = 0; int err = 0; #if LDEBUG fprintf(stderr, "set_lags_for_var: v=%d, lmin=%d, lmax=%d, lspec=%p\n", vlinfo->v, vlinfo->lmin, vlinfo->lmax, (void *) vlinfo->lspec); #endif if (vlinfo->lspec != NULL && *vlinfo->lspec != 0) { charsub(vlinfo->lspec, ',', ' '); llist = gretl_list_from_string(vlinfo->lspec); err = set_lag_prefs_from_list(vlinfo->v, llist, vlinfo->context, &changed); if (err) { free(llist); } } else if (vlinfo->lmin != NOT_LAG && vlinfo->lmax != NOT_LAG) { set_lag_prefs_from_minmax(vlinfo->v, vlinfo->lmin, vlinfo->lmax, vlinfo->context, &changed); } else { set_null_lagpref(vlinfo->v, vlinfo->context, &changed); } if (vlinfo->context == LAG_Y_X && yxlags != y_x_lags_enabled) { changed = 1; } else if (vlinfo->context == LAG_Y_W && ywlags != y_w_lags_enabled) { changed = 1; } return changed; } #if LDEBUG > 2 static void print_vlinfo (var_lag_info *vlinfo) { fprintf(stderr, "\nCreated vlinfo struct:\n"); fprintf(stderr, " v = %d\n", vlinfo->v); fprintf(stderr, " pos = %d\n", vlinfo->pos); fprintf(stderr, " nvl = %d\n", vlinfo->nvl); fprintf(stderr, " context = %d\n", (int) vlinfo->context); fprintf(stderr, " vlp = %p\n", (void *) vlinfo->vlp); fprintf(stderr, " lmin = %d\n", vlinfo->lmin); fprintf(stderr, " lmax = %d\n", vlinfo->lmax); if (vlinfo->lspec != NULL) { fprintf(stderr, " lspec = '%s'\n", vlinfo->lspec); } else { fprintf(stderr, " lspec = NULL\n"); } } #endif static gboolean lags_dialog_driver (GtkWidget *w, selector *sr) { var_lag_info *vlinfo; int yxlags = y_x_lags_enabled; int ywlags = y_w_lags_enabled; int context = 0; int i, j, resp, nvl; int *list; list = sr_get_stoch_list(sr, &nvl, &context); if (list == NULL) { return FALSE; } #if LDEBUG printlist(list, "stochastic vars list"); fprintf(stderr, "number of setters = %d\n", nvl); #endif vlinfo = mymalloc(nvl * sizeof *vlinfo); if (vlinfo == NULL) { free(list); return FALSE; } j = 0; for (i=1; i<=list[0]; i++) { const int *laglist = NULL; int v = list[i]; if (v >= LISTSEP) { context = v - LISTSEP; #if LDEBUG fprintf(stderr, "list[%d] = %d: set context = %d\n", i, v, context); #endif continue; } /* pick up any saved preferences (including saved defaults) */ get_lag_preference(v, &vlinfo[j].lmin, &vlinfo[j].lmax, &laglist, context); if (laglist != NULL) { vlinfo[j].lspec = gretl_list_to_string(laglist); } else { vlinfo[j].lspec = NULL; } vlinfo[j].v = v; vlinfo[j].pos = j; vlinfo[j].nvl = nvl; vlinfo[j].context = context; vlinfo[j].spin1 = NULL; vlinfo[j].spin2 = NULL; vlinfo[j].entry = NULL; vlinfo[j].toggle = NULL; vlinfo[j].vlp = vlinfo; #if LDEBUG > 2 print_vlinfo(&vlinfo[j]); #endif j++; } resp = lags_dialog(list, vlinfo, sr); for (j=0; j