summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Kang <jonathan121537@gmail.com>2015-08-20 17:16:27 +0800
committerJonathan Kang <jonathan121537@gmail.com>2015-08-21 19:16:07 +0800
commit013a62cd56eb204d1a82dbdaef08c1528ee0b55d (patch)
treead584909e2f1f3d1e3fe7d8517d96f67c5137c63
parentaaf43a8a0c6bd65b631084934bedaa33d72c4349 (diff)
downloadgnome-logs-013a62cd56eb204d1a82dbdaef08c1528ee0b55d.tar.gz
Use GtkModelButton to improve boot selection menu
https://bugzilla.gnome.org/show_bug.cgi?id=752963
-rw-r--r--data/gl-eventtoolbar.ui9
-rw-r--r--data/gl-style.css5
-rw-r--r--src/gl-eventtoolbar.c82
-rw-r--r--src/gl-eventtoolbar.h2
-rw-r--r--src/gl-eventview.c13
-rw-r--r--src/gl-eventview.h2
-rw-r--r--src/gl-eventviewlist.c12
-rw-r--r--src/gl-eventviewlist.h2
-rw-r--r--src/gl-journal-model.c7
-rw-r--r--src/gl-journal-model.h3
-rw-r--r--src/gl-journal.c62
-rw-r--r--src/gl-journal.h5
-rw-r--r--src/gl-util.c38
-rw-r--r--src/gl-util.h2
-rw-r--r--src/gl-window.c29
15 files changed, 244 insertions, 29 deletions
diff --git a/data/gl-eventtoolbar.ui b/data/gl-eventtoolbar.ui
index c9bc84a..c42af57 100644
--- a/data/gl-eventtoolbar.ui
+++ b/data/gl-eventtoolbar.ui
@@ -2,7 +2,6 @@
<template class="GlEventToolbar" parent="GtkHeaderBar">
<property name="expand">True</property>
<property name="show-close-button">True</property>
- <property name="title" translatable="yes">Logs</property>
<property name="visible">True</property>
<child>
<object class="GtkButton" id="back_button">
@@ -21,19 +20,17 @@
</child>
</object>
</child>
- <child>
+ <child type="title">
<object class="GtkMenuButton" id="menu_button">
<property name="direction">none</property>
<property name="tooltip-text" translatable="yes">Choose the boot from which to view logs</property>
<property name="valign">center</property>
<property name="visible">True</property>
+ <property name="relief">GTK_RELIEF_NONE</property>
<style>
- <class name="image-button"/>
+ <class name="title-menu-button"/>
</style>
</object>
- <packing>
- <property name="pack-type">end</property>
- </packing>
</child>
<child>
<object class="GtkToggleButton" id="search_button">
diff --git a/data/gl-style.css b/data/gl-style.css
index b67aba1..491ee90 100644
--- a/data/gl-style.css
+++ b/data/gl-style.css
@@ -28,3 +28,8 @@
.event-time {
font-size: small;
}
+
+.title-menu-button {
+ padding-top: 0px;
+ padding-bottom: 0px;
+}
diff --git a/src/gl-eventtoolbar.c b/src/gl-eventtoolbar.c
index e1132d5..2da145b 100644
--- a/src/gl-eventtoolbar.c
+++ b/src/gl-eventtoolbar.c
@@ -39,6 +39,7 @@ struct _GlEventToolbar
typedef struct
{
+ GtkWidget *current_boot;
GtkWidget *back_button;
GtkWidget *menu_button;
GtkWidget *search_button;
@@ -52,30 +53,40 @@ static const gchar CLOCK_FORMAT[] = "clock-format";
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
void
+gl_event_toolbar_change_current_boot (GlEventToolbar *toolbar,
+ const gchar *current_boot)
+{
+ GlEventToolbarPrivate *priv;
+
+ priv = gl_event_toolbar_get_instance_private (toolbar);
+
+ /* set text to priv->current_boot */
+ gtk_label_set_text (GTK_LABEL (priv->current_boot), current_boot);
+}
+
+void
gl_event_toolbar_add_boots (GlEventToolbar *toolbar,
GArray *boot_ids)
{
- gint i;
+ GtkWidget *grid;
+ GtkWidget *title_label;
+ GtkWidget *arrow;
GMenu *boot_menu;
+ GMenu *section;
GlEventToolbarPrivate *priv;
- GSettings *settings;
- GlUtilClockFormat clock_format;
+ GtkStyleContext *context;
+ gint i;
+ gchar *current_boot = NULL;
priv = gl_event_toolbar_get_instance_private (toolbar);
- /* TODO: Monitor and propagate any GSettings changes. */
- settings = g_settings_new (DESKTOP_SCHEMA);
- clock_format = g_settings_get_enum (settings, CLOCK_FORMAT);
-
- g_object_unref (settings);
-
boot_menu = g_menu_new ();
+ section = g_menu_new ();
for (i = boot_ids->len - 1; i >= boot_ids->len - 5 && i >= 0; i--)
{
gchar *boot_match;
- gchar *time;
- GDateTime *now;
+ gchar *time_display;
GlJournalBootID *boot_id;
GMenuItem *item;
GVariant *variant;
@@ -83,23 +94,52 @@ gl_event_toolbar_add_boots (GlEventToolbar *toolbar,
boot_id = &g_array_index (boot_ids, GlJournalBootID, i);
boot_match = boot_id->boot_match;
- now = g_date_time_new_now_local ();
- time = gl_util_timestamp_to_display (boot_id->realtime,
- now, clock_format);
+ time_display = gl_util_boot_time_to_display (boot_id->realtime_first,
+ boot_id->realtime_last);
+ if (i == boot_ids->len - 1)
+ {
+ current_boot = g_strdup (time_display);
+ }
- item = g_menu_item_new (time, NULL);
+ item = g_menu_item_new (time_display, NULL);
variant = g_variant_new_string (boot_match);
g_menu_item_set_action_and_target_value (item, "win.view-boot",
variant);
- g_menu_append_item (boot_menu, item);
+ g_menu_append_item (section, item);
- g_date_time_unref (now);
- g_free (time);
+ g_free (time_display);
g_object_unref (item);
}
+ /* Translators: Boot refers to a single run (or bootup) of the system */
+ g_menu_prepend_section (boot_menu, _("Boot"), G_MENU_MODEL (section));
+
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv->menu_button),
G_MENU_MODEL (boot_menu));
+
+ grid = gtk_grid_new ();
+ gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
+ gtk_container_add (GTK_CONTAINER (priv->menu_button), grid);
+
+ title_label = gtk_label_new ("Logs");
+ context = gtk_widget_get_style_context (GTK_WIDGET (title_label));
+ gtk_style_context_add_class (context, "title");
+ gtk_grid_attach (GTK_GRID (grid), title_label, 0, 0, 1, 1);
+
+ gtk_label_set_text (GTK_LABEL (priv->current_boot), current_boot);
+ context = gtk_widget_get_style_context (GTK_WIDGET (priv->current_boot));
+ gtk_style_context_add_class (context, "subtitle");
+ gtk_grid_attach (GTK_GRID (grid), priv->current_boot, 0, 1, 1, 1);
+
+ arrow = gtk_image_new_from_icon_name ("pan-down-symbolic",
+ GTK_ICON_SIZE_BUTTON);
+ gtk_grid_attach (GTK_GRID (grid), arrow, 1, 0, 1, 2);
+ gtk_widget_show_all (grid);
+
+ gtk_header_bar_set_custom_title (GTK_HEADER_BAR (toolbar),
+ priv->menu_button);
+
+ g_free (current_boot);
}
static void
@@ -235,8 +275,14 @@ gl_event_toolbar_class_init (GlEventToolbarClass *klass)
static void
gl_event_toolbar_init (GlEventToolbar *toolbar)
{
+ GlEventToolbarPrivate *priv;
+
+ priv = gl_event_toolbar_get_instance_private (toolbar);
+
gtk_widget_init_template (GTK_WIDGET (toolbar));
+ priv->current_boot = gtk_label_new (NULL);
+
g_signal_connect (toolbar, "notify::mode", G_CALLBACK (on_notify_mode),
NULL);
}
diff --git a/src/gl-eventtoolbar.h b/src/gl-eventtoolbar.h
index c8c92d4..ef6e104 100644
--- a/src/gl-eventtoolbar.h
+++ b/src/gl-eventtoolbar.h
@@ -45,6 +45,8 @@ gboolean gl_event_toolbar_handle_back_button_event (GlEventToolbar *toolbar,
void gl_event_toolbar_set_mode (GlEventToolbar *toolbar,
GlEventToolbarMode mode);
void gl_event_toolbar_add_boots (GlEventToolbar *toolbar, GArray *boot_ids);
+void gl_event_toolbar_change_current_boot (GlEventToolbar *toolbar,
+ const gchar *current_boot);
G_END_DECLS
diff --git a/src/gl-eventview.c b/src/gl-eventview.c
index 425f24d..41c8a9e 100644
--- a/src/gl-eventview.c
+++ b/src/gl-eventview.c
@@ -58,6 +58,19 @@ static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
static const gchar DESKTOP_SCHEMA[] = "org.gnome.desktop.interface";
static const gchar CLOCK_FORMAT[] = "clock-format";
+gchar *
+gl_event_view_get_current_boot_time (GlEventView *view,
+ const gchar *boot_match)
+{
+ GlEventViewPrivate *priv;
+ GlEventViewList *events;
+
+ priv = gl_event_view_get_instance_private (view);
+ events = GL_EVENT_VIEW_LIST (priv->events);
+
+ return gl_event_view_list_get_current_boot_time (events, boot_match);
+}
+
GArray *
gl_event_view_get_boot_ids (GlEventView *view)
{
diff --git a/src/gl-eventview.h b/src/gl-eventview.h
index ece1f4b..eb02ad4 100644
--- a/src/gl-eventview.h
+++ b/src/gl-eventview.h
@@ -51,6 +51,8 @@ void gl_event_view_set_search_mode (GlEventView *view, gboolean state);
void gl_event_view_set_sort_order (GlEventView *view, GlSortOrder sort_order);
GArray * gl_event_view_get_boot_ids (GlEventView *view);
void gl_event_view_view_boot (GlEventView *view, const gchar *match);
+gchar * gl_event_view_get_current_boot_time (GlEventView *view,
+ const gchar *boot_match);
G_END_DECLS
diff --git a/src/gl-eventviewlist.c b/src/gl-eventviewlist.c
index 5df55d5..614d0e8 100644
--- a/src/gl-eventviewlist.c
+++ b/src/gl-eventviewlist.c
@@ -478,6 +478,18 @@ gl_event_view_list_get_detail_entry (GlEventViewList *view)
return priv->entry;
}
+gchar *
+gl_event_view_list_get_current_boot_time (GlEventViewList *view,
+ const gchar *boot_match)
+{
+ GlEventViewListPrivate *priv;
+
+ priv = gl_event_view_list_get_instance_private (view);
+
+ return gl_journal_model_get_current_boot_time (priv->journal_model,
+ boot_match);
+}
+
GArray *
gl_event_view_list_get_boot_ids (GlEventViewList *view)
{
diff --git a/src/gl-eventviewlist.h b/src/gl-eventviewlist.h
index 02dc8da..3ba1083 100644
--- a/src/gl-eventviewlist.h
+++ b/src/gl-eventviewlist.h
@@ -39,6 +39,8 @@ void gl_event_view_list_set_search_mode (GlEventViewList *view, gboolean state);
void gl_event_view_list_set_sort_order (GlEventViewList *view, GlSortOrder sort_order);
void gl_event_view_list_view_boot (GlEventViewList *view, const gchar *match);
GArray * gl_event_view_list_get_boot_ids (GlEventViewList *view);
+gchar * gl_event_view_list_get_current_boot_time (GlEventViewList *view,
+ const gchar *boot_match);
G_END_DECLS
diff --git a/src/gl-journal-model.c b/src/gl-journal-model.c
index 3c53f31..e8b48e2 100644
--- a/src/gl-journal-model.c
+++ b/src/gl-journal-model.c
@@ -246,6 +246,13 @@ gl_journal_model_set_matches (GlJournalModel *model,
gl_journal_model_fetch_more_entries (model, FALSE);
}
+gchar *
+gl_journal_model_get_current_boot_time (GlJournalModel *model,
+ const gchar *boot_match)
+{
+ return gl_journal_get_current_boot_time (model->journal, boot_match);
+}
+
GArray *
gl_journal_model_get_boot_ids (GlJournalModel *model)
{
diff --git a/src/gl-journal-model.h b/src/gl-journal-model.h
index 1ebbb6e..c793b0a 100644
--- a/src/gl-journal-model.h
+++ b/src/gl-journal-model.h
@@ -36,4 +36,7 @@ void gl_journal_model_fetch_more_entries (GlJourn
GArray * gl_journal_model_get_boot_ids (GlJournalModel *model);
+gchar * gl_journal_model_get_current_boot_time (GlJournalModel *model,
+ const gchar *boot_match);
+
#endif
diff --git a/src/gl-journal.c b/src/gl-journal.c
index 942dde6..a8dd044 100644
--- a/src/gl-journal.c
+++ b/src/gl-journal.c
@@ -18,6 +18,7 @@
*/
#include "gl-journal.h"
+#include "gl-util.h"
#include <glib-unix.h>
#include <gio/gio.h>
@@ -65,13 +66,41 @@ gl_journal_error_quark (void)
return g_quark_from_static_string ("gl-journal-error-quark");
}
+gchar *
+gl_journal_get_current_boot_time (GlJournal *journal,
+ const gchar *boot_match)
+{
+ GArray *boot_ids;
+ gchar *time;
+ gint i;
+
+ boot_ids = gl_journal_get_boot_ids (journal);
+
+ for (i = boot_ids->len - 1; i >= boot_ids->len - 5 && i >= 0; i--)
+ {
+ GlJournalBootID *boot_id;
+
+ boot_id = &g_array_index (boot_ids, GlJournalBootID, i);
+
+ if (g_strcmp0 (boot_match, boot_id->boot_match) == 0)
+ {
+ time = gl_util_boot_time_to_display (boot_id->realtime_first,
+ boot_id->realtime_last);
+
+ return time;
+ }
+ }
+
+ return NULL;
+}
+
static gint
boot_id_cmp (const void *a, const void *b)
{
guint64 _a, _b;
- _a = ((const GlJournalBootID *)a)->realtime;
- _b = ((const GlJournalBootID *)b)->realtime;
+ _a = ((const GlJournalBootID *)a)->realtime_first;
+ _b = ((const GlJournalBootID *)b)->realtime_first;
return _a < _b ? -1 : (_a > _b ? 1 : 0);
}
@@ -138,7 +167,34 @@ gl_journal_get_boots (GlJournal *journal)
goto flush;
}
- r = sd_journal_get_realtime_usec (priv->journal, &boot_id.realtime);
+ r = sd_journal_get_realtime_usec (priv->journal,
+ &boot_id.realtime_first);
+ if (r < 0)
+ {
+ g_warning ("Error retrieving the sender timestamps: %s",
+ g_strerror (-r));
+ }
+
+ r = sd_journal_seek_tail (priv->journal);
+ if (r < 0)
+ {
+ g_warning ("Error seeking to the beginning of the journal: %s\n",
+ g_strerror (-r));
+ }
+
+ r = sd_journal_previous (priv->journal);
+ if (r < 0)
+ {
+ g_warning ("Error retreat the read pointer in the journal: %s",
+ g_strerror (-r));
+ }
+ else if (r == 0)
+ {
+ goto flush;
+ }
+
+ r = sd_journal_get_realtime_usec (priv->journal,
+ &boot_id.realtime_last);
if (r < 0)
{
g_warning ("Error retrieving the sender timestamps: %s",
diff --git a/src/gl-journal.h b/src/gl-journal.h
index 17bc67a..1e73480 100644
--- a/src/gl-journal.h
+++ b/src/gl-journal.h
@@ -62,7 +62,8 @@ typedef struct
typedef struct
{
gchar *boot_match;
- guint64 realtime;
+ guint64 realtime_first;
+ guint64 realtime_last;
} GlJournalBootID;
#define GL_TYPE_JOURNAL (gl_journal_get_type ())
@@ -74,6 +75,8 @@ void gl_journal_set_matches (GlJournal *journal, const gchar * const *matches);
GArray * gl_journal_get_boot_ids (GlJournal *journal);
GlJournalEntry * gl_journal_previous (GlJournal *journal);
GlJournal * gl_journal_new (void);
+gchar * gl_journal_get_current_boot_time (GlJournal *journal,
+ const gchar *boot_match);
guint64 gl_journal_entry_get_timestamp (GlJournalEntry *entry);
const gchar * gl_journal_entry_get_message (GlJournalEntry *entry);
diff --git a/src/gl-util.c b/src/gl-util.c
index 40cea30..7c1372c 100644
--- a/src/gl-util.c
+++ b/src/gl-util.c
@@ -40,6 +40,9 @@ typedef enum
GL_UTIL_TIMESTAMPS_DIFFERENT_YEAR
} GlUtilTimestamps;
+static const gchar DESKTOP_SCHEMA[] = "org.gnome.desktop.interface";
+static const gchar CLOCK_FORMAT[] = "clock-format";
+
/**
* gl_util_on_css_provider_parsing_error:
* @provider: the provider that had a parsing error
@@ -208,3 +211,38 @@ gl_util_get_uid (void)
return uid;
}
+
+gchar *
+gl_util_boot_time_to_display (guint64 realtime_first,
+ guint64 realtime_last)
+{
+ gchar *time_first;
+ gchar *time_last;
+ gchar *time_display;
+ GDateTime *now;
+ GSettings *settings;
+ GlUtilClockFormat clock_format;
+
+ /* TODO: Monitor and propagate any GSettings changes. */
+ settings = g_settings_new (DESKTOP_SCHEMA);
+ clock_format = g_settings_get_enum (settings, CLOCK_FORMAT);
+
+ g_object_unref (settings);
+
+ now = g_date_time_new_now_local ();
+ time_first = gl_util_timestamp_to_display (realtime_first,
+ now, clock_format);
+ time_last = gl_util_timestamp_to_display (realtime_last,
+ now, clock_format);
+
+ /* Transltors: the first string is the earliest timestamp of the boot,
+ * and the second string is the newest timestamp. An example string might
+ * be '08:10 - 08:30' */
+ time_display = g_strdup_printf ("%s - %s", time_first, time_last);
+
+ g_date_time_unref (now);
+ g_free (time_first);
+ g_free (time_last);
+
+ return time_display;
+}
diff --git a/src/gl-util.h b/src/gl-util.h
index 3590128..4971564 100644
--- a/src/gl-util.h
+++ b/src/gl-util.h
@@ -43,6 +43,8 @@ gchar * gl_util_timestamp_to_display (guint64 microsecs,
GDateTime *now,
GlUtilClockFormat format);
gint gl_util_get_uid (void);
+gchar * gl_util_boot_time_to_display (guint64 timestamp_first,
+ guint64 timestamp_last);
G_END_DECLS
diff --git a/src/gl-window.c b/src/gl-window.c
index e7372b8..8dfccad 100644
--- a/src/gl-window.c
+++ b/src/gl-window.c
@@ -175,14 +175,29 @@ on_view_boot (GSimpleAction *action,
{
GlWindowPrivate *priv;
GlEventView *event;
+ GlEventToolbar *toolbar;
+ gchar *current_boot;
const gchar *boot_match;
priv = gl_window_get_instance_private (GL_WINDOW (user_data));
event = GL_EVENT_VIEW (priv->event);
+ toolbar = GL_EVENT_TOOLBAR (priv->event_toolbar);
boot_match = g_variant_get_string (variant, NULL);
gl_event_view_view_boot (event, boot_match);
+
+ current_boot = gl_event_view_get_current_boot_time (event, boot_match);
+ if (current_boot == NULL)
+ {
+ g_debug ("Error fetching the time using boot_match");
+ }
+
+ gl_event_toolbar_change_current_boot (toolbar, current_boot);
+
+ g_simple_action_set_state (action, variant);
+
+ g_free (current_boot);
}
static gboolean
@@ -259,7 +274,7 @@ static GActionEntry actions[] = {
{ "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 },
- { "view-boot", on_view_boot, "s", NULL, NULL },
+ { "view-boot", on_action_radio, "s", "''", on_view_boot },
{ "close", on_close }
};
@@ -287,7 +302,11 @@ gl_window_init (GlWindow *window)
GlWindowPrivate *priv;
GlEventToolbar *toolbar;
GlEventView *event;
+ GAction *action_view_boot;
GArray *boot_ids;
+ GlJournalBootID *boot_id;
+ gchar *boot_match;
+ GVariant *variant;
gtk_widget_init_template (GTK_WIDGET (window));
@@ -296,11 +315,19 @@ gl_window_init (GlWindow *window)
toolbar = GL_EVENT_TOOLBAR (priv->event_toolbar);
boot_ids = gl_event_view_get_boot_ids (event);
+ boot_id = &g_array_index (boot_ids, GlJournalBootID, boot_ids->len - 1);
+ boot_match = boot_id->boot_match;
+
gl_event_toolbar_add_boots (toolbar, boot_ids);
g_action_map_add_action_entries (G_ACTION_MAP (window), actions,
G_N_ELEMENTS (actions), window);
+ action_view_boot = g_action_map_lookup_action (G_ACTION_MAP (window),
+ "view-boot");
+ variant = g_variant_new_string (boot_match);
+ g_action_change_state (action_view_boot, variant);
+
provider = gtk_css_provider_new ();
g_signal_connect (provider, "parsing-error",
G_CALLBACK (gl_util_on_css_provider_parsing_error),