1 /*
2  * dialog-advanced-filter.c:
3  *
4  * Authors:
5  *        Jukka-Pekka Iivonen <iivonen@iki.fi>
6  *        Andreas J. Guelzow <aguelzow@taliesin.ca>
7  *
8  * (C) Copyright 2000, 2001 by Jukka-Pekka Iivonen <jiivonen@hutcs.cs.hut.fi>
9  * (C) Copyright 2002 by Andreas J. Guelzow <aguelzow@taliesin.ca>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, see <https://www.gnu.org/licenses/>.
23  **/
24 #include <gnumeric-config.h>
25 #include <glib/gi18n-lib.h>
26 #include <gnumeric.h>
27 #include <dialogs/dialogs.h>
28 #include <dialogs/help.h>
29 
30 #include <sheet.h>
31 #include <cell.h>
32 #include <ranges.h>
33 #include <gui-util.h>
34 #include <dialogs/tool-dialogs.h>
35 #include <dialogs/dao-gui-utils.h>
36 #include <value.h>
37 #include <wbc-gtk.h>
38 
39 #include <widgets/gnm-expr-entry.h>
40 #include <widgets/gnm-dao.h>
41 #include <tools/filter.h>
42 #include <tools/analysis-tools.h>
43 #include <commands.h>
44 
45 
46 #define ADVANCED_FILTER_KEY         "advanced-filter-dialog"
47 
48 typedef GnmGenericToolState AdvancedFilterState;
49 
50 /**
51  * advanced_filter_update_sensitivity_cb:
52  * @dummy:
53  * @state:
54  *
55  * Update the dialog widgets sensitivity
56  **/
57 static void
advanced_filter_update_sensitivity_cb(G_GNUC_UNUSED GtkWidget * dummy,AdvancedFilterState * state)58 advanced_filter_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
59 				       AdvancedFilterState *state)
60 {
61         GnmValue *input_range    = NULL;
62         GnmValue *criteria_range = NULL;
63 
64         input_range = gnm_expr_entry_parse_as_value (
65 		GNM_EXPR_ENTRY (state->input_entry), state->sheet);
66 	if (input_range == NULL) {
67 		gtk_label_set_text (GTK_LABEL (state->warning),
68 				    _("The list range is invalid."));
69 		gtk_widget_set_sensitive (state->ok_button, FALSE);
70 		return;
71 	} else
72 		value_release (input_range);
73 
74 	criteria_range =  gnm_expr_entry_parse_as_value
75 		(state->input_entry_2, state->sheet);
76 	if (criteria_range == NULL) {
77 		gtk_label_set_text (GTK_LABEL (state->warning),
78 				    _("The criteria range is invalid."));
79 		gtk_widget_set_sensitive (state->ok_button, FALSE);
80 		return;
81 	} else
82 		value_release (criteria_range);
83 
84 	if (!gnm_dao_is_ready (GNM_DAO (state->gdao))) {
85 		gtk_label_set_text (GTK_LABEL (state->warning),
86 				    _("The output range is invalid."));
87 		gtk_widget_set_sensitive (state->ok_button, FALSE);
88 		return;
89 	}
90 
91 	gtk_label_set_text (GTK_LABEL (state->warning), "");
92 	gtk_widget_set_sensitive (state->ok_button, TRUE);
93 	return;
94 }
95 
96 /**
97  * advanced_filter_ok_clicked_cb:
98  * @button:
99  * @state:
100  *
101  * Retrieve the information from the dialog and call the advanced_filter.
102  * Note that we assume that the ok_button is only active if the entry fields
103  * contain sensible data.
104  **/
105 static void
advanced_filter_ok_clicked_cb(G_GNUC_UNUSED GtkWidget * button,AdvancedFilterState * state)106 advanced_filter_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
107 			       AdvancedFilterState *state)
108 {
109 	data_analysis_output_t  *dao;
110 	GnmValue                   *input;
111 	GnmValue                   *criteria;
112 	char                    *text;
113 	GtkWidget               *w;
114 	int                     err = 0;
115 	gboolean                unique;
116 
117 	input = gnm_expr_entry_parse_as_value (
118 		GNM_EXPR_ENTRY (state->input_entry), state->sheet);
119 
120 	criteria = gnm_expr_entry_parse_as_value
121 		(state->input_entry_2, state->sheet);
122 
123         dao  = parse_output ((GnmGenericToolState *) state, NULL);
124 
125 	w = go_gtk_builder_get_widget (state->gui, "unique-button");
126 	unique = (1 == gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
127 
128 	if (dao->type == InPlaceOutput)
129 		err = advanced_filter (GNM_WBC (state->wbcg),
130 				       dao, input, criteria, unique);
131 	else {
132 		analysis_tools_data_advanced_filter_t  *
133 			data = g_new0 (analysis_tools_data_advanced_filter_t, 1);
134 		data->base.wbc = GNM_WBC (state->wbcg);
135 		data->base.range_1 = input;
136 		data->base.range_2 = criteria;
137 		data->unique_only_flag = unique;
138 
139 		if (cmd_analysis_tool (GNM_WBC (state->wbcg), state->sheet,
140 				       dao, data, analysis_tool_advanced_filter_engine, FALSE)) {
141 			err = data->base.err;
142 			g_free (data);
143 		} else
144 			err = analysis_tools_noerr;
145 
146 	}
147 
148 	if (dao->type == InPlaceOutput || err != analysis_tools_noerr) {
149 		value_release (input);
150 		value_release (criteria);
151 		g_free (dao);
152 	}
153 
154 	switch (err) {
155 	case analysis_tools_noerr:
156 		gtk_widget_destroy (state->dialog);
157 		break;
158 	case analysis_tools_invalid_field:
159 		error_in_entry ((GnmGenericToolState *) state,
160 				GTK_WIDGET (state->input_entry_2),
161 				_("The given criteria are invalid."));
162 		break;
163 	case analysis_tools_no_records_found:
164 		go_gtk_notice_nonmodal_dialog ((GtkWindow *) state->dialog,
165 					  &(state->warning_dialog),
166 					  GTK_MESSAGE_INFO,
167 					  _("No matching records were found."));
168 		break;
169 	default:
170 		text = g_strdup_printf (_("An unexpected error has occurred: "
171 					  "%d."), err);
172 		error_in_entry ((GnmGenericToolState *) state,
173 				GTK_WIDGET (state->input_entry), text);
174 		g_free (text);
175 		break;
176 	}
177 	return;
178 }
179 
180 /**
181  * dialog_advanced_filter:
182  * @wbcg:
183  *
184  * Show the dialog (guru).
185  **/
186 void
dialog_advanced_filter(WBCGtk * wbcg)187 dialog_advanced_filter (WBCGtk *wbcg)
188 {
189         AdvancedFilterState *state;
190 	WorkbookControl *wbc;
191 
192 	g_return_if_fail (wbcg != NULL);
193 
194 	wbc = GNM_WBC (wbcg);
195 
196 	/* Only pop up one copy per workbook */
197 	if (gnm_dialog_raise_if_exists (wbcg, ADVANCED_FILTER_KEY))
198 		return;
199 
200 	state = g_new (AdvancedFilterState, 1);
201 
202 	if (dialog_tool_init (state, wbcg, wb_control_cur_sheet (wbc),
203 			      GNUMERIC_HELP_LINK_ADVANCED_FILTER,
204 			      "res:ui/advanced-filter.ui", "Filter",
205 			      _("Could not create the Advanced Filter dialog."),
206 			      ADVANCED_FILTER_KEY,
207 			      G_CALLBACK (advanced_filter_ok_clicked_cb), NULL,
208 			      G_CALLBACK (advanced_filter_update_sensitivity_cb),
209 			      0))
210 		return;
211 
212 	gnm_dao_set_inplace (GNM_DAO (state->gdao), _("Filter _in-place"));
213 	gnm_dao_set_put (GNM_DAO (state->gdao), FALSE, FALSE);
214 	advanced_filter_update_sensitivity_cb (NULL, state);
215 	tool_load_selection ((GnmGenericToolState *)state, TRUE);
216 
217         return;
218 }
219