[gnome-logs] Add search type option to search popover



commit 3f028d5430e06253fd66c4294a9652d02eb31a21
Author: Pranav Ganorkar <pranavg189 gmail com>
Date:   Sat Jul 23 19:34:00 2016 +0530

    Add search type option to search popover
    
    A radio button group was addded to select between "Exact"
    and "Substring" search types.The default search type is
    "Substring" search.
    
    We hide the search type radio button group if "All Available Fields"
    is selected as exact search doesn't make sense in that case.
    
    The GlJournalModel class was modified to handle the case when all
    search fields are exact and there are no substring matches.It was also
    modified to handle the case when the exact search match string has a
    null or empty value in which case we do not pass it to
    gl_journal_set_matches().
    
    GL_QUERY_* prefix was added to the enum nicks for making
    it consistent with the enum name GlQuerySearchType.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=767996

 Makefile.am              |    3 +-
 data/gl-searchpopover.ui |   82 +++++++++++++++++++++++++++++++++++++++++++
 src/gl-eventviewlist.c   |   87 ++++++++++++++++++++++++++++-----------------
 src/gl-journal-model.c   |   71 +++++++++++++++++++++++++++----------
 src/gl-journal-model.h   |    8 +++-
 src/gl-searchpopover.c   |   68 ++++++++++++++++++++++++++++++++++++
 src/gl-searchpopover.h   |    2 +
 7 files changed, 265 insertions(+), 56 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 762d858..f69b099 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -52,7 +52,8 @@ gnome_logs_enum_headers = \
        $(srcdir)/src/gl-eventview.h \
        $(srcdir)/src/gl-eventviewrow.h \
        $(srcdir)/src/gl-util.h \
-       $(srcdir)/src/gl-searchpopover.h
+       $(srcdir)/src/gl-searchpopover.h \
+       $(srcdir)/src/gl-journal-model.h
 
 noinst_gnome_logs_headers = \
        src/gl-application.h \
diff --git a/data/gl-searchpopover.ui b/data/gl-searchpopover.ui
index adeaee5..7721383 100644
--- a/data/gl-searchpopover.ui
+++ b/data/gl-searchpopover.ui
@@ -141,6 +141,88 @@
                         <property name="width">2</property>
                     </packing>
                 </child>
+                <child>
+                    <object class="GtkRevealer" id="search_type_revealer">
+                        <child>
+                            <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="orientation">vertical</property>
+                                <property name="spacing">8</property>
+                                <child>
+                                    <object class="GtkLabel" id="search_type_dim_label">
+                                        <property name="visible">True</property>
+                                        <property name="margin_top">10</property>
+                                        <property name="label" translatable="yes">Search Type</property>
+                                        <property name="xalign">0</property>
+                                        <style>
+                                        <class name="dim-label"/>
+                                        </style>
+                                    </object>
+                                    <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                    </packing>
+                                </child>
+                                <child>
+                                    <object class="GtkBox">
+                                        <property name="visible">True</property>
+                                        <child>
+                                            <object class="GtkRadioButton" id="radiobutton_substring">
+                                                <property name="label" 
translatable="yes">Substring</property>
+                                                <property name="visible">True</property>
+                                                <property name="can_focus">True</property>
+                                                <property name="receives_default">False</property>
+                                                <property name="tooltip_text" translatable="yes">Match in 
any part of the string</property>
+                                                <property name="hexpand">True</property>
+                                                <property name="xalign">0</property>
+                                                <property name="active">True</property>
+                                                <property name="draw_indicator">False</property>
+                                            </object>
+                                            <packing>
+                                                <property name="expand">False</property>
+                                                <property name="fill">True</property>
+                                                <property name="position">0</property>
+                                            </packing>
+                                        </child>
+                                        <child>
+                                            <object class="GtkRadioButton" id="radiobutton_exact">
+                                                <property name="label" translatable="yes">Exact</property>
+                                                <property name="visible">True</property>
+                                                <property name="can_focus">True</property>
+                                                <property name="receives_default">False</property>
+                                                <property name="tooltip_text" translatable="yes">Match 
complete string only</property>
+                                                <property name="hexpand">True</property>
+                                                <property name="xalign">0</property>
+                                                <property name="draw_indicator">False</property>
+                                                <property name="group">radiobutton_substring</property>
+                                                <signal name="toggled" handler="search_type_changed"/>
+                                            </object>
+                                            <packing>
+                                                <property name="expand">False</property>
+                                                <property name="fill">True</property>
+                                                <property name="position">1</property>
+                                            </packing>
+                                        </child>
+                                        <style>
+                                            <class name="linked"/>
+                                        </style>
+                                    </object>
+                                    <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">1</property>
+                                    </packing>
+                                </child>
+                            </object>
+                        </child>
+                    </object>
+                    <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">2</property>
+                        <property name="width">2</property>
+                    </packing>
+                </child>
             </object>
         </child>
     </template>
diff --git a/src/gl-eventviewlist.c b/src/gl-eventviewlist.c
index 9849fe7..22fcc83 100644
--- a/src/gl-eventviewlist.c
+++ b/src/gl-eventviewlist.c
@@ -53,6 +53,7 @@ typedef struct
     GtkWidget *search_entry;
     GtkWidget *search_dropdown_button;
     GlSearchPopoverJournalFieldFilter journal_search_field;
+    GlQuerySearchType search_type;
     gchar *search_text;
     const gchar *boot_match;
 } GlEventViewListPrivate;
@@ -386,7 +387,7 @@ query_add_category_matches (GlQuery *query,
     boot_id = get_current_boot_id (boot_match);
 
     /* Add boot match for all the categories */
-    gl_query_add_match (query, "_BOOT_ID", boot_id, SEARCH_TYPE_EXACT);
+    gl_query_add_match (query, "_BOOT_ID", boot_id, GL_QUERY_SEARCH_TYPE_EXACT);
 
     /* Add exact matches according to selected category */
     filter = gl_category_list_get_category (list);
@@ -396,10 +397,10 @@ query_add_category_matches (GlQuery *query,
         case GL_CATEGORY_LIST_FILTER_IMPORTANT:
             {
               /* Alert or emergency priority. */
-              gl_query_add_match (query, "PRIORITY", "0", SEARCH_TYPE_EXACT);
-              gl_query_add_match (query, "PRIORITY", "1", SEARCH_TYPE_EXACT);
-              gl_query_add_match (query, "PRIORITY", "2", SEARCH_TYPE_EXACT);
-              gl_query_add_match (query, "PRIORITY", "3", SEARCH_TYPE_EXACT);
+              gl_query_add_match (query, "PRIORITY", "0", GL_QUERY_SEARCH_TYPE_EXACT);
+              gl_query_add_match (query, "PRIORITY", "1", GL_QUERY_SEARCH_TYPE_EXACT);
+              gl_query_add_match (query, "PRIORITY", "2", GL_QUERY_SEARCH_TYPE_EXACT);
+              gl_query_add_match (query, "PRIORITY", "3", GL_QUERY_SEARCH_TYPE_EXACT);
             }
             break;
 
@@ -417,10 +418,10 @@ query_add_category_matches (GlQuery *query,
 
                 uid_str = get_uid_match_field_value ();
 
-                gl_query_add_match (query, "_TRANSPORT", "journal", SEARCH_TYPE_EXACT);
-                gl_query_add_match (query, "_TRANSPORT", "stdout", SEARCH_TYPE_EXACT);
-                gl_query_add_match (query, "_TRANSPORT", "syslog", SEARCH_TYPE_EXACT);
-                gl_query_add_match (query, "_UID", uid_str, SEARCH_TYPE_EXACT);
+                gl_query_add_match (query, "_TRANSPORT", "journal", GL_QUERY_SEARCH_TYPE_EXACT);
+                gl_query_add_match (query, "_TRANSPORT", "stdout", GL_QUERY_SEARCH_TYPE_EXACT);
+                gl_query_add_match (query, "_TRANSPORT", "syslog", GL_QUERY_SEARCH_TYPE_EXACT);
+                gl_query_add_match (query, "_UID", uid_str, GL_QUERY_SEARCH_TYPE_EXACT);
 
                 g_free (uid_str);
             }
@@ -428,20 +429,20 @@ query_add_category_matches (GlQuery *query,
 
         case GL_CATEGORY_LIST_FILTER_SYSTEM:
             {
-                gl_query_add_match (query, "_TRANSPORT", "kernel", SEARCH_TYPE_EXACT);
+                gl_query_add_match (query, "_TRANSPORT", "kernel", GL_QUERY_SEARCH_TYPE_EXACT);
             }
             break;
 
         case GL_CATEGORY_LIST_FILTER_HARDWARE:
             {
-                gl_query_add_match (query, "_TRANSPORT", "kernel", SEARCH_TYPE_EXACT);
-                gl_query_add_match ( query, "_KERNEL_DEVICE", NULL, SEARCH_TYPE_EXACT);
+                gl_query_add_match (query, "_TRANSPORT", "kernel", GL_QUERY_SEARCH_TYPE_EXACT);
+                gl_query_add_match ( query, "_KERNEL_DEVICE", NULL, GL_QUERY_SEARCH_TYPE_EXACT);
             }
             break;
 
         case GL_CATEGORY_LIST_FILTER_SECURITY:
             {
-                gl_query_add_match (query, "_AUDIT_SESSION", NULL, SEARCH_TYPE_EXACT);
+                gl_query_add_match (query, "_AUDIT_SESSION", NULL, GL_QUERY_SEARCH_TYPE_EXACT);
             }
             break;
 
@@ -455,47 +456,48 @@ query_add_category_matches (GlQuery *query,
 static void
 query_add_search_matches (GlQuery *query,
                           const gchar *search_text,
-                          GlSearchPopoverJournalFieldFilter journal_search_field)
+                          GlSearchPopoverJournalFieldFilter journal_search_field,
+                          GlQuerySearchType search_type)
 {
     switch (journal_search_field)
     {
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_ALL_AVAILABLE_FIELDS:
-            gl_query_add_match (query, "_PID", search_text, SEARCH_TYPE_SUBSTRING);
-            gl_query_add_match (query, "_UID", search_text, SEARCH_TYPE_SUBSTRING);
-            gl_query_add_match (query, "_GID", search_text, SEARCH_TYPE_SUBSTRING);
-            gl_query_add_match (query, "MESSAGE", search_text, SEARCH_TYPE_SUBSTRING);
-            gl_query_add_match (query, "_COMM", search_text, SEARCH_TYPE_SUBSTRING);
-            gl_query_add_match (query, "_SYSTEMD_UNIT", search_text, SEARCH_TYPE_SUBSTRING);
-            gl_query_add_match (query, "_KERNEL_DEVICE", search_text, SEARCH_TYPE_SUBSTRING);
-            gl_query_add_match (query, "_AUDIT_SESSION", search_text, SEARCH_TYPE_SUBSTRING);
-            gl_query_add_match (query, "_EXE", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_PID", search_text, GL_QUERY_SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_UID", search_text, GL_QUERY_SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_GID", search_text, GL_QUERY_SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "MESSAGE", search_text, GL_QUERY_SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_COMM", search_text, GL_QUERY_SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_SYSTEMD_UNIT", search_text, GL_QUERY_SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_KERNEL_DEVICE", search_text, GL_QUERY_SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_AUDIT_SESSION", search_text, GL_QUERY_SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_EXE", search_text, GL_QUERY_SEARCH_TYPE_SUBSTRING);
             break;
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_PID:
-            gl_query_add_match (query, "_PID", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_PID", search_text, search_type);
             break;
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_UID:
-            gl_query_add_match (query, "_UID", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_UID", search_text, search_type);
             break;
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_GID:
-            gl_query_add_match (query, "_GID", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_GID", search_text, search_type);
             break;
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_MESSAGE:
-            gl_query_add_match (query, "MESSAGE", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "MESSAGE", search_text, search_type);
             break;
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_PROCESS_NAME:
-            gl_query_add_match (query, "_COMM", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_COMM", search_text, search_type);
             break;
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_SYSTEMD_UNIT:
-            gl_query_add_match (query, "_SYSTEMD_UNIT", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_SYSTEMD_UNIT", search_text, search_type);
             break;
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_KERNEL_DEVICE:
-            gl_query_add_match (query, "_KERNEL_DEVICE", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_KERNEL_DEVICE", search_text, search_type);
             break;
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_AUDIT_SESSION:
-            gl_query_add_match (query, "_AUDIT_SESSION", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_AUDIT_SESSION", search_text, search_type);
             break;
         case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_EXECUTABLE_PATH:
-            gl_query_add_match (query, "_EXE", search_text, SEARCH_TYPE_SUBSTRING);
+            gl_query_add_match (query, "_EXE", search_text, search_type);
             break;
     }
 }
@@ -516,7 +518,9 @@ create_query_object (GlEventViewList *view)
 
     query_add_category_matches (query, list, priv->boot_match);
 
-    query_add_search_matches (query, priv->search_text, priv->journal_search_field);
+    query_add_search_matches (query, priv->search_text, priv->journal_search_field, priv->search_type);
+
+    gl_query_set_search_type (query, priv->search_type);
 
     return query;
 }
@@ -725,6 +729,21 @@ search_popover_journal_search_field_changed (GlSearchPopover *popover,
     gl_journal_model_take_query (priv->journal_model, query);
 }
 
+static void
+search_popover_search_type_changed (GlSearchPopover *popover,
+                                    GParamSpec *psec,
+                                    GlEventViewList *view)
+{
+    GlEventViewListPrivate *priv = gl_event_view_list_get_instance_private (view);
+    GlQuery *query;
+
+    priv->search_type = gl_search_popover_get_query_search_type (popover);
+
+    query = create_query_object (view);
+
+    gl_journal_model_take_query (priv->journal_model, query);
+}
+
 /* Get the view elements from ui file and link it with the drop down button */
 static void
 set_up_search_popover (GlEventViewList *view)
@@ -743,6 +762,8 @@ set_up_search_popover (GlEventViewList *view)
 
     g_signal_connect (search_popover, "notify::journal-search-field",
                       G_CALLBACK (search_popover_journal_search_field_changed), view);
+    g_signal_connect (search_popover, "notify::search-type",
+                      G_CALLBACK (search_popover_search_type_changed), view);
 
     /* Link the drop down button with search popover */
     gtk_menu_button_set_popover (GTK_MENU_BUTTON (priv->search_dropdown_button),
diff --git a/src/gl-journal-model.c b/src/gl-journal-model.c
index c2f95d7..73d9f3a 100644
--- a/src/gl-journal-model.c
+++ b/src/gl-journal-model.c
@@ -245,6 +245,7 @@ gl_query_new (void)
     query = g_slice_new (GlQuery);
 
     query->queryitems = g_ptr_array_new_with_free_func ((GDestroyNotify) gl_query_item_free);
+    query->search_type = GL_QUERY_SEARCH_TYPE_SUBSTRING;
 
     return query;
 }
@@ -265,6 +266,12 @@ gl_query_item_new (const gchar *field_name,
     return queryitem;
 }
 
+void
+gl_query_set_search_type (GlQuery *query, GlQuerySearchType search_type)
+{
+    query->search_type = search_type;
+}
+
 static gchar *
 gl_query_item_create_match_string (GlQueryItem *queryitem)
 {
@@ -287,7 +294,7 @@ populate_exact_matches (GlQueryItem *queryitem, GPtrArray *matches)
 {
     gchar *match;
 
-    if (queryitem->search_type == SEARCH_TYPE_EXACT)
+    if (queryitem->search_type == GL_QUERY_SEARCH_TYPE_EXACT)
     {
         match = gl_query_item_create_match_string (queryitem);
 
@@ -311,7 +318,7 @@ gl_query_get_exact_matches (GlQuery *query)
 static void
 populate_substring_matches (GlQueryItem *queryitem, GPtrArray *matches)
 {
-    if (queryitem->search_type == SEARCH_TYPE_SUBSTRING)
+    if (queryitem->search_type == GL_QUERY_SEARCH_TYPE_SUBSTRING)
     {
         g_ptr_array_add (matches, queryitem);
     }
@@ -339,6 +346,22 @@ gl_journal_model_process_query (GlJournalModel *model)
     /* Set the exact matches first */
     category_matches = gl_query_get_exact_matches (model->query);
 
+    /* Get the search string of the exact match field */
+    if (model->query->search_type == GL_QUERY_SEARCH_TYPE_EXACT)
+    {
+        gchar *search_match;
+        gchar *field_value_pos;
+
+        /* Get the search match string */
+        search_match = g_ptr_array_index (category_matches, category_matches->len - 1);
+
+        field_value_pos = strchr (search_match, '=');
+
+        /* If it has invalid string value remove it from the matches */
+        if (!field_value_pos || !*(field_value_pos + 1))
+            g_ptr_array_remove (category_matches, search_match);
+    }
+
     gl_journal_set_matches (model->journal, category_matches);
 
     /* Start re-population of the journal */
@@ -742,7 +765,7 @@ calculate_match (GlJournalEntry *entry,
 
 
         /* check for matches */
-        token_match = gl_query_item_new (field_name, field_value, SEARCH_TYPE_SUBSTRING);
+        token_match = gl_query_item_new (field_name, field_value, GL_QUERY_SEARCH_TYPE_SUBSTRING);
 
         field_name_case = is_string_case_sensitive (field_name);
         field_value_case = is_string_case_sensitive (field_value);
@@ -843,28 +866,36 @@ search_in_entry (GlJournalEntry *entry,
 
     search_matches = gl_query_get_substring_matches (query);
 
-    /* Get search text from a search match */
-    search_match = g_ptr_array_index (search_matches, 0);
-
-    /* check for null and empty strings */
-    if (!search_match->field_value || !*(search_match->field_value))
+    /* Check if there is atleast one substring queryitem */
+    if (search_matches->len)
     {
-        matches = TRUE;
-    }
-    else
-    {
-        gchar *search_text;
+        /* Get search text from a search match */
+        search_match = g_ptr_array_index (search_matches, 0);
+
+        /* check for null and empty strings */
+        if (!search_match->field_value || !*(search_match->field_value))
+        {
+            matches = TRUE;
+        }
+        else
+        {
+            gchar *search_text;
 
-        search_text = search_match->field_value;
+            search_text = search_match->field_value;
 
-        /* Tokenize the entered text */
-        token_array = tokenize_search_string (search_text);
+            /* Tokenize the entered text */
+            token_array = tokenize_search_string (search_text);
 
-        /* calculate match depending on the number of tokens */
-        matches = calculate_match (entry, token_array, search_matches);
+            /* calculate match depending on the number of tokens */
+            matches = calculate_match (entry, token_array, search_matches);
 
-        /* Free variables */
-        g_ptr_array_free (token_array, TRUE);
+            /* Free variables */
+            g_ptr_array_free (token_array, TRUE);
+        }
+    }
+    else
+    {
+        matches = TRUE;
     }
 
     g_ptr_array_free (search_matches, TRUE);
diff --git a/src/gl-journal-model.h b/src/gl-journal-model.h
index d25e835..7b42de6 100644
--- a/src/gl-journal-model.h
+++ b/src/gl-journal-model.h
@@ -23,14 +23,15 @@
 
 typedef enum
 {
-    SEARCH_TYPE_EXACT,
-    SEARCH_TYPE_SUBSTRING
+    GL_QUERY_SEARCH_TYPE_SUBSTRING,
+    GL_QUERY_SEARCH_TYPE_EXACT
 } GlQuerySearchType;
 
 /* Resultant query passed to journal model from eventviewlist */
 typedef struct GlQuery
 {
     GPtrArray *queryitems;   /* array of GlQueryItem structs */
+    GlQuerySearchType search_type;    /* indicates if search field is passed as exact match */
 } GlQuery;
 
 #define GL_TYPE_JOURNAL_MODEL gl_journal_model_get_type()
@@ -61,4 +62,7 @@ GArray *                gl_journal_model_get_boot_ids                   (GlJourn
 gchar *                 gl_journal_model_get_current_boot_time          (GlJournalModel *model,
                                                                          const gchar *boot_match);
 
+void                    gl_query_set_search_type                        (GlQuery *query,
+                                                                         GlQuerySearchType search_type);
+
 #endif
diff --git a/src/gl-searchpopover.c b/src/gl-searchpopover.c
index ef72667..d153260 100644
--- a/src/gl-searchpopover.c
+++ b/src/gl-searchpopover.c
@@ -35,14 +35,17 @@ typedef struct
     GtkWidget *parameter_label_stack;
     GtkWidget *parameter_treeview;
     GtkListStore *parameter_liststore;
+    GtkWidget *search_type_revealer;
 
     GlSearchPopoverJournalFieldFilter journal_search_field;
+    GlQuerySearchType search_type;
 } GlSearchPopoverPrivate;
 
 enum
 {
     PROP_0,
     PROP_JOURNAL_SEARCH_FIELD,
+    PROP_SEARCH_TYPE,
     N_PROPERTIES
 };
 
@@ -162,12 +165,49 @@ on_parameter_treeview_row_activated (GtkTreeView *tree_view,
     g_object_notify_by_pspec (G_OBJECT (popover),
                               obj_properties[PROP_JOURNAL_SEARCH_FIELD]);
 
+    /* Do not Show "Search Type" option if all available fields group is selected */
+    if (priv->journal_search_field == GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_ALL_AVAILABLE_FIELDS)
+    {
+        gtk_revealer_set_reveal_child (GTK_REVEALER (priv->search_type_revealer), FALSE);
+        gtk_widget_set_visible (priv->search_type_revealer, FALSE);
+    }
+    else
+    {
+        gtk_widget_set_visible (priv->search_type_revealer, TRUE);
+        gtk_revealer_set_reveal_child (GTK_REVEALER (priv->search_type_revealer), TRUE);
+    }
+
     gtk_stack_set_visible_child_name (GTK_STACK (priv->parameter_stack), "parameter-button");
     gtk_stack_set_visible_child_name (GTK_STACK (priv->parameter_label_stack), "what-label");
 
     g_free (journal_field_label);
 }
 
+static void
+search_type_changed (GtkToggleButton *togglebutton,
+                     gpointer user_data)
+{
+    GlSearchPopover *popover;
+    GlSearchPopoverPrivate *priv;
+
+    popover = GL_SEARCH_POPOVER (user_data);
+
+    priv = gl_search_popover_get_instance_private (popover);
+
+    if (gtk_toggle_button_get_active (togglebutton))
+    {
+        priv->search_type = GL_QUERY_SEARCH_TYPE_EXACT;
+    }
+    else
+    {
+        priv->search_type = GL_QUERY_SEARCH_TYPE_SUBSTRING;
+    }
+
+    /* Inform GlEventViewlist about search type property change */
+    g_object_notify_by_pspec (G_OBJECT (popover),
+                              obj_properties[PROP_SEARCH_TYPE]);
+}
+
 GlSearchPopoverJournalFieldFilter
 gl_search_popover_get_journal_search_field (GlSearchPopover *popover)
 {
@@ -178,6 +218,16 @@ gl_search_popover_get_journal_search_field (GlSearchPopover *popover)
     return priv->journal_search_field;
 }
 
+GlQuerySearchType
+gl_search_popover_get_query_search_type (GlSearchPopover *popover)
+{
+    GlSearchPopoverPrivate *priv;
+
+    priv = gl_search_popover_get_instance_private (popover);
+
+    return priv->search_type;
+}
+
 static void
 gl_search_popover_get_property (GObject *object,
                                 guint prop_id,
@@ -192,6 +242,9 @@ gl_search_popover_get_property (GObject *object,
         case PROP_JOURNAL_SEARCH_FIELD:
             g_value_set_enum (value, priv->journal_search_field);
             break;
+        case PROP_SEARCH_TYPE:
+            g_value_set_enum (value, priv->search_type);
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
             break;
@@ -212,6 +265,9 @@ gl_search_popover_set_property (GObject *object,
         case PROP_JOURNAL_SEARCH_FIELD:
             priv->journal_search_field = g_value_get_enum (value);
             break;
+        case PROP_SEARCH_TYPE:
+            priv->search_type = g_value_get_enum (value);
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
             break;
@@ -234,6 +290,13 @@ gl_search_popover_class_init (GlSearchPopoverClass *klass)
                                                                     G_PARAM_READWRITE |
                                                                     G_PARAM_STATIC_STRINGS);
 
+    obj_properties[PROP_SEARCH_TYPE] = g_param_spec_enum ("search-type", "Search Type",
+                                                          "Do exact or substring search",
+                                                          GL_TYPE_QUERY_SEARCH_TYPE,
+                                                          GL_QUERY_SEARCH_TYPE_SUBSTRING,
+                                                          G_PARAM_READWRITE |
+                                                          G_PARAM_STATIC_STRINGS);
+
     g_object_class_install_properties (gobject_class, N_PROPERTIES,
                                        obj_properties);
 
@@ -249,6 +312,9 @@ gl_search_popover_class_init (GlSearchPopoverClass *klass)
                                                   parameter_treeview);
     gtk_widget_class_bind_template_child_private (widget_class, GlSearchPopover,
                                                   parameter_liststore);
+    gtk_widget_class_bind_template_child_private (widget_class, GlSearchPopover,
+                                                  search_type_revealer);
+
 
     gtk_widget_class_bind_template_callback (widget_class,
                                              search_popover_closed);
@@ -256,6 +322,8 @@ gl_search_popover_class_init (GlSearchPopoverClass *klass)
                                              select_parameter_button_clicked);
     gtk_widget_class_bind_template_callback (widget_class,
                                              on_parameter_treeview_row_activated);
+    gtk_widget_class_bind_template_callback (widget_class,
+                                             search_type_changed);
 }
 
 static void
diff --git a/src/gl-searchpopover.h b/src/gl-searchpopover.h
index faf0a1f..d4a9cab 100644
--- a/src/gl-searchpopover.h
+++ b/src/gl-searchpopover.h
@@ -20,6 +20,7 @@
 #define GL_SEARCH_POPOVER_H_
 
 #include <gtk/gtk.h>
+#include "gl-journal-model.h"
 
 G_BEGIN_DECLS
 
@@ -43,6 +44,7 @@ G_DECLARE_FINAL_TYPE (GlSearchPopover, gl_search_popover, GL, SEARCH_POPOVER, Gt
 
 GtkWidget * gl_search_popover_new (void);
 GlSearchPopoverJournalFieldFilter gl_search_popover_get_journal_search_field (GlSearchPopover *popover);
+GlQuerySearchType gl_search_popover_get_query_search_type (GlSearchPopover *popover);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]