[gnome-logs] update boot timestamps when possible



commit 1f8e848cf7a6a307f9c58637411896ca36ab1517
Author: Jonathan Kang <jonathan121537 gmail com>
Date:   Fri Oct 27 17:56:43 2017 +0800

    update boot timestamps when possible
    
    Previously, boot timestamps in the boot selection menu is generated
    when Logs is opened and won't be updated later. This causes a problem
    that the timestamp of the latest log entry might be newer than what's
    shown in the boot selection menu.
    
    Fix that by updating the boot selection menu when users change the
    category list or view logs from other boots.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=762840

 src/gl-eventtoolbar.c  |   25 ++++++++++++++++++++++-
 src/gl-eventtoolbar.h  |    3 +-
 src/gl-eventviewlist.c |   20 ++++++++++++++++++
 src/gl-eventviewlist.h |    2 +
 src/gl-journal.c       |   52 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/gl-window.c        |   39 +++++++++++++++++++++++++++++++++++-
 6 files changed, 138 insertions(+), 3 deletions(-)
---
diff --git a/src/gl-eventtoolbar.c b/src/gl-eventtoolbar.c
index b68f2c2..da0cb71 100644
--- a/src/gl-eventtoolbar.c
+++ b/src/gl-eventtoolbar.c
@@ -42,9 +42,30 @@ typedef struct
 
 G_DEFINE_TYPE_WITH_PRIVATE (GlEventToolbar, gl_event_toolbar, GTK_TYPE_HEADER_BAR)
 
+static void
+gl_event_toolbar_update_boot_menu_label (GlEventToolbar *toolbar,
+                                         const gchar *latest_boot)
+{
+    GlEventToolbarPrivate *priv;
+    GMenuModel *boot_menu;
+    GMenuModel *section;
+    GMenuItem *menu_item;
+
+    priv = gl_event_toolbar_get_instance_private (toolbar);
+
+    boot_menu = gtk_menu_button_get_menu_model (GTK_MENU_BUTTON (priv->menu_button));
+    section = g_menu_model_get_item_link (boot_menu, 0, "section");
+    menu_item = g_menu_item_new_from_model (section, 0);
+    g_menu_item_set_label (menu_item, latest_boot);
+
+    g_menu_remove (G_MENU (section), 0);
+    g_menu_insert_item (G_MENU (section), 0, menu_item);
+}
+
 void
 gl_event_toolbar_change_current_boot (GlEventToolbar *toolbar,
-                                      const gchar *current_boot)
+                                      const gchar *current_boot,
+                                      const gchar *latest_boot)
 {
     GlEventToolbarPrivate *priv;
 
@@ -52,6 +73,8 @@ gl_event_toolbar_change_current_boot (GlEventToolbar *toolbar,
 
     /* set text to priv->current_boot */
     gtk_label_set_text (GTK_LABEL (priv->current_boot), current_boot);
+
+    gl_event_toolbar_update_boot_menu_label (toolbar, latest_boot);
 }
 
 void
diff --git a/src/gl-eventtoolbar.h b/src/gl-eventtoolbar.h
index a6bca45..461d274 100644
--- a/src/gl-eventtoolbar.h
+++ b/src/gl-eventtoolbar.h
@@ -42,7 +42,8 @@ G_DECLARE_FINAL_TYPE (GlEventToolbar, gl_event_toolbar, GL, EVENT_TOOLBAR, GtkHe
 GtkWidget * gl_event_toolbar_new (void);
 void gl_event_toolbar_add_boots (GlEventToolbar *toolbar, GArray *boot_ids);
 void gl_event_toolbar_change_current_boot (GlEventToolbar *toolbar,
-                                           const gchar *current_boot);
+                                           const gchar *current_boot,
+                                           const gchar *latest_boot);
 
 G_END_DECLS
 
diff --git a/src/gl-eventviewlist.c b/src/gl-eventviewlist.c
index 960ecee..a7431be 100644
--- a/src/gl-eventviewlist.c
+++ b/src/gl-eventviewlist.c
@@ -64,6 +64,26 @@ static const gchar SETTINGS_SCHEMA[] = "org.gnome.Logs";
 static const gchar CLOCK_FORMAT[] = "clock-format";
 static const gchar SORT_ORDER[] = "sort-order";
 
+GtkWidget *
+gl_event_view_list_get_category_list (GlEventViewList *view)
+{
+    GlEventViewListPrivate *priv;
+
+    priv = gl_event_view_list_get_instance_private (view);
+
+    return priv->categories;
+}
+
+const gchar *
+gl_event_view_list_get_boot_match (GlEventViewList *view)
+{
+    GlEventViewListPrivate *priv;
+
+    priv = gl_event_view_list_get_instance_private (view);
+
+    return priv->boot_match;
+}
+
 gchar *
 gl_event_view_list_get_output_logs (GlEventViewList *view)
 {
diff --git a/src/gl-eventviewlist.h b/src/gl-eventviewlist.h
index 8a39eb2..8e88c43 100644
--- a/src/gl-eventviewlist.h
+++ b/src/gl-eventviewlist.h
@@ -38,6 +38,8 @@ gboolean gl_event_view_list_handle_search_event (GlEventViewList *view,
 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);
+GtkWidget * gl_event_view_list_get_category_list (GlEventViewList *view);
+const gchar * gl_event_view_list_get_boot_match (GlEventViewList *view);
 GArray * gl_event_view_list_get_boot_ids (GlEventViewList *view);
 gchar * gl_event_view_list_get_output_logs (GlEventViewList *view);
 gchar * gl_event_view_list_get_boot_time (GlEventViewList *view,
diff --git a/src/gl-journal.c b/src/gl-journal.c
index d55b157..0070865 100644
--- a/src/gl-journal.c
+++ b/src/gl-journal.c
@@ -58,6 +58,57 @@ typedef struct
 
 G_DEFINE_TYPE_WITH_PRIVATE (GlJournal, gl_journal, G_TYPE_OBJECT)
 
+static void
+gl_journal_update_latest_timestamp (GlJournal *journal)
+{
+    GlJournalPrivate *priv;
+    GlJournalBootID *boot_id;
+    gint r;
+    guint64 realtime;
+
+    g_return_if_fail (GL_JOURNAL (journal));
+
+    priv = gl_journal_get_instance_private (journal);
+
+    r = sd_journal_seek_tail (priv->journal);
+    if (r < 0)
+    {
+        g_warning ("Error seeking to the end of the journal: %s",
+                   g_strerror (-r));
+    }
+
+    r = sd_journal_previous (priv->journal);
+    if (r < 0)
+    {
+        g_warning ("Error retreating the read pointer in the journal: %s",
+                   g_strerror (-r));
+    }
+
+    boot_id = &g_array_index (priv->boot_ids, GlJournalBootID,
+                              priv->boot_ids->len - 1);
+    r = sd_journal_get_realtime_usec (priv->journal,
+                                      &realtime);
+    if (r < 0)
+    {
+        g_warning ("Error retrieving the sender timestamps: %s",
+                   g_strerror (-r));
+    }
+
+    if (realtime > boot_id->realtime_last)
+    {
+        boot_id->realtime_last = realtime;
+    }
+
+    /* We set the reading cursor to the latest log entry using
+     * sd_journal_previous. Reset it here. */
+    r = sd_journal_seek_tail (priv->journal);
+    if (r < 0)
+    {
+        g_warning ("Error seeking to the end of the journal: %s",
+                   g_strerror (-r));
+    }
+}
+
 GQuark
 gl_journal_error_quark (void)
 {
@@ -72,6 +123,7 @@ gl_journal_get_boot_time (GlJournal *journal,
     gchar *time;
     gint i;
 
+    gl_journal_update_latest_timestamp (journal);
     boot_ids = gl_journal_get_boot_ids (journal);
 
     for (i = 0; i < boot_ids->len; i++)
diff --git a/src/gl-window.c b/src/gl-window.c
index dc0ef5a..65b67e8 100644
--- a/src/gl-window.c
+++ b/src/gl-window.c
@@ -193,8 +193,11 @@ on_view_boot (GSimpleAction *action,
     GlWindowPrivate *priv;
     GlEventViewList *event_list;
     GlEventToolbar *toolbar;
+    GArray *boot_ids;
+    GlJournalBootID *boot_id;
     gchar *current_boot;
     const gchar *boot_match;
+    const gchar *latest_boot;
 
     priv = gl_window_get_instance_private (GL_WINDOW (user_data));
     event_list = GL_EVENT_VIEW_LIST (priv->event_list);
@@ -210,13 +213,42 @@ on_view_boot (GSimpleAction *action,
         g_debug ("Error fetching the time using boot_match");
     }
 
-    gl_event_toolbar_change_current_boot (toolbar, current_boot);
+    boot_ids = gl_event_view_list_get_boot_ids (event_list);
+    boot_id = &g_array_index (boot_ids, GlJournalBootID,
+                              boot_ids->len - 1);
+    latest_boot = gl_event_view_list_get_boot_time (event_list,
+                                                    boot_id->boot_match);
+
+    gl_event_toolbar_change_current_boot (toolbar, current_boot, latest_boot);
 
     g_simple_action_set_state (action, variant);
 
     g_free (current_boot);
 }
 
+static void
+on_category_list_changed (GlCategoryList *list,
+                          GParamSpec *pspec,
+                          gpointer user_data)
+{
+    GlWindowPrivate *priv;
+    GlEventViewList *event_list;
+    GlEventToolbar *toolbar;
+    gchar *current_boot;
+    const gchar *boot_match;
+
+    priv = gl_window_get_instance_private (GL_WINDOW (user_data));
+    event_list = GL_EVENT_VIEW_LIST (priv->event_list);
+    toolbar = GL_EVENT_TOOLBAR (priv->event_toolbar);
+
+    boot_match = gl_event_view_list_get_boot_match (event_list);
+    current_boot = gl_event_view_list_get_boot_time (event_list, boot_match);
+
+    gl_event_toolbar_change_current_boot (toolbar, current_boot, current_boot);
+
+    g_free (current_boot);
+}
+
 static gboolean
 on_gl_window_key_press_event (GlWindow *window,
                               GdkEvent *event,
@@ -332,6 +364,7 @@ gl_window_init (GlWindow *window)
     GlWindowPrivate *priv;
     GlEventToolbar *toolbar;
     GlEventViewList *event_list;
+    GtkWidget *categories;
     GAction *action_view_boot;
     GArray *boot_ids;
     GlJournalStorage storage_type;
@@ -366,6 +399,10 @@ gl_window_init (GlWindow *window)
         g_action_change_state (action_view_boot, variant);
     }
 
+    categories = gl_event_view_list_get_category_list (event_list);
+    g_signal_connect (GL_CATEGORY_LIST (categories), "notify::category",
+                      G_CALLBACK (on_category_list_changed), window);
+
     provider = gtk_css_provider_new ();
     g_signal_connect (provider, "parsing-error",
                       G_CALLBACK (gl_util_on_css_provider_parsing_error),


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