diff options
author | Jonathan Kang <jonathan121537@gmail.com> | 2014-11-06 14:11:21 +0800 |
---|---|---|
committer | David King <davidk@gnome.org> | 2014-11-11 12:35:43 +0000 |
commit | afda11b8d616ee84d901e5904435c67131dc3cf5 (patch) | |
tree | 846a0cc5b49e3b5475f2fb5086e230bf02e0e061 | |
parent | b19f65206028ae8b4bb6c89635128d8f12350931 (diff) | |
download | gnome-logs-afda11b8d616ee84d901e5904435c67131dc3cf5.tar.gz |
Hide sidebar while viewing event details
https://bugzilla.gnome.org/show_bug.cgi?id=726228
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | data/gl-eventview.ui | 10 | ||||
-rw-r--r-- | data/gl-eventviewlist.ui | 45 | ||||
-rw-r--r-- | data/gl-window.ui | 42 | ||||
-rw-r--r-- | data/org.gnome.Logs.gresource.xml | 2 | ||||
-rw-r--r-- | src/gl-application.c | 2 | ||||
-rw-r--r-- | src/gl-categorylist.c | 124 | ||||
-rw-r--r-- | src/gl-categorylist.h | 30 | ||||
-rw-r--r-- | src/gl-eventview.c | 253 | ||||
-rw-r--r-- | src/gl-eventview.h | 65 | ||||
-rw-r--r-- | src/gl-eventviewlist.c | 394 | ||||
-rw-r--r-- | src/gl-eventviewlist.h | 54 | ||||
-rw-r--r-- | src/gl-window.c | 110 |
13 files changed, 723 insertions, 412 deletions
diff --git a/Makefile.am b/Makefile.am index 45d3c47..b1feb39 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,6 +27,7 @@ gnome_logs_SOURCES = \ src/gl-application.c \ src/gl-categorylist.c \ src/gl-eventtoolbar.c \ + src/gl-eventview.c \ src/gl-eventviewdetail.c \ src/gl-eventviewlist.c \ src/gl-eventviewrow.c \ @@ -44,8 +45,9 @@ enum_data = \ src/gl-enums.h gnome_logs_enum_headers = \ + $(srcdir)/src/gl-categorylist.h \ $(srcdir)/src/gl-eventtoolbar.h \ - $(srcdir)/src/gl-eventviewlist.h \ + $(srcdir)/src/gl-eventview.h \ $(srcdir)/src/gl-eventviewrow.h \ $(srcdir)/src/gl-util.h diff --git a/data/gl-eventview.ui b/data/gl-eventview.ui new file mode 100644 index 0000000..dde128a --- /dev/null +++ b/data/gl-eventview.ui @@ -0,0 +1,10 @@ +<interface domain="gnome-logs"> + <template class="GlEventView" parent="GtkStack"> + <property name="visible">True</property> + <child> + <object class="GlEventViewList" id="events"> + <property name="visible">True</property> + </object> + </child> + </template> +</interface> diff --git a/data/gl-eventviewlist.ui b/data/gl-eventviewlist.ui new file mode 100644 index 0000000..1f7a9af --- /dev/null +++ b/data/gl-eventviewlist.ui @@ -0,0 +1,45 @@ +<interface domain="gnome-logs"> + <template class="GlEventViewList" parent="GtkBox"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <child> + <object class="GlCategoryList" id="categories"> + <property name="visible">True</property> + <style> + <class name="categories"/> + </style> + </object> + </child> + <child> + <object class="GtkSeparator" id="content_separator"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + </object> + </child> + <child> + <object class="GtkBox" id="event_view"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <child> + <object class="GtkSearchBar" id="event_search"> + <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"> + <property name="visible">True</property> + <property name="width-request">400</property> + <signal name="search-changed" handler="on_search_entry_changed" /> + </object> + </child> + </object> + </child> + <child> + <object class="GtkStack" id="event_stack"> + <property name="visible">True</property> + <property name="expand">True</property> + </object> + </child> + </object> + </child> + </template> +</interface> diff --git a/data/gl-window.ui b/data/gl-window.ui index 4c67596..6f41df1 100644 --- a/data/gl-window.ui +++ b/data/gl-window.ui @@ -13,48 +13,8 @@ </object> </child> <child> - <object class="GtkBox" id="content"> - <property name="orientation">horizontal</property> + <object class="GlEventView" id="event"> <property name="visible">True</property> - <child> - <object class="GlCategoryList" id="categories"> - <property name="visible">True</property> - <style> - <class name="categories"/> - </style> - </object> - </child> - <child> - <object class="GtkSeparator" id="content_separator"> - <property name="orientation">vertical</property> - <property name="visible">True</property> - </object> - </child> - <child> - <object class="GtkBox" id="event_view"> - <property name="orientation">vertical</property> - <property name="visible">True</property> - <child> - <object class="GtkSearchBar" id="event_search"> - <property name="visible">True</property> - <signal name="notify::search-mode-enabled" handler="on_gl_window_search_bar_notify_search_mode_enabled"/> - <child> - <object class="GtkSearchEntry" id="search_entry"> - <property name="visible">True</property> - <property name="width-request">400</property> - <signal name="search-changed" handler="on_gl_window_search_entry_changed" /> - </object> - </child> - </object> - </child> - <child> - <object class="GlEventViewList" id="events"> - <property name="expand">True</property> - <property name="visible">True</property> - </object> - </child> - </object> - </child> </object> </child> </template> diff --git a/data/org.gnome.Logs.gresource.xml b/data/org.gnome.Logs.gresource.xml index 2b0ec8a..46d38a3 100644 --- a/data/org.gnome.Logs.gresource.xml +++ b/data/org.gnome.Logs.gresource.xml @@ -2,6 +2,8 @@ <gresources> <gresource prefix='/org/gnome/Logs'> <file preprocess='xml-stripblanks'>gl-categorylist.ui</file> + <file preprocess='xml-stripblanks'>gl-eventview.ui</file> + <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>gl-style.css</file> diff --git a/src/gl-application.c b/src/gl-application.c index 49ccaaa..8f3dcd0 100644 --- a/src/gl-application.c +++ b/src/gl-application.c @@ -23,6 +23,7 @@ #include "gl-categorylist.h" #include "gl-eventtoolbar.h" +#include "gl-eventview.h" #include "gl-eventviewlist.h" #include "gl-util.h" #include "gl-window.h" @@ -177,6 +178,7 @@ gl_application_startup (GApplication *application) gl_window_get_type (); gl_category_list_get_type (); gl_event_toolbar_get_type (); + gl_event_view_get_type (); gl_event_view_list_get_type (); } diff --git a/src/gl-categorylist.c b/src/gl-categorylist.c index 4d7e20f..d17bb08 100644 --- a/src/gl-categorylist.c +++ b/src/gl-categorylist.c @@ -23,6 +23,13 @@ #include "gl-enums.h" #include "gl-eventviewlist.h" +enum +{ + PROP_0, + PROP_CATEGORY, + N_PROPERTIES +}; + typedef struct { GtkWidget *important; @@ -35,10 +42,13 @@ typedef struct GtkWidget *hardware; GtkWidget *updates; GtkWidget *usage; + GlCategoryListFilter category; } GlCategoryListPrivate; G_DEFINE_TYPE_WITH_PRIVATE (GlCategoryList, gl_category_list, GTK_TYPE_LIST_BOX) +static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; + static gboolean gl_category_list_focus (GtkWidget *listbox, GtkDirectionType direction) { @@ -75,86 +85,137 @@ on_gl_category_list_row_selected (GlCategoryList *listbox, gpointer user_data) { GlCategoryListPrivate *priv; - GtkWidget *toplevel; - GActionMap *appwindow; - GAction *category; GEnumClass *eclass; GEnumValue *evalue; priv = gl_category_list_get_instance_private (listbox); - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (listbox)); - - if (gtk_widget_is_toplevel (toplevel)) - { - appwindow = G_ACTION_MAP (toplevel); - category = g_action_map_lookup_action (appwindow, "category"); - } - else - { - /* TODO: Investigate whether this only happens during dispose. */ - g_debug ("%s", - "Category list row selected while not in a toplevel"); - return; - } - - eclass = g_type_class_ref (GL_TYPE_EVENT_VIEW_LIST_FILTER); + eclass = g_type_class_ref (GL_TYPE_CATEGORY_LIST_FILTER); if (row == GTK_LIST_BOX_ROW (priv->important)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_IMPORTANT); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_IMPORTANT); } else if (row == GTK_LIST_BOX_ROW (priv->alerts)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_ALERTS); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_ALERTS); } else if (row == GTK_LIST_BOX_ROW (priv->starred)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_STARRED); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_STARRED); } else if (row == GTK_LIST_BOX_ROW (priv->all)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_ALL); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_ALL); } else if (row == GTK_LIST_BOX_ROW (priv->applications)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_APPLICATIONS); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_APPLICATIONS); } else if (row == GTK_LIST_BOX_ROW (priv->system)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_SYSTEM); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_SYSTEM); } else if (row == GTK_LIST_BOX_ROW (priv->security)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_SECURITY); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_SECURITY); } else if (row == GTK_LIST_BOX_ROW (priv->hardware)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_HARDWARE); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_HARDWARE); } else if (row == GTK_LIST_BOX_ROW (priv->updates)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_UPDATES); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_UPDATES); } else if (row == GTK_LIST_BOX_ROW (priv->usage)) { - evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_LIST_FILTER_USAGE); + evalue = g_enum_get_value (eclass, GL_CATEGORY_LIST_FILTER_USAGE); } else { - g_assert_not_reached (); + /* This is only for the occasion when GlCategoryList is destroyed, + * in other words when there are no children for GlCategoryList */ + return; } - g_action_activate (category, g_variant_new_string (evalue->value_nick)); + priv->category = evalue->value; + + g_object_notify_by_pspec (G_OBJECT (listbox), + obj_properties[PROP_CATEGORY]); g_type_class_unref (eclass); } +GlCategoryListFilter +gl_category_list_get_category (GlCategoryList *list) +{ + GlCategoryListPrivate *priv; + + priv = gl_category_list_get_instance_private (list); + + return priv->category; +} + +static void +gl_category_list_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GlCategoryList *list = GL_CATEGORY_LIST (object); + GlCategoryListPrivate *priv = gl_category_list_get_instance_private (list); + + switch (prop_id) + { + case PROP_CATEGORY: + g_value_set_enum (value, priv->category); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gl_category_list_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GlCategoryList *list = GL_CATEGORY_LIST (object); + GlCategoryListPrivate *priv = gl_category_list_get_instance_private (list); + + switch (prop_id) + { + case PROP_CATEGORY: + priv->category = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static void gl_category_list_class_init (GlCategoryListClass *klass) { + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + gobject_class->get_property = gl_category_list_get_property; + gobject_class->set_property = gl_category_list_set_property; widget_class->focus = gl_category_list_focus; + + obj_properties[PROP_CATEGORY] = g_param_spec_enum ("category", "Category", + "Filter events by", + GL_TYPE_CATEGORY_LIST_FILTER, + GL_CATEGORY_LIST_FILTER_ALL, + 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-categorylist.ui"); gtk_widget_class_bind_template_child_private (widget_class, GlCategoryList, @@ -201,6 +262,7 @@ gl_category_list_init (GlCategoryList *list) GlCategoryListPrivate *priv; gtk_widget_init_template (GTK_WIDGET (list)); + priv = gl_category_list_get_instance_private (list); gtk_list_box_set_header_func (GTK_LIST_BOX (list), (GtkListBoxUpdateHeaderFunc)gl_category_list_header_func, diff --git a/src/gl-categorylist.h b/src/gl-categorylist.h index 3dd8cea..32f3b79 100644 --- a/src/gl-categorylist.h +++ b/src/gl-categorylist.h @@ -35,11 +35,41 @@ typedef struct GtkListBoxClass parent_class; } GlCategoryListClass; +/* + * GlCategoryListFilter: + * @GL_CATEGORY_LIST_FILTER_IMPORTANT: + * @GL_CATEGORY_LIST_FILTER_ALERTS: + * @GL_CATEGORY_LIST_FILTER_STARRED: + * @GL_CATEGORY_LIST_FILTER_ALL: + * @GL_CATEGORY_LIST_FILTER_APPLICATIONS: + * @GL_CATEGORY_LIST_FILTER_SYSTEM: + * @GL_CATEGORY_LIST_FILTER_SECURITY: + * @GL_CATEGORY_LIST_FILTER_HARDWARE: + * @GL_CATEGORY_LIST_FILTER_UPDATES: + * @GL_CATEGORY_LIST_FILTER_USAGE: + * + * The category, selected in #GlCategoryList, to filter the events by. + */ +typedef enum +{ + GL_CATEGORY_LIST_FILTER_IMPORTANT, + GL_CATEGORY_LIST_FILTER_ALERTS, + GL_CATEGORY_LIST_FILTER_STARRED, + GL_CATEGORY_LIST_FILTER_ALL, + GL_CATEGORY_LIST_FILTER_APPLICATIONS, + GL_CATEGORY_LIST_FILTER_SYSTEM, + GL_CATEGORY_LIST_FILTER_SECURITY, + GL_CATEGORY_LIST_FILTER_HARDWARE, + GL_CATEGORY_LIST_FILTER_UPDATES, + GL_CATEGORY_LIST_FILTER_USAGE +} GlCategoryListFilter; + #define GL_TYPE_CATEGORY_LIST (gl_category_list_get_type ()) #define GL_CATEGORY_LIST(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GL_TYPE_CATEGORY_LIST, GlCategoryList)) GType gl_category_list_get_type (void); GtkWidget * gl_category_list_new (void); +GlCategoryListFilter gl_category_list_get_category (GlCategoryList *list); G_END_DECLS diff --git a/src/gl-eventview.c b/src/gl-eventview.c new file mode 100644 index 0000000..1df5148 --- /dev/null +++ b/src/gl-eventview.c @@ -0,0 +1,253 @@ +/* + * GNOME Logs - View and search logs + * Copyright (C) 2014 Red Hat, Inc. + * Copyright (C) 2014 Jonathan Kang + * + * 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-eventview.h" + +#include <glib/gi18n.h> +#include <glib-unix.h> +#include <stdlib.h> + +#include "gl-categorylist.h" +#include "gl-enums.h" +#include "gl-eventtoolbar.h" +#include "gl-eventviewdetail.h" +#include "gl-eventviewlist.h" +#include "gl-journal.h" +#include "gl-util.h" + +enum +{ + PROP_0, + PROP_MODE, + N_PROPERTIES +}; + +typedef struct +{ + GtkWidget *events; + GlJournalResult *result; + GlUtilClockFormat clock_format; + GlEventViewMode mode; +} GlEventViewPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (GlEventView, gl_event_view, GTK_TYPE_STACK) + +static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; +static const gchar DESKTOP_SCHEMA[] = "org.gnome.desktop.interface"; +static const gchar CLOCK_FORMAT[] = "clock-format"; + +void +gl_event_view_show_detail (GlEventView *view) +{ + GlEventViewList *events; + GlEventViewPrivate *priv; + + g_return_if_fail (GL_EVENT_VIEW (view)); + + priv = gl_event_view_get_instance_private (view); + events = GL_EVENT_VIEW_LIST (priv->events); + priv->result = gl_event_view_list_get_detail_result (events); +} + +gboolean +gl_event_view_handle_search_event (GlEventView *view, + GAction *action, + GdkEvent *event) +{ + GlEventViewPrivate *priv; + GlEventViewList *events; + + priv = gl_event_view_get_instance_private (view); + events = GL_EVENT_VIEW_LIST (priv->events); + + if (gl_event_view_list_handle_search_event (events, action, + event) == GDK_EVENT_STOP) + { + return GDK_EVENT_STOP; + } + + return GDK_EVENT_PROPAGATE; +} + +void +gl_event_view_set_search_mode (GlEventView *view, + gboolean state) +{ + GlEventViewPrivate *priv; + GlEventViewList *events; + + g_return_if_fail (GL_EVENT_VIEW (view)); + + priv = gl_event_view_get_instance_private (view); + events = GL_EVENT_VIEW_LIST (priv->events); + + gl_event_view_list_set_search_mode (events, state); +} + +static void +on_notify_mode (GlEventView *view, + GParamSpec *pspec, + gpointer user_data) +{ + GlEventViewPrivate *priv; + GtkStack *stack; + GtkWidget *detail; + + priv = gl_event_view_get_instance_private (view); + stack = GTK_STACK (view); + + switch (priv->mode) + { + case GL_EVENT_VIEW_MODE_LIST: + { + GtkWidget *child; + + child = gtk_stack_get_child_by_name (stack, "detail"); + + if (child) + { + gtk_container_remove (GTK_CONTAINER (stack), child); + } + + gtk_stack_set_visible_child (stack, priv->events); + } + break; + case GL_EVENT_VIEW_MODE_DETAIL: + { + gl_event_view_show_detail (view); + detail = gl_event_view_detail_new (priv->result, + priv->clock_format); + gtk_widget_show_all (detail); + gtk_stack_add_named (stack, detail, "detail"); + gtk_stack_set_visible_child_name (stack, "detail"); + } + break; + default: + g_assert_not_reached (); + break; + } +} + +static void +gl_event_view_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GlEventView *view = GL_EVENT_VIEW (object); + GlEventViewPrivate *priv = gl_event_view_get_instance_private (view); + + switch (prop_id) + { + case PROP_MODE: + g_value_set_enum (value, priv->mode); + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gl_event_view_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GlEventView *view = GL_EVENT_VIEW (object); + GlEventViewPrivate *priv = gl_event_view_get_instance_private (view); + + switch (prop_id) + { + case PROP_MODE: + priv->mode = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gl_event_view_class_init (GlEventViewClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + gobject_class->get_property = gl_event_view_get_property; + gobject_class->set_property = gl_event_view_set_property; + + obj_properties[PROP_MODE] = g_param_spec_enum ("mode", "Mode", + "Event display mode", + GL_TYPE_EVENT_VIEW_MODE, + GL_EVENT_VIEW_MODE_LIST, + 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-eventview.ui"); + gtk_widget_class_bind_template_child_private (widget_class, GlEventView, + events); +} + +static void +gl_event_view_init (GlEventView *view) +{ + GlEventViewPrivate *priv; + GSettings *settings; + + gtk_widget_init_template (GTK_WIDGET (view)); + + priv = gl_event_view_get_instance_private (view); + + /* TODO: Monitor and propagate any GSettings changes. */ + settings = g_settings_new (DESKTOP_SCHEMA); + priv->clock_format = g_settings_get_enum (settings, CLOCK_FORMAT); + + g_object_unref (settings); + + g_signal_connect (view, "notify::mode", G_CALLBACK (on_notify_mode), + NULL); +} + +void +gl_event_view_set_mode (GlEventView *view, + GlEventViewMode mode) +{ + GlEventViewPrivate *priv; + + g_return_if_fail (GL_EVENT_VIEW (view)); + + priv = gl_event_view_get_instance_private (view); + + if (priv->mode != mode) + { + priv->mode = mode; + g_object_notify_by_pspec (G_OBJECT (view), + obj_properties[PROP_MODE]); + } +} + +GtkWidget * +gl_event_view_new (void) +{ + return g_object_new (GL_TYPE_EVENT_VIEW, NULL); +} diff --git a/src/gl-eventview.h b/src/gl-eventview.h new file mode 100644 index 0000000..67e6e1a --- /dev/null +++ b/src/gl-eventview.h @@ -0,0 +1,65 @@ +/* + * GNOME Logs - View and search logs + * Copyright (C) 2014 Red Hat, Inc. + * Copyright (C) 2014 Jonathan Kang + * + * 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_EVENT_VIEW_H_ +#define GL_EVENT_VIEW_H_ + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +typedef struct +{ + /*< private >*/ + GtkStack parent_instance; +} GlEventView; + +typedef struct +{ + /*< private >*/ + GtkStackClass parent_class; +} GlEventViewClass; + +/* + * GlEventViewMode: + * @GL_EVENT_VIEW_MODE_LIST: + * @GL_EVENT_VIEW_MODE_DETAIL: + * + * The mode, mirroring the GlEventToolbar mode, used to show events. + */ +typedef enum +{ + GL_EVENT_VIEW_MODE_LIST, + GL_EVENT_VIEW_MODE_DETAIL +} GlEventViewMode; + +#define GL_TYPE_EVENT_VIEW (gl_event_view_get_type ()) +#define GL_EVENT_VIEW(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GL_TYPE_EVENT_VIEW, GlEventView)) + +GType gl_event_view_get_type (void); +GtkWidget * gl_event_view_new (void); +void gl_event_view_search (GlEventView *view, const gchar *needle); +void gl_event_view_set_mode (GlEventView *view, GlEventViewMode mode); +void gl_event_view_show_detail (GlEventView *view); +gboolean gl_event_view_handle_search_event (GlEventView *view, GAction *action, GdkEvent *event); +void gl_event_view_set_search_mode (GlEventView *view, gboolean state); + +G_END_DECLS + +#endif /* GL_EVENT_VIEW_H_ */ diff --git a/src/gl-eventviewlist.c b/src/gl-eventviewlist.c index 1c51190..0588536 100644 --- a/src/gl-eventviewlist.c +++ b/src/gl-eventviewlist.c @@ -22,28 +22,25 @@ #include <glib-unix.h> #include <stdlib.h> +#include "gl-categorylist.h" #include "gl-enums.h" #include "gl-eventtoolbar.h" +#include "gl-eventview.h" #include "gl-eventviewdetail.h" #include "gl-eventviewrow.h" #include "gl-journal.h" #include "gl-util.h" -enum -{ - PROP_0, - PROP_FILTER, - PROP_MODE, - N_PROPERTIES -}; - typedef struct { GlJournal *journal; + GlJournalResult *result; GlUtilClockFormat clock_format; - GlEventViewListFilter filter; GtkListBox *active_listbox; - GlEventViewMode mode; + GtkWidget *categories; + GtkWidget *event_search; + GtkWidget *event_stack; + GtkWidget *search_entry; gchar *search_text; GtkListBox *results_listbox; @@ -52,9 +49,8 @@ typedef struct guint insert_idle_id; } GlEventViewListPrivate; -G_DEFINE_TYPE_WITH_PRIVATE (GlEventViewList, gl_event_view_list, GTK_TYPE_STACK) +G_DEFINE_TYPE_WITH_PRIVATE (GlEventViewList, gl_event_view_list, GTK_TYPE_BOX) -static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; static const gssize N_RESULTS = -1; static const gssize N_RESULTS_IDLE = 25; static const gchar DESKTOP_SCHEMA[] = "org.gnome.desktop.interface"; @@ -171,20 +167,87 @@ on_listbox_row_activated (GtkListBox *listbox, GlEventViewList *view) { GlEventViewListPrivate *priv; - GlJournalResult *result; - GtkWidget *detail; - GtkStack *stack; + GtkWidget *toplevel; priv = gl_event_view_list_get_instance_private (view); - result = gl_event_view_row_get_result (GL_EVENT_VIEW_ROW (row)); + priv->result = gl_event_view_row_get_result (GL_EVENT_VIEW_ROW (row)); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view)); + + if (gtk_widget_is_toplevel (toplevel)) + { + GAction *mode; + GEnumClass *eclass; + GEnumValue *evalue; + + mode = g_action_map_lookup_action (G_ACTION_MAP (toplevel), "view-mode"); + eclass = g_type_class_ref (GL_TYPE_EVENT_VIEW_MODE); + evalue = g_enum_get_value (eclass, GL_EVENT_VIEW_MODE_DETAIL); + + g_action_activate (mode, g_variant_new_string (evalue->value_nick)); + + g_type_class_unref (eclass); + } + else + { + g_debug ("Widget not in toplevel window, not switching toolbar mode"); + } +} - detail = gl_event_view_detail_new (result, priv->clock_format); +GlJournalResult * +gl_event_view_list_get_detail_result (GlEventViewList *view) +{ + GlEventViewListPrivate *priv; - gtk_widget_show_all (detail); + priv = gl_event_view_list_get_instance_private (view); - stack = GTK_STACK (view); - gtk_stack_add_named (stack, detail, "detail"); - gl_event_view_list_set_mode (view, GL_EVENT_VIEW_MODE_DETAIL); + return priv->result; +} + +gboolean +gl_event_view_list_handle_search_event (GlEventViewList *view, + GAction *action, + GdkEvent *event) +{ + GlEventViewListPrivate *priv; + + priv = gl_event_view_list_get_instance_private (view); + + if (g_action_get_enabled (action)) + { + if (gtk_search_bar_handle_event (GTK_SEARCH_BAR (priv->event_search), + event) == GDK_EVENT_STOP) + { + g_action_change_state (action, g_variant_new_boolean (TRUE)); + + return GDK_EVENT_STOP; + } + } + + return GDK_EVENT_PROPAGATE; +} + +void +gl_event_view_list_set_search_mode (GlEventViewList *view, + gboolean state) +{ + GlEventViewListPrivate *priv; + + g_return_if_fail (GL_EVENT_VIEW_LIST (view)); + + priv = gl_event_view_list_get_instance_private (view); + + gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->event_search), state); + + if (state) + { + gtk_widget_grab_focus (priv->search_entry); + gtk_editable_set_position (GTK_EDITABLE (priv->search_entry), -1); + } + else + { + gtk_entry_set_text (GTK_ENTRY (priv->search_entry), ""); + } } static GtkWidget * @@ -238,7 +301,7 @@ gl_event_view_list_box_new (GlEventViewList *view) gtk_list_box_set_selection_mode (GTK_LIST_BOX (listbox), GTK_SELECTION_NONE); g_signal_connect (listbox, "row-activated", - G_CALLBACK (on_listbox_row_activated), GTK_STACK (view)); + G_CALLBACK (on_listbox_row_activated), GTK_BOX (view)); return listbox; } @@ -583,7 +646,9 @@ gl_event_view_list_add_listbox_important (GlEventViewList *view) NULL } }; GtkWidget *listbox; GtkWidget *scrolled; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); listbox = gl_event_view_list_box_new (view); insert_journal_query_cmdline (view, &query, @@ -592,27 +657,34 @@ gl_event_view_list_add_listbox_important (GlEventViewList *view) scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (scrolled), listbox); gtk_widget_show_all (scrolled); - gtk_stack_add_named (GTK_STACK (view), scrolled, "listbox-important"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), scrolled, + "listbox-important"); } static void gl_event_view_list_add_listbox_alerts (GlEventViewList *view) { GtkWidget *label; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); label = gtk_label_new (_("Not implemented")); gtk_widget_show_all (label); - gtk_stack_add_named (GTK_STACK (view), label, "listbox-alerts"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), label, + "listbox-alerts"); } static void gl_event_view_list_add_listbox_starred (GlEventViewList *view) { GtkWidget *label; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); label = gtk_label_new (_("Not implemented")); gtk_widget_show_all (label); - gtk_stack_add_named (GTK_STACK (view), label, "listbox-starred"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), label, + "listbox-starred"); } static void @@ -621,7 +693,9 @@ gl_event_view_list_add_listbox_all (GlEventViewList *view) const GlJournalQuery query = { N_RESULTS, NULL }; GtkWidget *listbox; GtkWidget *scrolled; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); listbox = gl_event_view_list_box_new (view); insert_journal_query_cmdline (view, &query, GTK_LIST_BOX (listbox)); @@ -629,7 +703,8 @@ gl_event_view_list_add_listbox_all (GlEventViewList *view) scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (scrolled), listbox); gtk_widget_show_all (scrolled); - gtk_stack_add_named (GTK_STACK (view), scrolled, "listbox-all"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), scrolled, + "listbox-all"); } static void @@ -639,7 +714,9 @@ gl_event_view_list_add_listbox_applications (GlEventViewList *view) uid_t uid; GtkWidget *listbox; GtkWidget *scrolled; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); listbox = gl_event_view_list_box_new (view); creds = g_credentials_new (); uid = g_credentials_get_unix_user (creds, NULL); @@ -678,7 +755,8 @@ gl_event_view_list_add_listbox_applications (GlEventViewList *view) scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (scrolled), listbox); gtk_widget_show_all (scrolled); - gtk_stack_add_named (GTK_STACK (view), scrolled, "listbox-applications"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), scrolled, + "listbox-applications"); g_object_unref (creds); } @@ -690,7 +768,9 @@ gl_event_view_list_add_listbox_system (GlEventViewList *view) (gchar *[2]){ "_TRANSPORT=kernel", NULL } }; GtkWidget *listbox; GtkWidget *scrolled; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); listbox = gl_event_view_list_box_new (view); insert_journal_query_simple (view, &query, GTK_LIST_BOX (listbox)); @@ -698,7 +778,8 @@ gl_event_view_list_add_listbox_system (GlEventViewList *view) scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (scrolled), listbox); gtk_widget_show_all (scrolled); - gtk_stack_add_named (GTK_STACK (view), scrolled, "listbox-system"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), scrolled, + "listbox-system"); } static void @@ -708,7 +789,9 @@ gl_event_view_list_add_listbox_hardware (GlEventViewList *view) (gchar *[2]){ "_TRANSPORT=kernel", NULL } }; GtkWidget *listbox; GtkWidget *scrolled; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); listbox = gl_event_view_list_box_new (view); insert_journal_query_devices (view, &query, GTK_LIST_BOX (listbox)); @@ -716,7 +799,8 @@ gl_event_view_list_add_listbox_hardware (GlEventViewList *view) scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (scrolled), listbox); gtk_widget_show_all (scrolled); - gtk_stack_add_named (GTK_STACK (view), scrolled, "listbox-hardware"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), scrolled, + "listbox-hardware"); } static void @@ -725,7 +809,9 @@ gl_event_view_list_add_listbox_security (GlEventViewList *view) const GlJournalQuery query = { N_RESULTS, NULL }; GtkWidget *listbox; GtkWidget *scrolled; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); listbox = gl_event_view_list_box_new (view); insert_journal_query_security (view, &query, GTK_LIST_BOX (listbox)); @@ -733,41 +819,52 @@ gl_event_view_list_add_listbox_security (GlEventViewList *view) scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (scrolled), listbox); gtk_widget_show_all (scrolled); - gtk_stack_add_named (GTK_STACK (view), scrolled, "listbox-security"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), scrolled, + "listbox-security"); } static void gl_event_view_list_add_listbox_updates (GlEventViewList *view) { GtkWidget *label; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); label = gtk_label_new (_("Not implemented")); gtk_widget_show_all (label); - gtk_stack_add_named (GTK_STACK (view), label, "listbox-updates"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), label, + "listbox-updates"); } static void gl_event_view_list_add_listbox_usage (GlEventViewList *view) { GtkWidget *label; + GlEventViewListPrivate *priv; + priv = gl_event_view_list_get_instance_private (view); label = gtk_label_new (_("Not implemented")); gtk_widget_show_all (label); - gtk_stack_add_named (GTK_STACK (view), label, "listbox-usage"); + gtk_stack_add_named (GTK_STACK (priv->event_stack), label, + "listbox-usage"); } static void -on_notify_filter (GlEventViewList *view, - G_GNUC_UNUSED GParamSpec *pspec, - G_GNUC_UNUSED gpointer user_data) +on_notify_category (GlCategoryList *list, + GParamSpec *pspec, + gpointer user_data) { + GlCategoryListFilter filter; + GlEventViewList *view; GlEventViewListPrivate *priv; GtkStack *stack; GtkWidget *scrolled; GtkWidget *viewport; + view = GL_EVENT_VIEW_LIST (user_data); priv = gl_event_view_list_get_instance_private (view); - stack = GTK_STACK (view); + stack = GTK_STACK (priv->event_stack); + filter = gl_category_list_get_category (list); if (priv->active_listbox) { @@ -777,45 +874,45 @@ on_notify_filter (GlEventViewList *view, gtk_widget_destroy (child); } - switch (priv->filter) + switch (filter) { - case GL_EVENT_VIEW_LIST_FILTER_IMPORTANT: + case GL_CATEGORY_LIST_FILTER_IMPORTANT: gl_event_view_list_add_listbox_important (view); gtk_stack_set_visible_child_name (stack, "listbox-important"); break; - case GL_EVENT_VIEW_LIST_FILTER_ALERTS: + case GL_CATEGORY_LIST_FILTER_ALERTS: gl_event_view_list_add_listbox_alerts (view); gtk_stack_set_visible_child_name (stack, "listbox-alerts"); break; - case GL_EVENT_VIEW_LIST_FILTER_STARRED: + case GL_CATEGORY_LIST_FILTER_STARRED: gl_event_view_list_add_listbox_starred (view); gtk_stack_set_visible_child_name (stack, "listbox-starred"); break; - case GL_EVENT_VIEW_LIST_FILTER_ALL: + case GL_CATEGORY_LIST_FILTER_ALL: gl_event_view_list_add_listbox_all (view); gtk_stack_set_visible_child_name (stack, "listbox-all"); break; - case GL_EVENT_VIEW_LIST_FILTER_APPLICATIONS: + case GL_CATEGORY_LIST_FILTER_APPLICATIONS: gl_event_view_list_add_listbox_applications (view); gtk_stack_set_visible_child_name (stack, "listbox-applications"); break; - case GL_EVENT_VIEW_LIST_FILTER_SYSTEM: + case GL_CATEGORY_LIST_FILTER_SYSTEM: gl_event_view_list_add_listbox_system (view); gtk_stack_set_visible_child_name (stack, "listbox-system"); break; - case GL_EVENT_VIEW_LIST_FILTER_HARDWARE: + case GL_CATEGORY_LIST_FILTER_HARDWARE: gl_event_view_list_add_listbox_hardware (view); gtk_stack_set_visible_child_name (stack, "listbox-hardware"); break; - case GL_EVENT_VIEW_LIST_FILTER_SECURITY: + case GL_CATEGORY_LIST_FILTER_SECURITY: gl_event_view_list_add_listbox_security (view); gtk_stack_set_visible_child_name (stack, "listbox-security"); break; - case GL_EVENT_VIEW_LIST_FILTER_UPDATES: + case GL_CATEGORY_LIST_FILTER_UPDATES: gl_event_view_list_add_listbox_updates (view); gtk_stack_set_visible_child_name (stack, "listbox-updates"); break; - case GL_EVENT_VIEW_LIST_FILTER_USAGE: + case GL_CATEGORY_LIST_FILTER_USAGE: gl_event_view_list_add_listbox_usage (view); gtk_stack_set_visible_child_name (stack, "listbox-usage"); break; @@ -826,70 +923,46 @@ on_notify_filter (GlEventViewList *view, scrolled = gtk_stack_get_visible_child (stack); viewport = gtk_bin_get_child (GTK_BIN (scrolled)); priv->active_listbox = GTK_LIST_BOX (gtk_bin_get_child (GTK_BIN (viewport))); - - gl_event_view_list_set_mode (view, GL_EVENT_VIEW_MODE_LIST); } static void -on_notify_mode (GlEventViewList *view, - GParamSpec *pspec, - gpointer user_data) +on_search_entry_changed (GtkSearchEntry *entry, + gpointer user_data) { GlEventViewListPrivate *priv; - GtkStack *stack; - GtkWidget *toplevel; - priv = gl_event_view_list_get_instance_private (view); - stack = GTK_STACK (view); + priv = gl_event_view_list_get_instance_private (GL_EVENT_VIEW_LIST (user_data)); - switch (priv->mode) - { - case GL_EVENT_VIEW_MODE_LIST: - { - GtkWidget *child; - GtkWidget *viewport; - GtkWidget *scrolled_window; - - child = gtk_stack_get_child_by_name (stack, "detail"); - - if (child) - { - gtk_container_remove (GTK_CONTAINER (stack), child); - } + gl_event_view_list_search (GL_EVENT_VIEW_LIST (user_data), + gtk_entry_get_text (GTK_ENTRY (priv->search_entry))); +} - viewport = gtk_widget_get_parent (GTK_WIDGET (priv->active_listbox)); - scrolled_window = gtk_widget_get_parent (viewport); - gtk_stack_set_visible_child (stack, scrolled_window); - } - break; - case GL_EVENT_VIEW_MODE_DETAIL: - gtk_stack_set_visible_child_name (stack, "detail"); - break; - default: - g_assert_not_reached (); - break; - } +static void +on_search_bar_notify_search_mode_enabled (GtkSearchBar *search_bar, + GParamSpec *pspec, + gpointer user_data) +{ + GAction *search; + GtkWidget *toplevel; + GActionMap *appwindow; - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view)); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (user_data)); if (gtk_widget_is_toplevel (toplevel)) { - GAction *mode; - GEnumClass *eclass; - GEnumValue *evalue; - - mode = g_action_map_lookup_action (G_ACTION_MAP (toplevel), "view-mode"); - eclass = g_type_class_ref (GL_TYPE_EVENT_VIEW_MODE); - evalue = g_enum_get_value (eclass, priv->mode); - - g_action_activate (mode, g_variant_new_string (evalue->value_nick)); - - g_type_class_unref (eclass); + appwindow = G_ACTION_MAP (toplevel); + search = g_action_map_lookup_action (appwindow, "search"); } else { - g_debug ("Widget not in toplevel window, not switching toolbar mode"); + /* TODO: Investigate whether this only happens during dispose. */ + g_debug ("%s", + "Search bar activated while not in a toplevel"); + return; } + + g_action_change_state (search, + g_variant_new_boolean (gtk_search_bar_get_search_mode (search_bar))); } static void @@ -908,102 +981,53 @@ gl_event_view_list_finalize (GObject *object) } static void -gl_event_view_list_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GlEventViewList *view = GL_EVENT_VIEW_LIST (object); - GlEventViewListPrivate *priv = gl_event_view_list_get_instance_private (view); - - switch (prop_id) - { - case PROP_FILTER: - g_value_set_enum (value, priv->filter); - break; - case PROP_MODE: - g_value_set_enum (value, priv->mode); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gl_event_view_list_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GlEventViewList *view = GL_EVENT_VIEW_LIST (object); - GlEventViewListPrivate *priv = gl_event_view_list_get_instance_private (view); - - switch (prop_id) - { - case PROP_FILTER: - priv->filter = g_value_get_enum (value); - break; - case PROP_MODE: - priv->mode = g_value_get_enum (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void gl_event_view_list_class_init (GlEventViewListClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); gobject_class->finalize = gl_event_view_list_finalize; - gobject_class->get_property = gl_event_view_list_get_property; - gobject_class->set_property = gl_event_view_list_set_property; - - obj_properties[PROP_FILTER] = g_param_spec_enum ("filter", "Filter", - "Filter events by", - GL_TYPE_EVENT_VIEW_LIST_FILTER, - GL_EVENT_VIEW_LIST_FILTER_IMPORTANT, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_MODE] = g_param_spec_enum ("mode", "Mode", - "Event display mode", - GL_TYPE_EVENT_VIEW_MODE, - GL_EVENT_VIEW_MODE_LIST, - 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-eventviewlist.ui"); + gtk_widget_class_bind_template_child_private (widget_class, GlEventViewList, + categories); + gtk_widget_class_bind_template_child_private (widget_class, GlEventViewList, + event_search); + gtk_widget_class_bind_template_child_private (widget_class, GlEventViewList, + event_stack); + gtk_widget_class_bind_template_child_private (widget_class, GlEventViewList, + search_entry); + + gtk_widget_class_bind_template_callback (widget_class, + on_search_entry_changed); + gtk_widget_class_bind_template_callback (widget_class, + on_search_bar_notify_search_mode_enabled); } static void gl_event_view_list_init (GlEventViewList *view) { + GlCategoryList *categories; GlEventViewListPrivate *priv; GSettings *settings; + gtk_widget_init_template (GTK_WIDGET (view)); + priv = gl_event_view_list_get_instance_private (view); priv->search_text = NULL; priv->active_listbox = NULL; priv->insert_idle_id = 0; priv->journal = gl_journal_new (); + categories = GL_CATEGORY_LIST (priv->categories); /* TODO: Monitor and propagate any GSettings changes. */ settings = g_settings_new (DESKTOP_SCHEMA); priv->clock_format = g_settings_get_enum (settings, CLOCK_FORMAT); g_object_unref (settings); - g_signal_connect (view, "notify::filter", G_CALLBACK (on_notify_filter), - NULL); - g_signal_connect (view, "notify::mode", G_CALLBACK (on_notify_mode), - NULL); - - /* Force an update of the active filter. */ - on_notify_filter (view, NULL, NULL); + g_signal_connect (categories, "notify::category", G_CALLBACK (on_notify_category), + view); } void @@ -1022,42 +1046,6 @@ gl_event_view_list_search (GlEventViewList *view, gtk_list_box_invalidate_filter (priv->active_listbox); } -void -gl_event_view_list_set_filter (GlEventViewList *view, - GlEventViewListFilter filter) -{ - GlEventViewListPrivate *priv; - - g_return_if_fail (GL_EVENT_VIEW_LIST (view)); - - priv = gl_event_view_list_get_instance_private (view); - - if (priv->filter != filter) - { - priv->filter = filter; - g_object_notify_by_pspec (G_OBJECT (view), - obj_properties[PROP_FILTER]); - } -} - -void -gl_event_view_list_set_mode (GlEventViewList *view, - GlEventViewMode mode) -{ - GlEventViewListPrivate *priv; - - g_return_if_fail (GL_EVENT_VIEW_LIST (view)); - - priv = gl_event_view_list_get_instance_private (view); - - if (priv->mode != mode) - { - priv->mode = mode; - g_object_notify_by_pspec (G_OBJECT (view), - obj_properties[PROP_MODE]); - } -} - GtkWidget * gl_event_view_list_new (void) { diff --git a/src/gl-eventviewlist.h b/src/gl-eventviewlist.h index d25cb57..22d50a0 100644 --- a/src/gl-eventviewlist.h +++ b/src/gl-eventviewlist.h @@ -20,71 +20,33 @@ #define GL_EVENT_VIEW_LIST_H_ #include <gtk/gtk.h> +#include "gl-journal.h" G_BEGIN_DECLS typedef struct { /*< private >*/ - GtkListBox parent_instance; + GtkBox parent_instance; } GlEventViewList; typedef struct { /*< private >*/ - GtkListBoxClass parent_class; + GtkBoxClass parent_class; } GlEventViewListClass; -/* - * GlEventViewListFilter: - * @GL_EVENT_VIEW_LIST_FILTER_IMPORTANT: - * @GL_EVENT_VIEW_LIST_FILTER_ALERTS: - * @GL_EVENT_VIEW_LIST_FILTER_STARRED: - * @GL_EVENT_VIEW_LIST_FILTER_ALL: - * @GL_EVENT_VIEW_LIST_FILTER_APPLICATIONS: - * @GL_EVENT_VIEW_LIST_FILTER_SYSTEM: - * @GL_EVENT_VIEW_LIST_FILTER_SECURITY: - * @GL_EVENT_VIEW_LIST_FILTER_HARDWARE: - * @GL_EVENT_VIEW_LIST_FILTER_UPDATES: - * @GL_EVENT_VIEW_LIST_FILTER_USAGE: - * - * The category, selected in #GlCategoryList, to filter the events by. - */ -typedef enum -{ - GL_EVENT_VIEW_LIST_FILTER_IMPORTANT, - GL_EVENT_VIEW_LIST_FILTER_ALERTS, - GL_EVENT_VIEW_LIST_FILTER_STARRED, - GL_EVENT_VIEW_LIST_FILTER_ALL, - GL_EVENT_VIEW_LIST_FILTER_APPLICATIONS, - GL_EVENT_VIEW_LIST_FILTER_SYSTEM, - GL_EVENT_VIEW_LIST_FILTER_SECURITY, - GL_EVENT_VIEW_LIST_FILTER_HARDWARE, - GL_EVENT_VIEW_LIST_FILTER_UPDATES, - GL_EVENT_VIEW_LIST_FILTER_USAGE -} GlEventViewListFilter; - -/* - * GlEventViewMode: - * @GL_EVENT_VIEW_MODE_LIST: - * @GL_EVENT_VIEW_MODE_DETAIL: - * - * The mode, mirroring the GlEventToolbar mode, used to show events. - */ -typedef enum -{ - GL_EVENT_VIEW_MODE_LIST, - GL_EVENT_VIEW_MODE_DETAIL -} GlEventViewMode; - #define GL_TYPE_EVENT_VIEW_LIST (gl_event_view_list_get_type ()) #define GL_EVENT_VIEW_LIST(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GL_TYPE_EVENT_VIEW_LIST, GlEventViewList)) GType gl_event_view_list_get_type (void); GtkWidget * gl_event_view_list_new (void); void gl_event_view_list_search (GlEventViewList *view, const gchar *needle); -void gl_event_view_list_set_filter (GlEventViewList *view, GlEventViewListFilter filter); -void gl_event_view_list_set_mode (GlEventViewList *view, GlEventViewMode mode); +GlJournalResult *gl_event_view_list_get_detail_result (GlEventViewList *view); +gboolean gl_event_view_list_handle_search_event (GlEventViewList *view, + GAction *action, + GdkEvent *event); +void gl_event_view_list_set_search_mode (GlEventViewList *view, gboolean state); G_END_DECLS diff --git a/src/gl-window.c b/src/gl-window.c index fbd93ae..fc6f6b6 100644 --- a/src/gl-window.c +++ b/src/gl-window.c @@ -22,6 +22,7 @@ #include "gl-categorylist.h" #include "gl-eventtoolbar.h" +#include "gl-eventview.h" #include "gl-eventviewlist.h" #include "gl-enums.h" #include "gl-util.h" @@ -29,9 +30,7 @@ typedef struct { GtkWidget *event_toolbar; - GtkWidget *event_search; - GtkWidget *search_entry; - GtkWidget *events; + GtkWidget *event; } GlWindowPrivate; G_DEFINE_TYPE_WITH_PRIVATE (GlWindow, gl_window, GTK_TYPE_APPLICATION_WINDOW) @@ -59,34 +58,7 @@ on_action_toggle (GSimpleAction *action, } static void -on_category (GSimpleAction *action, - GVariant *variant, - gpointer user_data) -{ - GlWindowPrivate *priv; - const gchar *category; - GlEventViewList *events; - GEnumClass *eclass; - GEnumValue *evalue; - - priv = gl_window_get_instance_private (GL_WINDOW (user_data)); - category = g_variant_get_string (variant, NULL); - events = GL_EVENT_VIEW_LIST (priv->events); - eclass = g_type_class_ref (GL_TYPE_EVENT_VIEW_LIST_FILTER); - evalue = g_enum_get_value_by_nick (eclass, category); - - /* First switch the event view back to list mode if the category - tab is clicked. */ - gl_event_view_list_set_mode (events, GL_EVENT_VIEW_MODE_LIST); - gl_event_view_list_set_filter (events, evalue->value); - - g_simple_action_set_state (action, variant); - - g_type_class_unref (eclass); -} - -static void -on_close (GSimpleAction *action, +on_close (GSimpleAction *action, GVariant *variant, gpointer user_data) { @@ -118,11 +90,11 @@ on_toolbar_mode (GSimpleAction *action, { /* Switch the event view back to list mode if the back button is * clicked. */ - GlEventViewList *view; + GlEventView *view; - view = GL_EVENT_VIEW_LIST (priv->events); + view = GL_EVENT_VIEW (priv->event); - gl_event_view_list_set_mode (view, GL_EVENT_VIEW_MODE_LIST); + gl_event_view_set_mode (view, GL_EVENT_VIEW_MODE_LIST); g_simple_action_set_enabled (G_SIMPLE_ACTION (search), TRUE); } @@ -145,11 +117,13 @@ on_view_mode (GSimpleAction *action, GlWindowPrivate *priv; const gchar *mode; GlEventToolbar *toolbar; + GlEventView *event; GEnumClass *eclass; GEnumValue *evalue; priv = gl_window_get_instance_private (GL_WINDOW (user_data)); mode = g_variant_get_string (variant, NULL); + event = GL_EVENT_VIEW (priv->event); toolbar = GL_EVENT_TOOLBAR (priv->event_toolbar); eclass = g_type_class_ref (GL_TYPE_EVENT_VIEW_MODE); evalue = g_enum_get_value_by_nick (eclass, mode); @@ -161,6 +135,7 @@ on_view_mode (GSimpleAction *action, break; case GL_EVENT_VIEW_MODE_DETAIL: gl_event_toolbar_set_mode (toolbar, GL_EVENT_TOOLBAR_MODE_DETAIL); + gl_event_view_set_mode (event, GL_EVENT_VIEW_MODE_DETAIL); break; } @@ -176,21 +151,13 @@ on_search (GSimpleAction *action, { gboolean state; GlWindowPrivate *priv; + GlEventView *view; state = g_variant_get_boolean (variant); priv = gl_window_get_instance_private (GL_WINDOW (user_data)); + view = GL_EVENT_VIEW (priv->event); - gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->event_search), state); - - if (state) - { - gtk_widget_grab_focus (priv->search_entry); - gtk_editable_set_position (GTK_EDITABLE (priv->search_entry), -1); - } - else - { - gtk_entry_set_text (GTK_ENTRY (priv->search_entry), ""); - } + gl_event_view_set_search_mode (view, state); g_simple_action_set_state (action, variant); } @@ -201,6 +168,7 @@ on_gl_window_key_press_event (GlWindow *window, gpointer user_data) { GlWindowPrivate *priv; + GlEventView *view; GAction *action; GVariant *variant; const gchar *mode; @@ -209,16 +177,11 @@ on_gl_window_key_press_event (GlWindow *window, priv = gl_window_get_instance_private (window); action = g_action_map_lookup_action (G_ACTION_MAP (window), "search"); + view = GL_EVENT_VIEW (priv->event); - if (g_action_get_enabled (action)) + if (gl_event_view_handle_search_event (view, action, event) == GDK_EVENT_STOP) { - if (gtk_search_bar_handle_event (GTK_SEARCH_BAR (priv->event_search), - event) == GDK_EVENT_STOP) - { - g_action_change_state (action, g_variant_new_boolean (TRUE)); - - return GDK_EVENT_STOP; - } + return GDK_EVENT_STOP; } action = g_action_map_lookup_action (G_ACTION_MAP (window), "view-mode"); @@ -238,10 +201,10 @@ on_gl_window_key_press_event (GlWindow *window, (GdkEventKey*)event) == GDK_EVENT_STOP) { - GlEventViewList *events; + GlEventView *view; - events = GL_EVENT_VIEW_LIST (priv->events); - gl_event_view_list_set_mode (events, GL_EVENT_VIEW_MODE_LIST); + view = GL_EVENT_VIEW (priv->event); + gl_event_view_set_mode (view, GL_EVENT_VIEW_MODE_LIST); g_type_class_unref (eclass); return GDK_EVENT_STOP; @@ -254,32 +217,7 @@ on_gl_window_key_press_event (GlWindow *window, return GDK_EVENT_PROPAGATE; } -static void -on_gl_window_search_entry_changed (GtkSearchEntry *entry, - gpointer user_data) -{ - GlWindowPrivate *priv; - - priv = gl_window_get_instance_private (GL_WINDOW (user_data)); - - gl_event_view_list_search (GL_EVENT_VIEW_LIST (priv->events), - gtk_entry_get_text (GTK_ENTRY (priv->search_entry))); -} - -static void -on_gl_window_search_bar_notify_search_mode_enabled (GtkSearchBar *search_bar, - GParamSpec *pspec, - gpointer user_data) -{ - GAction *search; - - search = g_action_map_lookup_action (G_ACTION_MAP (user_data), "search"); - g_action_change_state (search, - g_variant_new_boolean (gtk_search_bar_get_search_mode (search_bar))); -} - static GActionEntry actions[] = { - { "category", on_action_radio, "s", "'important'", on_category }, { "view-mode", on_action_radio, "s", "'list'", on_view_mode }, { "toolbar-mode", on_action_radio, "s", "'list'", on_toolbar_mode }, { "search", on_action_toggle, NULL, "false", on_search }, @@ -296,18 +234,10 @@ gl_window_class_init (GlWindowClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GlWindow, event_toolbar); gtk_widget_class_bind_template_child_private (widget_class, GlWindow, - event_search); - gtk_widget_class_bind_template_child_private (widget_class, GlWindow, - search_entry); - gtk_widget_class_bind_template_child_private (widget_class, GlWindow, - events); + event); gtk_widget_class_bind_template_callback (widget_class, on_gl_window_key_press_event); - gtk_widget_class_bind_template_callback (widget_class, - on_gl_window_search_entry_changed); - gtk_widget_class_bind_template_callback (widget_class, - on_gl_window_search_bar_notify_search_mode_enabled); } static void |