1.12.42
[gnumeric.git] / src / dialogs / dialog-analysis-tool-kaplan-meier.c
blob2f36b55d321dd220d4e7e4c5918d1cc3c9c1f79b
1 /*
2 * dialog-analysis-tool-kaplan-meier.c:
4 * Authors:
5 * Andreas J. Guelzow <aguelzow@taliesin.ca>
7 * (C) Copyright 2008 by Andreas J. Guelzow <aguelzow@pyrshep.ca>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <https://www.gnu.org/licenses/>.
23 #include <gnumeric-config.h>
24 #include <glib/gi18n-lib.h>
25 #include <gnumeric.h>
26 #include <dialogs/dialogs.h>
27 #include <tools/analysis-kaplan-meier.h>
28 #include <tools/analysis-tools.h>
30 #include <workbook.h>
31 #include <workbook-control.h>
32 #include <wbc-gtk.h>
33 #include <workbook-view.h>
34 #include <gui-util.h>
35 #include <parse-util.h>
36 #include <gnm-format.h>
37 #include <dialogs/tool-dialogs.h>
38 #include <dialogs/dao-gui-utils.h>
39 #include <sheet.h>
40 #include <expr.h>
41 #include <number-match.h>
42 #include <ranges.h>
43 #include <selection.h>
44 #include <value.h>
45 #include <commands.h>
46 #include <dialogs/help.h>
48 #include <widgets/gnm-dao.h>
49 #include <widgets/gnm-expr-entry.h>
51 #include <string.h>
53 #define KAPLAN_MEIER_KEY "analysistools-kaplan-meier-dialog"
55 typedef struct {
56 GnmGenericToolState base;
57 GtkWidget *censorship_button;
58 GtkWidget *censor_spin_from;
59 GtkWidget *censor_spin_to;
60 GtkWidget *graph_button;
61 GtkWidget *logrank_button;
62 GtkWidget *tick_button;
63 GtkWidget *add_group_button;
64 GtkWidget *remove_group_button;
65 GtkWidget *std_error_button;
66 GtkWidget *groups_check;
67 GtkWidget *groups_grid;
68 GnmExprEntry *groups_input;
69 GtkTreeView *groups_treeview;
70 GtkListStore *groups_list;
71 } KaplanMeierToolState;
73 enum
75 GROUP_NAME,
76 GROUP_FROM,
77 GROUP_TO,
78 GROUP_ADJUSTMENT_FROM,
79 GROUP_ADJUSTMENT_TO,
80 GROUP_COLUMNS
84 /**
85 * kaplan_meier_tool_update_sensitivity_cb:
86 * @dummy:
87 * @state:
89 * Update the dialog widgets sensitivity
90 **/
91 static void
92 kaplan_meier_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
93 KaplanMeierToolState *state)
95 gboolean censorship;
96 gboolean groups;
97 GnmValue *input_range;
98 GnmValue *input_range_2 = NULL;
99 int height, width;
101 censorship = gtk_toggle_button_get_active (
102 GTK_TOGGLE_BUTTON (state->censorship_button));
103 groups = gtk_toggle_button_get_active (
104 GTK_TOGGLE_BUTTON (state->groups_check));
106 gtk_widget_set_sensitive (state->tick_button, censorship);
108 input_range = gnm_expr_entry_parse_as_value
109 (GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
110 if (input_range == NULL) {
111 gtk_label_set_text (GTK_LABEL (state->base.warning),
112 _("The time column is not valid."));
113 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
114 return;
117 height = input_range->v_range.cell.b.row - input_range->v_range.cell.a.row;
118 width = input_range->v_range.cell.b.col - input_range->v_range.cell.a.col;
120 value_release (input_range);
122 if (width != 0) {
123 gtk_label_set_text (GTK_LABEL (state->base.warning),
124 _("The time column should be part of a single column."));
125 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
126 return;
129 if (censorship) {
130 input_range_2 = gnm_expr_entry_parse_as_value
131 (GNM_EXPR_ENTRY (state->base.input_entry_2), state->base.sheet);
132 if (input_range_2 == NULL) {
133 gtk_label_set_text (GTK_LABEL (state->base.warning),
134 _("The censorship column is not valid."));
135 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
136 return;
139 if (input_range_2->v_range.cell.b.col != input_range_2->v_range.cell.a.col) {
140 gtk_label_set_text (GTK_LABEL (state->base.warning),
141 _("The censorship column should be part of a single column."));
142 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
143 value_release (input_range_2);
144 return;
146 if (input_range_2->v_range.cell.b.row - input_range_2->v_range.cell.a.row != height) {
147 gtk_label_set_text (GTK_LABEL (state->base.warning),
148 _("The censorship and time columns should have the same height."));
149 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
150 value_release (input_range_2);
151 return;
154 value_release (input_range_2);
157 if (groups) {
158 input_range_2 = gnm_expr_entry_parse_as_value
159 (GNM_EXPR_ENTRY (state->groups_input), state->base.sheet);
161 if (input_range_2 == NULL) {
162 gtk_label_set_text (GTK_LABEL (state->base.warning),
163 _("The groups column is not valid."));
164 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
165 return;
167 if (input_range_2->v_range.cell.b.col != input_range_2->v_range.cell.a.col) {
168 gtk_label_set_text (GTK_LABEL (state->base.warning),
169 _("The groups column should be part of a single column."));
170 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
171 value_release (input_range_2);
172 return;
174 if (input_range_2->v_range.cell.b.row - input_range_2->v_range.cell.a.row != height) {
175 gtk_label_set_text (GTK_LABEL (state->base.warning),
176 _("The groups and time columns should have the same height."));
177 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
178 value_release (input_range_2);
179 return;
182 value_release (input_range_2);
185 if (!gnm_dao_is_ready (GNM_DAO (state->base.gdao))) {
186 gtk_label_set_text (GTK_LABEL (state->base.warning),
187 _("The output specification "
188 "is invalid."));
189 gtk_widget_set_sensitive (state->base.ok_button, FALSE);
190 return;
193 gtk_label_set_text (GTK_LABEL (state->base.warning), "");
194 gtk_widget_set_sensitive (state->base.ok_button, TRUE);
196 return;
199 static gboolean
200 kaplan_meier_tool_get_groups_cb (GtkTreeModel *model,
201 G_GNUC_UNUSED GtkTreePath *path,
202 GtkTreeIter *iter,
203 gpointer data)
205 GSList **list = data;
206 analysis_tools_kaplan_meier_group_t *group_item =
207 g_new0 (analysis_tools_kaplan_meier_group_t, 1);
209 gtk_tree_model_get (model, iter,
210 GROUP_NAME, &(group_item->name),
211 GROUP_FROM, &(group_item->group_from),
212 GROUP_TO, &(group_item->group_to),
213 -1);
214 *list = g_slist_prepend (*list, group_item);
216 return FALSE;
219 static GSList *
220 kaplan_meier_tool_get_groups (KaplanMeierToolState *state)
222 GSList *list = NULL;
224 if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->groups_check)))
225 return NULL;
227 gtk_tree_model_foreach (GTK_TREE_MODEL (state->groups_list),
228 kaplan_meier_tool_get_groups_cb,
229 &list);
230 return g_slist_reverse (list);
234 * kaplan_meier_tool_ok_clicked_cb:
235 * @button:
236 * @state:
238 * Retrieve the information from the dialog and call the kaplan_meier_tool.
239 * Note that we assume that the ok_button is only active if the entry fields
240 * contain sensible data.
242 static void
243 kaplan_meier_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
244 KaplanMeierToolState *state)
246 data_analysis_output_t *dao;
247 analysis_tools_data_kaplan_meier_t *data;
249 data = g_new0 (analysis_tools_data_kaplan_meier_t, 1);
250 dao = parse_output ((GnmGenericToolState *)state, NULL);
253 data->base.wbc = GNM_WBC (state->base.wbcg);
255 if (state->base.warning_dialog != NULL)
256 gtk_widget_destroy (state->base.warning_dialog);
258 data->base.range_1 = gnm_expr_entry_parse_as_value
259 (GNM_EXPR_ENTRY (state->base.input_entry), state->base.sheet);
261 data->censored = gtk_toggle_button_get_active (
262 GTK_TOGGLE_BUTTON (state->censorship_button));
264 if (data->censored)
265 data->base.range_2 = gnm_expr_entry_parse_as_value
266 (GNM_EXPR_ENTRY (state->base.input_entry_2), state->base.sheet);
267 else
268 data->base.range_2 = NULL;
270 data->censor_mark = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (state->censor_spin_from));
271 data->censor_mark_to = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (state->censor_spin_to));
273 data->group_list = kaplan_meier_tool_get_groups (state);
274 if (data->group_list == NULL) {
275 data->range_3 = NULL;
276 data->logrank_test = FALSE;
277 } else {
278 data->range_3 = gnm_expr_entry_parse_as_value
279 (GNM_EXPR_ENTRY (state->groups_input), state->base.sheet);
280 data->logrank_test = gtk_toggle_button_get_active (
281 GTK_TOGGLE_BUTTON (state->logrank_button));
284 data->median = gtk_toggle_button_get_active (
285 GTK_TOGGLE_BUTTON (go_gtk_builder_get_widget
286 (state->base.gui,
287 "median-button")));
288 data->chart = gtk_toggle_button_get_active (
289 GTK_TOGGLE_BUTTON (state->graph_button));
290 data->ticks = gtk_toggle_button_get_active (
291 GTK_TOGGLE_BUTTON (state->tick_button));
292 data->std_err = gtk_toggle_button_get_active (
293 GTK_TOGGLE_BUTTON (state->std_error_button));
295 if (!cmd_analysis_tool (GNM_WBC (state->base.wbcg),
296 state->base.sheet,
297 dao, data, analysis_tool_kaplan_meier_engine,
298 TRUE))
299 gtk_widget_destroy (state->base.dialog);
301 return;
305 * kaplan_meier_tool_set_graph:
306 * @widget:
307 * @focus_widget:
308 * @state:
312 static gboolean
313 kaplan_meier_tool_set_graph_cb (G_GNUC_UNUSED GtkWidget *dummy,
314 KaplanMeierToolState *state)
316 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->graph_button), TRUE);
317 kaplan_meier_tool_update_sensitivity_cb (NULL, state);
318 return FALSE;
322 * kaplan_meier_tool_set_censorship:
323 * @widget:
324 * @event:
325 * @state:
328 static gboolean
329 kaplan_meier_tool_set_censorship_cb (G_GNUC_UNUSED GtkWidget *widget,
330 G_GNUC_UNUSED GdkEventFocus *event,
331 KaplanMeierToolState *state)
333 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->censorship_button), TRUE);
334 return FALSE;
337 static gboolean
338 kaplan_meier_tool_set_groups_cb (G_GNUC_UNUSED GtkWidget *widget,
339 G_GNUC_UNUSED GdkEventFocus *event,
340 KaplanMeierToolState *state)
342 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->groups_check), TRUE);
343 return FALSE;
347 static gboolean
348 kaplan_meier_tool_set_censor_from_cb (G_GNUC_UNUSED GtkWidget *dummy,
349 KaplanMeierToolState *state)
351 gtk_spin_button_set_range (GTK_SPIN_BUTTON (state->censor_spin_to),
352 gtk_spin_button_get_value (GTK_SPIN_BUTTON (state->censor_spin_from)),G_MAXSHORT);
353 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->censorship_button), TRUE);
355 return FALSE;
357 static gboolean
358 kaplan_meier_tool_set_censor_cb (G_GNUC_UNUSED GtkWidget *dummy,
359 KaplanMeierToolState *state)
361 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->censorship_button), TRUE);
363 return FALSE;
366 static void
367 cb_group_name_edited (GtkCellRendererText *cell,
368 gchar *path_string,
369 gchar *new_text,
370 KaplanMeierToolState *state)
372 GtkTreeIter iter;
373 GtkTreePath *path;
375 if (cell != NULL) {
376 path = gtk_tree_path_new_from_string (path_string);
377 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (state->groups_list),
378 &iter, path))
379 gtk_list_store_set (state->groups_list, &iter,
380 GROUP_NAME, new_text, -1);
381 else
382 g_warning ("Did not get a valid iterator");
383 gtk_tree_path_free (path);
387 static void
388 cb_change_to (GtkCellRendererText *cell,
389 gchar *path_string,
390 gchar *new_text,
391 KaplanMeierToolState *state)
393 GtkTreeIter iter;
394 GtkTreePath *path;
395 guint val = (guint) (atoi (new_text));
397 if (cell != NULL) {
398 path = gtk_tree_path_new_from_string (path_string);
399 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (state->groups_list),
400 &iter, path))
401 gtk_list_store_set (state->groups_list, &iter,
402 GROUP_TO, val, -1);
403 else
404 g_warning ("Did not get a valid iterator");
405 gtk_tree_path_free (path);
409 static void
410 cb_change_from (GtkCellRendererText *cell,
411 gchar *path_string,
412 gchar *new_text,
413 KaplanMeierToolState *state)
415 if (cell != NULL) {
416 GtkTreeIter iter;
417 GtkTreePath *path;
418 guint val = (guint) (atoi (new_text));
419 guint old_to;
420 GObject *adjustment_to;
423 path = gtk_tree_path_new_from_string (path_string);
424 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (state->groups_list),
425 &iter, path))
426 gtk_list_store_set (state->groups_list, &iter,
427 GROUP_FROM, val,
428 -1);
429 else
430 g_warning ("Did not get a valid iterator");
431 gtk_tree_path_free (path);
433 gtk_tree_model_get (GTK_TREE_MODEL (state->groups_list), &iter,
434 GROUP_TO, &old_to,
435 GROUP_ADJUSTMENT_TO, &adjustment_to,
436 -1);
438 if (old_to < val)
439 gtk_list_store_set (state->groups_list, &iter,
440 GROUP_TO, val,
441 -1);
442 g_object_set (adjustment_to, "lower", (gdouble) val, NULL);
447 static void
448 cb_selection_changed (GtkTreeSelection *selection,
449 KaplanMeierToolState *state)
451 gtk_widget_set_sensitive (state->remove_group_button,
452 gtk_tree_selection_get_selected (selection, NULL, NULL));
455 static void
456 kaplan_meier_tool_update_groups_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
457 KaplanMeierToolState *state)
459 gboolean groups = gtk_toggle_button_get_active (
460 GTK_TOGGLE_BUTTON (state->groups_check));
461 GtkTreeSelection *selection = gtk_tree_view_get_selection (state->groups_treeview);
463 gtk_widget_set_sensitive (state->add_group_button, groups);
464 gtk_widget_set_sensitive (GTK_WIDGET (state->groups_treeview), groups);
466 if (groups) {
467 cb_selection_changed (selection, state);
468 gtk_widget_set_sensitive (state->logrank_button, TRUE);
469 } else {
470 gtk_tree_selection_unselect_all (selection);
471 gtk_widget_set_sensitive (state->remove_group_button, FALSE);
472 gtk_widget_set_sensitive (state->logrank_button, FALSE);
476 static void
477 dialog_kaplan_meier_tool_treeview_add_item (KaplanMeierToolState *state, guint i)
479 GtkTreeIter iter;
480 char * name = g_strdup_printf (_("Group %d"), i);
481 GObject *adjustment_to =
482 G_OBJECT (gtk_adjustment_new (0, 0, G_MAXUSHORT, 1, 1, 1));
483 GObject *adjustment_from =
484 G_OBJECT (gtk_adjustment_new (0, 0, G_MAXUSHORT, 1, 1, 1));
485 gtk_list_store_append (state->groups_list, &iter);
486 gtk_list_store_set (state->groups_list, &iter,
487 GROUP_NAME, name,
488 GROUP_FROM, (guint) i,
489 GROUP_TO, (guint) i,
490 GROUP_ADJUSTMENT_FROM, adjustment_from,
491 GROUP_ADJUSTMENT_TO, adjustment_to,
492 -1);
493 g_free (name);
496 static void
497 dialog_kaplan_meier_tool_setup_treeview (KaplanMeierToolState *state)
499 guint i;
500 GtkCellRenderer *renderer;
501 GtkWidget *scrolled = go_gtk_builder_get_widget (state->base.gui, "groups-scrolled");
502 GtkTreeSelection *selection;
504 state->groups_treeview = GTK_TREE_VIEW (go_gtk_builder_get_widget
505 (state->base.gui,
506 "groups-tree"));
507 state->groups_list = gtk_list_store_new (GROUP_COLUMNS,
508 G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_OBJECT);
509 state->groups_treeview = GTK_TREE_VIEW (gtk_tree_view_new_with_model
510 (GTK_TREE_MODEL (state->groups_list)));
511 g_object_unref (state->groups_list);
512 selection = gtk_tree_view_get_selection (state->groups_treeview);
513 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
515 for (i = 0; i<2; i++)
516 dialog_kaplan_meier_tool_treeview_add_item (state, i);
518 g_signal_connect (selection,
519 "changed",
520 G_CALLBACK (cb_selection_changed), state);
522 renderer = gtk_cell_renderer_text_new ();
523 g_object_set (G_OBJECT (renderer),
524 "editable", TRUE,
525 NULL);
526 gtk_tree_view_insert_column_with_attributes (state->groups_treeview,
527 -1, _("Group"),
528 renderer,
529 "text", GROUP_NAME,
530 NULL);
531 g_signal_connect (G_OBJECT (renderer), "edited",
532 G_CALLBACK (cb_group_name_edited), state);
534 renderer = gtk_cell_renderer_spin_new ();
536 g_object_set (G_OBJECT (renderer), "editable", TRUE, "xalign", 1.0,
537 "digits", 0, NULL);
538 g_signal_connect (G_OBJECT (renderer), "edited",
539 G_CALLBACK (cb_change_from), state);
540 gtk_tree_view_insert_column_with_attributes (state->groups_treeview,
541 -1, _("From"),
542 renderer,
543 "text", GROUP_FROM,
544 "adjustment", GROUP_ADJUSTMENT_FROM,
545 NULL);
547 renderer = gtk_cell_renderer_spin_new ();
548 g_object_set (G_OBJECT (renderer), "editable", TRUE, "xalign", 1.0,
549 "digits", 0, NULL);
550 g_signal_connect (G_OBJECT (renderer), "edited",
551 G_CALLBACK (cb_change_to), state);
552 gtk_tree_view_insert_column_with_attributes (state->groups_treeview,
553 -1, _("To"),
554 renderer,
555 "text", GROUP_TO,
556 "adjustment", GROUP_ADJUSTMENT_TO,
557 NULL);
559 gtk_container_add (GTK_CONTAINER (scrolled), GTK_WIDGET (state->groups_treeview));
561 cb_selection_changed (selection, state);
564 static gboolean
565 kaplan_meier_tool_add_group_cb (G_GNUC_UNUSED GtkWidget *dummy,
566 KaplanMeierToolState *state)
568 dialog_kaplan_meier_tool_treeview_add_item
569 (state, gtk_tree_model_iter_n_children (GTK_TREE_MODEL (state->groups_list),
570 NULL));
571 return FALSE;
574 static gboolean
575 kaplan_meier_tool_remove_group_cb (G_GNUC_UNUSED GtkWidget *dummy,
576 KaplanMeierToolState *state)
578 GtkTreeSelection *selection;
579 GtkTreeIter iter;
581 selection = gtk_tree_view_get_selection (state->groups_treeview);
583 if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
584 gtk_list_store_remove ( state->groups_list, &iter);
587 return FALSE;
592 * dialog_kaplan_meier_tool:
593 * @wbcg:
594 * @sheet:
596 * Show the dialog (guru).
600 dialog_kaplan_meier_tool (WBCGtk *wbcg, Sheet *sheet)
602 KaplanMeierToolState *state;
603 GtkWidget *widget;
604 char const * plugins[] = { "Gnumeric_fnstat",
605 "Gnumeric_fnlookup",
606 "Gnumeric_fnmath",
607 "Gnumeric_fninfo",
608 "Gnumeric_fnlogical",
609 NULL};
611 if ((wbcg == NULL) ||
612 gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
613 return 1;
615 /* Only pop up one copy per workbook */
616 if (gnm_dialog_raise_if_exists (wbcg, KAPLAN_MEIER_KEY))
617 return 0;
619 state = g_new0 (KaplanMeierToolState, 1);
621 if (dialog_tool_init (&state->base, wbcg, sheet,
622 GNUMERIC_HELP_LINK_KAPLAN_MEIER,
623 "res:ui/kaplan-meier.ui", "KaplanMeier",
624 _("Could not create the Kaplan Meier Tool dialog."),
625 KAPLAN_MEIER_KEY,
626 G_CALLBACK (kaplan_meier_tool_ok_clicked_cb), NULL,
627 G_CALLBACK (kaplan_meier_tool_update_sensitivity_cb),
630 g_free(state);
631 return 0;
636 state->censorship_button = GTK_WIDGET (go_gtk_builder_get_widget
637 (state->base.gui,
638 "censor-button"));
639 state->censor_spin_from = GTK_WIDGET (go_gtk_builder_get_widget
640 (state->base.gui,
641 "censored-spinbutton1"));
642 gtk_spin_button_set_range (GTK_SPIN_BUTTON (state->censor_spin_from), 0.,G_MAXSHORT);
643 state->censor_spin_to = GTK_WIDGET (go_gtk_builder_get_widget
644 (state->base.gui,
645 "censored-spinbutton2"));
646 gtk_spin_button_set_range (GTK_SPIN_BUTTON (state->censor_spin_to), 0.,G_MAXSHORT);
647 state->graph_button = GTK_WIDGET (go_gtk_builder_get_widget
648 (state->base.gui,
649 "graph-button"));
650 state->tick_button = GTK_WIDGET (go_gtk_builder_get_widget
651 (state->base.gui,
652 "tick-button"));
653 state->add_group_button = GTK_WIDGET (go_gtk_builder_get_widget
654 (state->base.gui,
655 "add-button"));
656 state->remove_group_button = GTK_WIDGET (go_gtk_builder_get_widget
657 (state->base.gui,
658 "remove-button"));
659 state->std_error_button = GTK_WIDGET (go_gtk_builder_get_widget
660 (state->base.gui,
661 "std-error-button"));
662 state->logrank_button = GTK_WIDGET (go_gtk_builder_get_widget
663 (state->base.gui,
664 "logrank-button"));
666 state->groups_check = GTK_WIDGET (go_gtk_builder_get_widget
667 (state->base.gui,
668 "groups-check"));
669 state->groups_grid = GTK_WIDGET (go_gtk_builder_get_widget
670 (state->base.gui,
671 "groups-grid"));
672 state->groups_input = gnm_expr_entry_new (state->base.wbcg, TRUE);
673 gnm_expr_entry_set_flags (state->groups_input, GNM_EE_FORCE_ABS_REF,
674 GNM_EE_MASK);
675 gtk_grid_attach (GTK_GRID (state->groups_grid),
676 GTK_WIDGET (state->groups_input), 1, 1, 2, 1);
678 dialog_kaplan_meier_tool_setup_treeview (state);
680 g_signal_connect_after (G_OBJECT (state->groups_check),
681 "toggled",
682 G_CALLBACK (kaplan_meier_tool_update_sensitivity_cb), state);
683 g_signal_connect_after (G_OBJECT (state->censorship_button),
684 "toggled",
685 G_CALLBACK (kaplan_meier_tool_update_sensitivity_cb), state);
686 g_signal_connect_after (G_OBJECT (state->graph_button),
687 "toggled",
688 G_CALLBACK (kaplan_meier_tool_update_sensitivity_cb), state);
689 g_signal_connect_after (G_OBJECT (state->std_error_button),
690 "toggled",
691 G_CALLBACK (kaplan_meier_tool_update_sensitivity_cb), state);
692 g_signal_connect_after (G_OBJECT (state->groups_input),
693 "changed",
694 G_CALLBACK (kaplan_meier_tool_update_sensitivity_cb),
695 state);
697 g_signal_connect_after (G_OBJECT (state->groups_check),
698 "toggled",
699 G_CALLBACK (kaplan_meier_tool_update_groups_sensitivity_cb), state);
700 g_signal_connect_after (G_OBJECT (state->tick_button),
701 "toggled",
702 G_CALLBACK (kaplan_meier_tool_set_graph_cb), state);
703 g_signal_connect_after (G_OBJECT (state->add_group_button),
704 "clicked",
705 G_CALLBACK (kaplan_meier_tool_add_group_cb), state);
706 g_signal_connect_after (G_OBJECT (state->remove_group_button),
707 "clicked",
708 G_CALLBACK (kaplan_meier_tool_remove_group_cb), state);
709 g_signal_connect_after (G_OBJECT (state->censor_spin_from),
710 "value-changed",
711 G_CALLBACK (kaplan_meier_tool_set_censor_from_cb), state);
712 g_signal_connect_after (G_OBJECT (state->censor_spin_to),
713 "value-changed",
714 G_CALLBACK (kaplan_meier_tool_set_censor_cb), state);
715 g_signal_connect (G_OBJECT
716 (gnm_expr_entry_get_entry (
717 GNM_EXPR_ENTRY (state->base.input_entry_2))),
718 "focus-in-event",
719 G_CALLBACK (kaplan_meier_tool_set_censorship_cb), state);
720 g_signal_connect (G_OBJECT
721 (gnm_expr_entry_get_entry (
722 GNM_EXPR_ENTRY (state->groups_input))),
723 "focus-in-event",
724 G_CALLBACK (kaplan_meier_tool_set_groups_cb), state);
726 gnm_editable_enters (GTK_WINDOW (state->base.dialog),
727 GTK_WIDGET (state->groups_input));
729 widget = go_gtk_builder_get_widget (state->base.gui, "groups-label");
730 gtk_label_set_mnemonic_widget (GTK_LABEL (widget),
731 GTK_WIDGET (state->groups_input));
732 go_atk_setup_label (widget, GTK_WIDGET (state->groups_input));
734 gnm_dao_set_put (GNM_DAO (state->base.gdao), TRUE, TRUE);
735 kaplan_meier_tool_update_sensitivity_cb (NULL, state);
736 kaplan_meier_tool_update_groups_sensitivity_cb (NULL, state);
737 tool_load_selection ((GnmGenericToolState *)state, TRUE);
739 gtk_widget_show_all (GTK_WIDGET (state->base.dialog));
740 /* And to hide the in-place button again */
741 gnm_dao_set_inplace ( GNM_DAO (state->base.gdao), NULL);
743 return 0;