filter.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *            filter.c
00003  *
00004  *  Sun Sep 24 12:11:27 2006
00005  *  Copyright  2006-2007  Neil Williams
00006  *  linux@codehelp.co.uk
00007  ****************************************************************************/
00013 /*
00014     This package is free software; you can redistribute it and/or modify
00015     it under the terms of the GNU General Public License as published by
00016     the Free Software Foundation; either version 3 of the License, or
00017     (at your option) any later version.
00018 
00019     This program is distributed in the hope that it will be useful,
00020     but WITHOUT ANY WARRANTY; without even the implied warranty of
00021     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022     GNU General Public License for more details.
00023 
00024     You should have received a copy of the GNU General Public License
00025     along with this program.  If not, see <http://www.gnu.org/licenses/>.
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     /* First handle the case of blank or nonblank criteria */
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         /* We are required to handle string/text types ourselves */
00114         case FIELD_TYPE_TEXT:
00115         {
00116             /* We'll allow nocase comparison for strings as we do with match/find.
00117              * By default, filters are case-sensitive. That's just the Unix way.
00118              * It also happens to be the RIGHT way; if you want things to be
00119              * considered the same, type them the same.
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         /* We must still handle all of the following for the other three types:
00168          * CONTAINS, CONTAINSNO, ISBLANK, ISNOTBLANK.
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                 /* For contains/does not contain, we ignore the conversion and do
00182                  * text comparison.
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     /* Selects a filter to work with and places its index 
00235     in working_idx */
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 /*  g_signal_connect (GTK_OBJECT (ok_button), "clicked",
00266         G_CALLBACK (add_ok), NULL);*/
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     /* now populate the treeview with filter names */
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     /* We must first ask which filter to apply, then call filter_do_apply
00334      * with its index */
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 /*      gint line_idx = atoi (gtk_widget_get_name (w));
00431         strncpy (tab->file->filters[filter_idx].line[line_idx].compare,
00432             gtk_entry_get_text (GTK_ENTRY (w)), sizeof
00433             (tab->file->filters[filter_idx].line[line_idx].compare));
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 /* Removes the selected filter. */
00486 static void
00487 filter_do_delete (QlTabData * tab, gint16 filter_index)
00488 {
00494     gint reportx;
00495 
00496 /*  if (dialog1_win)
00497         cancel_level1 (dialog1_win, NULL, NULL);*/
00498     tab->file->filter_ct--;
00499 
00500     dim_list_filter_menu (tab->qlc);
00501     front_is_changed (tab);
00502 
00503     /* Handle report modifications */
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         /* The user has requested that we cancel this operation. So first
00533          * find out what the operation is, then don't do it. :) For now, only
00534          * _filter_do_edit uses this.
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     /* The user clicked the OK Button. Since we've already done everything,
00546      * just return.
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 /*  g_signal_connect (GTK_OBJECT (cancel_button), "clicked",
00629         G_CALLBACK (filter_action), GINT_TO_POINTER(filter_index));
00630 */  gtk_widget_show (cancel_button);
00631 
00632 /*  g_signal_connect (GTK_OBJECT (edit_dialog), "delete_event",
00633         G_CALLBACK (filter_action), GINT_TO_POINTER(filter_index));
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 /*  g_signal_connect (GTK_OBJECT (boolean_check), "toggled",
00658         G_CALLBACK (filter_boolean_handler), 
00659         GINT_TO_POINTER (filter_index));
00660     g_signal_connect (GTK_OBJECT (case_check), "toggled",
00661         G_CALLBACK (filter_boolean_handler), 
00662         GINT_TO_POINTER (filter_index));
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 /*      g_signal_connect (GTK_OBJECT (entry[line_index]), "changed",
00698             G_CALLBACK (filter_entry_handler), 
00699             GINT_TO_POINTER (filter_index));
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                 /* workaround */
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 //      gtk_option_menu_set_menu ((GtkOptionMenu *) field_selector,
00744 //          field_selector_menu);
00745 //      gtk_widget_show (field_selector);
00746 
00747 /*      gtk_box_pack_start (GTK_BOX (line_hbox[line_index]),
00748                 field_selector, TRUE, TRUE, 5);
00749 */
00750 //      rule_selector = gtk_option_menu_new ();
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 //      gtk_option_menu_set_menu ((GtkOptionMenu *) rule_selector,
00776 //          rule_selector_menu);
00777 //      gtk_widget_show (rule_selector);
00778 
00779 /*      gtk_box_pack_start (GTK_BOX (line_hbox[line_index]),
00780                 rule_selector, TRUE, TRUE, 5);
00781     gtk_widget_show (line_hbox[line_index]);
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     /* Create a new filter and then edit it */
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     /* Allocate and clear a new entry */
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     /* Simply removes the selected filter from memory */
00849     CHECK_CHANGED(tab);
00850     in_add = FALSE;
00851     filter_select (tab, QL_FILTER_DELETE);
00852 }
00853 
00854 /* Handles treeview filter selections */
00856 /*static G_GNUC_UNUSED void
00857 select_ok (GtkButton * button, gpointer data)
00858 {
00859     GtkTreeSelection *selection;
00860     GtkTreeIter iter;
00861     GtkTreeModel *model;
00862     gchar * filter_name;
00863     QlFilterMode mode;
00864 
00865     selection = GTK_TREE_SELECTION (data);
00866     if (gtk_tree_selection_get_selected (selection, &model, &iter))
00867     {
00868         gtk_tree_model_get (model, &iter, FILTER_COL, 
00869             &filter_name, -1);
00870     }
00871     working_idx = row;
00872 //  mode = GPOINTER_TO_INT (data);
00873     switch (mode)
00874     {
00875     case QL_FILTER_APPLY:
00876         filter_do_apply (working_idx);
00877         break;
00878     case QL_FILTER_EDIT:
00879         filter_do_edit (working_idx);
00880         break;
00881     case QL_FILTER_DELETE:
00882         filter_do_delete (working_idx);
00883         break;
00884     default:
00885         level2_error (_("Unexpected mode in _filter_selection_made."));
00886         break;
00887     }
00888 }*/

Generated on Mon Jan 28 22:02:10 2008 for quicklist by  doxygen 1.5.4