00001
00002
00003
00004
00005
00006
00007
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "config.h"
00029
00030 #include <string.h>
00031 #include <glib.h>
00032 #include <gtk/gtk.h>
00033 #include <glib/gi18n.h>
00034 #include <gtkextra/gtksheet.h>
00035 #include "types.h"
00036 #include "dim_list_menu.h"
00037 #include "filter.h"
00038 #include "main.h"
00039
00040 static gint16 working_idx;
00041 static QlFilterInfo old_filter;
00042 static gboolean in_add = FALSE;
00043
00044 typedef enum
00045 {
00046 QL_FILTER_APPLY,
00047 QL_FILTER_EDIT,
00048 QL_FILTER_DELETE
00049 } QlFilterMode;
00050
00051 enum {
00052 FILTER_COL,
00053 FROM_COL,
00054 };
00055
00064 #define RETURN_AND_FREE(x) {\
00065 gint z = (x);\
00066 if (use_nocase) g_free (entry);\
00067 if (use_nocase) g_free (criterion);\
00068 return z;\
00069 }
00070
00071 void
00072 filter_show_all (GtkAction G_GNUC_UNUSED * w, gpointer data)
00073 {
00074 gint32 i;
00075 QlContext * qlc;
00076 QlTabData * tab;
00077
00078 qlc = ql_get_context (GTK_WIDGET(data));
00079 tab = ql_get_tabdata (qlc);
00080 CHECK_CHANGED(tab);
00081 big_draw_start (tab);
00082 for (i = 0; i < tab->file->last_row; i++)
00083 gtk_sheet_row_set_visibility (tab->view->sheet, i, TRUE);
00084 big_draw_end (tab);
00085 tab->file->filter_ptr = NULL;
00086 }
00087
00088 static gboolean
00089 filter_compare_record (QlTabData * tab, gint32 field_index,
00090 gint32 record_index, gchar * criterionx, QLFilterRule rule,
00091 gboolean use_nocase)
00092 {
00093 gint32 column;
00094 gchar *entry;
00095 gchar *entryx;
00096 gchar *criterion;
00097 QlFieldInfo * field;
00098
00099 field = ql_get_fieldinfo (tab, field_index);
00100 column = field->sheet_column;
00101 entryx = g_strdup (gtk_sheet_cell_get_text
00102 (tab->view->sheet, record_index, column));
00103 entry = entryx;
00104 criterion = criterionx;
00105
00106
00107 if (!entry && rule != FILTER_ISBLANK)
00108 return FALSE;
00109 if (rule == FILTER_ISBLANK && (!entry || strlen (entry) == 0))
00110 return TRUE;
00111 switch (field->type)
00112 {
00113
00114 case FIELD_TYPE_TEXT:
00115 {
00116
00117
00118
00119
00120
00121 if (use_nocase)
00122 {
00123 entry = g_strdup (entryx);
00124 g_strdown (entry);
00125 criterion = g_strdup (criterionx);
00126 g_strdown (criterion);
00127 }
00128 else
00129 {
00130 entry = entryx;
00131 criterion = criterionx;
00132 }
00133 switch (rule)
00134 {
00135 case FILTER_CONTAINS:
00136 if (strstr (entry, criterion))
00137 RETURN_AND_FREE (1);
00138 RETURN_AND_FREE (0);
00139 break;
00140 case FILTER_CONTAINSNO:
00141 RETURN_AND_FREE (!strstr (entry, criterion));
00142 break;
00143 case FILTER_IS:
00144 RETURN_AND_FREE (!strcmp (entry, criterion));
00145 break;
00146 case FILTER_ISNOT:
00147 RETURN_AND_FREE (!!strcmp (entry, criterion));
00148 break;
00149 case FILTER_LESS:
00150 RETURN_AND_FREE ((strcmp (entry, criterion) > 0));
00151 break;
00152 case FILTER_MORE:
00153 RETURN_AND_FREE ((strcmp (entry, criterion) < 0));
00154 break;
00155 case FILTER_ISBLANK:
00156 RETURN_AND_FREE (FALSE);
00157 break;
00158 case FILTER_ISNOTBLANK:
00159 RETURN_AND_FREE (TRUE);
00160 break;
00161 }
00162 }
00163 break;
00164
00165 #undef RETURN_AND_FREE
00166
00167
00168
00169
00170 case FIELD_TYPE_NUMERIC:
00171 case FIELD_TYPE_DATE:
00172 case FIELD_TYPE_TIME:
00173 {
00174 gdouble d_entry =
00175 qls2d (entry, field->type, field->formatting);
00176 gdouble d_criterion = qls2d (criterion,
00177 field->type, field->formatting);
00178 switch (rule)
00179 {
00180 case FILTER_CONTAINS:
00181
00182
00183
00184 if (strstr (entry, criterion))
00185 return 1;
00186 return 0;
00187 break;
00188 case FILTER_CONTAINSNO:
00189 if (strstr (entry, criterion))
00190 return 0;
00191 return 1;
00192 break;
00193 case FILTER_IS:
00195 return ((glong)d_entry == (glong)d_criterion);
00196 break;
00197 case FILTER_ISNOT:
00199 return ((glong)d_entry != (glong)d_criterion);
00200 break;
00201 case FILTER_LESS:
00202 return (d_entry < d_criterion);
00203 break;
00204 case FILTER_MORE:
00205 return (d_entry > d_criterion);
00206 break;
00207 case FILTER_ISBLANK:
00208 return FALSE;
00209 break;
00210 case FILTER_ISNOTBLANK:
00211 return TRUE;
00212 break;
00213 }
00214 }
00215 break;
00216 default:
00217 {
00218 level2_error (tab, _("Internal error in tools_compare_record: "
00219 "Invalid field type."));
00220 return 0;
00221 }
00222 break;
00223 }
00224 return 0;
00225 }
00226
00231 static void
00232 filter_select (QlTabData * tab, QlFilterMode G_GNUC_UNUSED mode)
00233 {
00234
00235
00236 GtkWidget *fsel_dialog, *cancel_button, *scroll_w;
00237 GtkWidget *tree_hbox, * ok_button;
00238 gchar *select_entries[2] = { "", NULL };
00239 gint16 idx;
00240 guint width;
00241 GtkTreeView * treeview;
00242 GtkTreeModel * model;
00243 GtkTreeStore * treestore;
00244 GtkTreeIter parent_iter, child_iter;
00245 GtkCellRenderer *renderer;
00246 GtkTreeViewColumn *column;
00247 GtkTreeSortable * sort;
00248 GtkTreeSelection * fselect;
00249
00250 fsel_dialog = gtk_dialog_new ();
00251 gtk_window_set_modal (GTK_WINDOW (fsel_dialog), TRUE);
00252 gtk_window_set_position (GTK_WINDOW (fsel_dialog), GTK_WIN_POS_CENTER);
00253 gtk_window_set_resizable (GTK_WINDOW (fsel_dialog), TRUE);
00254 gtk_container_set_border_width (GTK_CONTAINER (fsel_dialog), 5);
00255
00256 width = 0;
00257 gtk_window_set_title (GTK_WINDOW (fsel_dialog), _("Select a filter"));
00258 g_signal_connect (GTK_OBJECT (fsel_dialog), "delete_event",
00259 G_CALLBACK(close_dlg), fsel_dialog);
00260
00261 ok_button = gtk_button_new_from_stock (GTK_STOCK_OK);
00262 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (fsel_dialog)->action_area),
00263 ok_button, TRUE, TRUE, 0);
00264 gtk_widget_show (ok_button);
00265
00266
00267
00268 cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
00269 g_signal_connect (GTK_OBJECT (cancel_button), "clicked",
00270 G_CALLBACK(close_dlg), fsel_dialog);
00271 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (fsel_dialog)->action_area),
00272 cancel_button, FALSE, FALSE, 0);
00273 gtk_widget_show (cancel_button);
00274
00275 gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (fsel_dialog)->vbox), 10);
00276
00277 tree_hbox = gtk_hbox_new (FALSE, 5);
00278 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (fsel_dialog)->vbox),
00279 tree_hbox, TRUE, TRUE, 0);
00280
00281 treeview = GTK_TREE_VIEW (gtk_tree_view_new ());
00282 model = gtk_tree_view_get_model (treeview);
00283 treestore = gtk_tree_store_new (SINGLE_COL, G_TYPE_STRING);
00284 sort = GTK_TREE_SORTABLE (treestore);
00285 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
00286 GTK_TREE_MODEL (sort));
00287 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
00288 gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE);
00289 gtk_tree_store_append (treestore, &parent_iter, NULL);
00290 gtk_tree_store_set (treestore, &parent_iter, FILTER_COL,
00291 _("Available columns"), -1);
00292 renderer = gtk_cell_renderer_text_new ();
00293 column = gtk_tree_view_column_new_with_attributes
00294 (_("Column Name"), renderer, "text", FILTER_COL, NULL);
00295 gtk_tree_view_column_set_sort_column_id (column, FROM_COL);
00296 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
00297 fselect = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
00298 gtk_tree_selection_set_mode (GTK_TREE_SELECTION(fselect), GTK_SELECTION_SINGLE);
00299
00300 scroll_w = gtk_scrolled_window_new (NULL, NULL);
00301 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_w),
00302 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
00303 gtk_container_set_border_width (GTK_CONTAINER (scroll_w), 5);
00304 gtk_container_add (GTK_CONTAINER (scroll_w),
00305 GTK_WIDGET(treeview));
00306
00307 gtk_box_pack_start (GTK_BOX (tree_hbox), scroll_w, TRUE, TRUE, 0);
00308
00309
00310 for (idx = 0; idx < tab->file->filter_ct; idx++)
00311 {
00312 select_entries[0] = tab->file->filters[idx].name;
00313 gtk_tree_store_append (treestore, &child_iter, &parent_iter);
00314 gtk_tree_store_set (treestore, &child_iter, FILTER_COL,
00315 select_entries[0], -1);
00316 width = (strlen(select_entries[0]) > width) ?
00317 strlen(select_entries[0]) : width;
00318 }
00319 gtk_widget_set_size_request (GTK_WIDGET(treeview),
00320 width + 200, 200);
00321 gtk_tree_view_expand_all (GTK_TREE_VIEW(treeview));
00322 gtk_widget_show_all (fsel_dialog);
00323 }
00324
00325 void
00326 filter_apply (GtkAction G_GNUC_UNUSED * w, gpointer data)
00327 {
00328 QlContext * qlc;
00329 QlTabData * tab;
00330
00331 qlc = ql_get_context (GTK_WIDGET(data));
00332 tab = ql_get_tabdata (qlc);
00333
00334
00335 CHECK_CHANGED(tab);
00336 in_add = FALSE;
00337 filter_select (tab, QL_FILTER_APPLY);
00338 }
00339
00340 void
00341 filter_do_apply (QlTabData * tab, gint16 filter_index)
00342 {
00343 gint i, j;
00344 gboolean flag, selected = FALSE;
00345 GtkSheetRange *x;
00346 QlFilterInfo *cf = &tab->file->filters[filter_index];
00347 tab->file->filter_ptr = cf;
00348
00349 x = g_new0 (GtkSheetRange, 1);
00350 if (filter_index < 0)
00351 {
00352 filter_show_all (NULL, NULL);
00353 return;
00354 }
00355
00356 big_draw_start (tab);
00357 gtk_sheet_unselect_range (tab->view->sheet);
00358
00359 tab->view->sel_type = SELECT_NONE;
00360 for (i = 0; i < tab->file->last_row; i++)
00361 {
00362 gtk_sheet_row_set_visibility (tab->view->sheet, i, FALSE);
00363 if (cf->by_and)
00364 {
00365 flag = TRUE;
00366 for (j = 0; j < cf->line_ct; j++)
00367 {
00368 if (cf->line[j].field >= 0)
00369 {
00370 if (!filter_compare_record (tab, cf->line[j].field, i,
00371 cf->line[j].compare,
00372 cf->line[j].type, cf->use_nocase))
00373 flag = FALSE;
00374 }
00375 }
00376 }
00377 else
00378 {
00379 flag = FALSE;
00380 for (j = 0; j < cf->line_ct; j++)
00381 {
00382 if (cf->line[j].field >= 0)
00383 {
00384 if (filter_compare_record (tab, cf->line[j].field, i,
00385 cf->line[j].compare,
00386 cf->line[j].type, cf->use_nocase))
00387 flag = TRUE;
00388 }
00389 }
00390 }
00391 gtk_sheet_row_set_visibility (tab->view->sheet, i, flag);
00392 if (!selected && flag)
00393 {
00394 x->row0 = i;
00395 x->col0 = 0;
00396 x->rowi = i;
00397 x->coli = 0;
00398 selected = TRUE;
00399 }
00400 }
00401 gtk_sheet_select_range (tab->view->sheet, x);
00402 g_free (x);
00403 big_draw_end (tab);
00404 }
00405
00406 static void G_GNUC_UNUSED
00407 filter_entry_handler (GtkWidget * w, gpointer data)
00408 {
00409 QlContext * qlc;
00410 QlTabData * tab;
00411 gint filter_idx = GPOINTER_TO_INT (data);
00412
00413 qlc = ql_get_context (GTK_WIDGET(w));
00414 tab = ql_get_tabdata (qlc);
00415
00416 if (filter_idx < 0 || !gtk_widget_get_name (w))
00417 {
00418 level2_error (tab, _("** PANIC ** in _filter_entry_handler"));
00419 return;
00420 }
00421 if (!strcmp (gtk_widget_get_name (w), "filter"))
00422 {
00423 strncpy (tab->file->filters[filter_idx].name,
00424 gtk_entry_get_text (GTK_ENTRY (w)),
00425 sizeof (tab->file->filters[filter_idx].name));
00426 }
00427 else
00428 {
00430
00431
00432
00433
00434 }
00435 }
00436
00437 static void G_GNUC_UNUSED
00438 filter_boolean_handler (GtkWidget * w, gpointer data)
00439 {
00440 gint filter;
00441 QlContext * qlc;
00442 QlTabData * tab;
00443
00444 qlc = ql_get_context (w);
00445 tab = ql_get_tabdata (qlc);
00446 filter = GPOINTER_TO_INT (data);
00448 if (!strcmp (gtk_widget_get_name (w), "bool"))
00449 tab->file->filters[filter].by_and
00450 = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
00451 else
00452 tab->file->filters[filter].use_nocase
00453 = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
00454 }
00455
00461 static void
00462 filter_menuitem_select (GtkWidget * w, gpointer data)
00463 {
00464 QlContext * qlc;
00465 QlTabData * tab;
00466 gchar *name;
00467 gint16 line;
00468
00469 qlc = ql_get_context (w);
00470 tab = ql_get_tabdata (qlc);
00471 name = g_strdup (gtk_widget_get_name (w));
00472 line = (*(gint16 *) (data) & (gint16) 0xf000) >> 12;
00473 if (!strcmp (name, "field"))
00474 {
00475 gint16 field = *(gint16 *) (data) & (gint16) 0x0fff;
00476 tab->file->filters[working_idx].line[line].field = field - 1;
00477 }
00478 if (!strcmp (name, "rule"))
00479 {
00480 gint16 rule = *(gint16 *) (data) & (gint16) 0x0fff;
00481 tab->file->filters[working_idx].line[line].type = rule;
00482 }
00483 }
00484
00485
00486 static void
00487 filter_do_delete (QlTabData * tab, gint16 filter_index)
00488 {
00494 gint reportx;
00495
00496
00497
00498 tab->file->filter_ct--;
00499
00500 dim_list_filter_menu (tab->qlc);
00501 front_is_changed (tab);
00502
00503
00504 for (reportx = 0; reportx < tab->file->report_ct; reportx++)
00505 {
00506 if (tab->file->reports[reportx].filter == filter_index)
00507 tab->file->reports[reportx].filter = -1;
00508 else if (tab->file->reports[reportx].filter > filter_index)
00509 tab->file->reports[reportx].filter--;
00510 }
00512 if (tab->file->filter_ptr == &tab->file->filters[filter_index])
00513 tab->file->filter_ptr = NULL;
00514 if (filter_index == tab->file->filter_ct)
00515 return;
00516 if (tab->file->filter_ptr == &tab->file->filters[tab->file->filter_ct])
00517 tab->file->filter_ptr = &tab->file->filters[filter_index];
00518 tab->file->filters[filter_index] = tab->file->filters[tab->file->filter_ct];
00519 }
00520
00522 static void
00523 filter_action (GtkWidget G_GNUC_UNUSED * w, gpointer G_GNUC_UNUSED data)
00524 {
00525 QlContext * qlc;
00526 QlTabData * tab;
00527
00528 qlc = ql_get_context (w);
00529 tab = ql_get_tabdata (qlc);
00530 if (GTK_IS_DIALOG (w) || !strcmp (gtk_widget_get_name (w), "cancel"))
00531 {
00532
00533
00534
00535
00536 if (in_add)
00537 filter_do_delete (tab, working_idx);
00538 else
00539 tab->file->filters[working_idx] = old_filter;
00540
00541 in_add = FALSE;
00542 gtk_widget_destroy (w);
00543 return;
00544 }
00545
00546
00547
00548 filter_do_apply (tab, working_idx);
00549 in_add = FALSE;
00550 dim_list_filter_menu (tab->qlc);
00551 front_is_changed (tab);
00552 gtk_widget_destroy (w);
00553 }
00554
00556 typedef enum
00557 {
00558 IN = 0,
00559 NOT_IN,
00560 EXACT,
00561 NOT,
00562 LESS,
00563 MORE,
00564 BLANK,
00565 NOT_BLANK
00566 } QlRuleName;
00569 static GHashTable * rules = NULL;
00570
00572 static void
00573 filter_do_edit (QlTabData * tab, gint16 filter_index)
00574 {
00575 GtkWidget *edit_dialog, *ok_button, *cancel_button,
00576 *field_selector_menu, *field_selector_menu_item,
00577 *rule_selector_menu, *rule_selector_menu_item,
00578 *entry[MAX_FILTER_NESTING],
00579 *line_hbox[MAX_FILTER_NESTING],
00580 *filter_name, *filter_name_label, *name_hbox,
00581 *case_check, *boolean_check, *boolean_hbox;
00582
00583 gint16 line_index;
00584 gint16 field_index;
00585 gint rule_index;
00586
00587 if (!rules)
00588 {
00589 rules = g_hash_table_new (NULL, NULL);
00590 g_hash_table_insert (rules, GINT_TO_POINTER(IN),
00591 _("contains"));
00592 g_hash_table_insert (rules, GINT_TO_POINTER(NOT_IN),
00593 _("does not contain"));
00594 g_hash_table_insert (rules, GINT_TO_POINTER(EXACT),
00595 _("is exactly"));
00596 g_hash_table_insert (rules, GINT_TO_POINTER(NOT),
00597 _("is not"));
00598 g_hash_table_insert (rules, GINT_TO_POINTER(LESS),
00599 _("is less than"));
00600 g_hash_table_insert (rules, GINT_TO_POINTER(MORE),
00601 _("is more than"));
00602 g_hash_table_insert (rules, GINT_TO_POINTER(BLANK),
00603 _("is blank"));
00604 g_hash_table_insert (rules, GINT_TO_POINTER(NOT_BLANK),
00605 _("is not blank"));
00606 }
00607 old_filter = tab->file->filters[filter_index];
00608
00609 edit_dialog = gtk_dialog_new ();
00610 gtk_window_set_modal (GTK_WINDOW (edit_dialog), TRUE);
00611 gtk_window_set_position (GTK_WINDOW (edit_dialog), GTK_WIN_POS_CENTER);
00612 gtk_window_set_resizable (GTK_WINDOW (edit_dialog), TRUE);
00613 gtk_container_set_border_width (GTK_CONTAINER (edit_dialog), 5);
00614
00615 gtk_window_set_title (GTK_WINDOW (edit_dialog), _("Filter edit"));
00616
00617 ok_button = gtk_button_new_from_stock (GTK_STOCK_OK);
00618 gtk_widget_set_name (ok_button, "ok");
00620 g_signal_connect (GTK_OBJECT (ok_button), "clicked",
00621 G_CALLBACK (filter_action), tab);
00622 gtk_widget_show (ok_button);
00623
00624 cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
00625 gtk_widget_set_name (cancel_button, "cancel");
00628
00629
00630 gtk_widget_show (cancel_button);
00631
00632
00633
00634
00635 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (edit_dialog)->action_area),
00636 ok_button, FALSE, FALSE, 5);
00637 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (edit_dialog)->action_area),
00638 cancel_button, FALSE, FALSE, 5);
00639
00640 filter_name = gtk_entry_new ();
00641 gtk_widget_set_name (filter_name, "filter");
00642 filter_name_label = gtk_label_new (_("Filter name"));
00643 boolean_check = gtk_check_button_new_with_label
00644 (_("All of these must be true"));
00645 case_check = gtk_check_button_new_with_label
00646 (_("Text is case-insensitive"));
00647 gtk_widget_set_name (boolean_check, "bool");
00648 gtk_widget_set_name (case_check, "case");
00649
00650 if (tab->file->filters[filter_index].name != NULL)
00651 gtk_entry_set_text (GTK_ENTRY (filter_name),
00652 tab->file->filters[filter_index].name);
00653 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (boolean_check),
00654 tab->file->filters[filter_index].by_and);
00655 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (case_check),
00656 tab->file->filters[filter_index].use_nocase);
00657
00658
00659
00660
00661
00662
00663
00664 gtk_widget_show (filter_name);
00665 gtk_widget_show (filter_name_label);
00666 gtk_widget_show (boolean_check);
00667 gtk_widget_show (case_check);
00668
00669 name_hbox = gtk_hbox_new (TRUE, 5);
00670 boolean_hbox = gtk_hbox_new (TRUE, 5);
00671
00672 gtk_box_pack_start (GTK_BOX (name_hbox), filter_name_label, TRUE, TRUE,
00673 5);
00674 gtk_box_pack_start (GTK_BOX (name_hbox), filter_name, TRUE, TRUE, 5);
00675 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (edit_dialog)->vbox),
00676 name_hbox, TRUE, TRUE, 5);
00677 gtk_widget_show (name_hbox);
00678 gtk_box_pack_start (GTK_BOX (boolean_hbox), boolean_check, TRUE, TRUE,
00679 5);
00680 gtk_box_pack_start (GTK_BOX (boolean_hbox), case_check, TRUE, TRUE, 5);
00681 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (edit_dialog)->vbox),
00682 boolean_hbox, TRUE, TRUE, 5);
00683 gtk_widget_show (boolean_hbox);
00684
00685 for (line_index = 0; line_index < MAX_FILTER_NESTING; line_index++)
00686 {
00688 gchar nbuf[32];
00689
00690 line_hbox[line_index] = gtk_hbox_new (TRUE, 5);
00691
00692 entry[line_index] = gtk_entry_new ();
00693 g_snprintf (nbuf, 32, "%d", line_index);
00694 gtk_widget_set_name (entry[line_index], nbuf);
00695 gtk_entry_set_text (GTK_ENTRY (entry[line_index]),
00696 tab->file->filters[filter_index].line[line_index].compare);
00697
00698
00699
00700
00701 field_selector_menu = gtk_menu_new ();
00702
00712 for (field_index = 0; field_index <= tab->file->last_field + 1;
00713 field_index++)
00714 {
00715 if (!field_index)
00716 field_selector_menu_item = gtk_menu_item_new_with_label
00717 (_("--- Unused ---"));
00718 else
00719 {
00720 QlFieldInfo * field;
00721 field = ql_get_fieldinfo (tab, (field_index - 1));
00722 field_selector_menu_item = gtk_menu_item_new_with_label
00723 (field->name);
00724 }
00725
00726 gtk_widget_set_name (field_selector_menu_item, "field");
00727 {
00728
00729 gint t;
00730 t = (line_index << 12) | field_index;
00731 g_signal_connect (GTK_OBJECT (field_selector_menu_item),
00732 "activate", G_CALLBACK (filter_menuitem_select),
00733 GINT_TO_POINTER (t));
00734 }
00735 gtk_menu_attach (GTK_MENU (field_selector_menu),
00736 field_selector_menu_item, 0, 1, 0, 1);
00737 if (tab->file->filters[filter_index].line[line_index].field + 1
00738 == field_index)
00739 gtk_menu_set_active (GTK_MENU (field_selector_menu),
00740 field_index);
00741 gtk_widget_show (field_selector_menu_item);
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751 rule_selector_menu = gtk_menu_new ();
00752
00753 for (rule_index = FILTER_CONTAINS; rule_index < NOT_BLANK;
00754 rule_index++)
00755 {
00756 rule_selector_menu_item =
00757 gtk_menu_item_new_with_label
00758 (g_hash_table_lookup (rules, GINT_TO_POINTER(rule_index)));
00759 gtk_widget_set_name (rule_selector_menu_item, "rule");
00760 {
00761 gint t;
00762 t = (line_index << 12) | rule_index;
00763 g_signal_connect (GTK_OBJECT (rule_selector_menu_item),
00764 "activate", G_CALLBACK (filter_menuitem_select),
00765 GINT_TO_POINTER(t));
00766 }
00767 gtk_menu_attach (GTK_MENU (rule_selector_menu),
00768 rule_selector_menu_item, 0, 1, 0, 1);
00769 if (tab->file->filters[filter_index].line[line_index].type
00770 == rule_index)
00771 gtk_menu_set_active (GTK_MENU (rule_selector_menu),
00772 rule_index);
00773 gtk_widget_show (rule_selector_menu_item);
00774 }
00775
00776
00777
00778
00779
00780
00781
00782
00783 gtk_widget_show (entry[line_index]);
00784 gtk_box_pack_start (GTK_BOX (line_hbox[line_index]),
00785 entry[line_index], TRUE, TRUE, 5);
00786
00787 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (edit_dialog)->vbox),
00788 line_hbox[line_index], TRUE, TRUE, 5);
00789 }
00790 gtk_widget_show (edit_dialog);
00791 }
00792
00793 void
00794 filter_add (GtkAction G_GNUC_UNUSED * w, gpointer data)
00795 {
00796 QlContext * qlc;
00797 QlTabData * tab;
00798 gint j;
00799
00800 qlc = ql_get_context (GTK_WIDGET(data));
00801 tab = ql_get_tabdata (qlc);
00802
00803
00804 CHECK_CHANGED(tab);
00805 if (tab->file->filter_ct >= MAX_FILTERS)
00806 {
00807 level2_error (tab, _("Unexpected filter count overflow "
00808 "in filter_add"));
00809 return;
00810 }
00811
00812 in_add = TRUE;
00813
00814 working_idx = tab->file->filter_ct++;
00815
00816 memset (&tab->file->filters[working_idx], 0, sizeof (QlFilterInfo));
00817 strncpy (tab->file->filters[working_idx].name, "Untitled filter",
00818 MAX_FIELD_NAME);
00819 tab->file->filters[working_idx].line_ct = MAX_FILTER_NESTING;
00820 tab->file->filters[working_idx].by_and = FALSE;
00821 for (j = 0; j < MAX_FILTER_NESTING; j++)
00822 tab->file->filters[working_idx].line[j].field = -1;
00823 tab->file->filter_ptr = tab->file->filters + working_idx;
00824 filter_do_edit (tab, working_idx);
00825 }
00826
00827 void
00828 filter_edit (GtkAction G_GNUC_UNUSED * w, gpointer data)
00829 {
00830 QlContext * qlc;
00831 QlTabData * tab;
00832
00833 qlc = ql_get_context (GTK_WIDGET(data));
00834 tab = ql_get_tabdata (qlc);
00835 CHECK_CHANGED(tab);
00836 in_add = FALSE;
00837 filter_select (tab, QL_FILTER_EDIT);
00838 }
00839
00840 void
00841 filter_delete (GtkAction G_GNUC_UNUSED * w, gpointer data)
00842 {
00843 QlContext * qlc;
00844 QlTabData * tab;
00845
00846 qlc = ql_get_context (GTK_WIDGET(data));
00847 tab = ql_get_tabdata (qlc);
00848
00849 CHECK_CHANGED(tab);
00850 in_add = FALSE;
00851 filter_select (tab, QL_FILTER_DELETE);
00852 }
00853
00854
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888