1 /*
2 * Copyright (C) 2002 Derek Atkins
3 *
4 * Authors: Derek Atkins <warlord@MIT.EDU>
5 *
6 * Copyright (c) 2006 David Hampton <hampton@employees.org>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <gtk/gtk.h>
29 #include <glib/gi18n.h>
30
31 #include "gnc-amount-edit.h"
32 #include "qof.h"
33 #include "gnc-gui-query.h"
34
35 #include "search-numeric.h"
36 #include "search-core-utils.h"
37
38 #define d(x)
39
40 static void pass_parent (GNCSearchCoreType *fe, gpointer parent);
41 static void editable_enters (GNCSearchCoreType *fe);
42 static void grab_focus (GNCSearchCoreType *fe);
43 static GNCSearchCoreType *gncs_clone(GNCSearchCoreType *fe);
44 static gboolean gncs_validate (GNCSearchCoreType *fe);
45 static GtkWidget *gncs_get_widget(GNCSearchCoreType *fe);
46 static QofQueryPredData* gncs_get_predicate (GNCSearchCoreType *fe);
47
48 static void gnc_search_numeric_class_init (GNCSearchNumericClass *klass);
49 static void gnc_search_numeric_init (GNCSearchNumeric *gspaper);
50 static void gnc_search_numeric_finalize (GObject *obj);
51
52 typedef struct _GNCSearchNumericPrivate GNCSearchNumericPrivate;
53
54 struct _GNCSearchNumericPrivate
55 {
56 gboolean is_debcred;
57 GtkWidget * entry;
58 GNCAmountEdit *gae;
59 GtkWindow *parent;
60 };
61
G_DEFINE_TYPE_WITH_PRIVATE(GNCSearchNumeric,gnc_search_numeric,GNC_TYPE_SEARCH_CORE_TYPE)62 G_DEFINE_TYPE_WITH_PRIVATE(GNCSearchNumeric, gnc_search_numeric, GNC_TYPE_SEARCH_CORE_TYPE)
63
64 #define _PRIVATE(o) \
65 ((GNCSearchNumericPrivate*)g_type_instance_get_private((GTypeInstance*)o, GNC_TYPE_SEARCH_NUMERIC))
66
67 static GNCSearchCoreTypeClass *parent_class;
68
69 static void
70 gnc_search_numeric_class_init (GNCSearchNumericClass *klass)
71 {
72 GObjectClass *object_class;
73 GNCSearchCoreTypeClass *gnc_search_core_type = (GNCSearchCoreTypeClass *)klass;
74
75 object_class = G_OBJECT_CLASS (klass);
76 parent_class = g_type_class_peek_parent (klass);
77
78 object_class->finalize = gnc_search_numeric_finalize;
79
80 /* override methods */
81 gnc_search_core_type->pass_parent = pass_parent;
82 gnc_search_core_type->editable_enters = editable_enters;
83 gnc_search_core_type->grab_focus = grab_focus;
84 gnc_search_core_type->validate = gncs_validate;
85 gnc_search_core_type->get_widget = gncs_get_widget;
86 gnc_search_core_type->get_predicate = gncs_get_predicate;
87 gnc_search_core_type->clone = gncs_clone;
88 }
89
90 static void
gnc_search_numeric_init(GNCSearchNumeric * o)91 gnc_search_numeric_init (GNCSearchNumeric *o)
92 {
93 o->value = gnc_numeric_zero ();
94 o->how = QOF_COMPARE_EQUAL;
95 o->option = QOF_NUMERIC_MATCH_ANY;
96 }
97
98 static void
gnc_search_numeric_finalize(GObject * obj)99 gnc_search_numeric_finalize (GObject *obj)
100 {
101 GNCSearchNumeric *o = (GNCSearchNumeric *)obj;
102 g_assert (IS_GNCSEARCH_NUMERIC (o));
103
104 G_OBJECT_CLASS (parent_class)->finalize(obj);
105 }
106
107 /**
108 * gnc_search_numeric_new:
109 *
110 * Create a new GNCSearchNumeric object.
111 *
112 * Return value: A new #GNCSearchNumeric object.
113 **/
114 GNCSearchNumeric *
gnc_search_numeric_new(void)115 gnc_search_numeric_new (void)
116 {
117 GNCSearchNumeric *o = g_object_new(GNC_TYPE_SEARCH_NUMERIC, NULL);
118 return o;
119 }
120
121 /**
122 * gnc_search_numeric_debcred_new:
123 *
124 * Create a new GNCSearchNumeric object, configured for DebCred.
125 *
126 * Return value: A new #GNCSearchNumeric object.
127 **/
128 GNCSearchNumeric *
gnc_search_numeric_debcred_new(void)129 gnc_search_numeric_debcred_new (void)
130 {
131 GNCSearchNumeric *o;
132 GNCSearchNumericPrivate *priv;
133
134 o = g_object_new(GNC_TYPE_SEARCH_NUMERIC, NULL);
135 priv = _PRIVATE(o);
136 priv->is_debcred = TRUE;
137 return o;
138 }
139
140 void
gnc_search_numeric_set_value(GNCSearchNumeric * fi,gnc_numeric value)141 gnc_search_numeric_set_value (GNCSearchNumeric *fi, gnc_numeric value)
142 {
143 g_return_if_fail (fi);
144 g_return_if_fail (IS_GNCSEARCH_NUMERIC (fi));
145
146 fi->value = value;
147 }
148
149 void
gnc_search_numeric_set_how(GNCSearchNumeric * fi,QofQueryCompare how)150 gnc_search_numeric_set_how (GNCSearchNumeric *fi, QofQueryCompare how)
151 {
152 g_return_if_fail (fi);
153 g_return_if_fail (IS_GNCSEARCH_NUMERIC (fi));
154 fi->how = how;
155 }
156
157 void
gnc_search_numeric_set_option(GNCSearchNumeric * fi,QofNumericMatch option)158 gnc_search_numeric_set_option (GNCSearchNumeric *fi, QofNumericMatch option)
159 {
160 g_return_if_fail (fi);
161 g_return_if_fail (IS_GNCSEARCH_NUMERIC (fi));
162 fi->option = option;
163 }
164
165 static void
pass_parent(GNCSearchCoreType * fe,gpointer parent)166 pass_parent (GNCSearchCoreType *fe, gpointer parent)
167 {
168 GNCSearchNumeric *fi = (GNCSearchNumeric *)fe;
169 GNCSearchNumericPrivate *priv;
170
171 g_return_if_fail (fi);
172 g_return_if_fail (IS_GNCSEARCH_NUMERIC (fi));
173
174 priv = _PRIVATE(fi);
175 priv->parent = GTK_WINDOW(parent);
176 }
177
178 static gboolean
gncs_validate(GNCSearchCoreType * fe)179 gncs_validate (GNCSearchCoreType *fe)
180 {
181 GNCSearchNumeric *fi = (GNCSearchNumeric *)fe;
182 GNCSearchNumericPrivate *priv;
183 gboolean valid = TRUE;
184 GError *error = NULL;
185
186 g_return_val_if_fail (fi, FALSE);
187 g_return_val_if_fail (IS_GNCSEARCH_NUMERIC (fi), FALSE);
188
189 priv = _PRIVATE(fi);
190
191 if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT(priv->gae), &error))
192 {
193 gnc_error_dialog (GTK_WINDOW(priv->parent), "%s", error->message);
194 valid = FALSE;
195 g_error_free (error);
196 }
197 return valid;
198 }
199
200 static void
entry_changed(GNCAmountEdit * entry,GNCSearchNumeric * fe)201 entry_changed (GNCAmountEdit *entry, GNCSearchNumeric *fe)
202 {
203 fe->value = gnc_amount_edit_get_amount (entry);
204 }
205
206 static GtkWidget *
make_how_menu(GNCSearchCoreType * fe)207 make_how_menu (GNCSearchCoreType *fe)
208 {
209 GNCSearchNumeric *fi = (GNCSearchNumeric *)fe;
210 GNCSearchNumericPrivate *priv;
211 GtkComboBox *combo;
212
213 priv = _PRIVATE(fi);
214
215 combo = GTK_COMBO_BOX(gnc_combo_box_new_search());
216 gnc_combo_box_search_add(combo, (priv->is_debcred ?
217 _("less than") : _("is less than")),
218 QOF_COMPARE_LT);
219 gnc_combo_box_search_add(combo, (priv->is_debcred ?
220 _("less than or equal to") :
221 _("is less than or equal to")),
222 QOF_COMPARE_LTE);
223 gnc_combo_box_search_add(combo, (priv->is_debcred ?
224 _("equal to") : _("equals")),
225 QOF_COMPARE_EQUAL);
226 gnc_combo_box_search_add(combo, (priv->is_debcred ?
227 _("not equal to") : _("does not equal")),
228 QOF_COMPARE_NEQ);
229 gnc_combo_box_search_add(combo, (priv->is_debcred ?
230 _("greater than") : _("is greater than")),
231 QOF_COMPARE_GT);
232 gnc_combo_box_search_add(combo, (priv->is_debcred ?
233 _("greater than or equal to") :
234 _("is greater than or equal to")),
235 QOF_COMPARE_GTE);
236
237 gnc_combo_box_search_changed(combo, &fi->how);
238 gnc_combo_box_search_set_active(combo, fi->how ? fi->how : QOF_COMPARE_LT);
239
240 return GTK_WIDGET(combo);
241 }
242
243 static GtkWidget *
make_option_menu(GNCSearchCoreType * fe)244 make_option_menu (GNCSearchCoreType *fe)
245 {
246 GNCSearchNumeric *fi = (GNCSearchNumeric *)fe;
247 GtkComboBox *combo;
248
249 combo = GTK_COMBO_BOX(gnc_combo_box_new_search());
250 gnc_combo_box_search_add(combo, _("has credits or debits"), QOF_NUMERIC_MATCH_ANY);
251 gnc_combo_box_search_add(combo, _("has debits"), QOF_NUMERIC_MATCH_DEBIT);
252 gnc_combo_box_search_add(combo, _("has credits"), QOF_NUMERIC_MATCH_CREDIT);
253 gnc_combo_box_search_changed(combo, &fi->option);
254 gnc_combo_box_search_set_active(combo, fi->option ? fi->option : QOF_NUMERIC_MATCH_ANY);
255
256 return GTK_WIDGET(combo);
257 }
258
259 static void
grab_focus(GNCSearchCoreType * fe)260 grab_focus (GNCSearchCoreType *fe)
261 {
262 GNCSearchNumeric *fi = (GNCSearchNumeric *)fe;
263 GNCSearchNumericPrivate *priv;
264
265 g_return_if_fail (fi);
266 g_return_if_fail (IS_GNCSEARCH_NUMERIC (fi));
267
268 priv = _PRIVATE(fi);
269 if (priv->entry)
270 gtk_widget_grab_focus (priv->entry);
271 }
272
273 static void
editable_enters(GNCSearchCoreType * fe)274 editable_enters (GNCSearchCoreType *fe)
275 {
276 GNCSearchNumeric *fi = (GNCSearchNumeric *)fe;
277 GNCSearchNumericPrivate *priv;
278
279 g_return_if_fail (fi);
280 g_return_if_fail (IS_GNCSEARCH_NUMERIC (fi));
281
282 priv = _PRIVATE(fi);
283 if (priv->entry)
284 gtk_entry_set_activates_default(GTK_ENTRY (priv->entry), TRUE);
285 }
286
287 static GtkWidget *
gncs_get_widget(GNCSearchCoreType * fe)288 gncs_get_widget (GNCSearchCoreType *fe)
289 {
290 GtkWidget *entry, *menu, *box;
291 GNCSearchNumeric *fi = (GNCSearchNumeric *)fe;
292 GNCSearchNumericPrivate *priv;
293
294 g_return_val_if_fail (fi, NULL);
295 g_return_val_if_fail (IS_GNCSEARCH_NUMERIC (fi), NULL);
296
297 priv = _PRIVATE(fi);
298 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
299 gtk_box_set_homogeneous (GTK_BOX (box), FALSE);
300
301 /* Build and connect the option menu(s) */
302 if (priv->is_debcred)
303 {
304 menu = make_option_menu (fe);
305 gtk_box_pack_start (GTK_BOX (box), menu, FALSE, FALSE, 3);
306 }
307
308 menu = make_how_menu (fe);
309 gtk_box_pack_start (GTK_BOX (box), menu, FALSE, FALSE, 3);
310
311 /* Build and connect the entry window */
312 entry = gnc_amount_edit_new ();
313 gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (entry), fi->value);
314 g_signal_connect (G_OBJECT (entry), "amount_changed", G_CALLBACK (entry_changed), fe);
315 gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 3);
316 priv->gae = GNC_AMOUNT_EDIT (entry);
317 priv->entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT (entry));
318
319 /* And return the box */
320 return box;
321 }
322
gncs_get_predicate(GNCSearchCoreType * fe)323 static QofQueryPredData* gncs_get_predicate (GNCSearchCoreType *fe)
324 {
325 GNCSearchNumeric *fi = (GNCSearchNumeric *)fe;
326 GNCSearchNumericPrivate *priv;
327
328 g_return_val_if_fail (fi, NULL);
329 g_return_val_if_fail (IS_GNCSEARCH_NUMERIC (fi), NULL);
330
331 /* force the computation of the entry, because we may not get the signal */
332 priv = _PRIVATE(fi);
333 entry_changed (priv->gae, fi);
334
335 return qof_query_numeric_predicate (fi->how, fi->option, fi->value);
336 }
337
gncs_clone(GNCSearchCoreType * fe)338 static GNCSearchCoreType *gncs_clone(GNCSearchCoreType *fe)
339 {
340 GNCSearchNumeric *se, *fse = (GNCSearchNumeric *)fe;
341 GNCSearchNumericPrivate *se_priv, *fse_priv;
342
343 g_return_val_if_fail (fse, NULL);
344 g_return_val_if_fail (IS_GNCSEARCH_NUMERIC (fse), NULL);
345 fse_priv = _PRIVATE(fse);
346
347 se = gnc_search_numeric_new ();
348 gnc_search_numeric_set_value (se, fse->value);
349 gnc_search_numeric_set_how (se, fse->how);
350 se_priv = _PRIVATE(se);
351 gnc_search_numeric_set_option (se, fse->option);
352 se_priv->is_debcred = fse_priv->is_debcred;
353
354 return (GNCSearchCoreType *)se;
355 }
356