diff options
-rw-r--r-- | data/gl-eventtoolbar.ui | 9 | ||||
-rw-r--r-- | data/gl-style.css | 5 | ||||
-rw-r--r-- | src/gl-eventtoolbar.c | 82 | ||||
-rw-r--r-- | src/gl-eventtoolbar.h | 2 | ||||
-rw-r--r-- | src/gl-eventview.c | 13 | ||||
-rw-r--r-- | src/gl-eventview.h | 2 | ||||
-rw-r--r-- | src/gl-eventviewlist.c | 12 | ||||
-rw-r--r-- | src/gl-eventviewlist.h | 2 | ||||
-rw-r--r-- | src/gl-journal-model.c | 7 | ||||
-rw-r--r-- | src/gl-journal-model.h | 3 | ||||
-rw-r--r-- | src/gl-journal.c | 62 | ||||
-rw-r--r-- | src/gl-journal.h | 5 | ||||
-rw-r--r-- | src/gl-util.c | 38 | ||||
-rw-r--r-- | src/gl-util.h | 2 | ||||
-rw-r--r-- | src/gl-window.c | 29 |
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), |