summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPranav Ganorkar <pranavg189@gmail.com>2016-07-22 18:55:37 +0530
committerJonathan Kang <jonathan121537@gmail.com>2016-10-20 10:58:39 +0800
commitb58ad1fcc1973da8869b39e28b65c751619d3036 (patch)
tree584e331e347bf055ac6be713e519c95b3f23b3d5 /src
parent191a1df44eb813170b15a862e59bfbecb4e66b19 (diff)
downloadgnome-logs-b58ad1fcc1973da8869b39e28b65c751619d3036.tar.gz
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
Diffstat (limited to 'src')
-rw-r--r--src/gl-eventviewlist.c102
-rw-r--r--src/gl-searchpopover.c280
-rw-r--r--src/gl-searchpopover.h49
3 files changed, 419 insertions, 12 deletions
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_ */