28 #include "dialog-utils.h"
31 #include "gnc-component-manager.h"
32 #include "gnc-query-view.h"
33 #include "search-param.h"
52 #define GNC_QUERY_VIEW_GET_PRIVATE(o) \
53 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_QUERY_VIEW, GNCQueryViewPriv))
56 static GtkTreeViewClass *parent_class = NULL;
57 static guint query_view_signals[LAST_SIGNAL] = {0};
61 static void gnc_query_view_init_view (
GNCQueryView *qview);
63 static void gnc_query_view_select_row_cb (GtkTreeSelection *selection, gpointer user_data);
64 static void gnc_query_view_toggled_cb (GtkCellRendererToggle *cell_renderer,
65 gchar *path, gpointer user_data);
66 static void gnc_query_view_double_click_cb (GtkTreeView *tree_view,
68 GtkTreeViewColumn *column,
71 static void gnc_query_view_destroy (GtkObject *
object);
73 static void gnc_query_view_set_query_sort (
GNCQueryView *qview, gboolean new_column);
77 gnc_query_view_get_type (
void)
79 static GType gnc_query_view_type = 0;
81 if (!gnc_query_view_type)
88 (GClassInitFunc)gnc_query_view_class_init,
93 (GInstanceInitFunc)gnc_query_view_init,
96 gnc_query_view_type = g_type_register_static (GTK_TYPE_TREE_VIEW,
100 return gnc_query_view_type;
113 gnc_query_view_construct (
GNCQueryView *qview, GList *param_list, Query *query)
117 g_return_if_fail (qview);
118 g_return_if_fail (param_list);
119 g_return_if_fail (query);
120 g_return_if_fail (GNC_IS_QUERY_VIEW(qview));
124 qview->column_params = param_list;
127 priv = GNC_QUERY_VIEW_GET_PRIVATE (qview);
132 gnc_query_view_init_view (qview);
135 gnc_query_view_set_query_sort (qview, TRUE);
139 gnc_query_view_new (GList *param_list, Query *query)
142 GtkListStore *liststore;
148 g_return_val_if_fail (param_list, NULL);
149 g_return_val_if_fail (query, NULL);
152 columns = g_list_length (param_list) + 1;
153 qview = GNC_QUERY_VIEW (g_object_new (gnc_query_view_get_type(), NULL));
155 array_size =
sizeof( GType ) * columns;
156 types = g_slice_alloc ( array_size );
158 types[0] = G_TYPE_POINTER;
161 for (i = 0, node = param_list; node; node = node->next, i++)
164 const char *type = gnc_search_param_get_param_type (param);
166 if (g_strcmp0 (type, QOF_TYPE_BOOLEAN) == 0)
167 types[i+1] = G_TYPE_BOOLEAN;
169 types[i+1] = G_TYPE_STRING;
173 liststore = gtk_list_store_newv (columns, types );
174 gtk_tree_view_set_model (GTK_TREE_VIEW (qview), GTK_TREE_MODEL (liststore));
175 g_object_unref (liststore);
178 g_slice_free1( array_size, types );
180 gnc_query_view_construct (qview, param_list, query);
182 return GTK_WIDGET (qview);
186 void gnc_query_view_reset_query (
GNCQueryView *qview, Query *query)
188 g_return_if_fail (qview);
189 g_return_if_fail (query);
190 g_return_if_fail (GNC_IS_QUERY_VIEW (qview));
195 gnc_query_view_set_query_sort (qview, TRUE);
200 gnc_query_view_refresh_handler (GHashTable *changes, gpointer user_data)
203 g_return_if_fail (qview);
204 g_return_if_fail (GNC_IS_QUERY_VIEW (qview));
206 gnc_query_view_set_query_sort (qview, TRUE);
217 qview->num_columns = 0;
218 qview->column_params = NULL;
220 qview->sort_column = 0;
221 qview->increasing = FALSE;
223 qview->numeric_abs = FALSE;
224 qview->numeric_inv_sort = FALSE;
226 priv = GNC_QUERY_VIEW_GET_PRIVATE (qview);
228 gnc_register_gui_component (
"gnc-query-view-cm-class",
229 gnc_query_view_refresh_handler,
235 sort_iter_compare_func (GtkTreeModel *model,
254 gnc_query_sort_order (
GNCQueryView *qview, gint column, GtkSortType order)
256 GtkTreeSortable *sortable;
259 g_return_if_fail (qview != NULL);
260 g_return_if_fail (GNC_IS_QUERY_VIEW (qview));
262 sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (qview)));
264 if((column > qview->num_columns) || (column == 0) )
269 gtk_tree_sortable_set_sort_column_id (sortable, sortcol, order);
274 gnc_query_sort_cb (GtkTreeSortable *sortable, gpointer user_data)
279 gboolean new_column = FALSE;
281 g_return_if_fail (qview != NULL);
282 g_return_if_fail (GNC_IS_QUERY_VIEW (qview));
283 g_return_if_fail (qview->query != NULL);
285 gtk_tree_sortable_get_sort_column_id (sortable, &sortcol, &type);
289 sortcol = sortcol - 1;
291 if(type == GTK_SORT_ASCENDING)
292 qview->increasing = TRUE;
294 qview->increasing = FALSE;
297 new_column = (qview->sort_column != sortcol);
300 qview->sort_column = sortcol;
302 gnc_query_view_set_query_sort (qview, new_column);
309 GtkTreeView *view = GTK_TREE_VIEW (qview);
310 GtkTreeSortable *sortable;
311 GtkTreeSelection *selection;
312 GtkTreeViewColumn *col;
313 GtkCellRenderer *renderer;
317 sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (view)));
320 qview->num_columns = g_list_length (qview->column_params);
322 for (i = 0, node = qview->column_params; node; node = node->next, i++)
328 col = gtk_tree_view_column_new ();
331 gtk_tree_view_column_set_title (col, (gchar *)param->title);
334 gtk_tree_view_append_column (view, col);
337 if (param->justify == GTK_JUSTIFY_CENTER)
339 else if (param->justify == GTK_JUSTIFY_RIGHT)
343 if (param->non_resizeable)
345 gtk_tree_view_column_set_resizable (col, FALSE);
346 gtk_tree_view_column_set_expand (col, FALSE);
349 gtk_tree_view_column_set_resizable (col, TRUE);
353 gtk_tree_view_column_set_clickable (col, FALSE);
356 gtk_tree_view_column_set_clickable (col, TRUE);
358 gtk_tree_view_column_set_sort_column_id (col, i+1);
359 gtk_tree_sortable_set_sort_func (sortable, i+1, sort_iter_compare_func,
360 GINT_TO_POINTER (i+1), NULL);
363 type = gnc_search_param_get_param_type (param);
365 if (g_strcmp0 (type, QOF_TYPE_BOOLEAN) == 0)
367 renderer = gtk_cell_renderer_toggle_new ();
370 gtk_tree_view_column_pack_start (col, renderer, TRUE);
371 gtk_tree_view_column_add_attribute (col, renderer,
"active", i+1);
372 g_object_set (renderer,
"xalign", algn, NULL );
373 g_object_set_data (G_OBJECT (renderer),
"column", GINT_TO_POINTER (i+1) );
374 g_signal_connect (renderer,
"toggled", G_CALLBACK (gnc_query_view_toggled_cb), view);
378 renderer = gtk_cell_renderer_text_new ();
381 gtk_tree_view_column_pack_start (col, renderer, TRUE);
382 gtk_tree_view_column_add_attribute (col, renderer,
"text", i+1);
383 g_object_set (renderer,
"xalign", algn, NULL );
384 g_object_set_data (G_OBJECT (renderer),
"column", GINT_TO_POINTER (i+1) );
389 gtk_tree_sortable_set_default_sort_func (sortable, NULL, NULL, NULL);
390 gtk_tree_sortable_set_sort_column_id (sortable, 1, GTK_SORT_DESCENDING);
392 g_signal_connect (sortable,
"sort-column-changed",
393 G_CALLBACK (gnc_query_sort_cb),
396 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
397 g_signal_connect (selection,
"changed",
398 G_CALLBACK (gnc_query_view_select_row_cb),
401 g_signal_connect (view,
"row-activated",
402 G_CALLBACK (gnc_query_view_double_click_cb),
410 GtkObjectClass *object_class;
411 GtkTreeViewClass *view_class;
413 object_class = (GtkObjectClass*) klass;
414 view_class = (GtkTreeViewClass*) klass;
416 parent_class = g_type_class_peek (GTK_TYPE_TREE_VIEW);
420 query_view_signals[COLUMN_TOGGLED] =
421 g_signal_new(
"column_toggled",
422 G_TYPE_FROM_CLASS (object_class),
426 g_cclosure_marshal_VOID__POINTER,
431 query_view_signals[ROW_SELECTED] =
432 g_signal_new(
"row_selected",
433 G_TYPE_FROM_CLASS (object_class),
437 g_cclosure_marshal_VOID__POINTER,
442 query_view_signals[DOUBLE_CLICK_ENTRY] =
443 g_signal_new(
"double_click_entry",
444 G_TYPE_FROM_CLASS (object_class),
448 g_cclosure_marshal_VOID__POINTER,
453 object_class->destroy = gnc_query_view_destroy;
455 klass->column_toggled = NULL;
456 klass->row_selected = NULL;
457 klass->double_click_entry = NULL;
462 gnc_query_view_select_row_cb (GtkTreeSelection *selection, gpointer user_data)
464 GNCQueryView *qview = GNC_QUERY_VIEW (gtk_tree_selection_get_tree_view (selection));
468 gpointer entry = NULL;
472 qview->selected_entry_list = NULL;
473 qview->selected_entry = NULL;
475 model = gtk_tree_view_get_model (GTK_TREE_VIEW (qview));
476 list_of_rows = gtk_tree_selection_get_selected_rows (selection, &model);
477 number_of_rows = gtk_tree_selection_count_selected_rows (selection);
480 for(node = list_of_rows; node; node = node->next)
483 if(gtk_tree_model_get_iter(model, &iter, node->data))
486 gtk_tree_model_get (model, &iter, 0, &entry, -1);
487 if(number_of_rows == 1)
489 qview->selected_entry = entry;
490 qview->selected_entry_list = g_list_prepend(qview->selected_entry_list, entry);
494 qview->selected_entry = NULL;
495 qview->selected_entry_list = g_list_prepend(qview->selected_entry_list, entry);
498 gtk_tree_path_free(node->data);
500 g_list_free(list_of_rows);
502 g_signal_emit (qview, query_view_signals[ROW_SELECTED], 0, GINT_TO_POINTER(number_of_rows));
507 gnc_query_view_double_click_cb (GtkTreeView *view,
509 GtkTreeViewColumn *column,
515 gpointer entry = NULL;
517 model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
519 if (gtk_tree_model_get_iter (model, &iter, path))
520 gtk_tree_model_get (model, &iter, 0, &entry, -1);
522 qview->selected_entry = entry;
523 qview->selected_entry_list = NULL;
525 g_signal_emit (qview, query_view_signals[DOUBLE_CLICK_ENTRY], 0, entry);
530 gnc_query_view_toggled_cb (GtkCellRendererToggle *cell_renderer,
537 GtkTreePath *treepath;
539 gpointer entry = NULL;
543 model = gtk_tree_view_get_model (GTK_TREE_VIEW (qview));
545 column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell_renderer),
"column"));
547 toggled = gtk_cell_renderer_toggle_get_active (cell_renderer);
549 treepath = gtk_tree_path_new_from_string (path);
551 if (gtk_tree_model_get_iter(model, &iter, treepath))
553 gtk_tree_model_get (model, &iter, 0, &entry, -1);
554 indices = gtk_tree_path_get_indices (treepath);
555 qview->toggled_row = indices[0];
556 qview->toggled_column = column;
557 qview->selected_entry = entry;
560 g_signal_emit (qview, query_view_signals[COLUMN_TOGGLED], 0, GINT_TO_POINTER(0));
562 g_signal_emit (qview, query_view_signals[COLUMN_TOGGLED], 0, GINT_TO_POINTER(1));
564 qview->selected_entry = entry;
569 gnc_query_view_destroy (GtkObject *
object)
574 priv = GNC_QUERY_VIEW_GET_PRIVATE (qview);
575 if (priv->component_id > 0)
577 gnc_unregister_gui_component (priv->component_id);
578 priv->component_id = 0;
581 if (qview->selected_entry_list)
583 g_list_free(qview->selected_entry_list);
584 qview->selected_entry_list = NULL;
592 if (GTK_OBJECT_CLASS (parent_class)->destroy)
593 GTK_OBJECT_CLASS (parent_class)->destroy (
object);
600 g_return_val_if_fail (qview != NULL, 0);
601 g_return_val_if_fail (GNC_IS_QUERY_VIEW (qview), 0);
603 return qview->num_entries;
610 g_return_val_if_fail (qview != NULL, NULL);
611 g_return_val_if_fail (GNC_IS_QUERY_VIEW (qview), NULL);
613 return qview->selected_entry;
618 gnc_query_view_get_selected_entry_list (
GNCQueryView *qview)
620 g_return_val_if_fail (qview != NULL, NULL);
621 g_return_val_if_fail (GNC_IS_QUERY_VIEW (qview), NULL);
623 return qview->selected_entry_list;
628 gnc_query_view_refresh_selected (
GNCQueryView *qview, GList *old_entry)
632 GtkTreeSelection *selection;
636 g_return_if_fail (qview != NULL);
637 g_return_if_fail (GNC_IS_QUERY_VIEW (qview));
639 model = gtk_tree_view_get_model (GTK_TREE_VIEW (qview));
640 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (qview));
642 if(g_list_length (old_entry) > 0)
645 for(node = old_entry; node; node = node->next)
649 valid = gtk_tree_model_get_iter_first (model, &iter);
654 gtk_tree_model_get (model, &iter, 0, &pointer, -1);
656 if(pointer == node->data)
658 gtk_tree_selection_select_iter (selection, &iter);
661 valid = gtk_tree_model_iter_next (model, &iter);
680 GtkTreeSelection *selection;
683 g_return_if_fail (qview != NULL);
684 g_return_if_fail (GNC_IS_QUERY_VIEW (qview));
686 old_entry = qview->selected_entry_list;
687 model = gtk_tree_view_get_model (GTK_TREE_VIEW (qview));
688 gtk_list_store_clear (GTK_LIST_STORE (model));
690 qview->num_entries = 0;
691 qview->selected_entry = NULL;
692 qview->selected_entry_list = NULL;
694 gnc_query_view_fill (qview);
696 gnc_query_view_refresh_selected (qview, old_entry);
698 g_list_free(old_entry);
712 gnc_query_view_set_query_sort (
GNCQueryView *qview, gboolean new_column)
714 gboolean sort_order = qview->increasing;
719 node = g_list_nth (qview->column_params, qview->sort_column);
725 if (qview->numeric_inv_sort)
727 const char *type = gnc_search_param_get_param_type (param);
728 if (!g_strcmp0(type, QOF_TYPE_NUMERIC) ||
729 !g_strcmp0(type, QOF_TYPE_DEBCRED))
730 sort_order = !sort_order;
738 p1 = gnc_search_param_get_param_path (param);
748 gnc_query_view_refresh (qview);
765 GList *entries, *item;
770 priv = GNC_QUERY_VIEW_GET_PRIVATE (qview);
771 gnc_gui_component_clear_watches (priv->component_id);
775 model = gtk_tree_view_get_model (GTK_TREE_VIEW (qview));
777 for (item = entries; item; item = item->next)
785 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
787 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, item->data, -1);
789 for (i = 0, node = qview->column_params; node; node = node->next)
793 GSList *converters = gnc_search_param_get_converters (param);
794 const char *type = gnc_search_param_get_param_type (param);
795 gpointer res = item->data;
799 if (g_strcmp0 (type, QOF_TYPE_BOOLEAN) == 0)
801 result = (gboolean) GPOINTER_TO_INT (gnc_search_param_compute_value (param, res));
802 gtk_list_store_set (GTK_LIST_STORE (model), &iter, i + 1, result, -1);
808 for (; converters; converters = converters->next)
810 qp = converters->data;
811 if (converters->next)
812 res = (qp->param_getfcn)(res, qp);
816 if ( g_strcmp0(type, QOF_TYPE_DEBCRED) == 0 || g_strcmp0(type, QOF_TYPE_NUMERIC) == 0 )
823 if (qview->numeric_abs)
825 gtk_list_store_set (GTK_LIST_STORE (model), &iter, i + 1, xaccPrintAmount (value, gnc_default_print_info (FALSE)), -1);
830 gtk_list_store_set (GTK_LIST_STORE (model), &iter, i + 1, qofstring , -1);
837 gup = priv->get_guid;
838 guid = (
const GncGUID*)((gup->param_getfcn)(item->data, gup));
839 gnc_gui_component_watch_entity (priv->component_id, guid,
840 QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
842 qview->num_entries++;
857 GtkTreeSelection *selection;
859 g_return_if_fail (qview != NULL);
860 g_return_if_fail (GNC_IS_QUERY_VIEW (qview));
862 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (qview));
863 gtk_tree_selection_unselect_all (selection);
865 qview->selected_entry = NULL;
866 qview->selected_entry_list = NULL;
870 gboolean gnc_query_view_item_in_view (
GNCQueryView *qview, gpointer item)
877 g_return_val_if_fail (qview, FALSE);
878 g_return_val_if_fail (item, FALSE);
879 g_return_val_if_fail (GNC_IS_QUERY_VIEW (qview), FALSE);
881 model = gtk_tree_view_get_model (GTK_TREE_VIEW (qview));
882 valid = gtk_tree_model_get_iter_first (model, &iter);
887 gtk_tree_model_get (model, &iter, 0, &pointer, -1);
892 valid = gtk_tree_model_iter_next (model, &iter);
899 gnc_query_view_set_numerics (
GNCQueryView *qview, gboolean abs, gboolean inv_sort)
901 g_return_if_fail (qview);
902 g_return_if_fail (GNC_IS_QUERY_VIEW (qview));
904 qview->numeric_abs = abs;
905 qview->numeric_inv_sort = inv_sort;
utility functions for the GnuCash UI
void qof_query_set_sort_order(QofQuery *q, QofQueryParamList *primary_sort_params, QofQueryParamList *secondary_sort_params, QofQueryParamList *tertiary_sort_params)
QofQuery * qof_query_copy(QofQuery *q)
void qof_query_set_sort_increasing(QofQuery *q, gboolean prim_inc, gboolean sec_inc, gboolean tert_inc)
const QofParam * qof_class_get_parameter(QofIdTypeConst obj_name, const char *parameter)
void qof_query_destroy(QofQuery *q)
char * qof_query_core_to_string(QofType, gpointer object, QofParam *getter)
gnc_numeric gnc_numeric_abs(gnc_numeric a)
struct _gnc_numeric gnc_numeric
An rational-number type.
GList * qof_query_run(QofQuery *query)
QofIdType qof_query_get_search_for(const QofQuery *q)
#define QUERY_DEFAULT_SORT