1 /*
2 * dialog-analysis-tools.c:
3 *
4 * Authors:
5 * Jukka-Pekka Iivonen <jiivonen@hutcs.cs.hut.fi>
6 * Andreas J. Guelzow <aguelzow@taliesin.ca>
7 *
8 * (C) Copyright 2000, 2001 by Jukka-Pekka Iivonen <jiivonen@hutcs.cs.hut.fi>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <https://www.gnu.org/licenses/>.
22 */
23
24 #include <gnumeric-config.h>
25 #include <glib/gi18n-lib.h>
26 #include <gnumeric.h>
27 #include <dialogs/dialogs.h>
28 #include <tools/analysis-tools.h>
29 #include <tools/analysis-anova.h>
30 #include <tools/analysis-histogram.h>
31 #include <tools/analysis-exp-smoothing.h>
32
33 #include <workbook.h>
34 #include <workbook-control.h>
35 #include <wbc-gtk.h>
36 #include <workbook-view.h>
37 #include <gui-util.h>
38 #include <parse-util.h>
39 #include <gnm-format.h>
40 #include <dialogs/tool-dialogs.h>
41 #include <dialogs/dao-gui-utils.h>
42 #include <sheet.h>
43 #include <expr.h>
44 #include <number-match.h>
45 #include <ranges.h>
46 #include <selection.h>
47 #include <value.h>
48 #include <commands.h>
49 #include <dialogs/help.h>
50
51 #include <widgets/gnm-dao.h>
52 #include <widgets/gnm-expr-entry.h>
53
54 #include <string.h>
55
56 /**********************************************/
57 /* Generic guru items */
58 /**********************************************/
59
60
61
62 #define CORRELATION_KEY "analysistools-correlation-dialog"
63 #define COVARIANCE_KEY "analysistools-covariance-dialog"
64 #define DESCRIPTIVE_STATS_KEY "analysistools-descriptive-stats-dialog"
65 #define RANK_PERCENTILE_KEY "analysistools-rank-percentile-dialog"
66 #define TTEST_KEY "analysistools-ttest-dialog"
67 #define FTEST_KEY "analysistools-ftest-dialog"
68 #define SAMPLING_KEY "analysistools-sampling-dialog"
69 #define HISTOGRAM_KEY "analysistools-histogram-dialog"
70 #define FOURIER_KEY "analysistools-fourier-dialog"
71 #define AVERAGE_KEY "analysistools-moving-average-dialog"
72 #define EXP_SMOOTHING_KEY "analysistools-exp-smoothing-dialog"
73 #define REGRESSION_KEY "analysistools-regression-dialog"
74 #define ANOVA_TWO_FACTOR_KEY "analysistools-anova-two-factor-dialog"
75 #define ANOVA_SINGLE_KEY "analysistools-anova-single-factor-dialog"
76
77
78 static char const * const grouped_by_group[] = {
79 "grouped_by_row",
80 "grouped_by_col",
81 "grouped_by_area",
82 NULL
83 };
84
85 typedef struct {
86 GnmGenericToolState base;
87 GtkWidget *predetermined_button;
88 GtkWidget *calculated_button;
89 GtkEntry *n_entry;
90 GtkEntry *max_entry;
91 GtkEntry *min_entry;
92 } HistogramToolState;
93
94 static char const * const bin_type_group[] = {
95 "bintype_no_inf_lower",
96 "bintype_no_inf_upper",
97 "bintype_p_inf_lower",
98 "bintype_p_inf_upper",
99 "bintype_m_inf_lower",
100 "bintype_m_inf_upper",
101 "bintype_pm_inf_lower",
102 "bintype_pm_inf_upper",
103 NULL
104 };
105
106 static char const * const chart_group[] = {
107 "nochart-button",
108 "histogram-button",
109 "barchart-button",
110 "columnchart-button",
111 NULL
112 };
113
114 static char const * const n_group[] = {
115 "n-button",
116 "nm1-button",
117 "nm2-button",
118 "nm3-button",
119 NULL
120 };
121
122 /* Note: the items in this group need to match */
123 /* moving_average_type_t except that */
124 /* moving_average_type_central_sma is a */
125 /* subtype of moving_average_type_sma. */
126 static char const * const moving_average_group[] = {
127 "sma-button",
128 "cma-button",
129 "wma-button",
130 "spencer-ma-button",
131 NULL
132 };
133
134 static char const * const exp_smoothing_group[] = {
135 "ses-h-button",
136 "ses-r-button",
137 "des-button",
138 "ates-button",
139 "mtes-button",
140 NULL
141 };
142
143
144
145 typedef struct {
146 GnmGenericToolState base;
147 GtkWidget *summary_stats_button;
148 GtkWidget *mean_stats_button;
149 GtkWidget *kth_largest_button;
150 GtkWidget *kth_smallest_button;
151 GtkWidget *ss_button;
152 GtkWidget *c_entry;
153 GtkWidget *l_entry;
154 GtkWidget *s_entry;
155 } DescriptiveStatState;
156
157 typedef struct {
158 GnmGenericToolState base;
159 GtkWidget *paired_button;
160 GtkWidget *unpaired_button;
161 GtkWidget *known_button;
162 GtkWidget *unknown_button;
163 GtkWidget *equal_button;
164 GtkWidget *unequal_button;
165 GtkWidget *variablespaired_label;
166 GtkWidget *varianceknown_label;
167 GtkWidget *varianceequal_label;
168 GtkWidget *var1_variance_label;
169 GtkWidget *var2_variance_label;
170 GtkWidget *var1_variance;
171 GtkWidget *var2_variance;
172 GtkWidget *options_grid;
173 GtkWidget *mean_diff_entry;
174 GtkWidget *alpha_entry;
175 ttest_type invocation;
176 } TTestState;
177
178 typedef struct {
179 GnmGenericToolState base;
180 GtkWidget *options_grid;
181 GtkWidget *method_label;
182 GtkWidget *periodic_button;
183 GtkWidget *random_button;
184 GtkWidget *period_label;
185 GtkWidget *random_label;
186 GtkWidget *period_entry;
187 GtkWidget *random_entry;
188 GtkWidget *number_entry;
189 GtkWidget *offset_label;
190 GtkWidget *offset_entry;
191 GtkWidget *major_label;
192 GtkWidget *row_major_button;
193 GtkWidget *col_major_button;
194 } SamplingState;
195
196 typedef struct {
197 GnmGenericToolState base;
198 GtkWidget *interval_entry;
199 GtkWidget *show_std_errors;
200 GtkWidget *n_button;
201 GtkWidget *nm1_button;
202 GtkWidget *nm2_button;
203 GtkWidget *prior_button;
204 GtkWidget *central_button;
205 GtkWidget *offset_button;
206 GtkWidget *offset_spin;
207 GtkWidget *graph_button;
208 GtkWidget *sma_button;
209 GtkWidget *cma_button;
210 GtkWidget *wma_button;
211 GtkWidget *spencer_button;
212 } AverageToolState;
213
214 typedef struct {
215 GnmGenericToolState base;
216 GtkWidget *damping_fact_entry;
217 GtkWidget *g_damping_fact_entry;
218 GtkWidget *s_damping_fact_entry;
219 GtkWidget *s_period_entry;
220 GtkWidget *show_std_errors;
221 GtkWidget *n_button;
222 GtkWidget *nm1_button;
223 GtkWidget *nm2_button;
224 GtkWidget *nm3_button;
225 GtkWidget *graph_button;
226 GtkWidget *ses_h_button;
227 GtkWidget *ses_r_button;
228 GtkWidget *des_button;
229 GtkWidget *ates_button;
230 GtkWidget *mtes_button;
231 } ExpSmoothToolState;
232
233 typedef struct {
234 GnmGenericToolState base;
235 GtkWidget *confidence_entry;
236 GtkWidget *simple_linear_regression_radio;
237 GtkWidget *switch_variables_check;
238 GtkWidget *residuals_check;
239 } RegressionToolState;
240
241 typedef struct {
242 GnmGenericToolState base;
243 GtkWidget *alpha_entry;
244 } AnovaSingleToolState;
245
246 typedef struct {
247 GnmGenericToolState base;
248 GtkWidget *alpha_entry;
249 GtkWidget *replication_entry;
250 } AnovaTwoFactorToolState;
251
252 typedef struct {
253 GnmGenericToolState base;
254 GtkWidget *alpha_entry;
255 } FTestToolState;
256
257
258 /**********************************************/
259 /* Generic functions for the analysis tools. */
260 /* Functions in this section are being used */
261 /* by virtually all tools. */
262 /**********************************************/
263
264
265 /**
266 * error_in_entry:
267 * @state:
268 * @entry:
269 * @err_str:
270 *
271 * Show an error dialog and select corresponding entry
272 */
273 void
error_in_entry(GnmGenericToolState * state,GtkWidget * entry,char const * err_str)274 error_in_entry (GnmGenericToolState *state, GtkWidget *entry, char const *err_str)
275 {
276 go_gtk_notice_nonmodal_dialog ((GtkWindow *) state->dialog,
277 &(state->warning_dialog),
278 GTK_MESSAGE_ERROR,
279 "%s", err_str);
280
281 if (GNM_EXPR_ENTRY_IS (entry))
282 gnm_expr_entry_grab_focus (GNM_EXPR_ENTRY (entry), TRUE);
283 else
284 focus_on_entry (GTK_ENTRY (entry));
285 }
286
287 static void
cb_tool_destroy(GnmGenericToolState * state)288 cb_tool_destroy (GnmGenericToolState *state)
289 {
290 if (state->gui != NULL)
291 g_object_unref (state->gui);
292 wbcg_edit_finish (state->wbcg, WBC_EDIT_REJECT, NULL);
293 if (state->state_destroy)
294 state->state_destroy (state);
295 g_free (state);
296 }
297
298 /**
299 * cb_tool_cancel_clicked:
300 * @button:
301 * @state:
302 *
303 * Close (destroy) the dialog
304 **/
305 static void
cb_tool_cancel_clicked(G_GNUC_UNUSED GtkWidget * button,GnmGenericToolState * state)306 cb_tool_cancel_clicked (G_GNUC_UNUSED GtkWidget *button,
307 GnmGenericToolState *state)
308 {
309 gtk_widget_destroy (state->dialog);
310 return;
311 }
312
313
314
315 /**
316 * dialog_tool_init_buttons:
317 * @state:
318 * @ok_function:
319 *
320 * Setup the buttons
321 *
322 **/
323 static void
dialog_tool_init_buttons(GnmGenericToolState * state,GCallback ok_function,GCallback close_function)324 dialog_tool_init_buttons (GnmGenericToolState *state,
325 GCallback ok_function,
326 GCallback close_function)
327 {
328 state->ok_button = go_gtk_builder_get_widget (state->gui, "okbutton");
329 g_signal_connect (G_OBJECT (state->ok_button),
330 "clicked",
331 G_CALLBACK (ok_function), state);
332
333 state->cancel_button = go_gtk_builder_get_widget (state->gui,
334 "cancelbutton");
335 if (close_function == NULL)
336 g_signal_connect (G_OBJECT (state->cancel_button),
337 "clicked",
338 G_CALLBACK (cb_tool_cancel_clicked), state);
339 else
340 g_signal_connect (G_OBJECT (state->cancel_button),
341 "clicked",
342 G_CALLBACK (close_function), state);
343
344 state->apply_button = go_gtk_builder_get_widget (state->gui, "applybutton");
345 if (state->apply_button != NULL )
346 g_signal_connect (G_OBJECT (state->apply_button),
347 "clicked",
348 G_CALLBACK (ok_function), state);
349 state->help_button = go_gtk_builder_get_widget (state->gui, "helpbutton");
350 if (state->help_button != NULL )
351 gnm_init_help_button (state->help_button,
352 state->help_link);
353 }
354
355
356 /**
357 * dialog_tool_init: (skip)
358 * @state:
359 * @gui_name:
360 * @dialog_name:
361 * @ok_function:
362 * @sensitivity_cb:
363 *
364 * Create the dialog (guru).
365 *
366 **/
367 gboolean
dialog_tool_init(GnmGenericToolState * state,WBCGtk * wbcg,Sheet * sheet,char const * help_file,char const * gui_name,char const * dialog_name,char const * error_str,char const * key,GCallback ok_function,GCallback close_function,GCallback sensitivity_cb,GnmExprEntryFlags flags)368 dialog_tool_init (GnmGenericToolState *state,
369 WBCGtk *wbcg,
370 Sheet *sheet,
371 char const *help_file,
372 char const *gui_name,
373 char const *dialog_name,
374 char const *error_str,
375 char const *key,
376 GCallback ok_function,
377 GCallback close_function,
378 GCallback sensitivity_cb,
379 GnmExprEntryFlags flags)
380 {
381 GtkGrid *grid;
382 GtkWidget *widget;
383
384 state->wbcg = wbcg;
385 state->wb = wb_control_get_workbook (GNM_WBC (wbcg));
386 state->sheet = sheet;
387 state->sv = wb_control_cur_sheet_view (GNM_WBC (wbcg));
388 state->warning_dialog = NULL;
389 state->help_link = help_file;
390 state->state_destroy = NULL;
391
392 state->gui = gnm_gtk_builder_load (gui_name, NULL, GO_CMD_CONTEXT (wbcg));
393 if (state->gui == NULL)
394 goto dialog_tool_init_error;
395
396 state->dialog = go_gtk_builder_get_widget (state->gui, dialog_name);
397 if (state->dialog == NULL)
398 goto dialog_tool_init_error;
399
400
401 dialog_tool_init_buttons (state, ok_function, close_function);
402
403 widget = go_gtk_builder_get_widget (state->gui, "var1-label");
404 if (widget == NULL) {
405 state->input_entry = NULL;
406 } else {
407 guint left_attach, top_attach, width, height;
408
409 grid = GTK_GRID (gtk_widget_get_parent (widget));
410 state->input_entry = gnm_expr_entry_new (state->wbcg, TRUE);
411 g_object_set (G_OBJECT (state->input_entry), "hexpand", TRUE, NULL);
412 gnm_expr_entry_disable_tips (state->input_entry);
413 gnm_expr_entry_set_flags (state->input_entry,
414 flags | GNM_EE_FORCE_ABS_REF,
415 GNM_EE_MASK);
416
417 gtk_container_child_get (GTK_CONTAINER (grid), widget,
418 "left-attach", &left_attach,
419 "top-attach", &top_attach,
420 "width", &width,
421 "height", &height,
422 NULL);
423
424 gtk_grid_attach (grid, GTK_WIDGET (state->input_entry),
425 left_attach + width, top_attach,
426 1, height);
427 g_signal_connect_after (G_OBJECT (state->input_entry),
428 "changed",
429 G_CALLBACK (sensitivity_cb), state);
430 gnm_editable_enters (GTK_WINDOW (state->dialog),
431 GTK_WIDGET (state->input_entry));
432 gtk_label_set_mnemonic_widget (GTK_LABEL (widget),
433 GTK_WIDGET (state->input_entry));
434 go_atk_setup_label (widget, GTK_WIDGET (state->input_entry));
435 gtk_widget_show (GTK_WIDGET (state->input_entry));
436 }
437
438
439 /* */
440 /* If there is a var2-label, we need a second input field */
441 /* */
442 widget = go_gtk_builder_get_widget (state->gui, "var2-label");
443 if (widget == NULL) {
444 state->input_entry_2 = NULL;
445 } else {
446 guint left_attach, top_attach, width, height;
447
448 state->input_entry_2 = gnm_expr_entry_new (state->wbcg, TRUE);
449 g_object_set (G_OBJECT (state->input_entry_2), "hexpand", TRUE, NULL);
450 gnm_expr_entry_disable_tips (state->input_entry_2);
451 gnm_expr_entry_set_flags (state->input_entry_2,
452 GNM_EE_SINGLE_RANGE | GNM_EE_FORCE_ABS_REF, GNM_EE_MASK);
453 grid = GTK_GRID (gtk_widget_get_parent (widget));
454
455 gtk_container_child_get (GTK_CONTAINER (grid), widget,
456 "left-attach", &left_attach,
457 "top-attach", &top_attach,
458 "width", &width,
459 "height", &height,
460 NULL);
461
462 gtk_grid_attach (grid, GTK_WIDGET (state->input_entry_2),
463 left_attach + width, top_attach,
464 1, height);
465 g_signal_connect_after (G_OBJECT (state->input_entry_2),
466 "changed",
467 G_CALLBACK (sensitivity_cb), state);
468 gnm_editable_enters (GTK_WINDOW (state->dialog),
469 GTK_WIDGET (state->input_entry_2));
470 gtk_label_set_mnemonic_widget (GTK_LABEL (widget),
471 GTK_WIDGET (state->input_entry_2));
472 go_atk_setup_label (widget, GTK_WIDGET (state->input_entry_2));
473 gtk_widget_show (GTK_WIDGET (state->input_entry_2));
474 }
475
476 state->warning = go_gtk_builder_get_widget (state->gui, "warnings");
477 wbc_gtk_attach_guru (state->wbcg, state->dialog);
478 g_object_set_data_full (G_OBJECT (state->dialog),
479 "state", state, (GDestroyNotify) cb_tool_destroy);
480
481 dialog_tool_init_outputs (state, sensitivity_cb);
482
483 gnm_keyed_dialog (wbcg, GTK_WINDOW (state->dialog), key);
484
485 gnm_dialog_setup_destroy_handlers (GTK_DIALOG (state->dialog),
486 state->wbcg,
487 GNM_DIALOG_DESTROY_SHEET_REMOVED |
488 GNM_DIALOG_DESTROY_SHEET_RENAMED);
489
490 return FALSE;
491
492 dialog_tool_init_error:
493 go_gtk_notice_dialog (wbcg_toplevel (wbcg),
494 GTK_MESSAGE_ERROR,
495 "%s", error_str);
496 g_free (state);
497 return TRUE;
498 }
499
500 /**
501 * tool_load_selection:
502 * @state:
503 *
504 * load the current selection in the output and input entries
505 * show the dialog and focus the input_entry
506 *
507 **/
508 void
tool_load_selection(GnmGenericToolState * state,gboolean allow_multiple)509 tool_load_selection (GnmGenericToolState *state, gboolean allow_multiple)
510 {
511 GnmRange const *first = selection_first_range (state->sv, NULL, NULL);
512
513 if (first != NULL) {
514 if (allow_multiple) {
515 char *text = selection_to_string (state->sv, TRUE);
516 gnm_expr_entry_load_from_text (state->input_entry,
517 text);
518 g_free (text);
519 } else
520 gnm_expr_entry_load_from_range (state->input_entry,
521 state->sheet, first);
522 if (state->gdao != NULL)
523 gnm_dao_load_range (GNM_DAO (state->gdao), first);
524 }
525
526 gtk_widget_show (state->dialog);
527 gnm_expr_entry_grab_focus (GNM_EXPR_ENTRY (state->input_entry),
528 TRUE);
529
530 }
531
532 /**
533 * tool_setup_update: (skip)
534 */
535 GtkWidget *
tool_setup_update(GnmGenericToolState * state,char const * name,GCallback cb,gpointer closure)536 tool_setup_update (GnmGenericToolState* state, char const *name, GCallback cb,
537 gpointer closure)
538 {
539 GtkWidget *w = go_gtk_builder_get_widget (state->gui, name);
540 if (GTK_IS_SPIN_BUTTON (w)) {
541 g_signal_connect_after (w, "value-changed", cb, closure);
542 gnm_editable_enters (GTK_WINDOW (state->dialog), w);
543 } else if (GTK_IS_ENTRY (w)) {
544 g_signal_connect_after (w, "changed", cb, closure);
545 gnm_editable_enters (GTK_WINDOW (state->dialog), w);
546 } else if (GTK_IS_TOGGLE_BUTTON (w))
547 g_signal_connect_after (w, "toggled", cb, closure);
548 else
549 g_warning ("tool_setup_update called with unknown type");
550 return w;
551 }
552
553
554
555
556 /**********************************************/
557 /* Generic functions for the analysis tools */
558 /* Functions in this section are being used */
559 /* some tools */
560 /**********************************************/
561
562 /**
563 * tool_update_sensitivity_cb:
564 * @dummy:
565 * @state:
566 *
567 * Update the dialog widgets sensitivity if the only items of interest
568 * are one or two standard input and one output item, permitting multiple
569 * areas as first input.
570 *
571 * used by:
572 * Correlation
573 * Covariance
574 * RankPercentile
575 * FourierAnalysis
576 *
577 **/
578 static void
tool_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,GnmGenericToolState * state)579 tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
580 GnmGenericToolState *state)
581 {
582 GSList *input_range;
583
584 /* Checking Input Range */
585 input_range = gnm_expr_entry_parse_as_list (
586 GNM_EXPR_ENTRY (state->input_entry), state->sheet);
587 if (input_range == NULL) {
588 gtk_label_set_text (GTK_LABEL (state->warning),
589 _("The input range is invalid."));
590 gtk_widget_set_sensitive (state->ok_button, FALSE);
591 return;
592 } else
593 range_list_destroy (input_range);
594
595 /* Checking Output Page */
596 if (!gnm_dao_is_ready (GNM_DAO (state->gdao))) {
597 gtk_label_set_text (GTK_LABEL (state->warning),
598 _("The output specification "
599 "is invalid."));
600 gtk_widget_set_sensitive (state->ok_button, FALSE);
601 return;
602 }
603
604 gtk_label_set_text (GTK_LABEL (state->warning), "");
605 gtk_widget_set_sensitive (state->ok_button, TRUE);
606
607 return;
608 }
609
610 /**********************************************/
611 /* Begin of correlation tool code */
612 /**********************************************/
613
614
615 /**
616 * corr_tool_ok_clicked_cb:
617 * @button:
618 * @state:
619 *
620 * Retrieve the information from the dialog and call the correlation_tool.
621 * Note that we assume that the ok_button is only active if the entry fields
622 * contain sensible data.
623 **/
624 static void
corr_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,GnmGenericToolState * state)625 corr_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
626 GnmGenericToolState *state)
627 {
628 data_analysis_output_t *dao;
629 analysis_tools_data_generic_t *data;
630
631 char *text;
632 GtkWidget *w;
633
634 if (state->warning_dialog != NULL)
635 gtk_widget_destroy (state->warning_dialog);
636
637 data = g_new0 (analysis_tools_data_generic_t, 1);
638 dao = parse_output (state, NULL);
639
640 data->input = gnm_expr_entry_parse_as_list (
641 GNM_EXPR_ENTRY (state->input_entry), state->sheet);
642 data->group_by = gnm_gui_group_value (state->gui, grouped_by_group);
643
644 w = go_gtk_builder_get_widget (state->gui, "labels_button");
645 data->labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
646
647 if (cmd_analysis_tool (GNM_WBC (state->wbcg), state->sheet,
648 dao, data, analysis_tool_correlation_engine, FALSE)) {
649
650 switch (data->err - 1) {
651 case GROUPED_BY_ROW:
652 error_in_entry ((GnmGenericToolState *) state,
653 GTK_WIDGET (state->input_entry),
654 _("The selected input rows must have equal size!"));
655 break;
656 case GROUPED_BY_COL:
657 error_in_entry ((GnmGenericToolState *) state,
658 GTK_WIDGET (state->input_entry),
659 _("The selected input columns must have equal size!"));
660 break;
661 case GROUPED_BY_AREA:
662 error_in_entry ((GnmGenericToolState *) state,
663 GTK_WIDGET (state->input_entry),
664 _("The selected input areas must have equal size!"));
665 break;
666 default:
667 text = g_strdup_printf (
668 _("An unexpected error has occurred: %d."), data->err);
669 error_in_entry ((GnmGenericToolState *) state,
670 GTK_WIDGET (state->input_entry), text);
671 g_free (text);
672 break;
673 }
674 range_list_destroy (data->input);
675 g_free (dao);
676 g_free (data);
677 } else
678 gtk_widget_destroy (state->dialog);
679 return;
680 }
681
682
683
684 /**
685 * dialog_correlation_tool:
686 * @wbcg:
687 * @sheet:
688 *
689 * Show the dialog (guru).
690 *
691 **/
692 int
dialog_correlation_tool(WBCGtk * wbcg,Sheet * sheet)693 dialog_correlation_tool (WBCGtk *wbcg, Sheet *sheet)
694 {
695 GnmGenericToolState *state;
696 char const * plugins[] = { "Gnumeric_fnstat",
697 NULL};
698
699 if ((wbcg == NULL) ||
700 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
701 return 1;
702
703 /* Only pop up one copy per workbook */
704 if (gnm_dialog_raise_if_exists (wbcg, CORRELATION_KEY))
705 return 0;
706
707 state = g_new0 (GnmGenericToolState, 1);
708
709 if (dialog_tool_init (state, wbcg, sheet,
710 GNUMERIC_HELP_LINK_CORRELATION,
711 "res:ui/correlation.ui", "Correlation",
712 _("Could not create the Correlation Tool dialog."),
713 CORRELATION_KEY,
714 G_CALLBACK (corr_tool_ok_clicked_cb), NULL,
715 G_CALLBACK (tool_update_sensitivity_cb),
716 0))
717 return 0;
718
719 gnm_dao_set_put (GNM_DAO (state->gdao), TRUE, TRUE);
720 tool_update_sensitivity_cb (NULL, state);
721 tool_load_selection ((GnmGenericToolState *)state, TRUE);
722
723 return 0;
724 }
725
726 /**********************************************/
727 /* End of correlation tool code */
728 /**********************************************/
729
730 /**********************************************/
731 /* Begin of covariance tool code */
732 /**********************************************/
733
734
735 /**
736 * cov_tool_ok_clicked_cb:
737 * @button:
738 * @state:
739 *
740 * Retrieve the information from the dialog and call the covariance_tool.
741 * Note that we assume that the ok_button is only active if the entry fields
742 * contain sensible data.
743 **/
744 static void
cov_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,GnmGenericToolState * state)745 cov_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
746 GnmGenericToolState *state)
747 {
748 data_analysis_output_t *dao;
749 analysis_tools_data_generic_t *data;
750
751 char *text;
752 GtkWidget *w;
753
754 if (state->warning_dialog != NULL)
755 gtk_widget_destroy (state->warning_dialog);
756
757 data = g_new0 (analysis_tools_data_generic_t, 1);
758 dao = parse_output (state, NULL);
759
760 data->input = gnm_expr_entry_parse_as_list (
761 GNM_EXPR_ENTRY (state->input_entry), state->sheet);
762 data->group_by = gnm_gui_group_value (state->gui, grouped_by_group);
763
764 w = go_gtk_builder_get_widget (state->gui, "labels_button");
765 data->labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
766
767 if (cmd_analysis_tool (GNM_WBC (state->wbcg), state->sheet,
768 dao, data, analysis_tool_covariance_engine, FALSE)) {
769
770 switch (data->err - 1) {
771 case GROUPED_BY_ROW:
772 error_in_entry ((GnmGenericToolState *) state,
773 GTK_WIDGET (state->input_entry),
774 _("The selected input rows must have equal size!"));
775 break;
776 case GROUPED_BY_COL:
777 error_in_entry ((GnmGenericToolState *) state,
778 GTK_WIDGET (state->input_entry),
779 _("The selected input columns must have equal size!"));
780 break;
781 case GROUPED_BY_AREA:
782 error_in_entry ((GnmGenericToolState *) state,
783 GTK_WIDGET (state->input_entry),
784 _("The selected input areas must have equal size!"));
785 break;
786 default:
787 text = g_strdup_printf (
788 _("An unexpected error has occurred: %d."), data->err);
789 error_in_entry ((GnmGenericToolState *) state,
790 GTK_WIDGET (state->input_entry), text);
791 g_free (text);
792 break;
793 }
794 range_list_destroy (data->input);
795 g_free (dao);
796 g_free (data);
797 } else
798 gtk_widget_destroy (state->dialog);
799 return;
800 }
801
802
803
804 /**
805 * dialog_covariance_tool:
806 * @wbcg:
807 * @sheet:
808 *
809 * Show the dialog (guru).
810 *
811 **/
812 int
dialog_covariance_tool(WBCGtk * wbcg,Sheet * sheet)813 dialog_covariance_tool (WBCGtk *wbcg, Sheet *sheet)
814 {
815 GnmGenericToolState *state;
816 char const * plugins[] = { "Gnumeric_fnstat",
817 NULL};
818
819 if ((wbcg == NULL) ||
820 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
821 return 1;
822
823 /* Only pop up one copy per workbook */
824 if (gnm_dialog_raise_if_exists (wbcg, COVARIANCE_KEY))
825 return 0;
826
827 state = g_new0 (GnmGenericToolState, 1);
828
829 if (dialog_tool_init (state, wbcg, sheet,
830 GNUMERIC_HELP_LINK_COVARIANCE,
831 "res:ui/covariance.ui", "Covariance",
832 _("Could not create the Covariance Tool dialog."),
833 COVARIANCE_KEY,
834 G_CALLBACK (cov_tool_ok_clicked_cb), NULL,
835 G_CALLBACK (tool_update_sensitivity_cb),
836 0))
837 return 0;
838
839 gnm_dao_set_put (GNM_DAO (state->gdao), TRUE, TRUE);
840 tool_update_sensitivity_cb (NULL, state);
841 tool_load_selection ((GnmGenericToolState *)state, TRUE);
842
843 return 0;
844 }
845
846 /**********************************************/
847 /* End of covariance tool code */
848 /**********************************************/
849
850 /**********************************************/
851 /* Begin of rank and percentile tool code */
852 /**********************************************/
853
854
855 /**
856 * rank_tool_ok_clicked_cb:
857 * @button:
858 * @state:
859 *
860 * Retrieve the information from the dialog and call the ranking_tool.
861 * Note that we assume that the ok_button is only active if the entry fields
862 * contain sensible data.
863 **/
864 static void
rank_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,GnmGenericToolState * state)865 rank_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
866 GnmGenericToolState *state)
867 {
868 data_analysis_output_t *dao;
869 analysis_tools_data_ranking_t *data;
870
871 GtkWidget *w;
872
873 data = g_new0 (analysis_tools_data_ranking_t, 1);
874 dao = parse_output (state, NULL);
875
876 data->base.input = gnm_expr_entry_parse_as_list (
877 GNM_EXPR_ENTRY (state->input_entry), state->sheet);
878 data->base.group_by = gnm_gui_group_value (state->gui, grouped_by_group);
879
880 w = go_gtk_builder_get_widget (state->gui, "labels_button");
881 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
882
883 w = go_gtk_builder_get_widget (state->gui, "rank_button");
884 data->av_ties = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
885
886
887 if (!cmd_analysis_tool (GNM_WBC (state->wbcg), state->sheet,
888 dao, data, analysis_tool_ranking_engine, TRUE))
889 gtk_widget_destroy (state->dialog);
890 return;
891 }
892
893
894
895 /**
896 * dialog_ranking_tool:
897 * @wbcg:
898 * @sheet:
899 *
900 * Show the dialog (guru).
901 *
902 **/
903 int
dialog_ranking_tool(WBCGtk * wbcg,Sheet * sheet)904 dialog_ranking_tool (WBCGtk *wbcg, Sheet *sheet)
905 {
906 GnmGenericToolState *state;
907 char const * plugins[] = { "Gnumeric_fnstat",
908 "Gnumeric_fnlookup",
909 NULL};
910
911 if ((wbcg == NULL) ||
912 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
913 return 1;
914
915 /* Only pop up one copy per workbook */
916 if (gnm_dialog_raise_if_exists (wbcg, RANK_PERCENTILE_KEY))
917 return 0;
918
919 state = g_new0 (GnmGenericToolState, 1);
920
921 if (dialog_tool_init (state, wbcg, sheet,
922 GNUMERIC_HELP_LINK_RANKING,
923 "res:ui/rank.ui", "RankPercentile",
924 _("Could not create the Rank and Percentile "
925 "Tools dialog."),
926 RANK_PERCENTILE_KEY,
927 G_CALLBACK (rank_tool_ok_clicked_cb), NULL,
928 G_CALLBACK (tool_update_sensitivity_cb),
929 0))
930 return 0;
931
932 gnm_dao_set_put (GNM_DAO (state->gdao), TRUE, TRUE);
933 tool_update_sensitivity_cb (NULL, state);
934 tool_load_selection ((GnmGenericToolState *)state, TRUE);
935
936 return 0;
937 }
938
939 /**********************************************/
940 /* End of rank and percentile tool code */
941 /**********************************************/
942
943 /**********************************************/
944 /* Begin of Fourier analysis tool code */
945 /**********************************************/
946
947 /**
948 * fourier_tool_ok_clicked_cb:
949 * @button:
950 * @state:
951 *
952 * Retrieve the information from the dialog and call the fourier_tool.
953 * Note that we assume that the ok_button is only active if the entry fields
954 * contain sensible data.
955 **/
956 static void
fourier_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,GnmGenericToolState * state)957 fourier_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
958 GnmGenericToolState *state)
959 {
960 data_analysis_output_t *dao;
961 analysis_tools_data_fourier_t *data;
962
963 GtkWidget *w;
964
965 data = g_new0 (analysis_tools_data_fourier_t, 1);
966 dao = parse_output (state, NULL);
967
968 data->base.wbc = GNM_WBC (state->wbcg);
969 data->base.input = gnm_expr_entry_parse_as_list (
970 GNM_EXPR_ENTRY (state->input_entry), state->sheet);
971 data->base.group_by = gnm_gui_group_value (state->gui, grouped_by_group);
972
973 w = go_gtk_builder_get_widget (state->gui, "labels_button");
974 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
975
976 w = go_gtk_builder_get_widget (state->gui, "inverse_button");
977 data->inverse = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)) != 0;
978
979 if (!cmd_analysis_tool (GNM_WBC (state->wbcg), state->sheet,
980 dao, data, analysis_tool_fourier_engine, TRUE))
981 gtk_widget_destroy (state->dialog);
982
983 return;
984 }
985
986
987
988 /**
989 * dialog_fourier_tool:
990 * @wbcg:
991 * @sheet:
992 *
993 * Show the dialog (guru).
994 *
995 **/
996 int
dialog_fourier_tool(WBCGtk * wbcg,Sheet * sheet)997 dialog_fourier_tool (WBCGtk *wbcg, Sheet *sheet)
998 {
999 GnmGenericToolState *state;
1000 char const * plugins[] = { "Gnumeric_fnTimeSeriesAnalysis",
1001 "Gnumeric_fncomplex",
1002 NULL};
1003
1004 if ((wbcg == NULL) ||
1005 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
1006 return 1;
1007
1008 /* Only pop up one copy per workbook */
1009 if (gnm_dialog_raise_if_exists (wbcg, FOURIER_KEY))
1010 return 0;
1011
1012 state = g_new0 (GnmGenericToolState, 1);
1013
1014 if (dialog_tool_init (state, wbcg, sheet,
1015 GNUMERIC_HELP_LINK_FOURIER_ANALYSIS,
1016 "res:ui/fourier-analysis.ui", "FourierAnalysis",
1017 _("Could not create the Fourier Analysis Tool "
1018 "dialog."),
1019 FOURIER_KEY,
1020 G_CALLBACK (fourier_tool_ok_clicked_cb), NULL,
1021 G_CALLBACK (tool_update_sensitivity_cb),
1022 0))
1023 return 0;
1024
1025 gnm_dao_set_put (GNM_DAO (state->gdao), TRUE, TRUE);
1026 tool_update_sensitivity_cb (NULL, state);
1027 tool_load_selection ((GnmGenericToolState *)state, TRUE);
1028
1029 return 0;
1030 }
1031
1032 /**********************************************/
1033 /* End of Fourier analysis tool code */
1034 /**********************************************/
1035
1036 /**********************************************/
1037 /* Begin of descriptive statistics tool code */
1038 /**********************************************/
1039
1040 /**
1041 * cb_desc_stat_tool_ok_clicked:
1042 * @button:
1043 * @state:
1044 *
1045 * Retrieve the information from the dialog and call the descriptive_stat_tool.
1046 * Note that we assume that the ok_button is only active if the entry fields
1047 * contain sensible data.
1048 **/
1049 static void
cb_desc_stat_tool_ok_clicked(G_GNUC_UNUSED GtkWidget * button,DescriptiveStatState * state)1050 cb_desc_stat_tool_ok_clicked (G_GNUC_UNUSED GtkWidget *button,
1051 DescriptiveStatState *state)
1052 {
1053 data_analysis_output_t *dao;
1054 analysis_tools_data_descriptive_t *data;
1055
1056 GtkWidget *w;
1057
1058 data = g_new0 (analysis_tools_data_descriptive_t, 1);
1059 dao = parse_output ((GnmGenericToolState *)state, NULL);
1060
1061 data->base.input = gnm_expr_entry_parse_as_list (
1062 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
1063 data->base.group_by = gnm_gui_group_value (state->base.gui, grouped_by_group);
1064
1065 data->summary_statistics = gtk_toggle_button_get_active (
1066 GTK_TOGGLE_BUTTON (state->summary_stats_button));
1067 data->confidence_level = gtk_toggle_button_get_active (
1068 GTK_TOGGLE_BUTTON (state->mean_stats_button));
1069 data->kth_largest = gtk_toggle_button_get_active (
1070 GTK_TOGGLE_BUTTON (state->kth_largest_button));
1071 data->kth_smallest = gtk_toggle_button_get_active (
1072 GTK_TOGGLE_BUTTON (state->kth_smallest_button));
1073 data->use_ssmedian = gtk_toggle_button_get_active (
1074 GTK_TOGGLE_BUTTON (state->ss_button));
1075
1076 if (data->confidence_level == 1)
1077 data->c_level = gtk_spin_button_get_value
1078 (GTK_SPIN_BUTTON (state->c_entry));
1079
1080 if (data->kth_largest == 1)
1081 entry_to_int (GTK_ENTRY (state->l_entry), &data->k_largest, TRUE);
1082 if (data->kth_smallest == 1)
1083 entry_to_int (GTK_ENTRY (state->s_entry), &data->k_smallest, TRUE);
1084
1085 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
1086 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
1087
1088 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
1089 dao, data, analysis_tool_descriptive_engine, TRUE))
1090 gtk_widget_destroy (state->base.dialog);
1091 return;
1092 }
1093
1094 /**
1095 * desc_stat_tool_update_sensitivity_cb:
1096 * @state:
1097 *
1098 * Update the dialog widgets sensitivity.
1099 * We cannot use tool_update_sensitivity_cb
1100 * since we are also considering whether in fact
1101 * a statistic is selected.
1102 **/
1103 static void
desc_stat_tool_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,DescriptiveStatState * state)1104 desc_stat_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
1105 DescriptiveStatState *state)
1106 {
1107 gboolean stats_button, ci_button, largest_button, smallest_button;
1108 GSList *input_range;
1109
1110 /* Part 1: set the buttons on the statistics page. */
1111
1112 stats_button = gtk_toggle_button_get_active
1113 (GTK_TOGGLE_BUTTON (state->summary_stats_button));
1114 gtk_widget_set_sensitive (state->ss_button, stats_button);
1115
1116 ci_button = gtk_toggle_button_get_active
1117 (GTK_TOGGLE_BUTTON (state->mean_stats_button));
1118 gtk_widget_set_sensitive (state->c_entry, ci_button);
1119
1120 largest_button = gtk_toggle_button_get_active
1121 (GTK_TOGGLE_BUTTON (state->kth_largest_button));
1122 gtk_widget_set_sensitive (state->l_entry, largest_button);
1123
1124 smallest_button = gtk_toggle_button_get_active
1125 (GTK_TOGGLE_BUTTON (state->kth_smallest_button));
1126 gtk_widget_set_sensitive (state->s_entry, smallest_button);
1127
1128 /* Part 2: set the okay button */
1129
1130 /* Checking Input Page */
1131 input_range = gnm_expr_entry_parse_as_list (
1132 GNM_EXPR_ENTRY (state->base.input_entry),
1133 state->base.sheet);
1134 if (input_range == NULL) {
1135 gtk_label_set_text (GTK_LABEL (state->base.warning),
1136 _("The input range is invalid."));
1137 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1138 return;
1139 } else
1140 range_list_destroy (input_range);
1141
1142 /* Checking Statistics Page */
1143 if (!(stats_button || ci_button || largest_button || smallest_button)) {
1144 gtk_label_set_text (GTK_LABEL (state->base.warning),
1145 _("No statistics are selected."));
1146 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1147 return;
1148 }
1149
1150 if (ci_button) {
1151 gdouble c_level = gtk_spin_button_get_value
1152 (GTK_SPIN_BUTTON (state->c_entry));
1153 if (!(c_level > 0 && c_level <1)) {
1154 gtk_label_set_text (GTK_LABEL (state->base.warning),
1155 _("The confidence level should be "
1156 "between 0 and 1."));
1157 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1158 return;
1159 }
1160 }
1161
1162 if (largest_button) {
1163 int k;
1164 if ((0 != entry_to_int (GTK_ENTRY (state->l_entry), &k, FALSE))
1165 || !(k >0)) {
1166 gtk_label_set_text (GTK_LABEL (state->base.warning),
1167 _("K must be a positive integer."));
1168 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1169 return;
1170 }
1171 }
1172
1173 if (smallest_button) {
1174 int k;
1175 if ((0 != entry_to_int (GTK_ENTRY (state->s_entry), &k, FALSE))
1176 || !(k >0)) {
1177 gtk_label_set_text (GTK_LABEL (state->base.warning),
1178 _("K must be a positive integer."));
1179 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1180 return;
1181 }
1182 }
1183
1184 /* Checking Output Page */
1185 if (!gnm_dao_is_ready (GNM_DAO (state->base.gdao))) {
1186 gtk_label_set_text (GTK_LABEL (state->base.warning),
1187 _("The output specification "
1188 "is invalid."));
1189 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1190 return;
1191 }
1192
1193 gtk_label_set_text (GTK_LABEL (state->base.warning), "");
1194 gtk_widget_set_sensitive (state->base.ok_button, TRUE);
1195
1196 return;
1197 }
1198
1199
1200 /**
1201 * dialog_descriptive_stat_tool:
1202 * @wbcg:
1203 * @sheet:
1204 *
1205 * Show the dialog (guru).
1206 *
1207 **/
1208 int
dialog_descriptive_stat_tool(WBCGtk * wbcg,Sheet * sheet)1209 dialog_descriptive_stat_tool (WBCGtk *wbcg, Sheet *sheet)
1210 {
1211 DescriptiveStatState *state;
1212 char const * plugins[] = {"Gnumeric_fnstat",
1213 "Gnumeric_fnmath",
1214 NULL};
1215
1216 if ((wbcg == NULL) ||
1217 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
1218 return 1;
1219
1220 /* Only pop up one copy per workbook */
1221 if (gnm_dialog_raise_if_exists (wbcg, DESCRIPTIVE_STATS_KEY))
1222 return 0;
1223
1224 state = g_new0 (DescriptiveStatState, 1);
1225
1226 if (dialog_tool_init (&state->base, wbcg, sheet,
1227 GNUMERIC_HELP_LINK_DESCRIPTIVE_STATS,
1228 "res:ui/descriptive-stats.ui", "DescStats",
1229 _("Could not create the Descriptive Statistics "
1230 "Tool dialog."),
1231 DESCRIPTIVE_STATS_KEY,
1232 G_CALLBACK (cb_desc_stat_tool_ok_clicked), NULL,
1233 G_CALLBACK (desc_stat_tool_update_sensitivity_cb),
1234 0))
1235 {
1236 g_free(state);
1237 return 0;
1238 }
1239
1240 state->summary_stats_button = go_gtk_builder_get_widget
1241 (state->base.gui, "summary_stats_button");
1242 state->ss_button = go_gtk_builder_get_widget
1243 (state->base.gui, "ss_button");
1244 state->mean_stats_button = go_gtk_builder_get_widget
1245 (state->base.gui, "mean_stats_button");
1246 state->kth_largest_button = go_gtk_builder_get_widget
1247 (state->base.gui, "kth_largest_button");
1248 state->kth_smallest_button = go_gtk_builder_get_widget
1249 (state->base.gui, "kth_smallest_button");
1250 state->c_entry = go_gtk_builder_get_widget (state->base.gui, "c_entry");
1251 gtk_spin_button_set_value (GTK_SPIN_BUTTON (state->c_entry), 0.95);
1252 state->l_entry = go_gtk_builder_get_widget (state->base.gui, "l_entry");
1253 int_to_entry (GTK_ENTRY (state->l_entry), 1);
1254 state->s_entry = go_gtk_builder_get_widget (state->base.gui, "s_entry");
1255 int_to_entry (GTK_ENTRY (state->s_entry), 1);
1256
1257
1258 g_signal_connect_after (G_OBJECT (state->summary_stats_button),
1259 "toggled",
1260 G_CALLBACK (desc_stat_tool_update_sensitivity_cb), state);
1261 g_signal_connect_after (G_OBJECT (state->mean_stats_button),
1262 "toggled",
1263 G_CALLBACK (desc_stat_tool_update_sensitivity_cb), state);
1264 g_signal_connect_after (G_OBJECT (state->kth_largest_button),
1265 "toggled",
1266 G_CALLBACK (desc_stat_tool_update_sensitivity_cb), state);
1267 g_signal_connect_after (G_OBJECT (state->kth_smallest_button),
1268 "toggled",
1269 G_CALLBACK (desc_stat_tool_update_sensitivity_cb), state);
1270 g_signal_connect_after (G_OBJECT (state->c_entry),
1271 "changed",
1272 G_CALLBACK (desc_stat_tool_update_sensitivity_cb), state);
1273 g_signal_connect_after (G_OBJECT (state->l_entry),
1274 "changed",
1275 G_CALLBACK (desc_stat_tool_update_sensitivity_cb), state);
1276 g_signal_connect_after (G_OBJECT (state->s_entry),
1277 "changed",
1278 G_CALLBACK (desc_stat_tool_update_sensitivity_cb), state);
1279 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
1280 GTK_WIDGET (state->c_entry));
1281 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
1282 GTK_WIDGET (state->l_entry));
1283 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
1284 GTK_WIDGET (state->s_entry));
1285
1286 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
1287 desc_stat_tool_update_sensitivity_cb (NULL, state);
1288 tool_load_selection ((GnmGenericToolState *)state, TRUE);
1289
1290 return 0;
1291 }
1292
1293
1294 /**********************************************/
1295 /* End of descriptive statistics tool code */
1296 /**********************************************/
1297
1298
1299 /**********************************************/
1300 /* Begin of ttest tool code */
1301 /**********************************************/
1302
1303 /**
1304 * ttest_tool_ok_clicked_cb:
1305 * @button:
1306 * @state:
1307 *
1308 * Retrieve the information from the dialog and call the appropriate tool.
1309 * Note that we assume that the ok_button is only active if the entry fields
1310 * contain sensible data.
1311 **/
1312 static void
ttest_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,TTestState * state)1313 ttest_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
1314 TTestState *state)
1315 {
1316 data_analysis_output_t *dao;
1317 analysis_tools_data_ttests_t *data;
1318
1319 GtkWidget *w;
1320 int err = 0;
1321
1322 data = g_new0 (analysis_tools_data_ttests_t, 1);
1323 dao = parse_output ((GnmGenericToolState *)state, NULL);
1324
1325 data->base.wbc = GNM_WBC (state->base.wbcg);
1326
1327 if (state->base.warning_dialog != NULL)
1328 gtk_widget_destroy (state->base.warning_dialog);
1329
1330 data->base.range_1 = gnm_expr_entry_parse_as_value
1331 (GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
1332
1333 data->base.range_2 = gnm_expr_entry_parse_as_value
1334 (GNM_EXPR_ENTRY (state->base.input_entry_2), state->base.sheet);
1335
1336 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
1337 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
1338
1339 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->paired_button)) == 1) {
1340 state->invocation = TTEST_PAIRED;
1341 } else {
1342 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->known_button)) == 1) {
1343 state->invocation = TTEST_ZTEST;
1344 } else {
1345 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
1346 (state->equal_button)) == 1) {
1347 state->invocation = TTEST_UNPAIRED_EQUALVARIANCES;
1348 } else {
1349 state->invocation = TTEST_UNPAIRED_UNEQUALVARIANCES;
1350 }
1351 }
1352 }
1353
1354 err = entry_to_float (GTK_ENTRY (state->mean_diff_entry), &data->mean_diff, TRUE);
1355 err = entry_to_float (GTK_ENTRY (state->alpha_entry), &data->base.alpha, TRUE);
1356
1357 switch (state->invocation) {
1358 case TTEST_PAIRED:
1359 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg),
1360 state->base.sheet,
1361 dao, data, analysis_tool_ttest_paired_engine,
1362 TRUE))
1363 gtk_widget_destroy (state->base.dialog);
1364 break;
1365 case TTEST_UNPAIRED_EQUALVARIANCES:
1366 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
1367 dao, data, analysis_tool_ttest_eqvar_engine, TRUE))
1368 gtk_widget_destroy (state->base.dialog);
1369 break;
1370 case TTEST_UNPAIRED_UNEQUALVARIANCES:
1371 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
1372 dao, data, analysis_tool_ttest_neqvar_engine, TRUE))
1373 gtk_widget_destroy (state->base.dialog);
1374 break;
1375 case TTEST_ZTEST:
1376 err = entry_to_float (GTK_ENTRY (state->var1_variance), &data->var1, TRUE);
1377 if (err != 0 || data->var1 <= 0.0) {
1378 error_in_entry ((GnmGenericToolState *) state, GTK_WIDGET (state->var1_variance),
1379 _("Please enter a valid\n"
1380 "population variance for variable 1."));
1381 g_free (data);
1382 g_free (dao);
1383 return;
1384 }
1385 err = entry_to_float (GTK_ENTRY (state->var2_variance), &data->var2, TRUE);
1386 if (err != 0 || data->var2 <= 0.0) {
1387 error_in_entry ((GnmGenericToolState *) state, GTK_WIDGET (state->var2_variance),
1388 _("Please enter a valid\n"
1389 "population variance for variable 2."));
1390 g_free (data);
1391 g_free (dao);
1392 return;
1393 }
1394
1395 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
1396 dao, data, analysis_tool_ztest_engine, TRUE))
1397 gtk_widget_destroy (state->base.dialog);
1398 break;
1399 }
1400
1401 return;
1402 }
1403
1404 /**
1405 * ttest_update_sensitivity_cb:
1406 * @dummy:
1407 * @state:
1408 *
1409 * Update the dialog widgets sensitivity if the only items of interest
1410 * are the standard input (one or two ranges) and output items.
1411 **/
1412 static void
ttest_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,TTestState * state)1413 ttest_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
1414 TTestState *state)
1415 {
1416 gboolean ready = FALSE;
1417 gboolean input_1_ready = FALSE;
1418 gboolean input_2_ready = FALSE;
1419 gboolean output_ready = FALSE;
1420 gboolean mean_diff_ready = FALSE;
1421 gboolean alpha_ready = FALSE;
1422 int err;
1423 gnm_float mean_diff, alpha;
1424 GnmValue *input_range;
1425 GnmValue *input_range_2;
1426
1427 input_range = gnm_expr_entry_parse_as_value
1428 (GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
1429 input_range_2 = gnm_expr_entry_parse_as_value
1430 (GNM_EXPR_ENTRY (state->base.input_entry_2), state->base.sheet);
1431
1432 err = entry_to_float (GTK_ENTRY (state->mean_diff_entry), &mean_diff, FALSE);
1433 mean_diff_ready = (err == 0);
1434 err = entry_to_float (GTK_ENTRY (state->alpha_entry), &alpha, FALSE);
1435 alpha_ready = (err == 0 && alpha > 0.0 && alpha < 1.0);
1436 input_1_ready = (input_range != NULL);
1437 input_2_ready = ((state->base.input_entry_2 == NULL) || (input_range_2 != NULL));
1438 output_ready = gnm_dao_is_ready (GNM_DAO (state->base.gdao));
1439
1440 value_release (input_range);
1441 value_release (input_range_2);
1442
1443 ready = input_1_ready && input_2_ready && output_ready && alpha_ready && mean_diff_ready;
1444 gtk_widget_set_sensitive (state->base.ok_button, ready);
1445
1446 return;
1447 }
1448
1449 /**
1450 * ttest_known_toggled_cb:
1451 * @button:
1452 * @state:
1453 *
1454 * The paired/unpaired variables status has changed.
1455 *
1456 **/
1457 static void
ttest_known_toggled_cb(GtkWidget * button,TTestState * state)1458 ttest_known_toggled_cb (GtkWidget *button, TTestState *state)
1459 {
1460 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) == 1) {
1461 gtk_widget_hide (state->equal_button);
1462 gtk_widget_hide (state->unequal_button);
1463 gtk_widget_hide (state->varianceequal_label);
1464 gtk_widget_show (state->var2_variance_label);
1465 gtk_widget_show (state->var2_variance);
1466 gtk_widget_show (state->var1_variance_label);
1467 gtk_widget_show (state->var1_variance);
1468 } else {
1469 gtk_widget_hide (state->var2_variance_label);
1470 gtk_widget_hide (state->var2_variance);
1471 gtk_widget_hide (state->var1_variance_label);
1472 gtk_widget_hide (state->var1_variance);
1473 gtk_widget_show (state->equal_button);
1474 gtk_widget_show (state->unequal_button);
1475 gtk_widget_show (state->varianceequal_label);
1476 }
1477 }
1478 /**
1479 * ttest_paired_toggled_cb:
1480 * @button:
1481 * @state:
1482 *
1483 * The paired/unpaired variables status has changed.
1484 *
1485 **/
1486 static void
ttest_paired_toggled_cb(GtkWidget * button,TTestState * state)1487 ttest_paired_toggled_cb (GtkWidget *button, TTestState *state)
1488 {
1489 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) == 1) {
1490 gtk_widget_hide (state->var2_variance_label);
1491 gtk_widget_hide (state->var2_variance);
1492 gtk_widget_hide (state->var1_variance_label);
1493 gtk_widget_hide (state->var1_variance);
1494 gtk_widget_hide (state->equal_button);
1495 gtk_widget_hide (state->unequal_button);
1496 gtk_widget_hide (state->varianceequal_label);
1497 gtk_widget_hide (state->known_button);
1498 gtk_widget_hide (state->unknown_button);
1499 gtk_widget_hide (state->varianceknown_label);
1500 } else {
1501 gtk_widget_show (state->known_button);
1502 gtk_widget_show (state->unknown_button);
1503 gtk_widget_show (state->varianceknown_label);
1504 ttest_known_toggled_cb (GTK_WIDGET (state->known_button), state);
1505 }
1506 }
1507
1508 /**
1509 * dialog_ttest_adjust_to_invocation:
1510 * @state:
1511 *
1512 * Set the options to match the invocation.
1513 *
1514 **/
1515 static void
dialog_ttest_adjust_to_invocation(TTestState * state)1516 dialog_ttest_adjust_to_invocation (TTestState *state)
1517 {
1518 switch (state->invocation) {
1519 case TTEST_PAIRED:
1520 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->paired_button), TRUE);
1521 break;
1522 case TTEST_UNPAIRED_EQUALVARIANCES:
1523 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->equal_button), TRUE);
1524 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->unknown_button), TRUE);
1525 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->unpaired_button), TRUE);
1526 break;
1527 case TTEST_UNPAIRED_UNEQUALVARIANCES:
1528 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->unequal_button), TRUE);
1529 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->unknown_button), TRUE);
1530 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->unpaired_button), TRUE);
1531 break;
1532 case TTEST_ZTEST:
1533 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->known_button), TRUE);
1534 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->unpaired_button), TRUE);
1535 break;
1536 default:
1537 break;
1538 }
1539 }
1540
1541
1542 /**
1543 * dialog_ttest_realized:
1544 * @widget
1545 * @state:
1546 *
1547 * Fix the size of the options table.
1548 *
1549 **/
1550 static void
dialog_ttest_realized(G_GNUC_UNUSED GtkWidget * widget,TTestState * state)1551 dialog_ttest_realized (G_GNUC_UNUSED GtkWidget *widget,
1552 TTestState *state)
1553 {
1554 GtkAllocation alloc;
1555
1556 gtk_widget_get_allocation (state->options_grid, &alloc);
1557 gtk_widget_set_size_request (state->options_grid,
1558 alloc.width, alloc.height);
1559
1560 gtk_widget_get_allocation (state->paired_button, &alloc);
1561 gtk_widget_set_size_request (state->paired_button,
1562 alloc.width, alloc.height);
1563
1564 gtk_widget_get_allocation (state->unpaired_button, &alloc);
1565 gtk_widget_set_size_request (state->unpaired_button,
1566 alloc.width, alloc.height);
1567
1568 gtk_widget_get_allocation (state->variablespaired_label, &alloc);
1569 gtk_widget_set_size_request (state->variablespaired_label,
1570 alloc.width, alloc.height);
1571
1572 ttest_paired_toggled_cb (state->paired_button, state);
1573 dialog_ttest_adjust_to_invocation (state);
1574 }
1575
1576 /**
1577 * dialog_ttest_tool:
1578 * @wbcg:
1579 * @sheet:
1580 * @test:
1581 *
1582 * Show the dialog (guru).
1583 *
1584 **/
1585 int
dialog_ttest_tool(WBCGtk * wbcg,Sheet * sheet,ttest_type test)1586 dialog_ttest_tool (WBCGtk *wbcg, Sheet *sheet, ttest_type test)
1587 {
1588 TTestState *state;
1589 GtkDialog *dialog;
1590 char const * plugins[] = {"Gnumeric_fnstat",
1591 "Gnumeric_fnmath",
1592 "Gnumeric_fninfo",
1593 "Gnumeric_fnlogical",
1594 NULL};
1595
1596 if ((wbcg == NULL) ||
1597 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
1598 return 1;
1599
1600 /* Only pop up one copy per workbook */
1601 dialog = gnm_dialog_raise_if_exists (wbcg, TTEST_KEY);
1602 if (dialog) {
1603 state = g_object_get_data (G_OBJECT (dialog), "state");
1604 state->invocation = test;
1605 dialog_ttest_adjust_to_invocation (state);
1606 return 0;
1607 }
1608
1609 state = g_new0 (TTestState, 1);
1610 state->invocation = test;
1611
1612 if (dialog_tool_init (&state->base, wbcg, sheet,
1613 GNUMERIC_HELP_LINK_MEAN_TESTS,
1614 "res:ui/mean-tests.ui", "MeanTests",
1615 _("Could not create the Mean Tests Tool dialog."),
1616 TTEST_KEY,
1617 G_CALLBACK (ttest_tool_ok_clicked_cb), NULL,
1618 G_CALLBACK (ttest_update_sensitivity_cb),
1619 GNM_EE_SINGLE_RANGE))
1620 {
1621 g_free(state);
1622 return 0;
1623 }
1624
1625 state->paired_button = go_gtk_builder_get_widget (state->base.gui, "paired-button");
1626 state->unpaired_button = go_gtk_builder_get_widget (state->base.gui, "unpaired-button");
1627 state->variablespaired_label = go_gtk_builder_get_widget (state->base.gui, "variablespaired-label");
1628 state->known_button = go_gtk_builder_get_widget (state->base.gui, "known-button");
1629 state->unknown_button = go_gtk_builder_get_widget (state->base.gui, "unknown-button");
1630 state->varianceknown_label = go_gtk_builder_get_widget (state->base.gui, "varianceknown-label");
1631 state->equal_button = go_gtk_builder_get_widget (state->base.gui, "equal-button");
1632 state->unequal_button = go_gtk_builder_get_widget (state->base.gui, "unequal-button");
1633 state->varianceequal_label = go_gtk_builder_get_widget (state->base.gui, "varianceequal-label");
1634 state->options_grid = go_gtk_builder_get_widget (state->base.gui, "options-grid");
1635 state->var1_variance_label = go_gtk_builder_get_widget (state->base.gui, "var1_variance-label");
1636 state->var1_variance = go_gtk_builder_get_widget (state->base.gui, "var1-variance");
1637 state->var2_variance_label = go_gtk_builder_get_widget (state->base.gui, "var2_variance-label");
1638 state->var2_variance = go_gtk_builder_get_widget (state->base.gui, "var2-variance");
1639 state->mean_diff_entry = go_gtk_builder_get_widget (state->base.gui, "meandiff");
1640 float_to_entry (GTK_ENTRY (state->mean_diff_entry), 0);
1641 state->alpha_entry = go_gtk_builder_get_widget (state->base.gui, "one_alpha");
1642 float_to_entry (GTK_ENTRY (state->alpha_entry), 0.05);
1643
1644 g_signal_connect_after (G_OBJECT (state->paired_button),
1645 "toggled",
1646 G_CALLBACK (ttest_update_sensitivity_cb), state);
1647 g_signal_connect (G_OBJECT (state->paired_button),
1648 "toggled",
1649 G_CALLBACK (ttest_paired_toggled_cb), state);
1650 g_signal_connect_after (G_OBJECT (state->known_button),
1651 "toggled",
1652 G_CALLBACK (ttest_update_sensitivity_cb), state);
1653 g_signal_connect_after (G_OBJECT (state->mean_diff_entry),
1654 "changed",
1655 G_CALLBACK (ttest_update_sensitivity_cb), state);
1656 g_signal_connect_after (G_OBJECT (state->alpha_entry),
1657 "changed",
1658 G_CALLBACK (ttest_update_sensitivity_cb), state);
1659 g_signal_connect (G_OBJECT (state->known_button),
1660 "toggled",
1661 G_CALLBACK (ttest_known_toggled_cb), state);
1662 g_signal_connect (G_OBJECT (state->base.dialog),
1663 "realize",
1664 G_CALLBACK (dialog_ttest_realized), state);
1665 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
1666 GTK_WIDGET (state->var1_variance));
1667 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
1668 GTK_WIDGET (state->var2_variance));
1669 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
1670 GTK_WIDGET (state->mean_diff_entry));
1671 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
1672 GTK_WIDGET (state->alpha_entry));
1673
1674 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
1675 ttest_update_sensitivity_cb (NULL, state);
1676 tool_load_selection ((GnmGenericToolState *)state, FALSE);
1677
1678 return 0;
1679 }
1680
1681 /**********************************************/
1682 /* End of ttest tool code */
1683 /**********************************************/
1684
1685
1686 /**********************************************/
1687 /* Begin of ftest tool code */
1688 /**********************************************/
1689
1690
1691 /**
1692 * ftest_tool_ok_clicked_cb:
1693 * @button:
1694 * @state:
1695 *
1696 * Retrieve the information from the dialog and call the correlation_tool.
1697 * Note that we assume that the ok_button is only active if the entry fields
1698 * contain sensible data.
1699 **/
1700 static void
ftest_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,FTestToolState * state)1701 ftest_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
1702 FTestToolState *state)
1703 {
1704 data_analysis_output_t *dao;
1705 analysis_tools_data_generic_b_t *data;
1706
1707 GtkWidget *w;
1708
1709 data = g_new0 (analysis_tools_data_generic_b_t, 1);
1710 dao = parse_output ((GnmGenericToolState *)state, NULL);
1711
1712 data->wbc = GNM_WBC (state->base.wbcg);
1713
1714 if (state->base.warning_dialog != NULL)
1715 gtk_widget_destroy (state->base.warning_dialog);
1716
1717 data->range_1 = gnm_expr_entry_parse_as_value
1718 (GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
1719
1720 data->range_2 = gnm_expr_entry_parse_as_value
1721 (GNM_EXPR_ENTRY (state->base.input_entry_2), state->base.sheet);
1722
1723 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
1724 data->labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
1725
1726 entry_to_float (GTK_ENTRY (state->alpha_entry), &data->alpha, TRUE);
1727
1728 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
1729 dao, data, analysis_tool_ftest_engine, TRUE))
1730 gtk_widget_destroy (state->base.dialog);
1731
1732 return;
1733 }
1734
1735 /**
1736 * ftest_update_sensitivity_cb:
1737 * @dummy:
1738 * @state:
1739 *
1740 * Update the dialog widgets sensitivity if the only items of interest
1741 * are the standard input (one or two ranges) and output items.
1742 **/
1743 static void
ftest_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,FTestToolState * state)1744 ftest_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
1745 FTestToolState *state)
1746 {
1747 gboolean ready = FALSE;
1748 gboolean input_1_ready = FALSE;
1749 gboolean input_2_ready = FALSE;
1750 gboolean output_ready = FALSE;
1751 gboolean alpha_ready = FALSE;
1752 int err;
1753 gnm_float alpha;
1754 GnmValue *input_range;
1755 GnmValue *input_range_2;
1756
1757 input_range = gnm_expr_entry_parse_as_value
1758 (GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
1759 input_range_2 = gnm_expr_entry_parse_as_value
1760 (GNM_EXPR_ENTRY (state->base.input_entry_2), state->base.sheet);
1761
1762 err = entry_to_float (GTK_ENTRY (state->alpha_entry), &alpha, FALSE);
1763 alpha_ready = (err == 0 && alpha > 0.0 && alpha < 1.0);
1764 input_1_ready = (input_range != NULL);
1765 input_2_ready = ((state->base.input_entry_2 == NULL) || (input_range_2 != NULL));
1766 output_ready = gnm_dao_is_ready (GNM_DAO (state->base.gdao));
1767
1768 value_release (input_range);
1769 value_release (input_range_2);
1770
1771 ready = input_1_ready && input_2_ready && output_ready && alpha_ready;
1772 gtk_widget_set_sensitive (state->base.ok_button, ready);
1773
1774 return;
1775 }
1776
1777 /**
1778 * dialog_ftest_tool:
1779 * @wbcg:
1780 * @sheet:
1781 *
1782 * Show the dialog (guru).
1783 *
1784 **/
1785 int
dialog_ftest_tool(WBCGtk * wbcg,Sheet * sheet)1786 dialog_ftest_tool (WBCGtk *wbcg, Sheet *sheet)
1787 {
1788 FTestToolState *state;
1789 char const * plugins[] = { "Gnumeric_fnstat",
1790 NULL};
1791
1792 if ((wbcg == NULL) ||
1793 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
1794 return 1;
1795
1796 /* Only pop up one copy per workbook */
1797 if (gnm_dialog_raise_if_exists (wbcg, FTEST_KEY))
1798 return 0;
1799
1800 state = g_new0 (FTestToolState, 1);
1801
1802 if (dialog_tool_init (&state->base, wbcg, sheet,
1803 GNUMERIC_HELP_LINK_F_TEST_TWO_SAMPLE,
1804 "res:ui/variance-tests.ui", "VarianceTests",
1805 _("Could not create the FTest Tool dialog."),
1806 FTEST_KEY,
1807 G_CALLBACK (ftest_tool_ok_clicked_cb), NULL,
1808 G_CALLBACK (ftest_update_sensitivity_cb),
1809 GNM_EE_SINGLE_RANGE))
1810 {
1811 g_free(state);
1812 return 0;
1813 }
1814
1815 state->alpha_entry = go_gtk_builder_get_widget (state->base.gui, "one_alpha");
1816 float_to_entry (GTK_ENTRY (state->alpha_entry), 0.05);
1817 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
1818 GTK_WIDGET (state->alpha_entry));
1819 g_signal_connect_after (G_OBJECT (state->alpha_entry),
1820 "changed",
1821 G_CALLBACK (ftest_update_sensitivity_cb), state);
1822
1823 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
1824 ftest_update_sensitivity_cb (NULL, state);
1825 tool_load_selection ((GnmGenericToolState *)state, FALSE);
1826
1827 return 0;
1828 }
1829
1830 /**********************************************/
1831 /* End of ftest tool code */
1832 /**********************************************/
1833
1834 /**********************************************/
1835 /* Begin of sampling tool code */
1836 /**********************************************/
1837
1838 /**
1839 * sampling_tool_update_sensitivity:
1840 * @dummy:
1841 * @state:
1842 *
1843 * Update the dialog widgets sensitivity if the only items of interest
1844 * are the standard input (one range) and output items.
1845 **/
1846 static void
sampling_tool_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,SamplingState * state)1847 sampling_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
1848 SamplingState *state)
1849 {
1850 int periodic, size, number, err;
1851 GSList *input_range;
1852
1853 input_range = gnm_expr_entry_parse_as_list (
1854 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
1855
1856 if (input_range == NULL) {
1857 gtk_label_set_text (GTK_LABEL (state->base.warning),
1858 _("The input range is invalid."));
1859 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1860 return;
1861 } else
1862 range_list_destroy (input_range);
1863
1864 err = entry_to_int (GTK_ENTRY (state->number_entry), &number, FALSE);
1865
1866 if (err != 0 || number < 1) {
1867 gtk_label_set_text (GTK_LABEL (state->base.warning),
1868 _("The requested number of samples is invalid."));
1869 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1870 return;
1871 }
1872
1873 periodic = gtk_toggle_button_get_active
1874 (GTK_TOGGLE_BUTTON (state->periodic_button));
1875
1876 if (periodic) {
1877 err = entry_to_int
1878 (GTK_ENTRY (state->period_entry), &size, FALSE);
1879 if (err != 0 || size < 1) {
1880 gtk_label_set_text (GTK_LABEL (state->base.warning),
1881 _("The requested period is invalid."));
1882 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1883 return;
1884 }
1885 err = entry_to_int
1886 (GTK_ENTRY (state->offset_entry), &number, FALSE);
1887 if (err != 0 || number < 0) {
1888 gtk_label_set_text (GTK_LABEL (state->base.warning),
1889 _("The requested offset is invalid."));
1890 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1891 return;
1892 }
1893 } else {
1894 err = entry_to_int
1895 (GTK_ENTRY (state->random_entry), &size, FALSE);
1896 if (err != 0 || size < 1) {
1897 gtk_label_set_text (GTK_LABEL (state->base.warning),
1898 _("The requested sample size is invalid."));
1899 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1900 return;
1901 }
1902 }
1903
1904 if (!gnm_dao_is_ready (GNM_DAO (state->base.gdao))) {
1905 gtk_label_set_text (GTK_LABEL (state->base.warning),
1906 _("The output specification "
1907 "is invalid."));
1908 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
1909 return;
1910 }
1911
1912 gtk_label_set_text (GTK_LABEL (state->base.warning), "");
1913 gtk_widget_set_sensitive (state->base.ok_button, TRUE);
1914 }
1915
1916 /**
1917 * sampling_tool_ok_clicked_cb:
1918 * @button:
1919 * @state:
1920 *
1921 * Retrieve the information from the dialog and call the appropriate tool.
1922 * Note that we assume that the ok_button is only active if the entry fields
1923 * contain sensible data.
1924 **/
1925 static void
sampling_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,SamplingState * state)1926 sampling_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
1927 SamplingState *state)
1928 {
1929 data_analysis_output_t *dao;
1930 analysis_tools_data_sampling_t *data;
1931
1932 GtkWidget *w;
1933
1934 data = g_new0 (analysis_tools_data_sampling_t, 1);
1935 dao = parse_output ((GnmGenericToolState *)state, NULL);
1936
1937 data->base.wbc = GNM_WBC (state->base.wbcg);
1938
1939 data->base.input = gnm_expr_entry_parse_as_list (
1940 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
1941 data->base.group_by = gnm_gui_group_value (state->base.gui, grouped_by_group);
1942
1943 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
1944 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
1945
1946 data->periodic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->periodic_button));
1947
1948 if (data->periodic) {
1949 entry_to_int (GTK_ENTRY (state->period_entry), &data->period, TRUE);
1950 entry_to_int (GTK_ENTRY (state->offset_entry), &data->offset, TRUE);
1951 data->row_major = gtk_toggle_button_get_active
1952 (GTK_TOGGLE_BUTTON (state->row_major_button));
1953 } else
1954 entry_to_int (GTK_ENTRY (state->random_entry), &data->size, TRUE);
1955
1956 entry_to_int (GTK_ENTRY (state->number_entry), &data->number, TRUE);
1957
1958 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
1959 dao, data, analysis_tool_sampling_engine, TRUE))
1960 gtk_widget_destroy (state->base.dialog);
1961 return;
1962 }
1963
1964 /**
1965 * sampling_method_toggled_cb:
1966 * @button:
1967 * @state:
1968 *
1969 * The method status has changed.
1970 *
1971 **/
1972 static void
sampling_method_toggled_cb(GtkWidget * button,SamplingState * state)1973 sampling_method_toggled_cb (GtkWidget *button, SamplingState *state)
1974 {
1975 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) == 1) {
1976 gtk_widget_hide (state->random_label);
1977 gtk_widget_hide (state->random_entry);
1978 gtk_widget_show (state->period_label);
1979 gtk_widget_show (state->period_entry);
1980 gtk_widget_show (state->offset_label);
1981 gtk_widget_show (state->offset_entry);
1982 gtk_widget_show (state->major_label);
1983 gtk_widget_show (state->row_major_button);
1984 gtk_widget_show (state->col_major_button);
1985 } else {
1986 gtk_widget_hide (state->period_label);
1987 gtk_widget_hide (state->period_entry);
1988 gtk_widget_hide (state->period_entry);
1989 gtk_widget_hide (state->offset_label);
1990 gtk_widget_hide (state->offset_entry);
1991 gtk_widget_hide (state->major_label);
1992 gtk_widget_hide (state->row_major_button);
1993 gtk_widget_hide (state->col_major_button);
1994 gtk_widget_show (state->random_label);
1995 gtk_widget_show (state->random_entry);
1996 }
1997 }
1998
1999
2000 /**
2001 * dialog_sampling_realized:
2002 * @widget
2003 * @state:
2004 *
2005 * Fix the size of the options table.
2006 *
2007 **/
2008 static void
dialog_sampling_realized(G_GNUC_UNUSED GtkWidget * widget,SamplingState * state)2009 dialog_sampling_realized (G_GNUC_UNUSED GtkWidget *widget,
2010 SamplingState *state)
2011 {
2012 GtkAllocation alloc;
2013
2014 gtk_widget_get_allocation (state->options_grid, &alloc);
2015 gtk_widget_set_size_request (state->options_grid,
2016 alloc.width, alloc.height);
2017
2018 gtk_widget_get_allocation (state->random_button, &alloc);
2019 gtk_widget_set_size_request (state->random_button,
2020 alloc.width, alloc.height);
2021
2022 gtk_widget_get_allocation (state->periodic_button, &alloc);
2023 gtk_widget_set_size_request (state->periodic_button,
2024 alloc.width, alloc.height);
2025
2026 gtk_widget_get_allocation (state->method_label, &alloc);
2027 gtk_widget_set_size_request (state->method_label,
2028 alloc.width, alloc.height);
2029
2030 sampling_method_toggled_cb (state->periodic_button, state);
2031 }
2032
2033 /**
2034 * dialog_sampling_tool:
2035 * @wbcg:
2036 * @sheet:
2037 *
2038 * Show the dialog (guru).
2039 *
2040 **/
2041 int
dialog_sampling_tool(WBCGtk * wbcg,Sheet * sheet)2042 dialog_sampling_tool (WBCGtk *wbcg, Sheet *sheet)
2043 {
2044 SamplingState *state;
2045 char const * plugins[] = { "Gnumeric_fnlookup",
2046 "Gnumeric_fnrandom",
2047 NULL};
2048
2049 if ((wbcg == NULL) ||
2050 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
2051 return 1;
2052
2053 /* Only pop up one copy per workbook */
2054 if (gnm_dialog_raise_if_exists (wbcg, SAMPLING_KEY)) {
2055 return 0;
2056 }
2057
2058 state = g_new0 (SamplingState, 1);
2059
2060 if (dialog_tool_init (&state->base, wbcg, sheet,
2061 GNUMERIC_HELP_LINK_SAMPLING,
2062 "res:ui/sampling.ui", "Sampling",
2063 _("Could not create the Sampling Tool dialog."),
2064 SAMPLING_KEY,
2065 G_CALLBACK (sampling_tool_ok_clicked_cb), NULL,
2066 G_CALLBACK (sampling_tool_update_sensitivity_cb),
2067 0))
2068 {
2069 g_free(state);
2070 return 0;
2071 }
2072
2073 state->periodic_button = go_gtk_builder_get_widget (state->base.gui, "periodic-button");
2074 state->random_button = go_gtk_builder_get_widget (state->base.gui, "random-button");
2075 state->method_label = go_gtk_builder_get_widget (state->base.gui, "method-label");
2076 state->options_grid = go_gtk_builder_get_widget (state->base.gui, "options-grid");
2077 state->period_label = go_gtk_builder_get_widget (state->base.gui, "period-label");
2078 state->random_label = go_gtk_builder_get_widget (state->base.gui, "random-label");
2079 state->period_entry = go_gtk_builder_get_widget (state->base.gui, "period-entry");
2080 state->random_entry = go_gtk_builder_get_widget (state->base.gui, "random-entry");
2081 state->number_entry = go_gtk_builder_get_widget (state->base.gui, "number-entry");
2082 state->offset_label = go_gtk_builder_get_widget (state->base.gui, "offset-label");
2083 state->offset_entry = go_gtk_builder_get_widget (state->base.gui, "offset-entry");
2084 state->major_label = go_gtk_builder_get_widget (state->base.gui, "pdir-label");
2085 state->row_major_button = go_gtk_builder_get_widget (state->base.gui, "row-major-button");
2086 state->col_major_button = go_gtk_builder_get_widget (state->base.gui, "col-major-button");
2087
2088 int_to_entry (GTK_ENTRY (state->number_entry), 1);
2089 int_to_entry (GTK_ENTRY (state->offset_entry), 0);
2090
2091 g_signal_connect_after (G_OBJECT (state->periodic_button),
2092 "toggled",
2093 G_CALLBACK (sampling_tool_update_sensitivity_cb), state);
2094 g_signal_connect (G_OBJECT (state->periodic_button),
2095 "toggled",
2096 G_CALLBACK (sampling_method_toggled_cb), state);
2097 g_signal_connect (G_OBJECT (state->base.dialog),
2098 "realize",
2099 G_CALLBACK (dialog_sampling_realized), state);
2100 g_signal_connect_after (G_OBJECT (state->period_entry),
2101 "changed",
2102 G_CALLBACK (sampling_tool_update_sensitivity_cb), state);
2103 g_signal_connect_after (G_OBJECT (state->random_entry),
2104 "changed",
2105 G_CALLBACK (sampling_tool_update_sensitivity_cb), state);
2106 g_signal_connect_after (G_OBJECT (state->number_entry),
2107 "changed",
2108 G_CALLBACK (sampling_tool_update_sensitivity_cb), state);
2109 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
2110 GTK_WIDGET (state->period_entry));
2111 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
2112 GTK_WIDGET (state->random_entry));
2113 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
2114 GTK_WIDGET (state->number_entry));
2115
2116 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
2117 sampling_tool_update_sensitivity_cb (NULL, state);
2118 tool_load_selection ((GnmGenericToolState *)state, TRUE);
2119
2120 return 0;
2121 }
2122 /**********************************************/
2123 /* End of sampling tool code */
2124 /**********************************************/
2125
2126 /**********************************************/
2127 /* Begin of Regression tool code */
2128 /**********************************************/
2129
2130 static gint
regression_tool_calc_height(GnmValue * val)2131 regression_tool_calc_height (GnmValue *val)
2132 {
2133 GnmRange r;
2134
2135 if (NULL == range_init_value (&r, val))
2136 return 0;
2137 return range_height (&r);
2138 }
2139
2140 static gint
regression_tool_calc_width(GnmValue * val)2141 regression_tool_calc_width (GnmValue *val)
2142 {
2143 GnmRange r;
2144
2145 if (NULL == range_init_value (&r, val))
2146 return 0;
2147 return range_width (&r);
2148 }
2149
2150
2151 /**
2152 * regression_tool_ok_clicked_cb:
2153 * @button:
2154 * @state:
2155 *
2156 * Retrieve the information from the dialog and call the regression_tool.
2157 * Note that we assume that the ok_button is only active if the entry fields
2158 * contain sensible data.
2159 **/
2160 static void
regression_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,RegressionToolState * state)2161 regression_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
2162 RegressionToolState *state)
2163 {
2164 data_analysis_output_t *dao;
2165 analysis_tools_data_regression_t *data;
2166
2167 GtkWidget *w;
2168 gnm_float confidence;
2169 gint y_h;
2170
2171 if (state->base.warning_dialog != NULL)
2172 gtk_widget_destroy (state->base.warning_dialog);
2173
2174 data = g_new0 (analysis_tools_data_regression_t, 1);
2175 dao = parse_output ((GnmGenericToolState *)state, NULL);
2176
2177 data->base.wbc = GNM_WBC (state->base.wbcg);
2178
2179 data->base.range_1 = gnm_expr_entry_parse_as_value (
2180 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
2181 data->base.range_2 = gnm_expr_entry_parse_as_value
2182 (GNM_EXPR_ENTRY (state->base.input_entry_2), state->base.sheet);
2183
2184 y_h = regression_tool_calc_height(data->base.range_2);
2185
2186 data->group_by = (y_h == 1) ? GROUPED_BY_ROW : GROUPED_BY_COL;
2187
2188 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
2189 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
2190
2191 entry_to_float (GTK_ENTRY (state->confidence_entry), &confidence, TRUE);
2192 data->base.alpha = 1 - confidence;
2193
2194 w = go_gtk_builder_get_widget (state->base.gui, "intercept-button");
2195 data->intercept = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
2196
2197 data->residual = gtk_toggle_button_get_active
2198 (GTK_TOGGLE_BUTTON (state->residuals_check));
2199
2200 data->multiple_regression
2201 = !gtk_toggle_button_get_active
2202 (GTK_TOGGLE_BUTTON (state->simple_linear_regression_radio));
2203
2204 data->multiple_y = gtk_toggle_button_get_active
2205 (GTK_TOGGLE_BUTTON (state->switch_variables_check));
2206
2207 if (cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
2208 dao, data, analysis_tool_regression_engine, FALSE)) {
2209 char *text;
2210
2211 text = g_strdup_printf (
2212 _("An unexpected error has occurred: %d."), data->base.err);
2213 error_in_entry ((GnmGenericToolState *) state,
2214 GTK_WIDGET (state->base.input_entry), text);
2215 g_free (text);
2216
2217 value_release (data->base.range_1);
2218 value_release (data->base.range_2);
2219 g_free (dao);
2220 g_free (data);
2221 } else
2222 gtk_widget_destroy (state->base.dialog);
2223
2224 }
2225
2226 /**
2227 * regression_tool_update_sensitivity_cb:
2228 * @state:
2229 *
2230 * Update the dialog widgets sensitivity.
2231 * We cannot use tool_update_sensitivity_cb
2232 * since we are also considering whether in fact
2233 * an interval is given.
2234 **/
2235 static void
regression_tool_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,RegressionToolState * state)2236 regression_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
2237 RegressionToolState *state)
2238 {
2239 int err;
2240 gnm_float confidence;
2241 GnmValue *input_range;
2242 GnmValue *input_range_2;
2243 gint y_h, y_w;
2244 gint x_h, x_w;
2245 gboolean switch_v;
2246
2247 switch_v = gtk_toggle_button_get_active
2248 (GTK_TOGGLE_BUTTON (state->switch_variables_check));
2249
2250 /* Checking Input Range */
2251 input_range_2 = gnm_expr_entry_parse_as_value (
2252 GNM_EXPR_ENTRY (state->base.input_entry_2), state->base.sheet);
2253 if (input_range_2 == NULL) {
2254 gtk_label_set_text (GTK_LABEL (state->base.warning),
2255 switch_v ?
2256 _("The x variable range is invalid.") :
2257 _("The y variable range is invalid.") );
2258 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2259 return;
2260 }
2261
2262 y_h = regression_tool_calc_height(input_range_2);
2263 y_w = regression_tool_calc_width (input_range_2);
2264 value_release (input_range_2);
2265
2266 if (y_h == 0 || y_w == 0) {
2267 gtk_label_set_text (GTK_LABEL (state->base.warning),
2268 switch_v ?
2269 _("The x variable range is invalid.") :
2270 _("The y variable range is invalid."));
2271 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2272 return;
2273 }
2274 if (y_h != 1 && y_w != 1) {
2275 gtk_label_set_text (GTK_LABEL (state->base.warning),
2276 switch_v ?
2277 _("The x variable range must be a vector (n by 1 or 1 by n).") :
2278 _("The y variable range must be a vector (n by 1 or 1 by n)."));
2279 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2280 return;
2281 }
2282 if (y_h <= 2 && y_w <= 2) {
2283 gtk_label_set_text (GTK_LABEL (state->base.warning),
2284 switch_v ?
2285 _("The x variable range is too small") :
2286 _("The y variable range is too small"));
2287 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2288 return;
2289 }
2290
2291 input_range = gnm_expr_entry_parse_as_value
2292 (GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
2293 if (input_range == NULL) {
2294 gtk_label_set_text (GTK_LABEL (state->base.warning),
2295 switch_v ?
2296 _("The y variables range is invalid.") :
2297 _("The x variables range is invalid."));
2298 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2299 return;
2300 }
2301
2302 x_h = regression_tool_calc_height(input_range);
2303 x_w = regression_tool_calc_width (input_range);
2304 value_release (input_range);
2305
2306 if (x_h == 0 || x_w == 0) {
2307 gtk_label_set_text (GTK_LABEL (state->base.warning),
2308 switch_v ?
2309 _("The y variables range is invalid.") :
2310 _("The x variables range is invalid."));
2311 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2312 return;
2313 }
2314
2315 if ((y_h == 1 && y_w != x_w) || (y_w == 1 && y_h != x_h)) {
2316 gtk_label_set_text (GTK_LABEL (state->base.warning),
2317 switch_v ?
2318 _("The sizes of the y variable and x variables ranges do not match.") :
2319 _("The sizes of the x variable and y variables ranges do not match."));
2320 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2321 return;
2322 }
2323
2324 err = entry_to_float (GTK_ENTRY (state->confidence_entry), &confidence, FALSE);
2325
2326 if (err != 0 || (1 < confidence || confidence < 0)) {
2327 gtk_label_set_text (GTK_LABEL (state->base.warning),
2328 _("The confidence level is invalid."));
2329 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2330 return;
2331 }
2332
2333 if (!gnm_dao_is_ready (GNM_DAO (state->base.gdao))) {
2334 gtk_label_set_text (GTK_LABEL (state->base.warning),
2335 _("The output specification "
2336 "is invalid."));
2337 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2338 return;
2339 }
2340
2341 gtk_label_set_text (GTK_LABEL (state->base.warning), "");
2342 gtk_widget_set_sensitive (state->base.ok_button, TRUE);
2343 }
2344
2345 static void
regression_tool_regression_radio_toggled_cb(G_GNUC_UNUSED GtkToggleButton * togglebutton,RegressionToolState * state)2346 regression_tool_regression_radio_toggled_cb (G_GNUC_UNUSED
2347 GtkToggleButton *togglebutton,
2348 RegressionToolState *state)
2349 {
2350 gboolean simple = gtk_toggle_button_get_active
2351 (GTK_TOGGLE_BUTTON (state->simple_linear_regression_radio));
2352 if (!simple)
2353 gtk_toggle_button_set_active
2354 (GTK_TOGGLE_BUTTON (state->switch_variables_check),
2355 FALSE);
2356
2357 gtk_toggle_button_set_active
2358 (GTK_TOGGLE_BUTTON (state->residuals_check), !simple);
2359 gtk_widget_set_sensitive (state->residuals_check, !simple);
2360
2361 }
2362
2363 static void
regression_tool_regression_check_toggled_cb(G_GNUC_UNUSED GtkToggleButton * togglebutton,RegressionToolState * state)2364 regression_tool_regression_check_toggled_cb (G_GNUC_UNUSED
2365 GtkToggleButton *togglebutton,
2366 RegressionToolState *state)
2367 {
2368 GtkWidget *w1, *w2;
2369
2370 w1 = go_gtk_builder_get_widget (state->base.gui, "var1-label");
2371 w2 = go_gtk_builder_get_widget (state->base.gui, "var2-label");
2372
2373 if (gtk_toggle_button_get_active
2374 (GTK_TOGGLE_BUTTON (state->switch_variables_check))) {
2375 gtk_toggle_button_set_active
2376 (GTK_TOGGLE_BUTTON
2377 (state->simple_linear_regression_radio),
2378 TRUE);
2379 gtk_label_set_markup_with_mnemonic (GTK_LABEL (w1),
2380 _("_Y variables:"));
2381 gtk_label_set_markup_with_mnemonic (GTK_LABEL (w2),
2382 _("_X variable:"));
2383 } else {
2384 gtk_label_set_markup_with_mnemonic (GTK_LABEL (w1),
2385 _("_X variables:"));
2386 gtk_label_set_markup_with_mnemonic (GTK_LABEL (w2),
2387 _("_Y variable:"));
2388 }
2389 regression_tool_update_sensitivity_cb (NULL, state);
2390 }
2391
2392
2393 /**
2394 * dialog_regression_tool:
2395 * @wbcg:
2396 * @sheet:
2397 *
2398 * Show the dialog (guru).
2399 *
2400 **/
2401 int
dialog_regression_tool(WBCGtk * wbcg,Sheet * sheet)2402 dialog_regression_tool (WBCGtk *wbcg, Sheet *sheet)
2403 {
2404 RegressionToolState *state;
2405 char const * plugins[] = { "Gnumeric_fnstat",
2406 "Gnumeric_fnlookup",
2407 "Gnumeric_fnmath",
2408 "Gnumeric_fninfo",
2409 "Gnumeric_fnstring",
2410 NULL};
2411
2412 if ((wbcg == NULL) ||
2413 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
2414 return 1;
2415
2416 /* Only pop up one copy per workbook */
2417 if (gnm_dialog_raise_if_exists (wbcg, REGRESSION_KEY))
2418 return 0;
2419
2420 state = g_new0 (RegressionToolState, 1);
2421
2422 if (dialog_tool_init (&state->base, wbcg, sheet,
2423 GNUMERIC_HELP_LINK_REGRESSION,
2424 "res:ui/regression.ui", "Regression",
2425 _("Could not create the Regression Tool dialog."),
2426 REGRESSION_KEY,
2427 G_CALLBACK (regression_tool_ok_clicked_cb), NULL,
2428 G_CALLBACK (regression_tool_update_sensitivity_cb),
2429 GNM_EE_SINGLE_RANGE))
2430 {
2431 g_free(state);
2432 return 0;
2433 }
2434
2435 state->confidence_entry = go_gtk_builder_get_widget (state->base.gui, "confidence-entry");
2436 float_to_entry (GTK_ENTRY (state->confidence_entry), 0.95);
2437 g_signal_connect_after (G_OBJECT (state->confidence_entry),
2438 "changed",
2439 G_CALLBACK (regression_tool_update_sensitivity_cb), state);
2440 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
2441 GTK_WIDGET (state->confidence_entry));
2442
2443 state->simple_linear_regression_radio
2444 = go_gtk_builder_get_widget
2445 (state->base.gui, "simple-regression-button");
2446 state->switch_variables_check
2447 = go_gtk_builder_get_widget
2448 (state->base.gui, "multiple-independent-check");
2449 state->residuals_check
2450 = go_gtk_builder_get_widget
2451 (state->base.gui, "residuals-button");
2452 gtk_toggle_button_set_active
2453 (GTK_TOGGLE_BUTTON (state->simple_linear_regression_radio),
2454 FALSE);
2455 gtk_toggle_button_set_active
2456 (GTK_TOGGLE_BUTTON (state->switch_variables_check),
2457 FALSE);
2458 gtk_toggle_button_set_active
2459 (GTK_TOGGLE_BUTTON (state->residuals_check),
2460 TRUE);
2461 g_signal_connect
2462 (G_OBJECT (state->simple_linear_regression_radio),
2463 "toggled",
2464 G_CALLBACK (regression_tool_regression_radio_toggled_cb),
2465 state);
2466 g_signal_connect
2467 (G_OBJECT (state->switch_variables_check),
2468 "toggled",
2469 G_CALLBACK (regression_tool_regression_check_toggled_cb),
2470 state);
2471
2472
2473
2474 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
2475 regression_tool_update_sensitivity_cb (NULL, state);
2476 tool_load_selection ((GnmGenericToolState *)state, TRUE);
2477
2478 return 0;
2479 }
2480
2481 /**********************************************/
2482 /* End of Regression tool code */
2483 /**********************************************/
2484
2485 /**********************************************/
2486 /* Begin of Exponential smoothing tool code */
2487 /**********************************************/
2488
2489
2490 /**
2491 * exp_smoothing_tool_ok_clicked_cb:
2492 * @button:
2493 * @state:
2494 *
2495 **/
2496 static void
exp_smoothing_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,ExpSmoothToolState * state)2497 exp_smoothing_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
2498 ExpSmoothToolState *state)
2499 {
2500 data_analysis_output_t *dao;
2501 analysis_tools_data_exponential_smoothing_t *data;
2502
2503 GtkWidget *w;
2504
2505 data = g_new0 (analysis_tools_data_exponential_smoothing_t, 1);
2506 dao = parse_output ((GnmGenericToolState *)state, NULL);
2507
2508 data->base.input = gnm_expr_entry_parse_as_list (
2509 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
2510 data->base.group_by = gnm_gui_group_value (state->base.gui, grouped_by_group);
2511
2512 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
2513 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
2514
2515 entry_to_float (GTK_ENTRY (state->damping_fact_entry),
2516 &data->damp_fact, TRUE);
2517 entry_to_float (GTK_ENTRY (state->g_damping_fact_entry),
2518 &data->g_damp_fact, TRUE);
2519 entry_to_float (GTK_ENTRY (state->s_damping_fact_entry),
2520 &data->s_damp_fact, TRUE);
2521 entry_to_int (GTK_ENTRY (state->s_period_entry),
2522 &data->s_period, TRUE);
2523
2524 data->std_error_flag = gtk_toggle_button_get_active
2525 (GTK_TOGGLE_BUTTON (state->show_std_errors));
2526 data->show_graph = gtk_toggle_button_get_active
2527 (GTK_TOGGLE_BUTTON (state->graph_button));
2528 data->df = gnm_gui_group_value (state->base.gui, n_group);
2529
2530 data->es_type = gnm_gui_group_value (state->base.gui, exp_smoothing_group);
2531
2532 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
2533 dao, data, analysis_tool_exponential_smoothing_engine,
2534 TRUE))
2535 gtk_widget_destroy (state->base.dialog);
2536
2537 return;
2538 }
2539
2540 /**
2541 * exp_smoothing_tool_update_sensitivity_cb:
2542 * @state:
2543 *
2544 * Update the dialog widgets sensitivity.
2545 * We cannot use tool_update_sensitivity_cb
2546 * since we are also considering whether in fact
2547 * a damping factor is given.
2548 **/
2549 static void
exp_smoothing_tool_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,ExpSmoothToolState * state)2550 exp_smoothing_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
2551 ExpSmoothToolState *state)
2552 {
2553 int err, period;
2554 gnm_float damp_fact;
2555 GSList *input_range;
2556
2557 input_range = gnm_expr_entry_parse_as_list (
2558 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
2559 if (input_range == NULL) {
2560 gtk_label_set_text (GTK_LABEL (state->base.warning),
2561 _("The input range is invalid."));
2562 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2563 return;
2564 } else
2565 range_list_destroy (input_range);
2566
2567 switch (gnm_gui_group_value (state->base.gui, exp_smoothing_group)) {
2568 case exp_smoothing_type_mtes:
2569 case exp_smoothing_type_ates:
2570 err = entry_to_float (GTK_ENTRY (state->s_damping_fact_entry),
2571 &damp_fact, FALSE);
2572 if (err!= 0 || damp_fact < 0 || damp_fact > 1) {
2573 gtk_label_set_text (GTK_LABEL (state->base.warning),
2574 _("The given seasonal damping "
2575 "factor is invalid."));
2576 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2577 return;
2578 }
2579 err = entry_to_int (GTK_ENTRY (state->s_period_entry),
2580 &period, FALSE);
2581 if (err!= 0 || period < 2) {
2582 gtk_label_set_text (GTK_LABEL (state->base.warning),
2583 _("The given seasonal period "
2584 "is invalid."));
2585 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2586 return;
2587 }
2588 /* no break */
2589 case exp_smoothing_type_des:
2590 err = entry_to_float (GTK_ENTRY (state->g_damping_fact_entry),
2591 &damp_fact, FALSE);
2592 if (err!= 0 || damp_fact < 0 || damp_fact > 1) {
2593 gtk_label_set_text (GTK_LABEL (state->base.warning),
2594 _("The given growth "
2595 "damping factor is invalid."));
2596 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2597 return;
2598 }
2599 /* no break */
2600 case exp_smoothing_type_ses_r:
2601 case exp_smoothing_type_ses_h:
2602 err = entry_to_float (GTK_ENTRY (state->damping_fact_entry),
2603 &damp_fact, FALSE);
2604 if (err!= 0 || damp_fact < 0 || damp_fact > 1) {
2605 gtk_label_set_text (GTK_LABEL (state->base.warning),
2606 _("The given damping factor is invalid."));
2607 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2608 return;
2609 }
2610 break;
2611 }
2612
2613 if (!gnm_dao_is_ready (GNM_DAO (state->base.gdao))) {
2614 gtk_label_set_text (GTK_LABEL (state->base.warning),
2615 _("The output specification "
2616 "is invalid."));
2617 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2618 return;
2619 }
2620
2621 gtk_label_set_text (GTK_LABEL (state->base.warning), "");
2622 gtk_widget_set_sensitive (state->base.ok_button, TRUE);
2623 }
2624
2625 static void
exp_smoothing_tool_check_error_cb(G_GNUC_UNUSED GtkToggleButton * togglebutton,gpointer user_data)2626 exp_smoothing_tool_check_error_cb (G_GNUC_UNUSED GtkToggleButton *togglebutton, gpointer user_data)
2627 {
2628 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (user_data), TRUE);
2629 }
2630
2631
2632 static void
exp_smoothing_ses_h_cb(GtkToggleButton * togglebutton,gpointer user_data)2633 exp_smoothing_ses_h_cb (GtkToggleButton *togglebutton, gpointer user_data)
2634 {
2635 ExpSmoothToolState *state = (ExpSmoothToolState *)user_data;
2636 gboolean std_error;
2637
2638 if (!gtk_toggle_button_get_active (togglebutton))
2639 return;
2640
2641 gtk_widget_set_sensitive (state->g_damping_fact_entry, FALSE);
2642 gtk_widget_set_sensitive (state->s_damping_fact_entry, FALSE);
2643 gtk_widget_set_sensitive (state->s_period_entry, FALSE);
2644
2645 std_error = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->show_std_errors));
2646 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->n_button), TRUE);
2647 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->show_std_errors), std_error);
2648 }
2649
2650 static void
exp_smoothing_ses_r_cb(GtkToggleButton * togglebutton,gpointer user_data)2651 exp_smoothing_ses_r_cb (GtkToggleButton *togglebutton, gpointer user_data)
2652 {
2653 ExpSmoothToolState *state = (ExpSmoothToolState *)user_data;
2654 gboolean std_error;
2655
2656 if (!gtk_toggle_button_get_active (togglebutton))
2657 return;
2658
2659 gtk_widget_set_sensitive (state->g_damping_fact_entry, FALSE);
2660 gtk_widget_set_sensitive (state->s_damping_fact_entry, FALSE);
2661 gtk_widget_set_sensitive (state->s_period_entry, FALSE);
2662
2663 std_error = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->show_std_errors));
2664 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->nm1_button), TRUE);
2665 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->show_std_errors), std_error);
2666 }
2667
2668 static void
exp_smoothing_des_cb(GtkToggleButton * togglebutton,gpointer user_data)2669 exp_smoothing_des_cb (GtkToggleButton *togglebutton, gpointer user_data)
2670 {
2671 ExpSmoothToolState *state = (ExpSmoothToolState *)user_data;
2672 gboolean std_error;
2673
2674 if (!gtk_toggle_button_get_active (togglebutton))
2675 return;
2676
2677 gtk_widget_set_sensitive (state->g_damping_fact_entry, TRUE);
2678 gtk_widget_set_sensitive (state->s_damping_fact_entry, FALSE);
2679 gtk_widget_set_sensitive (state->s_period_entry, FALSE);
2680
2681 std_error = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->show_std_errors));
2682 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->nm2_button), TRUE);
2683 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->show_std_errors), std_error);
2684 }
2685
2686 static void
exp_smoothing_tes_cb(GtkToggleButton * togglebutton,gpointer user_data)2687 exp_smoothing_tes_cb (GtkToggleButton *togglebutton, gpointer user_data)
2688 {
2689 ExpSmoothToolState *state = (ExpSmoothToolState *)user_data;
2690 gboolean std_error;
2691
2692 if (!gtk_toggle_button_get_active (togglebutton))
2693 return;
2694
2695 gtk_widget_set_sensitive (state->g_damping_fact_entry, TRUE);
2696 gtk_widget_set_sensitive (state->s_damping_fact_entry, TRUE);
2697 gtk_widget_set_sensitive (state->s_period_entry, TRUE);
2698
2699 std_error = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->show_std_errors));
2700 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->nm3_button), TRUE);
2701 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->show_std_errors), std_error);
2702 }
2703
2704 /**
2705 * dialog_exp_smoothing_tool:
2706 * @wbcg:
2707 * @sheet:
2708 *
2709 * Show the dialog (guru).
2710 *
2711 **/
2712 int
dialog_exp_smoothing_tool(WBCGtk * wbcg,Sheet * sheet)2713 dialog_exp_smoothing_tool (WBCGtk *wbcg, Sheet *sheet)
2714 {
2715 ExpSmoothToolState *state;
2716 char const * plugins[] = { "Gnumeric_fnstat",
2717 "Gnumeric_fnlookup",
2718 "Gnumeric_fnmath",
2719 "Gnumeric_fnlogical",
2720 NULL};
2721
2722 if ((wbcg == NULL) ||
2723 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
2724 return 1;
2725
2726 /* Only pop up one copy per workbook */
2727 if (gnm_dialog_raise_if_exists (wbcg, EXP_SMOOTHING_KEY))
2728 return 0;
2729
2730 state = g_new0 (ExpSmoothToolState, 1);
2731
2732 if (dialog_tool_init (&state->base, wbcg, sheet,
2733 GNUMERIC_HELP_LINK_EXP_SMOOTHING,
2734 "res:ui/exp-smoothing.ui",
2735 "ExpSmoothing",
2736 _("Could not create the Exponential Smoothing "
2737 "Tool dialog."),
2738 EXP_SMOOTHING_KEY,
2739 G_CALLBACK (exp_smoothing_tool_ok_clicked_cb),
2740 NULL,
2741 G_CALLBACK (exp_smoothing_tool_update_sensitivity_cb),
2742 0))
2743 {
2744 g_free(state);
2745 return 0;
2746 }
2747
2748 state->damping_fact_entry = go_gtk_builder_get_widget (state->base.gui,
2749 "damping-fact-spin");
2750 gtk_spin_button_set_value (GTK_SPIN_BUTTON (state->damping_fact_entry), 0.2);
2751 float_to_entry (GTK_ENTRY (state->damping_fact_entry), 0.2);
2752 state->g_damping_fact_entry = go_gtk_builder_get_widget (state->base.gui,
2753 "g-damping-fact-spin");
2754 gtk_spin_button_set_value (GTK_SPIN_BUTTON (state->g_damping_fact_entry), 0.25);
2755 state->s_damping_fact_entry = go_gtk_builder_get_widget (state->base.gui,
2756 "s-damping-fact-spin");
2757 gtk_spin_button_set_value (GTK_SPIN_BUTTON (state->s_damping_fact_entry), 0.3);
2758 state->s_period_entry = go_gtk_builder_get_widget (state->base.gui,
2759 "s-period-spin");
2760 gtk_spin_button_set_value (GTK_SPIN_BUTTON (state->s_period_entry), 12.);
2761
2762
2763 state->n_button = go_gtk_builder_get_widget (state->base.gui, "n-button");
2764 state->nm1_button = go_gtk_builder_get_widget (state->base.gui, "nm1-button");
2765 state->nm2_button = go_gtk_builder_get_widget (state->base.gui, "nm2-button");
2766 state->nm3_button = go_gtk_builder_get_widget (state->base.gui, "nm3-button");
2767
2768 state->show_std_errors = go_gtk_builder_get_widget (state->base.gui, "std-errors-button");
2769 state->graph_button = go_gtk_builder_get_widget (state->base.gui, "graph-check");
2770
2771 state->ses_h_button = go_gtk_builder_get_widget (state->base.gui, "ses-h-button");
2772 state->ses_r_button = go_gtk_builder_get_widget (state->base.gui, "ses-r-button");
2773 state->des_button = go_gtk_builder_get_widget (state->base.gui, "des-button");
2774 state->ates_button = go_gtk_builder_get_widget (state->base.gui, "ates-button");
2775 state->mtes_button = go_gtk_builder_get_widget (state->base.gui, "mtes-button");
2776
2777 g_signal_connect_after (G_OBJECT (state->n_button),
2778 "toggled",
2779 G_CALLBACK (exp_smoothing_tool_check_error_cb), state->show_std_errors);
2780 g_signal_connect_after (G_OBJECT (state->nm1_button),
2781 "toggled",
2782 G_CALLBACK (exp_smoothing_tool_check_error_cb), state->show_std_errors);
2783 g_signal_connect_after (G_OBJECT (state->nm2_button),
2784 "toggled",
2785 G_CALLBACK (exp_smoothing_tool_check_error_cb), state->show_std_errors);
2786 g_signal_connect_after (G_OBJECT (state->nm3_button),
2787 "toggled",
2788 G_CALLBACK (exp_smoothing_tool_check_error_cb), state->show_std_errors);
2789 g_signal_connect_after (G_OBJECT (state->damping_fact_entry),
2790 "changed",
2791 G_CALLBACK (exp_smoothing_tool_update_sensitivity_cb), state);
2792
2793 g_signal_connect_after (G_OBJECT (state->ses_h_button),
2794 "toggled",
2795 G_CALLBACK (exp_smoothing_ses_h_cb), state);
2796 g_signal_connect_after (G_OBJECT (state->ses_r_button),
2797 "toggled",
2798 G_CALLBACK (exp_smoothing_ses_r_cb), state);
2799 g_signal_connect_after (G_OBJECT (state->des_button),
2800 "toggled",
2801 G_CALLBACK (exp_smoothing_des_cb), state);
2802 g_signal_connect_after (G_OBJECT (state->ates_button),
2803 "toggled",
2804 G_CALLBACK (exp_smoothing_tes_cb), state);
2805 g_signal_connect_after (G_OBJECT (state->mtes_button),
2806 "toggled",
2807 G_CALLBACK (exp_smoothing_tes_cb), state);
2808
2809 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
2810 GTK_WIDGET (state->damping_fact_entry));
2811 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
2812 GTK_WIDGET (state->g_damping_fact_entry));
2813 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
2814 GTK_WIDGET (state->s_damping_fact_entry));
2815
2816 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
2817 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->ses_h_button), TRUE);
2818 exp_smoothing_ses_h_cb (GTK_TOGGLE_BUTTON (state->ses_h_button), state);
2819 exp_smoothing_tool_update_sensitivity_cb (NULL, state);
2820 tool_load_selection ((GnmGenericToolState *)state, TRUE);
2821
2822 return 0;
2823 }
2824
2825 /**********************************************/
2826 /* End of Exponential Smoothing tool code */
2827 /**********************************************/
2828
2829 /**********************************************/
2830 /* Begin of Moving Averages tool code */
2831 /**********************************************/
2832
2833
2834 /**
2835 * average_tool_ok_clicked_cb:
2836 * @button:
2837 * @state:
2838 *
2839 * Retrieve the information from the dialog and call the average_tool.
2840 * Note that we assume that the ok_button is only active if the entry fields
2841 * contain sensible data.
2842 **/
2843 static void
average_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,AverageToolState * state)2844 average_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
2845 AverageToolState *state)
2846 {
2847 data_analysis_output_t *dao;
2848 analysis_tools_data_moving_average_t *data;
2849
2850 GtkWidget *w;
2851
2852 data = g_new0 (analysis_tools_data_moving_average_t, 1);
2853 dao = parse_output ((GnmGenericToolState *)state, NULL);
2854
2855 data->base.input = gnm_expr_entry_parse_as_list (
2856 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
2857 data->base.group_by = gnm_gui_group_value (state->base.gui, grouped_by_group);
2858
2859 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
2860 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
2861
2862 entry_to_int (GTK_ENTRY (state->interval_entry), &data->interval, TRUE);
2863 entry_to_int (GTK_ENTRY (state->offset_spin), &data->offset, TRUE);
2864
2865 data->std_error_flag = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->show_std_errors));
2866 data->show_graph = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->graph_button));
2867
2868 data->df = gnm_gui_group_value (state->base.gui, n_group);
2869
2870 data->ma_type = gnm_gui_group_value (state->base.gui, moving_average_group);
2871
2872 switch (data->ma_type) {
2873 case moving_average_type_sma:
2874 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->central_button))
2875 && (data->interval % 2 == 0))
2876 data->ma_type = moving_average_type_central_sma;
2877 break;
2878 case moving_average_type_cma:
2879 data->interval = 0;
2880 data->offset = 0;
2881 break;
2882 case moving_average_type_spencer_ma:
2883 data->interval = 15;
2884 data->offset = 7;
2885 break;
2886 case moving_average_type_wma:
2887 data->offset = 0;
2888 break;
2889 default:
2890 break;
2891 }
2892
2893 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
2894 dao, data, analysis_tool_moving_average_engine, TRUE))
2895 gtk_widget_destroy (state->base.dialog);
2896
2897 return;
2898 }
2899
2900 /**
2901 * average_tool_update_sensitivity_cb:
2902 * @state:
2903 *
2904 * Update the dialog widgets sensitivity.
2905 * We cannot use tool_update_sensitivity_cb
2906 * since we are also considering whether in fact
2907 * an interval is given.
2908 **/
2909 static void
average_tool_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,AverageToolState * state)2910 average_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
2911 AverageToolState *state)
2912 {
2913 int interval, err, offset;
2914 GSList *input_range;
2915 moving_average_type_t type;
2916
2917
2918 input_range = gnm_expr_entry_parse_as_list (
2919 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
2920 if (input_range == NULL) {
2921 gtk_label_set_text (GTK_LABEL (state->base.warning),
2922 _("The input range is invalid."));
2923 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2924 return;
2925 } else
2926 range_list_destroy (input_range);
2927
2928 type = gnm_gui_group_value (state->base.gui, moving_average_group);
2929
2930 if ((type == moving_average_type_sma) || (type == moving_average_type_wma)) {
2931 err = entry_to_int (GTK_ENTRY (state->interval_entry),
2932 &interval, FALSE);
2933 if (err!= 0 || interval <= 0) {
2934 gtk_label_set_text (GTK_LABEL (state->base.warning),
2935 _("The given interval is invalid."));
2936 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2937 return;
2938 }
2939 }
2940
2941 if (type == moving_average_type_sma) {
2942 err = entry_to_int (GTK_ENTRY (state->offset_spin), &offset, FALSE);
2943 if (err!= 0 || offset < 0 || offset > interval) {
2944 gtk_label_set_text (GTK_LABEL (state->base.warning),
2945 _("The given offset is invalid."));
2946 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2947 return;
2948 }
2949 }
2950
2951 if (!gnm_dao_is_ready (GNM_DAO (state->base.gdao))) {
2952 gtk_label_set_text (GTK_LABEL (state->base.warning),
2953 _("The output specification "
2954 "is invalid."));
2955 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
2956 return;
2957 }
2958
2959 gtk_label_set_text (GTK_LABEL (state->base.warning), "");
2960 gtk_widget_set_sensitive (state->base.ok_button, TRUE);
2961 }
2962
2963 static void
average_tool_check_error_cb(G_GNUC_UNUSED GtkToggleButton * togglebutton,gpointer user_data)2964 average_tool_check_error_cb (G_GNUC_UNUSED GtkToggleButton *togglebutton, gpointer user_data)
2965 {
2966 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (user_data), TRUE);
2967 }
2968
2969 static void
average_tool_central_cb(GtkToggleButton * togglebutton,gpointer user_data)2970 average_tool_central_cb (GtkToggleButton *togglebutton, gpointer user_data)
2971 {
2972 AverageToolState *state = (AverageToolState *)user_data;
2973 int interval;
2974 int err;
2975
2976 if (gtk_toggle_button_get_active (togglebutton)) {
2977 err = entry_to_int (GTK_ENTRY (state->interval_entry), &interval, TRUE);
2978 if (err == 0)
2979 gtk_spin_button_set_value (GTK_SPIN_BUTTON (state->offset_spin), (interval/2));
2980 }
2981 }
2982
2983 static void
average_tool_prior_cb(GtkToggleButton * togglebutton,gpointer user_data)2984 average_tool_prior_cb (GtkToggleButton *togglebutton, gpointer user_data)
2985 {
2986 AverageToolState *state = (AverageToolState *)user_data;
2987
2988 if (gtk_toggle_button_get_active (togglebutton))
2989 gtk_spin_button_set_value (GTK_SPIN_BUTTON (state->offset_spin), 0.0);
2990 }
2991
2992 static void
average_tool_interval_cb(G_GNUC_UNUSED GtkWidget * dummy,AverageToolState * state)2993 average_tool_interval_cb (G_GNUC_UNUSED GtkWidget *dummy, AverageToolState *state)
2994 {
2995 int interval;
2996 int err;
2997
2998 err = entry_to_int (GTK_ENTRY (state->interval_entry), &interval, TRUE);
2999
3000 if (err == 0)
3001 gtk_spin_button_set_range (GTK_SPIN_BUTTON (state->offset_spin),
3002 0, interval - 1);
3003 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->central_button)))
3004 gtk_spin_button_set_value (GTK_SPIN_BUTTON (state->offset_spin), interval/2);
3005 }
3006
3007 static void
average_tool_offset_cb(GtkToggleButton * togglebutton,gpointer user_data)3008 average_tool_offset_cb (GtkToggleButton *togglebutton, gpointer user_data)
3009 {
3010 AverageToolState *state = (AverageToolState *)user_data;
3011
3012 gtk_widget_set_sensitive (state->offset_spin, gtk_toggle_button_get_active (togglebutton));
3013 }
3014
3015
3016 static void
average_tool_sma_cb(GtkToggleButton * togglebutton,gpointer user_data)3017 average_tool_sma_cb (GtkToggleButton *togglebutton, gpointer user_data)
3018 {
3019 AverageToolState *state = (AverageToolState *)user_data;
3020
3021 if (!gtk_toggle_button_get_active (togglebutton))
3022 return;
3023
3024 gtk_widget_set_sensitive (state->prior_button, TRUE);
3025 gtk_widget_set_sensitive (state->central_button, TRUE);
3026 gtk_widget_set_sensitive (state->offset_button, TRUE);
3027 gtk_widget_set_sensitive (state->interval_entry, TRUE);
3028 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->prior_button), TRUE);
3029 average_tool_update_sensitivity_cb (NULL, state);
3030 }
3031
3032 static void
average_tool_cma_cb(GtkToggleButton * togglebutton,gpointer user_data)3033 average_tool_cma_cb (GtkToggleButton *togglebutton, gpointer user_data)
3034 {
3035 AverageToolState *state = (AverageToolState *)user_data;
3036
3037 if (!gtk_toggle_button_get_active (togglebutton))
3038 return;
3039
3040 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->prior_button), TRUE);
3041 gtk_widget_set_sensitive (state->prior_button, FALSE);
3042 gtk_widget_set_sensitive (state->central_button, FALSE);
3043 gtk_widget_set_sensitive (state->offset_button, FALSE);
3044 gtk_widget_set_sensitive (state->interval_entry, FALSE);
3045 average_tool_update_sensitivity_cb (NULL, state);
3046 }
3047
3048 static void
average_tool_wma_cb(GtkToggleButton * togglebutton,gpointer user_data)3049 average_tool_wma_cb (GtkToggleButton *togglebutton, gpointer user_data)
3050 {
3051 AverageToolState *state = (AverageToolState *)user_data;
3052
3053 if (!gtk_toggle_button_get_active (togglebutton))
3054 return;
3055 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->prior_button), TRUE);
3056 gtk_widget_set_sensitive (state->prior_button, FALSE);
3057 gtk_widget_set_sensitive (state->central_button, FALSE);
3058 gtk_widget_set_sensitive (state->offset_button, FALSE);
3059 gtk_widget_set_sensitive (state->interval_entry, TRUE);
3060 average_tool_update_sensitivity_cb (NULL, state);
3061 }
3062
3063 static void
average_tool_spencer_cb(GtkToggleButton * togglebutton,gpointer user_data)3064 average_tool_spencer_cb (GtkToggleButton *togglebutton, gpointer user_data)
3065 {
3066 AverageToolState *state = (AverageToolState *)user_data;
3067
3068 if (!gtk_toggle_button_get_active (togglebutton))
3069 return;
3070 int_to_entry (GTK_ENTRY (state->interval_entry), 15);
3071 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->central_button), TRUE);
3072 gtk_widget_set_sensitive (state->prior_button, FALSE);
3073 gtk_widget_set_sensitive (state->central_button, FALSE);
3074 gtk_widget_set_sensitive (state->offset_button, FALSE);
3075 gtk_widget_set_sensitive (state->interval_entry, FALSE);
3076 average_tool_update_sensitivity_cb (NULL, state);
3077 }
3078
3079 /**
3080 * dialog_average_tool:
3081 * @wbcg:
3082 * @sheet:
3083 *
3084 * Show the dialog (guru).
3085 *
3086 **/
3087 int
dialog_average_tool(WBCGtk * wbcg,Sheet * sheet)3088 dialog_average_tool (WBCGtk *wbcg, Sheet *sheet)
3089 {
3090 AverageToolState *state;
3091 char const * plugins[] = { "Gnumeric_fnstat",
3092 "Gnumeric_fnlookup",
3093 "Gnumeric_fnmath",
3094 NULL};
3095
3096 if ((wbcg == NULL) ||
3097 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
3098 return 1;
3099
3100 /* Only pop up one copy per workbook */
3101 if (gnm_dialog_raise_if_exists (wbcg, AVERAGE_KEY))
3102 return 0;
3103
3104 state = g_new0 (AverageToolState, 1);
3105
3106 if (dialog_tool_init (&state->base, wbcg, sheet,
3107 GNUMERIC_HELP_LINK_MOVING_AVERAGES,
3108 "res:ui/moving-averages.ui",
3109 "MovAverages",
3110 _("Could not create the Moving Average Tool "
3111 "dialog."),
3112 AVERAGE_KEY,
3113 G_CALLBACK (average_tool_ok_clicked_cb), NULL,
3114 G_CALLBACK (average_tool_update_sensitivity_cb),
3115 0))
3116 {
3117 g_free(state);
3118 return 0;
3119 }
3120
3121 state->interval_entry = go_gtk_builder_get_widget (state->base.gui, "interval-entry");
3122 int_to_entry (GTK_ENTRY (state->interval_entry), 3);
3123 state->n_button = go_gtk_builder_get_widget (state->base.gui, "n-button");
3124 state->nm1_button = go_gtk_builder_get_widget (state->base.gui, "nm1-button");
3125 state->nm2_button = go_gtk_builder_get_widget (state->base.gui, "nm2-button");
3126 state->prior_button = go_gtk_builder_get_widget (state->base.gui, "prior-button");
3127 state->central_button = go_gtk_builder_get_widget (state->base.gui, "central-button");
3128 state->offset_button = go_gtk_builder_get_widget (state->base.gui, "offset-button");
3129 state->offset_spin = go_gtk_builder_get_widget (state->base.gui, "offset-spinbutton");
3130 state->show_std_errors = go_gtk_builder_get_widget (state->base.gui, "std-errors-button");
3131 state->graph_button = go_gtk_builder_get_widget (state->base.gui, "graph-check");
3132 state->sma_button = go_gtk_builder_get_widget (state->base.gui, "sma-button");
3133 state->cma_button = go_gtk_builder_get_widget (state->base.gui, "cma-button");
3134 state->wma_button = go_gtk_builder_get_widget (state->base.gui, "wma-button");
3135 state->spencer_button = go_gtk_builder_get_widget (state->base.gui, "spencer-ma-button");
3136
3137
3138 g_signal_connect_after (G_OBJECT (state->n_button),
3139 "toggled",
3140 G_CALLBACK (average_tool_check_error_cb), state->show_std_errors);
3141 g_signal_connect_after (G_OBJECT (state->nm1_button),
3142 "toggled",
3143 G_CALLBACK (average_tool_check_error_cb), state->show_std_errors);
3144 g_signal_connect_after (G_OBJECT (state->nm2_button),
3145 "toggled",
3146 G_CALLBACK (average_tool_check_error_cb), state->show_std_errors);
3147
3148 g_signal_connect_after (G_OBJECT (state->prior_button),
3149 "toggled",
3150 G_CALLBACK (average_tool_prior_cb), state);
3151 g_signal_connect_after (G_OBJECT (state->central_button),
3152 "toggled",
3153 G_CALLBACK (average_tool_central_cb), state);
3154 g_signal_connect_after (G_OBJECT (state->offset_button),
3155 "toggled",
3156 G_CALLBACK (average_tool_offset_cb), state);
3157
3158 g_signal_connect_after (G_OBJECT (state->sma_button),
3159 "toggled",
3160 G_CALLBACK (average_tool_sma_cb), state);
3161 g_signal_connect_after (G_OBJECT (state->cma_button),
3162 "toggled",
3163 G_CALLBACK (average_tool_cma_cb), state);
3164 g_signal_connect_after (G_OBJECT (state->wma_button),
3165 "toggled",
3166 G_CALLBACK (average_tool_wma_cb), state);
3167 g_signal_connect_after (G_OBJECT (state->spencer_button),
3168 "toggled",
3169 G_CALLBACK (average_tool_spencer_cb), state);
3170
3171
3172 g_signal_connect_after (G_OBJECT (state->interval_entry),
3173 "changed",
3174 G_CALLBACK (average_tool_update_sensitivity_cb), state);
3175 g_signal_connect_after (G_OBJECT (state->interval_entry),
3176 "changed",
3177 G_CALLBACK (average_tool_interval_cb), state);
3178
3179 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
3180 GTK_WIDGET (state->interval_entry));
3181
3182 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
3183 average_tool_update_sensitivity_cb (NULL, state);
3184 tool_load_selection ((GnmGenericToolState *)state, TRUE);
3185
3186 return 0;
3187 }
3188
3189 /**********************************************/
3190 /* End of Moving Averages tool code */
3191 /**********************************************/
3192
3193 /**********************************************/
3194 /* Begin of histogram tool code */
3195 /**********************************************/
3196
3197 /**
3198 * histogram_tool_update_sensitivity_cb:
3199 * @dummy:
3200 * @state:
3201 *
3202 * Update the dialog widgets sensitivity
3203 **/
3204 static void
histogram_tool_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,HistogramToolState * state)3205 histogram_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
3206 HistogramToolState *state)
3207 {
3208 int the_n;
3209 gboolean predetermined_bins;
3210 GSList *input_range;
3211 GnmValue *input_range_2 = NULL;
3212
3213 input_range = gnm_expr_entry_parse_as_list
3214 (GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
3215 if (input_range == NULL) {
3216 gtk_label_set_text (GTK_LABEL (state->base.warning),
3217 _("The input range is invalid."));
3218 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3219 return;
3220 }
3221
3222 range_list_destroy (input_range);
3223
3224 predetermined_bins = gtk_toggle_button_get_active (
3225 GTK_TOGGLE_BUTTON (state->predetermined_button));
3226 if (predetermined_bins) {
3227 input_range_2 = gnm_expr_entry_parse_as_value
3228 (GNM_EXPR_ENTRY (state->base.input_entry_2), state->base.sheet);
3229 if (input_range_2 == NULL) {
3230 gtk_label_set_text (GTK_LABEL (state->base.warning),
3231 _("The cutoff range is not valid."));
3232 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3233 return;
3234 }
3235 value_release (input_range_2);
3236 } else if (entry_to_int(state->n_entry, &the_n,FALSE) != 0 || the_n <= 0) {
3237 gtk_label_set_text (GTK_LABEL (state->base.warning),
3238 _("The number of to be calculated cutoffs is invalid."));
3239 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3240 return;
3241 }
3242
3243 if (!gnm_dao_is_ready (GNM_DAO (state->base.gdao))) {
3244 gtk_label_set_text (GTK_LABEL (state->base.warning),
3245 _("The output specification "
3246 "is invalid."));
3247 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3248 return;
3249 }
3250
3251 gtk_label_set_text (GTK_LABEL (state->base.warning), "");
3252 gtk_widget_set_sensitive (state->base.ok_button, TRUE);
3253
3254 return;
3255 }
3256
3257 /**
3258 * histogram_tool_ok_clicked_cb:
3259 * @button:
3260 * @state:
3261 *
3262 * Retrieve the information from the dialog and call the histogram_tool.
3263 * Note that we assume that the ok_button is only active if the entry fields
3264 * contain sensible data.
3265 **/
3266 static void
histogram_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,HistogramToolState * state)3267 histogram_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
3268 HistogramToolState *state)
3269 {
3270 data_analysis_output_t *dao;
3271 analysis_tools_data_histogram_t *data;
3272
3273 GtkWidget *w;
3274
3275 data = g_new0 (analysis_tools_data_histogram_t, 1);
3276 dao = parse_output ((GnmGenericToolState *)state, NULL);
3277
3278 data->base.input = gnm_expr_entry_parse_as_list (
3279 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
3280 data->base.group_by = gnm_gui_group_value (state->base.gui, grouped_by_group);
3281
3282 data->predetermined = gtk_toggle_button_get_active (
3283 GTK_TOGGLE_BUTTON (state->predetermined_button));
3284 if (data->predetermined) {
3285 w = go_gtk_builder_get_widget (state->base.gui, "labels_2_button");
3286 data->bin = gnm_expr_entry_parse_as_value
3287 (GNM_EXPR_ENTRY (state->base.input_entry_2),
3288 state->base.sheet);
3289 } else {
3290 entry_to_int(state->n_entry, &data->n,TRUE);
3291 data->max_given = (0 == entry_to_float (state->max_entry,
3292 &data->max , TRUE));
3293 data->min_given = (0 == entry_to_float (state->min_entry,
3294 &data->min , TRUE));
3295 data->bin = NULL;
3296 }
3297
3298 data->bin_type = gnm_gui_group_value (state->base.gui, bin_type_group);
3299 data->chart = gnm_gui_group_value (state->base.gui, chart_group);
3300
3301 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
3302 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
3303 w = go_gtk_builder_get_widget (state->base.gui, "percentage-button");
3304 data->percentage = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
3305 w = go_gtk_builder_get_widget (state->base.gui, "cum-button");
3306 data->cumulative = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
3307 w = go_gtk_builder_get_widget (state->base.gui, "only-num-button");
3308 data->only_numbers = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
3309
3310 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
3311 dao, data, analysis_tool_histogram_engine, TRUE))
3312 gtk_widget_destroy (state->base.dialog);
3313
3314 return;
3315 }
3316
3317 /**
3318 * histogram_tool_set_predetermined:
3319 * @widget:
3320 * @focus_widget:
3321 * @state:
3322 *
3323 * Output range entry was focused. Switch to output range.
3324 *
3325 **/
3326 static gboolean
histogram_tool_set_predetermined(G_GNUC_UNUSED GtkWidget * widget,G_GNUC_UNUSED GdkEventFocus * event,HistogramToolState * state)3327 histogram_tool_set_predetermined (G_GNUC_UNUSED GtkWidget *widget,
3328 G_GNUC_UNUSED GdkEventFocus *event,
3329 HistogramToolState *state)
3330 {
3331 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->predetermined_button), TRUE);
3332 return FALSE;
3333 }
3334
3335 /**
3336 * histogram_tool_set_calculated:
3337 * @widget:
3338 * @event:
3339 * @state:
3340 *
3341 **/
3342 static gboolean
histogram_tool_set_calculated(G_GNUC_UNUSED GtkWidget * widget,G_GNUC_UNUSED GdkEventFocus * event,HistogramToolState * state)3343 histogram_tool_set_calculated (G_GNUC_UNUSED GtkWidget *widget,
3344 G_GNUC_UNUSED GdkEventFocus *event,
3345 HistogramToolState *state)
3346 {
3347 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->calculated_button), TRUE);
3348 return FALSE;
3349 }
3350
3351 /**
3352 * dialog_histogram_tool:
3353 * @wbcg:
3354 * @sheet:
3355 *
3356 * Show the dialog (guru).
3357 *
3358 **/
3359 int
dialog_histogram_tool(WBCGtk * wbcg,Sheet * sheet)3360 dialog_histogram_tool (WBCGtk *wbcg, Sheet *sheet)
3361 {
3362 HistogramToolState *state;
3363 char const * plugins[] = {"Gnumeric_fnlogical",
3364 "Gnumeric_fnstat",
3365 "Gnumeric_fnlookup",
3366 NULL};
3367
3368 if ((wbcg == NULL) ||
3369 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
3370 return 1;
3371
3372 /* Only pop up one copy per workbook */
3373 if (gnm_dialog_raise_if_exists (wbcg, HISTOGRAM_KEY))
3374 return 0;
3375
3376 state = g_new0 (HistogramToolState, 1);
3377
3378 if (dialog_tool_init (&state->base, wbcg, sheet,
3379 GNUMERIC_HELP_LINK_HISTOGRAM,
3380 "res:ui/histogram.ui", "Histogram",
3381 _("Could not create the Histogram Tool dialog."),
3382 HISTOGRAM_KEY,
3383 G_CALLBACK (histogram_tool_ok_clicked_cb), NULL,
3384 G_CALLBACK (histogram_tool_update_sensitivity_cb),
3385 0))
3386 {
3387 g_free(state);
3388 return 0;
3389 }
3390
3391 state->predetermined_button = GTK_WIDGET (go_gtk_builder_get_widget
3392 (state->base.gui,
3393 "pre_determined_button"));
3394 state->calculated_button = GTK_WIDGET (go_gtk_builder_get_widget
3395 (state->base.gui,
3396 "calculated_button"));
3397 state->n_entry = GTK_ENTRY(go_gtk_builder_get_widget (state->base.gui,
3398 "n_entry"));
3399 state->max_entry = GTK_ENTRY(go_gtk_builder_get_widget (state->base.gui,
3400 "max_entry"));
3401 state->min_entry = GTK_ENTRY(go_gtk_builder_get_widget (state->base.gui,
3402 "min_entry"));
3403
3404 g_signal_connect_after (G_OBJECT (state->predetermined_button),
3405 "toggled",
3406 G_CALLBACK (histogram_tool_update_sensitivity_cb), state);
3407 g_signal_connect_after (G_OBJECT (state->calculated_button),
3408 "toggled",
3409 G_CALLBACK (histogram_tool_update_sensitivity_cb), state);
3410 g_signal_connect_after (G_OBJECT (state->n_entry),
3411 "changed",
3412 G_CALLBACK (histogram_tool_update_sensitivity_cb), state);
3413 g_signal_connect (G_OBJECT (state->n_entry),
3414 "key-press-event",
3415 G_CALLBACK (histogram_tool_set_calculated), state);
3416 g_signal_connect (G_OBJECT (state->min_entry),
3417 "key-press-event",
3418 G_CALLBACK (histogram_tool_set_calculated), state);
3419 g_signal_connect (G_OBJECT (state->max_entry),
3420 "key-press-event",
3421 G_CALLBACK (histogram_tool_set_calculated), state);
3422 g_signal_connect (G_OBJECT
3423 (gnm_expr_entry_get_entry (
3424 GNM_EXPR_ENTRY (state->base.input_entry_2))),
3425 "focus-in-event",
3426 G_CALLBACK (histogram_tool_set_predetermined), state);
3427
3428 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
3429 histogram_tool_update_sensitivity_cb (NULL, state);
3430 tool_load_selection ((GnmGenericToolState *)state, TRUE);
3431
3432 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->calculated_button), TRUE);
3433 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (go_gtk_builder_get_widget (state->base.gui,"histogram-button")), TRUE);
3434 gtk_entry_set_text (GTK_ENTRY (state->n_entry), "12");
3435
3436 return 0;
3437 }
3438
3439 /**********************************************/
3440 /* End of histogram tool code */
3441 /**********************************************/
3442
3443 /**********************************************/
3444 /* Begin of ANOVA (single factor) tool code */
3445 /**********************************************/
3446
3447
3448 /**
3449 * anova_single_tool_ok_clicked_cb:
3450 * @button:
3451 * @state:
3452 *
3453 * Retrieve the information from the dialog and call the fourier_tool.
3454 * Note that we assume that the ok_button is only active if the entry fields
3455 * contain sensible data.
3456 **/
3457 static void
anova_single_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,AnovaSingleToolState * state)3458 anova_single_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
3459 AnovaSingleToolState *state)
3460 {
3461 data_analysis_output_t *dao;
3462 GtkWidget *w;
3463 analysis_tools_data_anova_single_t *data;
3464
3465 data = g_new0 (analysis_tools_data_anova_single_t, 1);
3466 dao = parse_output ((GnmGenericToolState *)state, NULL);
3467
3468 data->base.input = gnm_expr_entry_parse_as_list (
3469 GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
3470 data->base.group_by = gnm_gui_group_value (state->base.gui, grouped_by_group);
3471
3472 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
3473 data->base.labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
3474 data->alpha = gtk_spin_button_get_value
3475 (GTK_SPIN_BUTTON (state->alpha_entry));
3476
3477 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg), state->base.sheet,
3478 dao, data, analysis_tool_anova_single_engine, TRUE))
3479 gtk_widget_destroy (state->base.dialog);
3480
3481 return;
3482 }
3483
3484 /**
3485 * anova_single_tool_update_sensitivity_cb:
3486 * @state:
3487 *
3488 * Update the dialog widgets sensitivity.
3489 * We cannot use tool_update_sensitivity_cb
3490 * since we are also considering whether in fact
3491 * an alpha is given.
3492 **/
3493 static void
anova_single_tool_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,AnovaSingleToolState * state)3494 anova_single_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
3495 AnovaSingleToolState *state)
3496 {
3497 gnm_float alpha;
3498 GSList *input_range;
3499
3500 input_range = gnm_expr_entry_parse_as_list (
3501 GNM_EXPR_ENTRY (state->base.input_entry),
3502 state->base.sheet);
3503 if (input_range == NULL) {
3504 gtk_label_set_text (GTK_LABEL (state->base.warning),
3505 _("The input range is invalid."));
3506 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3507 return;
3508 } else
3509 range_list_destroy (input_range);
3510
3511 /* Checking Alpha*/
3512 alpha = gtk_spin_button_get_value
3513 (GTK_SPIN_BUTTON (state->alpha_entry));
3514 if (!(alpha > 0 && alpha < 1)) {
3515 gtk_label_set_text (GTK_LABEL (state->base.warning),
3516 _("The alpha value should "
3517 "be a number between 0 and 1."));
3518 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3519 return;
3520 }
3521
3522 /* Checking Output Page */
3523 if (!gnm_dao_is_ready (GNM_DAO (state->base.gdao))) {
3524 gtk_label_set_text (GTK_LABEL (state->base.warning),
3525 _("The output specification "
3526 "is invalid."));
3527 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3528 return;
3529 }
3530
3531 gtk_label_set_text (GTK_LABEL (state->base.warning), "");
3532 gtk_widget_set_sensitive (state->base.ok_button, TRUE);
3533
3534 }
3535
3536
3537 /**
3538 * dialog_anova_single_tool:
3539 * @wbcg:
3540 * @sheet:
3541 *
3542 * Show the dialog (guru).
3543 *
3544 **/
3545 int
dialog_anova_single_factor_tool(WBCGtk * wbcg,Sheet * sheet)3546 dialog_anova_single_factor_tool (WBCGtk *wbcg, Sheet *sheet)
3547 {
3548 AnovaSingleToolState *state;
3549 char const * plugins[] = { "Gnumeric_fnstat",
3550 NULL};
3551
3552 if ((wbcg == NULL) ||
3553 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
3554 return 1;
3555
3556 /* Only pop up one copy per workbook */
3557 if (gnm_dialog_raise_if_exists (wbcg, ANOVA_SINGLE_KEY))
3558 return 0;
3559
3560 state = g_new0 (AnovaSingleToolState, 1);
3561
3562 if (dialog_tool_init (&state->base, wbcg, sheet,
3563 GNUMERIC_HELP_LINK_ANOVA_SINGLE_FACTOR,
3564 "res:ui/anova-one.ui", "ANOVA",
3565 _("Could not create the ANOVA (single factor) "
3566 "tool dialog."),
3567 ANOVA_SINGLE_KEY,
3568 G_CALLBACK (anova_single_tool_ok_clicked_cb),
3569 NULL,
3570 G_CALLBACK (anova_single_tool_update_sensitivity_cb),
3571 0))
3572 {
3573 g_free(state);
3574 return 0;
3575 }
3576
3577 state->alpha_entry = go_gtk_builder_get_widget (state->base.gui,
3578 "alpha-entry");
3579 float_to_entry (GTK_ENTRY (state->alpha_entry), 0.05);
3580 g_signal_connect_after (G_OBJECT (state->alpha_entry),
3581 "changed",
3582 G_CALLBACK (anova_single_tool_update_sensitivity_cb), state);
3583 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
3584 GTK_WIDGET (state->alpha_entry));
3585
3586 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
3587 anova_single_tool_update_sensitivity_cb (NULL, state);
3588 tool_load_selection ((GnmGenericToolState *)state, TRUE);
3589
3590 return 0;
3591 }
3592
3593 /**********************************************/
3594 /* End of ANOVA (Single Factor) tool code */
3595 /**********************************************/
3596
3597 /**********************************************/
3598 /* Begin of ANOVA (two factor) tool code */
3599 /**********************************************/
3600
3601
3602 /**
3603 * anova_two_factor_tool_ok_clicked_cb:
3604 * @button:
3605 * @state:
3606 *
3607 * Retrieve the information from the dialog and call the fourier_tool.
3608 * Note that we assume that the ok_button is only active if the entry fields
3609 * contain sensible data.
3610 **/
3611 static void
anova_two_factor_tool_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,AnovaTwoFactorToolState * state)3612 anova_two_factor_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
3613 AnovaTwoFactorToolState *state)
3614 {
3615 data_analysis_output_t *dao;
3616 GtkWidget *w;
3617 analysis_tools_data_anova_two_factor_t *data;
3618 char *text;
3619
3620 if (state->base.warning_dialog != NULL)
3621 gtk_widget_destroy (state->base.warning_dialog);
3622
3623 data = g_new0 (analysis_tools_data_anova_two_factor_t, 1);
3624 dao = parse_output ((GnmGenericToolState *)state, NULL);
3625
3626 data->input = gnm_expr_entry_parse_as_value
3627 (GNM_EXPR_ENTRY (state->base.input_entry),
3628 state->base.sheet);
3629 data->err = analysis_tools_noerr;
3630 data->wbc = GNM_WBC (state->base.wbcg);
3631
3632 w = go_gtk_builder_get_widget (state->base.gui, "labels_button");
3633 data->labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
3634
3635 data->alpha = gtk_spin_button_get_value
3636 (GTK_SPIN_BUTTON (state->alpha_entry));
3637 entry_to_int (GTK_ENTRY (state->replication_entry),
3638 &data->replication, TRUE);
3639
3640 if (cmd_analysis_tool (GNM_WBC (state->base.wbcg),
3641 state->base.sheet,
3642 dao, data, analysis_tool_anova_two_factor_engine, FALSE)) {
3643 switch (data->err) {
3644 case analysis_tools_missing_data:
3645 error_in_entry ((GnmGenericToolState *) state,
3646 GTK_WIDGET (state->base.input_entry),
3647 data->labels ? _("The given input range should contain at "
3648 "least two columns and two rows of data and the "
3649 "labels.") :
3650 _("The given input range should contain at "
3651 "least two columns and two rows of data."));
3652 break;
3653 case analysis_tools_too_few_cols:
3654 error_in_entry ((GnmGenericToolState *) state,
3655 GTK_WIDGET (state->base.input_entry),
3656 data->labels ? _("The given input range should contain at "
3657 "least two columns of data and the "
3658 "labels.") :
3659 _("The given input range should contain at "
3660 "least two columns of data."));
3661 break;
3662 case analysis_tools_too_few_rows:
3663 error_in_entry ((GnmGenericToolState *) state,
3664 GTK_WIDGET (state->base.input_entry),
3665 data->labels ? _("The given input range should contain at "
3666 "least two rows of data and the "
3667 "labels.") :
3668 _("The given input range should "
3669 "contain at least two rows of "
3670 "data."));
3671 break;
3672 case analysis_tools_replication_invalid:
3673 error_in_entry ((GnmGenericToolState *) state,
3674 GTK_WIDGET (state->base.input_entry),
3675 _("The number of data rows must be a "
3676 "multiple of the replication "
3677 "number."));
3678 break;
3679 default:
3680 text = g_strdup_printf (
3681 _("An unexpected error has occurred: %d."),
3682 data->err);
3683 error_in_entry ((GnmGenericToolState *) state,
3684 GTK_WIDGET (state->base.input_entry),
3685 text);
3686 g_free (text);
3687 break;
3688 }
3689 value_release (data->input);
3690 g_free (dao);
3691 g_free (data);
3692 } else
3693 gtk_widget_destroy (state->base.dialog);
3694
3695 return;
3696 }
3697
3698 /**
3699 * anova_two_factor_tool_update_sensitivity_cb:
3700 * @state:
3701 *
3702 * Update the dialog widgets sensitivity.
3703 * We cannot use tool_update_sensitivity_cb
3704 * since we are also considering whether in fact
3705 * an alpha and a replication is given.
3706 **/
3707 static void
anova_two_factor_tool_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,AnovaTwoFactorToolState * state)3708 anova_two_factor_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
3709 AnovaTwoFactorToolState *state)
3710 {
3711 int replication, err_replication;
3712 gnm_float alpha;
3713 GnmValue *input_range;
3714
3715 /* Checking Input Range */
3716 input_range = gnm_expr_entry_parse_as_value
3717 (GNM_EXPR_ENTRY (state->base.input_entry),
3718 state->base.sheet);
3719 if (input_range == NULL) {
3720 gtk_label_set_text (GTK_LABEL (state->base.warning),
3721 _("The input range is invalid."));
3722 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3723 return;
3724 } else
3725 value_release (input_range);
3726
3727 /* Checking Alpha*/
3728 alpha = gtk_spin_button_get_value
3729 (GTK_SPIN_BUTTON (state->alpha_entry));
3730 if (!(alpha > 0 && alpha < 1)) {
3731 gtk_label_set_text (GTK_LABEL (state->base.warning),
3732 _("The alpha value should "
3733 "be a number between 0 and 1."));
3734 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3735 return;
3736 }
3737
3738
3739 /* Checking Replication*/
3740 err_replication = entry_to_int (GTK_ENTRY (state->replication_entry),
3741 &replication, FALSE);
3742 if (!(err_replication == 0 && replication > 0)) {
3743 gtk_label_set_text (GTK_LABEL (state->base.warning),
3744 _("The number of rows per sample "
3745 "should be a positive integer."));
3746 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3747 return;
3748 }
3749
3750 /* Checking Output Page */
3751 if (!gnm_dao_is_ready (GNM_DAO (state->base.gdao))) {
3752 gtk_label_set_text (GTK_LABEL (state->base.warning),
3753 _("The output specification "
3754 "is invalid."));
3755 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
3756 return;
3757 }
3758
3759 gtk_label_set_text (GTK_LABEL (state->base.warning), "");
3760 gtk_widget_set_sensitive (state->base.ok_button, TRUE);
3761
3762 return;
3763 }
3764
3765 /**
3766 * dialog_anova_two_factor_tool:
3767 * @wbcg:
3768 * @sheet:
3769 *
3770 * Show the dialog (guru).
3771 *
3772 **/
3773 int
dialog_anova_two_factor_tool(WBCGtk * wbcg,Sheet * sheet)3774 dialog_anova_two_factor_tool (WBCGtk *wbcg, Sheet *sheet)
3775 {
3776 AnovaTwoFactorToolState *state;
3777 char const * plugins[] = { "Gnumeric_fnstat",
3778 "Gnumeric_fnlookup",
3779 "Gnumeric_fnmath",
3780 "Gnumeric_fninfo",
3781 "Gnumeric_fnlogical",
3782 NULL};
3783
3784 if ((wbcg == NULL) ||
3785 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
3786 return 1;
3787
3788 /* Only pop up one copy per workbook */
3789 if (gnm_dialog_raise_if_exists (wbcg, ANOVA_TWO_FACTOR_KEY))
3790 return 0;
3791
3792 state = g_new0 (AnovaTwoFactorToolState, 1);
3793
3794 if (dialog_tool_init (&state->base, wbcg, sheet,
3795 GNUMERIC_HELP_LINK_ANOVA_TWO_FACTOR,
3796 "res:ui/anova-two.ui", "ANOVA",
3797 _("Could not create the ANOVA (two factor) "
3798 "tool dialog."),
3799 ANOVA_TWO_FACTOR_KEY,
3800 G_CALLBACK (anova_two_factor_tool_ok_clicked_cb),
3801 NULL,
3802 G_CALLBACK (anova_two_factor_tool_update_sensitivity_cb),
3803 GNM_EE_SINGLE_RANGE))
3804 {
3805 g_free(state);
3806 return 0;
3807 }
3808
3809 state->alpha_entry = go_gtk_builder_get_widget (state->base.gui,
3810 "alpha-entry");
3811 float_to_entry (GTK_ENTRY(state->alpha_entry), 0.05);
3812 state->replication_entry = go_gtk_builder_get_widget (state->base.gui,
3813 "replication-entry");
3814 int_to_entry (GTK_ENTRY(state->replication_entry), 1);
3815
3816 g_signal_connect_after (G_OBJECT (state->alpha_entry),
3817 "changed",
3818 G_CALLBACK (anova_two_factor_tool_update_sensitivity_cb),
3819 state);
3820 g_signal_connect_after (G_OBJECT (state->replication_entry),
3821 "changed",
3822 G_CALLBACK (anova_two_factor_tool_update_sensitivity_cb),
3823 state);
3824 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
3825 GTK_WIDGET (state->alpha_entry));
3826 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
3827 GTK_WIDGET (state->replication_entry));
3828
3829 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
3830 anova_two_factor_tool_update_sensitivity_cb (NULL, state);
3831 tool_load_selection ((GnmGenericToolState *)state, FALSE);
3832
3833 return 0;
3834 }
3835
3836 /**********************************************/
3837 /* End of ANOVA (Two Factor) tool code */
3838 /**********************************************/
3839