GnuCash c935c2f+
Loading...
Searching...
No Matches
dialog-query-view.c
1/*
2 * dialog-query-view.c -- a simple dialog to display a query view and
3 * allow users to select items (or close the view)
4 *
5 * Created By: Derek Atkins <derek@ihtfp.com>
6 * Copyright (c) 2003 Derek Atkins <warlord@MIT.EDU>
7 * Copyright (c) 2012 Robert Fewell
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
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.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, contact:
21 *
22 * Free Software Foundation Voice: +1-617-542-5942
23 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
24 * Boston, MA 02110-1301, USA gnu@gnu.org
25 */
26
27#include <config.h>
28#include <gtk/gtk.h>
29#include <glib/gi18n.h>
30
31#include "qof.h"
32
33#include "dialog-utils.h"
34#include "gnc-component-manager.h"
35
36#include "dialog-query-view.h"
37#include "gnc-query-view.h"
38
40{
41 GtkWidget * dialog;
42 GtkWidget * label;
43 GtkWidget * qview;
44 GtkWidget * button_box;
45 GNCDisplayViewButton * buttons;
46 const gchar * pref_group;
47 gpointer user_data;
48 GList * books;
49 gint component_id;
50};
51
52static void
53dqv_clear_booklist (DialogQueryView *dqv)
54{
55 GList *node;
56
57 g_return_if_fail (dqv);
58
59 for (node = dqv->books; node; node = node->next)
60 guid_free ((GncGUID*)node->data);
61 g_list_free (dqv->books);
62 dqv->books = NULL;
63}
64
65static void
66dqv_build_booklist (DialogQueryView *dqv, Query *q)
67{
68 GList *node;
69
70 g_return_if_fail (dqv);
71
72 for (node = qof_query_get_books(q); node; node = node->next)
73 {
74 QofBook *book = node->data;
75 GncGUID *guid = guid_malloc();
76 *guid = *(qof_book_get_guid(book));
77 dqv->books = g_list_prepend(dqv->books, guid);
78 }
79}
80
81static void
82gnc_dialog_query_run_callback (GNCDisplayViewButton *cb, gpointer item,
83 DialogQueryView *dqv)
84{
85 if (!cb)
86 return;
87
88 if (cb->cb_fcn)
89 (cb->cb_fcn)(GTK_WINDOW (dqv->dialog), item, dqv->user_data);
90}
91
92static void
93gnc_dialog_query_view_button_clicked (GtkButton *button, DialogQueryView *dqv)
94{
96 gpointer entry;
97
98 g_return_if_fail (dqv);
99 entry = gnc_query_view_get_selected_entry (GNC_QUERY_VIEW (dqv->qview));
100 if (!entry)
101 return;
102
103 cb = g_object_get_data (G_OBJECT (button), "data");
104 g_return_if_fail (cb);
105
106 gnc_dialog_query_run_callback (cb, entry, dqv);
107}
108
109static void
110gnc_dialog_query_view_double_click_entry (GNCQueryView *qview, gpointer item,
111 gpointer user_data)
112{
113 DialogQueryView *dqv = user_data;
114
115 g_return_if_fail (dqv);
116 g_return_if_fail (item);
117
118 if (!dqv->buttons)
119 return;
120
121 gnc_dialog_query_run_callback (dqv->buttons, item, dqv);
122}
123
124static void
125dqv_save_window_size (DialogQueryView *dqv)
126{
127 g_return_if_fail (dqv);
128
129 if (dqv->pref_group)
130 gnc_save_window_size (dqv->pref_group, GTK_WINDOW(dqv->dialog));
131}
132
133static int
134gnc_dialog_query_view_delete_cb (GtkDialog *dialog, GdkEvent *event, DialogQueryView *dqv)
135{
136 g_return_val_if_fail (dqv, TRUE);
137
138 dqv_save_window_size (dqv);
139
140 gnc_unregister_gui_component (dqv->component_id);
141
142 /* destroy the book list */
143 dqv_clear_booklist (dqv);
144
145 /* Destroy and exit */
146 gtk_widget_destroy(dqv->dialog);
147 g_free (dqv);
148 return FALSE;
149}
150
151static void
152close_handler (gpointer data)
153{
154 DialogQueryView *dqv = data;
155
156 g_return_if_fail (dqv);
157 gnc_dialog_query_view_delete_cb (GTK_DIALOG(dqv->dialog), NULL, dqv);
158}
159
160static void
161gnc_dialog_query_view_refresh_handler (GHashTable *changes, gpointer user_data)
162{
163 DialogQueryView *dqv = (DialogQueryView *)user_data;
164 const EventInfo *info;
165 GList *node;
166
167 if (changes)
168 {
169 for (node = dqv->books; node; node = node->next)
170 {
171 info = gnc_gui_get_entity_events (changes, (const GncGUID*)(node->data));
172 if (info && (info->event_mask & QOF_EVENT_DESTROY))
173 {
174 gnc_close_gui_component (dqv->component_id);
175 return;
176 }
177 }
178 }
179}
180
181static void
182gnc_dialog_query_view_close (GtkButton *button, DialogQueryView *dqv)
183{
184 dqv_save_window_size (dqv);
185
186 /* Don't select anything */
187 gnc_dialog_query_view_destroy (dqv);
188}
189
190static gboolean
191dqv_window_key_press_cb (GtkWidget *widget, GdkEventKey *event,
192 gpointer user_data)
193{
194 DialogQueryView *dqv = user_data;
195
196 if (event->keyval == GDK_KEY_Escape)
197 dqv_save_window_size (dqv);
198
199 return FALSE;
200}
201
202/*****************************************************************/
203/* PUBLIC INTERFACES */
204
205DialogQueryView *
206gnc_dialog_query_view_new (GtkWindow *parent, GList *param_list, Query *q, const gchar *pref_group)
207{
208 GtkBuilder *builder;
209 DialogQueryView *dqv;
210 GtkWidget *result_hbox, *close, *scrollWin, *frame;
211 GList *node;
212
213 dqv = g_new0 (DialogQueryView, 1);
214 builder = gtk_builder_new();
215 gnc_builder_add_from_file (builder, "dialog-query-view.glade", "query_view_dialog");
216 dqv->pref_group = pref_group;
217
218 /* Grab the dialog, save the dialog info */
219 dqv->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "query_view_dialog"));
220 g_object_set_data (G_OBJECT (dqv->dialog), "dialog-info", dqv);
221 gtk_window_set_transient_for(GTK_WINDOW(dqv->dialog), parent);
222
223 // Set the name for this dialog so it can be easily manipulated with css
224 gtk_widget_set_name (GTK_WIDGET(dqv->dialog), "gnc-id-query-view");
225
226 /* grab the widgets */
227 dqv->label = GTK_WIDGET(gtk_builder_get_object (builder, "dialog_label"));
228 result_hbox = GTK_WIDGET(gtk_builder_get_object (builder, "result_hbox"));
229 close = GTK_WIDGET(gtk_builder_get_object (builder, "close_button"));
230
231 /* build the query list */
232 dqv->qview = gnc_query_view_new (param_list, q);
233
234 frame = gtk_frame_new(NULL);
235
236 scrollWin = gtk_scrolled_window_new (NULL, NULL);
237 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrollWin),
238 GTK_POLICY_AUTOMATIC,
239 GTK_POLICY_AUTOMATIC);
240 gtk_container_set_border_width(GTK_CONTAINER(scrollWin), 5);
241
242 gtk_container_add(GTK_CONTAINER(scrollWin), dqv->qview);
243 gtk_container_add(GTK_CONTAINER(frame), scrollWin);
244
245 gtk_box_pack_start (GTK_BOX (result_hbox), frame, TRUE, TRUE, 3);
246
247 /* Create the button_box */
248 dqv->button_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
249 gtk_box_set_homogeneous (GTK_BOX (dqv->button_box), FALSE);
250
251 gtk_box_pack_start (GTK_BOX (result_hbox), dqv->button_box, FALSE, FALSE, 3);
252
253 /* connect the double-click signal of the qview */
254 g_signal_connect (G_OBJECT (dqv->qview), "double_click_entry",
255 G_CALLBACK(gnc_dialog_query_view_double_click_entry), dqv);
256
257 /* connect to the close button */
258 g_signal_connect (G_OBJECT (close), "clicked",
259 G_CALLBACK (gnc_dialog_query_view_close), dqv);
260
261 /* connect to the cleanup */
262 g_signal_connect (G_OBJECT (dqv->dialog), "delete_event",
263 G_CALLBACK (gnc_dialog_query_view_delete_cb), dqv);
264
265 /* register ourselves */
266 dqv->component_id = gnc_register_gui_component ("GNC Dialog Query View",
267 gnc_dialog_query_view_refresh_handler,
268 close_handler, dqv);
269
270 /* Build the book list */
271 dqv_build_booklist (dqv, q);
272
273 /* and register the books */
274 for (node = dqv->books; node; node = node->next)
275 gnc_gui_component_watch_entity (dqv->component_id, (GncGUID*)node->data,
276 QOF_EVENT_DESTROY);
277
278 g_signal_connect (G_OBJECT (dqv->dialog), "key_press_event",
279 G_CALLBACK (dqv_window_key_press_cb), dqv);
280
281 if (pref_group)
282 gnc_restore_window_size (pref_group, GTK_WINDOW(dqv->dialog), GTK_WINDOW(parent));
283
284
285 g_object_unref(G_OBJECT(builder));
286
287 return dqv;
288}
289
290void gnc_dialog_query_view_set_title (DialogQueryView *dqv, const char *title)
291{
292 if (!dqv || !title) return;
293 gtk_window_set_title (GTK_WINDOW (dqv->dialog), title);
294}
295
296void gnc_dialog_query_view_set_label (DialogQueryView *dqv, const char *label)
297{
298 if (!dqv || !label) return;
299 gtk_label_set_text (GTK_LABEL(dqv->label), label);
300}
301
302void gnc_dialog_query_view_set_buttons (DialogQueryView *dqv,
303 GNCDisplayViewButton *buttons,
304 gpointer user_data)
305{
306 GtkWidget *button;
307 int i;
308
309 if (!dqv || !buttons) return;
310 g_return_if_fail (dqv->buttons == NULL);
311
312 dqv->buttons = buttons;
313 dqv->user_data = user_data;
314
315 /* build up the buttons */
316 for (i = 0; buttons[i].label; i++)
317 {
318 /* Note: The "label" member of the GNCDisplayListButton still
319 * isn't translated. Hence, we must translate it here. */
320 button = gtk_button_new_with_label (_(buttons[i].label));
321 g_object_set_data (G_OBJECT (button), "data", &(dqv->buttons[i]));
322 g_signal_connect (G_OBJECT (button), "clicked",
323 G_CALLBACK(gnc_dialog_query_view_button_clicked), dqv);
324 gtk_box_pack_start (GTK_BOX (dqv->button_box), button, FALSE, FALSE, 3);
325 }
326}
327
328void gnc_dialog_query_view_set_numerics (DialogQueryView *dqv, gboolean abs,
329 gboolean inv_sort)
330{
331 if (!dqv) return;
332
333 gnc_query_view_set_numerics (GNC_QUERY_VIEW(dqv->qview), abs, inv_sort);
334}
335
336void gnc_dialog_query_view_refresh (DialogQueryView *dqv)
337{
338 if (!dqv) return;
339
340 gnc_query_view_refresh (GNC_QUERY_VIEW(dqv->qview));
341 gtk_widget_show_all (dqv->dialog);
342}
343
344void gnc_dialog_query_view_destroy (DialogQueryView *dqv)
345{
346 if (!dqv) return;
347 gnc_close_gui_component (dqv->component_id);
348}
349
350DialogQueryView *
351gnc_dialog_query_view_create (GtkWindow *parent, GList *param_list, Query *q,
352 const char *title, const char *label,
353 gboolean abs, gboolean inv_sort,
354 gint sort_column, GtkSortType order,
355 gint expand_column,
356 GNCDisplayViewButton *buttons,
357 const gchar *pref_group, gpointer user_data)
358{
359 DialogQueryView *dqv;
360
361 if (!param_list || !q)
362 return NULL;
363
364 dqv = gnc_dialog_query_view_new (parent, param_list, q, pref_group);
365 if (!dqv)
366 return NULL;
367
368 if (title)
369 gnc_dialog_query_view_set_title (dqv, title);
370
371 if (label)
372 gnc_dialog_query_view_set_label (dqv, label);
373
374 gnc_dialog_query_view_set_numerics (dqv, abs, inv_sort);
375
376 if (buttons)
377 gnc_dialog_query_view_set_buttons (dqv, buttons, user_data);
378
379 gnc_dialog_query_view_refresh (dqv);
380
381 /* Set the sort order */
382 gnc_query_sort_order (GNC_QUERY_VIEW (dqv->qview), sort_column, order);
383
384 /* Set the column that expands, columns start from 0 */
385 gnc_query_set_expand_column (GNC_QUERY_VIEW (dqv->qview), expand_column);
386
387 /* Unselect all rows */
388 gnc_query_view_unselect_all (GNC_QUERY_VIEW (dqv->qview));
389
390 return dqv;
391}
#define qof_book_get_guid(X)
deprecated
Definition qofbook.h:362
GncGUID * guid_malloc(void)
Allocate memory for a GUID.
Definition guid.cpp:139
GList * qof_query_get_books(QofQuery *q)
Return the list of books we're using.
The type used to store guids in C.
Definition guid.h:75
QofBook reference.
Definition qofbook-p.hpp:47
A Query.
Definition qofquery.cpp:75