[gnome-logs] Add search popover with journal field filtering



commit b58ad1fcc1973da8869b39e28b65c751619d3036
Author: Pranav Ganorkar <pranavg189 gmail com>
Date:   Fri Jul 22 18:55:37 2016 +0530

    Add search popover with journal field filtering
    
    The search popover can be selected from the
    drop down menu besides the search bar. Individual
    journal field or all available journal fields can
    be selected from the search popover.The default
    journal field filter is "All Available fields".
    
    The search popover is designed to look similar to the
    Nautilus search popover.
    
    If Nautilus implementation of search popover changes in
    future, gnome-logs implementation of search popover should
    be kept in sync with it.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=767996

 Makefile.am                       |    5 +-
 data/gl-eventviewlist.ui          |   21 +++-
 data/gl-searchpopover.ui          |  210 +++++++++++++++++++++++++++
 data/org.gnome.Logs.gresource.xml |    1 +
 src/gl-eventviewlist.c            |  102 ++++++++++++--
 src/gl-searchpopover.c            |  280 +++++++++++++++++++++++++++++++++++++
 src/gl-searchpopover.h            |   49 +++++++
 7 files changed, 652 insertions(+), 16 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 10afe2e..762d858 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -30,6 +30,7 @@ gnome_logs_SOURCES = \
        src/gl-eventview.c \
        src/gl-eventviewdetail.c \
        src/gl-eventviewlist.c \
+       src/gl-searchpopover.c \
        src/gl-eventviewrow.c \
        src/gl-journal.c \
        src/gl-journal-model.c \
@@ -50,7 +51,8 @@ gnome_logs_enum_headers = \
        $(srcdir)/src/gl-eventtoolbar.h \
        $(srcdir)/src/gl-eventview.h \
        $(srcdir)/src/gl-eventviewrow.h \
-       $(srcdir)/src/gl-util.h
+       $(srcdir)/src/gl-util.h \
+       $(srcdir)/src/gl-searchpopover.h
 
 noinst_gnome_logs_headers = \
        src/gl-application.h \
@@ -59,6 +61,7 @@ noinst_gnome_logs_headers = \
        src/gl-eventview.h \
        src/gl-eventviewdetail.h \
        src/gl-eventviewlist.h \
+       src/gl-searchpopover.h \
        src/gl-eventviewrow.h \
        src/gl-journal.h \
        src/gl-journal-model.h \
diff --git a/data/gl-eventviewlist.ui b/data/gl-eventviewlist.ui
index 61dfa98..df8c75c 100644
--- a/data/gl-eventviewlist.ui
+++ b/data/gl-eventviewlist.ui
@@ -25,10 +25,25 @@
                         <property name="visible">True</property>
                         <signal name="notify::search-mode-enabled" 
handler="on_search_bar_notify_search_mode_enabled"/>
                         <child>
-                            <object class="GtkSearchEntry" id="search_entry">
+                            <object class="GtkBox" id="search_entry_box">
+                                <property name="orientation">horizontal</property>
                                 <property name="visible">True</property>
-                                <property name="width-request">400</property>
-                                <signal name="search-changed" handler="on_search_entry_changed" />
+                                <style>
+                                    <class name="linked"/>
+                                </style>
+                                <child>
+                                    <object class="GtkSearchEntry" id="search_entry">
+                                        <property name="visible">True</property>
+                                        <property name="width-request">400</property>
+                                        <signal name="search-changed" handler="on_search_entry_changed" />
+                                    </object>
+                                </child>
+                                <child>
+                                    <object class="GtkMenuButton" id="search_dropdown_button">
+                                        <property name="tooltip-text" translatable="yes">Select journal 
field and timestamp range filtering options</property>
+                                        <property name="visible">True</property>
+                                    </object>
+                                </child>
                             </object>
                         </child>
                     </object>
diff --git a/data/gl-searchpopover.ui b/data/gl-searchpopover.ui
new file mode 100644
index 0000000..adeaee5
--- /dev/null
+++ b/data/gl-searchpopover.ui
@@ -0,0 +1,210 @@
+<interface domain="gnome-logs">
+    <template class="GlSearchPopover" parent="GtkPopover">
+        <signal name="closed" handler="search_popover_closed"/>
+        <child>
+            <object class="GtkGrid" id="popover_grid">
+                <property name="visible">True</property>
+                <property name="border_width">20</property>
+                <property name="row_spacing">8</property>
+                <property name="column_spacing">18</property>
+                <child>
+                    <object class="GtkStack" id="parameter_stack">
+                        <property name="visible">True</property>
+                        <property name="vhomogeneous">False</property>
+                        <property name="transition_type">crossfade</property>
+                        <child>
+                            <object class="GtkButton" id="select_parameter_button">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="tooltip_text" translatable="yes">Select a Journal Field to 
filter the Logs according to it</property>
+                                <signal name="clicked" handler="select_parameter_button_clicked"/>
+                                    <child>
+                                        <object class="GtkBox" id="parameter_filter_box">
+                                            <property name="visible">True</property>
+                                            <child>
+                                                <object class="GtkLabel" id="parameter_button_label">
+                                                    <property name="visible">True</property>
+                                                    <property name="hexpand">True</property>
+                                                    <property name="label" translatable="yes">All Available 
Fields</property>
+                                                    <property name="width_chars">30</property>
+                                                    <property name="xalign">0</property>
+                                                </object>
+                                                <packing>
+                                                    <property name="expand">False</property>
+                                                    <property name="fill">True</property>
+                                                    <property name="position">0</property>
+                                                </packing>
+                                            </child>
+                                            <child>
+                                                <object class="GtkImage" id="parameter_button_image">
+                                                    <property name="visible">True</property>
+                                                    <property name="icon_name">pan-down-symbolic</property>
+                                                </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="name">parameter-button</property>
+                            </packing>
+                        </child>
+                        <child>
+                            <object class="GtkScrolledWindow" id="parameter_scrolled_window">
+                                <property name="height_request">150</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="shadow_type">in</property>
+                                <child>
+                                    <object class="GtkTreeView" id="parameter_treeview">
+                                        <property name="visible">True</property>
+                                        <property name="model">parameter_liststore</property>
+                                        <property name="headers-visible">False</property>
+                                        <property name="activate-on-single-click">True</property>
+                                        <signal name="row-activated" 
handler="on_parameter_treeview_row_activated"/>
+                                        <child>
+                                            <object class="GtkTreeViewColumn" id="parameter-column">
+                                                <property name="title">Parameters</property>
+                                                <property name="visible">True</property>
+                                                <child>
+                                                    <object class="GtkCellRendererText" id="test-renderer"/>
+                                                    <attributes>
+                                                        <attribute name="text">0</attribute>
+                                                    </attributes>
+                                                </child>
+                                            </object>
+                                        </child>
+                                        <child internal-child="selection">
+                                            <object class="GtkTreeSelection" id="selection">
+                                            <property name="mode">GTK_SELECTION_BROWSE</property>
+                                            </object>
+                                        </child>
+                                    </object>
+                                </child>
+                            </object>
+                            <packing>
+                                <property name="name">parameter-list</property>
+                                <property name="position">1</property>
+                            </packing>
+                        </child>
+                    </object>
+                    <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">1</property>
+                        <property name="width">2</property>
+                    </packing>
+                </child>
+                <child>
+                    <object class="GtkStack" id="parameter_label_stack">
+                        <property name="visible">True</property>
+                        <child>
+                            <object class="GtkLabel" id="what_dim_label">
+                                <property name="visible">True</property>
+                                <property name="margin_top">10</property>
+                                <!-- Translators: What [journal fields to search in] -->
+                                <property name="label" translatable="yes">What</property>
+                                <property name="xalign">0</property>
+                                <style>
+                                  <class name="dim-label"/>
+                                </style>
+                            </object>
+                            <packing>
+                                <property name="name">what-label</property>
+                                <property name="title">page0</property>
+                            </packing>
+                        </child>
+                        <child>
+                            <object class="GtkLabel" id="select_parameter_dim_label">
+                                <property name="visible">True</property>
+                                <property name="margin_top">10</property>
+                                <property name="label" translatable="yes">Select Journal Field…</property>
+                                <property name="xalign">0</property>
+                                <style>
+                                  <class name="dim-label"/>
+                                </style>
+                            </object>
+                            <packing>
+                                <property name="name">select-parameter-label</property>
+                                <property name="title">page1</property>
+                                <property name="position">1</property>
+                            </packing>
+                        </child>
+                    </object>
+                    <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                        <property name="width">2</property>
+                    </packing>
+                </child>
+            </object>
+        </child>
+    </template>
+    <object class="GtkListStore" id="parameter_liststore">
+        <columns>
+            <column type="gchararray"/>
+            <column type="gboolean"/>
+            <column type="GlSearchPopoverJournalFieldFilter"/>
+        </columns>
+        <data>
+            <row>
+                <col id="0" translatable="yes">All Available Fields</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_ALL_AVAILABLE_FIELDS</col>
+            </row>
+            <row>
+                <col id="0">Separator</col>
+                <col id="1">True</col>
+            </row>
+            <row>
+                <col id="0" translatable="yes">PID</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_PID</col>
+            </row>
+            <row>
+                <col id="0" translatable="yes">UID</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_UID</col>
+            </row>
+            <row>
+                <col id="0" translatable="yes">GID</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_GID</col>
+            </row>
+            <row>
+                <col id="0" translatable="yes">Message</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_MESSAGE</col>
+            </row>
+            <row>
+                <col id="0" translatable="yes">Process Name</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_PROCESS_NAME</col>
+            </row>
+            <row>
+                <col id="0" translatable="yes">Systemd Unit</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_SYSTEMD_UNIT</col>
+            </row>
+            <row>
+                <col id="0" translatable="yes">Kernel Device</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_KERNEL_DEVICE</col>
+            </row>
+            <row>
+                <col id="0" translatable="yes">Audit Session</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_AUDIT_SESSION</col>
+            </row>
+            <row>
+                <col id="0" translatable="yes">Executable Path</col>
+                <col id="1">False</col>
+                <col id="2">GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_EXECUTABLE_PATH</col>
+            </row>
+        </data>
+    </object>
+</interface>
diff --git a/data/org.gnome.Logs.gresource.xml b/data/org.gnome.Logs.gresource.xml
index f91a628..291fd85 100644
--- a/data/org.gnome.Logs.gresource.xml
+++ b/data/org.gnome.Logs.gresource.xml
@@ -6,6 +6,7 @@
     <file preprocess="xml-stripblanks">gl-eventviewlist.ui</file>
     <file preprocess='xml-stripblanks'>gl-eventtoolbar.ui</file>
     <file preprocess='xml-stripblanks'>gl-eventviewdetail.ui</file>
+    <file preprocess='xml-stripblanks'>gl-searchpopover.ui</file>
     <file>gl-style.css</file>
     <file preprocess='xml-stripblanks'>gl-window.ui</file>
   </gresource>
diff --git a/src/gl-eventviewlist.c b/src/gl-eventviewlist.c
index ad3f5bd..9849fe7 100644
--- a/src/gl-eventviewlist.c
+++ b/src/gl-eventviewlist.c
@@ -30,6 +30,7 @@
 #include "gl-eventviewrow.h"
 #include "gl-journal-model.h"
 #include "gl-util.h"
+#include "gl-searchpopover.h"
 
 struct _GlEventViewList
 {
@@ -50,6 +51,8 @@ typedef struct
     GtkWidget *event_search;
     GtkWidget *event_scrolled;
     GtkWidget *search_entry;
+    GtkWidget *search_dropdown_button;
+    GlSearchPopoverJournalFieldFilter journal_search_field;
     gchar *search_text;
     const gchar *boot_match;
 } GlEventViewListPrivate;
@@ -451,18 +454,50 @@ query_add_category_matches (GlQuery *query,
 
 static void
 query_add_search_matches (GlQuery *query,
-                          const gchar *search_text)
+                          const gchar *search_text,
+                          GlSearchPopoverJournalFieldFilter journal_search_field)
 {
-    /* Add substring matches */
-    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);
+    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);
+            break;
+        case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_PID:
+            gl_query_add_match (query, "_PID", search_text, SEARCH_TYPE_SUBSTRING);
+            break;
+        case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_UID:
+            gl_query_add_match (query, "_UID", search_text, SEARCH_TYPE_SUBSTRING);
+            break;
+        case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_GID:
+            gl_query_add_match (query, "_GID", search_text, SEARCH_TYPE_SUBSTRING);
+            break;
+        case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_MESSAGE:
+            gl_query_add_match (query, "MESSAGE", search_text, SEARCH_TYPE_SUBSTRING);
+            break;
+        case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_PROCESS_NAME:
+            gl_query_add_match (query, "_COMM", search_text, SEARCH_TYPE_SUBSTRING);
+            break;
+        case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_SYSTEMD_UNIT:
+            gl_query_add_match (query, "_SYSTEMD_UNIT", search_text, SEARCH_TYPE_SUBSTRING);
+            break;
+        case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_KERNEL_DEVICE:
+            gl_query_add_match (query, "_KERNEL_DEVICE", search_text, SEARCH_TYPE_SUBSTRING);
+            break;
+        case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_AUDIT_SESSION:
+            gl_query_add_match (query, "_AUDIT_SESSION", search_text, SEARCH_TYPE_SUBSTRING);
+            break;
+        case GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_EXECUTABLE_PATH:
+            gl_query_add_match (query, "_EXE", search_text, SEARCH_TYPE_SUBSTRING);
+            break;
+    }
 }
 
 /* Create query object according to selected category */
@@ -481,7 +516,7 @@ create_query_object (GlEventViewList *view)
 
     query_add_category_matches (query, list, priv->boot_match);
 
-    query_add_search_matches (query, priv->search_text);
+    query_add_search_matches (query, priv->search_text, priv->journal_search_field);
 
     return query;
 }
@@ -676,6 +711,45 @@ gl_event_list_view_edge_reached (GtkScrolledWindow *scrolled,
 }
 
 static void
+search_popover_journal_search_field_changed (GlSearchPopover *popover,
+                                             GParamSpec *psec,
+                                             GlEventViewList *view)
+{
+    GlEventViewListPrivate *priv = gl_event_view_list_get_instance_private (view);
+    GlQuery *query;
+
+    priv->journal_search_field = gl_search_popover_get_journal_search_field (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)
+{
+
+    GlEventViewListPrivate *priv;
+    GtkWidget *search_popover;
+
+    priv = gl_event_view_list_get_instance_private (view);
+
+    search_popover = gl_search_popover_new ();
+
+    /* Grab/Remove keyboard focus from popover menu when it is opened or closed */
+    g_signal_connect (search_popover, "show", (GCallback) gtk_widget_grab_focus, NULL);
+    g_signal_connect_swapped (search_popover, "closed", (GCallback) gtk_widget_grab_focus, view);
+
+    g_signal_connect (search_popover, "notify::journal-search-field",
+                      G_CALLBACK (search_popover_journal_search_field_changed), view);
+
+    /* Link the drop down button with search popover */
+    gtk_menu_button_set_popover (GTK_MENU_BUTTON (priv->search_dropdown_button),
+                                 search_popover);
+}
+
+static void
 gl_event_view_list_finalize (GObject *object)
 {
     GlEventViewList *view = GL_EVENT_VIEW_LIST (object);
@@ -708,6 +782,8 @@ gl_event_view_list_class_init (GlEventViewListClass *klass)
                                                   event_scrolled);
     gtk_widget_class_bind_template_child_private (widget_class, GlEventViewList,
                                                   search_entry);
+    gtk_widget_class_bind_template_child_private (widget_class, GlEventViewList,
+                                                  search_dropdown_button);
 
     gtk_widget_class_bind_template_callback (widget_class,
                                              on_search_entry_changed);
@@ -758,6 +834,8 @@ gl_event_view_list_init (GlEventViewList *view)
     priv->clock_format = g_settings_get_enum (settings, CLOCK_FORMAT);
     g_object_unref (settings);
 
+    set_up_search_popover (view);
+
     g_signal_connect (categories, "notify::category", G_CALLBACK (on_notify_category),
                       view);
 }
diff --git a/src/gl-searchpopover.c b/src/gl-searchpopover.c
new file mode 100644
index 0000000..ef72667
--- /dev/null
+++ b/src/gl-searchpopover.c
@@ -0,0 +1,280 @@
+/*
+ *  GNOME Logs - View and search logs
+ *  Copyright (C) 2016  Pranav Ganorkar <pranavg189 gmail com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gl-searchpopover.h"
+#include "gl-enums.h"
+
+#include <glib/gi18n.h>
+
+struct _GlSearchPopover
+{
+    /*< private >*/
+    GtkPopover parent_instance;
+};
+
+typedef struct
+{
+    /* Search popover elements */
+    GtkWidget *parameter_stack;
+    GtkWidget *parameter_button_label;
+    GtkWidget *parameter_label_stack;
+    GtkWidget *parameter_treeview;
+    GtkListStore *parameter_liststore;
+
+    GlSearchPopoverJournalFieldFilter journal_search_field;
+} GlSearchPopoverPrivate;
+
+enum
+{
+    PROP_0,
+    PROP_JOURNAL_SEARCH_FIELD,
+    N_PROPERTIES
+};
+
+enum
+{
+    COLUMN_JOURNAL_FIELD_LABEL,
+    COLUMN_JOURNAL_FIELD_SHOW_SEPARATOR,
+    COLUMN_JOURNAL_FIELD_ENUM_VALUE,
+    JOURNAL_FIELD_N_COLUMNS
+};
+
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GlSearchPopover, gl_search_popover, GTK_TYPE_POPOVER)
+
+/* Event handlers for search popover elements */
+static void
+search_popover_closed (GtkPopover *popover,
+                       gpointer user_data)
+{
+    GlSearchPopoverPrivate *priv;
+
+    priv = gl_search_popover_get_instance_private (GL_SEARCH_POPOVER (user_data));
+
+    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");
+}
+
+static void
+select_parameter_button_clicked (GtkButton *button,
+                                 gpointer user_data)
+{
+    GlSearchPopoverPrivate *priv;
+    GtkTreeSelection *selection;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    gboolean valid;
+
+    priv = gl_search_popover_get_instance_private (GL_SEARCH_POPOVER (user_data));
+
+    gtk_stack_set_visible_child_name (GTK_STACK (priv->parameter_stack), "parameter-list");
+    gtk_stack_set_visible_child_name (GTK_STACK (priv->parameter_label_stack), "select-parameter-label");
+
+    model = GTK_TREE_MODEL (priv->parameter_liststore);
+
+    valid = gtk_tree_model_get_iter_first (model, &iter);
+
+    while (valid)
+    {
+        GlSearchPopoverJournalFieldFilter journal_field_enum_value;
+
+        gtk_tree_model_get (GTK_TREE_MODEL (priv->parameter_liststore), &iter,
+                            COLUMN_JOURNAL_FIELD_ENUM_VALUE, &journal_field_enum_value,
+                            -1);
+
+        if (priv->journal_search_field == journal_field_enum_value)
+        {
+            break;
+        }
+
+        valid = gtk_tree_model_iter_next (model, &iter);
+    }
+
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->parameter_treeview));
+
+    gtk_tree_selection_select_iter (selection, &iter);
+}
+
+static gboolean
+parameter_treeview_row_seperator (GtkTreeModel *model,
+                                  GtkTreeIter *iter,
+                                  gpointer user_data)
+{
+    GlSearchPopover *popover;
+    GlSearchPopoverPrivate *priv;
+    gboolean show_separator;
+
+    popover = GL_SEARCH_POPOVER (user_data);
+
+    priv = gl_search_popover_get_instance_private (popover);
+
+    gtk_tree_model_get (GTK_TREE_MODEL (priv->parameter_liststore), iter,
+                        COLUMN_JOURNAL_FIELD_SHOW_SEPARATOR, &show_separator,
+                        -1);
+
+    return show_separator;
+}
+
+static void
+on_parameter_treeview_row_activated (GtkTreeView *tree_view,
+                                     GtkTreePath *path,
+                                     GtkTreeViewColumn *column,
+                                     gpointer user_data)
+{
+    GtkTreeIter iter;
+    GlSearchPopover *popover;
+    GlSearchPopoverPrivate *priv;
+    gchar *journal_field_label;
+    GlSearchPopoverJournalFieldFilter journal_field_enum_value;
+
+    popover = GL_SEARCH_POPOVER (user_data);
+
+    priv = gl_search_popover_get_instance_private (popover);
+
+    gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->parameter_liststore), &iter, path);
+
+    gtk_tree_model_get (GTK_TREE_MODEL (priv->parameter_liststore), &iter,
+                        COLUMN_JOURNAL_FIELD_LABEL, &journal_field_label,
+                        COLUMN_JOURNAL_FIELD_ENUM_VALUE, &journal_field_enum_value,
+                        -1);
+
+    gtk_label_set_label (GTK_LABEL (priv->parameter_button_label),
+                         _(journal_field_label));
+
+    priv->journal_search_field = journal_field_enum_value;
+
+    g_object_notify_by_pspec (G_OBJECT (popover),
+                              obj_properties[PROP_JOURNAL_SEARCH_FIELD]);
+
+    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);
+}
+
+GlSearchPopoverJournalFieldFilter
+gl_search_popover_get_journal_search_field (GlSearchPopover *popover)
+{
+    GlSearchPopoverPrivate *priv;
+
+    priv = gl_search_popover_get_instance_private (popover);
+
+    return priv->journal_search_field;
+}
+
+static void
+gl_search_popover_get_property (GObject *object,
+                                guint prop_id,
+                                GValue *value,
+                                GParamSpec *pspec)
+{
+    GlSearchPopover *popover = GL_SEARCH_POPOVER (object);
+    GlSearchPopoverPrivate *priv = gl_search_popover_get_instance_private (popover);
+
+    switch (prop_id)
+    {
+        case PROP_JOURNAL_SEARCH_FIELD:
+            g_value_set_enum (value, priv->journal_search_field);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gl_search_popover_set_property (GObject *object,
+                                guint prop_id,
+                                const GValue *value,
+                                GParamSpec *pspec)
+{
+    GlSearchPopover *popover = GL_SEARCH_POPOVER (object);
+    GlSearchPopoverPrivate *priv = gl_search_popover_get_instance_private (popover);
+
+    switch (prop_id)
+    {
+        case PROP_JOURNAL_SEARCH_FIELD:
+            priv->journal_search_field = g_value_get_enum (value);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gl_search_popover_class_init (GlSearchPopoverClass *klass)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+    gobject_class->get_property = gl_search_popover_get_property;
+    gobject_class->set_property = gl_search_popover_set_property;
+
+    obj_properties[PROP_JOURNAL_SEARCH_FIELD] = g_param_spec_enum ("journal-search-field", "Journal Search 
Field",
+                                                                    "The Journal search field by which to 
filter the logs",
+                                                                    
GL_TYPE_SEARCH_POPOVER_JOURNAL_FIELD_FILTER,
+                                                                    
GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_ALL_AVAILABLE_FIELDS,
+                                                                    G_PARAM_READWRITE |
+                                                                    G_PARAM_STATIC_STRINGS);
+
+    g_object_class_install_properties (gobject_class, N_PROPERTIES,
+                                       obj_properties);
+
+    gtk_widget_class_set_template_from_resource (widget_class,
+                                                 "/org/gnome/Logs/gl-searchpopover.ui");
+    gtk_widget_class_bind_template_child_private (widget_class, GlSearchPopover,
+                                                  parameter_stack);
+    gtk_widget_class_bind_template_child_private (widget_class, GlSearchPopover,
+                                                  parameter_button_label);
+    gtk_widget_class_bind_template_child_private (widget_class, GlSearchPopover,
+                                                  parameter_label_stack);
+    gtk_widget_class_bind_template_child_private (widget_class, GlSearchPopover,
+                                                  parameter_treeview);
+    gtk_widget_class_bind_template_child_private (widget_class, GlSearchPopover,
+                                                  parameter_liststore);
+
+    gtk_widget_class_bind_template_callback (widget_class,
+                                             search_popover_closed);
+    gtk_widget_class_bind_template_callback (widget_class,
+                                             select_parameter_button_clicked);
+    gtk_widget_class_bind_template_callback (widget_class,
+                                             on_parameter_treeview_row_activated);
+}
+
+static void
+gl_search_popover_init (GlSearchPopover *popover)
+{
+    GlSearchPopoverPrivate *priv;
+
+    gtk_widget_init_template (GTK_WIDGET (popover));
+
+    priv = gl_search_popover_get_instance_private (popover);
+
+    gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (priv->parameter_treeview),
+                                          (GtkTreeViewRowSeparatorFunc) parameter_treeview_row_seperator,
+                                          popover,
+                                          NULL);
+}
+
+GtkWidget *
+gl_search_popover_new (void)
+{
+    return g_object_new (GL_TYPE_SEARCH_POPOVER, NULL);
+}
diff --git a/src/gl-searchpopover.h b/src/gl-searchpopover.h
new file mode 100644
index 0000000..faf0a1f
--- /dev/null
+++ b/src/gl-searchpopover.h
@@ -0,0 +1,49 @@
+/*
+ *  GNOME Logs - View and search logs
+ *  Copyright (C) 2016  Pranav Ganorkar <pranavg189 gmail com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GL_SEARCH_POPOVER_H_
+#define GL_SEARCH_POPOVER_H_
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/* Rows in parameter treeview */
+typedef enum
+{
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_ALL_AVAILABLE_FIELDS,
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_PID,
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_UID,
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_GID,
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_MESSAGE,
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_PROCESS_NAME,
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_SYSTEMD_UNIT,
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_KERNEL_DEVICE,
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_AUDIT_SESSION,
+    GL_SEARCH_POPOVER_JOURNAL_FIELD_FILTER_EXECUTABLE_PATH
+} GlSearchPopoverJournalFieldFilter;
+
+#define GL_TYPE_SEARCH_POPOVER (gl_search_popover_get_type ())
+G_DECLARE_FINAL_TYPE (GlSearchPopover, gl_search_popover, GL, SEARCH_POPOVER, GtkPopover)
+
+GtkWidget * gl_search_popover_new (void);
+GlSearchPopoverJournalFieldFilter gl_search_popover_get_journal_search_field (GlSearchPopover *popover);
+
+G_END_DECLS
+
+#endif /* GL_SEARCH_POPOVER_H_ */


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