[gnome-logs/journal-from-file] application: Add the ability to open journal files



commit 938cb8996f4fe9e4c26097e19522f628bdf1ba9f
Author: Jonathan Kang <jonathankang gnome org>
Date:   Fri Feb 21 14:53:11 2020 +0800

    application: Add the ability to open journal files
    
    You can use the command "gnome-logs $path-to-journal-files" to view
    logs from those journal files.
    
    https://gitlab.gnome.org/GNOME/gnome-logs/issues/45

 src/gl-application.c   |  55 +++++++++++++++++++++++--
 src/gl-journal-model.c |  12 ++++--
 src/gl-journal-model.h |   3 ++
 src/gl-journal.c       | 107 +++++++++++++++++++++++++++++++++++++++++++------
 src/gl-journal.h       |   2 +-
 src/gl-window.c        |  60 ++++++++++++++++-----------
 src/gl-window.h        |   2 +
 7 files changed, 197 insertions(+), 44 deletions(-)
---
diff --git a/src/gl-application.c b/src/gl-application.c
index c20052c..f2d9eaa 100644
--- a/src/gl-application.c
+++ b/src/gl-application.c
@@ -24,6 +24,8 @@
 #include "gl-categorylist.h"
 #include "gl-eventtoolbar.h"
 #include "gl-eventviewlist.h"
+#include "gl-journal.h"
+#include "gl-journal-model.h"
 #include "gl-util.h"
 #include "gl-window.h"
 
@@ -35,6 +37,7 @@ struct _GlApplication
 
 typedef struct
 {
+    GlJournal *journal;
     GSettings *desktop;
     GSettings *settings;
     gchar *monospace_font;
@@ -54,10 +57,13 @@ on_new_window (GSimpleAction *action,
 {
     GtkApplication *application;
     GtkWidget *window;
+    GlApplicationPrivate *priv;
 
     application = GTK_APPLICATION (user_data);
+    priv = gl_application_get_instance_private (GL_APPLICATION (application));
 
     window = gl_window_new (GTK_APPLICATION (application));
+    gl_window_load_journal (GL_WINDOW (window), priv->journal);
     gtk_widget_show (window);
 }
 
@@ -199,26 +205,37 @@ gl_application_startup (GApplication *application)
 }
 
 static void
-gl_application_activate (GApplication *application)
+launch_window (GApplication *application)
 {
     GtkWidget *window;
     GlApplicationPrivate *priv;
     const gchar * const close_accel[] = { "<Primary>w", NULL };
     const gchar * const search_accel[] = { "<Primary>f", NULL };
 
+    priv = gl_application_get_instance_private (GL_APPLICATION (application));
+
     window = gl_window_new (GTK_APPLICATION (application));
+    gl_window_load_journal (GL_WINDOW (window), priv->journal);
     gtk_widget_show (window);
     gtk_application_set_accels_for_action (GTK_APPLICATION (application),
                                            "win.close", close_accel);
     gtk_application_set_accels_for_action (GTK_APPLICATION (application),
                                            "win.search", search_accel);
 
-    priv = gl_application_get_instance_private (GL_APPLICATION (application));
-
     on_monospace_font_name_changed (priv->desktop, DESKTOP_MONOSPACE_FONT_NAME,
                                     priv);
 }
 
+static void
+gl_application_activate (GApplication *application)
+{
+    GlApplicationPrivate *priv;
+
+    priv = gl_application_get_instance_private (GL_APPLICATION (application));
+    priv->journal = gl_journal_new (NULL);
+    launch_window (application);
+}
+
 static const GOptionEntry options[] =
 {
     { "version", 'v', 0, G_OPTION_ARG_NONE, NULL,
@@ -239,6 +256,33 @@ gl_application_handle_local_options (GApplication *application,
     return -1;
 }
 
+static void
+gl_application_open (GApplication *application,
+                     GFile **files,
+                     gint n_files,
+                     const gchar *hint)
+{
+    gint i;
+    GPtrArray *array;
+    GlApplicationPrivate *priv;
+
+    priv = gl_application_get_instance_private (GL_APPLICATION (application));
+
+    array = g_ptr_array_new ();
+    for (i = 0; i < n_files; i++)
+    {
+        GFile *file;
+
+        file = files[i];
+        g_ptr_array_add (array, g_file_get_path (file));
+    }
+
+    g_ptr_array_add (array, NULL);
+
+    priv->journal = gl_journal_new (array);
+    launch_window (application);
+}
+
 static void
 gl_application_finalize (GObject *object)
 {
@@ -252,6 +296,8 @@ gl_application_finalize (GObject *object)
     g_clear_object (&priv->settings);
     g_clear_pointer (&priv->monospace_font, g_free);
 
+    g_clear_object (&priv->journal);
+
     G_OBJECT_CLASS (gl_application_parent_class)->finalize (object);
 }
 
@@ -262,6 +308,8 @@ gl_application_init (GlApplication *application)
     gchar *changed_font;
     GAction *action;
 
+    g_application_set_flags (G_APPLICATION (application), G_APPLICATION_HANDLES_OPEN);
+
     priv = gl_application_get_instance_private (application);
 
     priv->monospace_font = NULL;
@@ -297,6 +345,7 @@ gl_application_class_init (GlApplicationClass *klass)
 
     app_class = G_APPLICATION_CLASS (klass);
     app_class->activate = gl_application_activate;
+    app_class->open = gl_application_open;
     app_class->startup = gl_application_startup;
     app_class->handle_local_options = gl_application_handle_local_options;
 }
diff --git a/src/gl-journal-model.c b/src/gl-journal-model.c
index b1a54ec..a2fe03a 100644
--- a/src/gl-journal-model.c
+++ b/src/gl-journal-model.c
@@ -254,11 +254,8 @@ static void
 gl_journal_model_init (GlJournalModel *model)
 {
     model->batch_size = 50;
-    model->journal = gl_journal_new ();
     model->entries = g_ptr_array_new_with_free_func (g_object_unref);
     model->export = FALSE;
-
-    gl_journal_model_fetch_more_entries (model, FALSE);
 }
 
 static void
@@ -309,7 +306,6 @@ gl_journal_model_dispose (GObject *object)
         model->entries = NULL;
     }
 
-    g_clear_object (&model->journal);
     if (model->token_array != NULL)
     {
         g_ptr_array_free (model->token_array, TRUE);
@@ -1211,6 +1207,14 @@ gl_journal_model_fetch_more_entries (GlJournalModel *model,
     }
 }
 
+void
+gl_journal_model_load_journal (GlJournalModel *model,
+                               GlJournal *journal)
+{
+    model->journal = journal;
+    gl_journal_model_fetch_more_entries (model, FALSE);
+}
+
 GlRowEntry *
 gl_row_entry_new (void)
 {
diff --git a/src/gl-journal-model.h b/src/gl-journal-model.h
index 49818b8..52a2945 100644
--- a/src/gl-journal-model.h
+++ b/src/gl-journal-model.h
@@ -79,6 +79,9 @@ gboolean                gl_journal_model_get_loading                    (GlJourn
 void                    gl_journal_model_fetch_more_entries             (GlJournalModel *model,
                                                                          gboolean        all);
 
+void                    gl_journal_model_load_journal                   (GlJournalModel *model,
+                                                                         GlJournal      *journal);
+
 GArray *                gl_journal_model_get_boot_ids                   (GlJournalModel *model);
 
 gchar *                 gl_journal_model_get_boot_time                  (GlJournalModel *model,
diff --git a/src/gl-journal.c b/src/gl-journal.c
index 3aebab8..da0b2b6 100644
--- a/src/gl-journal.c
+++ b/src/gl-journal.c
@@ -25,6 +25,13 @@
 #include <stdlib.h>
 #include <systemd/sd-journal.h>
 
+enum
+{
+    PROP_0,
+    PROP_FILES,
+    N_PROPERTIES
+};
+
 struct _GlJournalEntry
 {
   GObject parent_instance;
@@ -48,6 +55,8 @@ struct _GlJournalEntry
 
 G_DEFINE_TYPE (GlJournalEntry, gl_journal_entry, G_TYPE_OBJECT);
 
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
 typedef struct
 {
     sd_journal *journal;
@@ -55,6 +64,7 @@ typedef struct
     guint source_id;
     gchar **mandatory_fields;
     GArray *boot_ids;
+    GPtrArray *files;
 } GlJournalPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (GlJournal, gl_journal, G_TYPE_OBJECT)
@@ -322,6 +332,46 @@ on_journal_changed (gint fd,
     return G_SOURCE_CONTINUE;
 }
 
+static void
+gl_journal_get_property (GObject *object,
+                         guint prop_id,
+                         GValue *value,
+                         GParamSpec *pspec)
+{
+    GlJournal *self = GL_JOURNAL (object);
+    GlJournalPrivate *priv = gl_journal_get_instance_private (self);
+
+    switch (prop_id)
+    {
+        case PROP_FILES:
+            g_value_set_pointer (value, priv->files);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+gl_journal_set_property (GObject *object,
+                         guint prop_id,
+                         const GValue *value,
+                         GParamSpec *pspec)
+{
+    GlJournal *self = GL_JOURNAL (object);
+    GlJournalPrivate *priv = gl_journal_get_instance_private (self);
+
+    switch (prop_id)
+    {
+        case PROP_FILES:
+            priv->files = g_value_get_pointer (value);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
 static void
 gl_journal_finalize (GObject *object)
 {
@@ -347,24 +397,31 @@ gl_journal_finalize (GObject *object)
 }
 
 static void
-gl_journal_class_init (GlJournalClass *klass)
-{
-    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-    gobject_class->finalize = gl_journal_finalize;
-}
-
-static void
-gl_journal_init (GlJournal *self)
+gl_journal_constructed (GObject *object)
 {
+    GlJournal *self;
     GlJournalPrivate *priv;
     sd_journal *journal;
     gint ret;
 
+    self = GL_JOURNAL (object);
     priv = gl_journal_get_instance_private (self);
 
-    ret = sd_journal_open (&journal, 0);
-    priv->journal = journal;
+    if (priv->files == NULL)
+    {
+        ret = sd_journal_open (&journal, 0);
+        priv->journal = journal;
+    }
+    else
+    {
+        gchar **paths;
+
+        paths = (gchar **) g_ptr_array_free (priv->files, FALSE);
+        ret = sd_journal_open_files (&journal, (const gchar **) paths, 0);
+        priv->journal = journal;
+
+        g_clear_pointer (&paths, g_strfreev);
+    }
 
     if (ret < 0)
     {
@@ -412,6 +469,28 @@ gl_journal_init (GlJournal *self)
     gl_journal_get_boots (self);
 }
 
+static void
+gl_journal_class_init (GlJournalClass *klass)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+    gobject_class->constructed = gl_journal_constructed;
+    gobject_class->get_property = gl_journal_get_property;
+    gobject_class->set_property = gl_journal_set_property;
+    gobject_class->finalize = gl_journal_finalize;
+
+    obj_properties[PROP_FILES] = g_param_spec_pointer ("files", "Files",
+                                                       "Journal Files",
+                                                       G_PARAM_READWRITE |
+                                                       G_PARAM_CONSTRUCT_ONLY);
+    g_object_class_install_properties (gobject_class, N_PROPERTIES, obj_properties);
+}
+
+static void
+gl_journal_init (GlJournal *self)
+{
+}
+
 static GlJournalEntry *
 _gl_journal_query_entry (GlJournal *self)
 {
@@ -730,9 +809,11 @@ gl_journal_previous (GlJournal *journal)
 }
 
 GlJournal *
-gl_journal_new (void)
+gl_journal_new (GPtrArray *files)
 {
-    return g_object_new (GL_TYPE_JOURNAL, NULL);
+    return g_object_new (GL_TYPE_JOURNAL,
+                         "files", files,
+                         NULL);
 }
 
 static void
diff --git a/src/gl-journal.h b/src/gl-journal.h
index 9ddfb06..bea8758 100644
--- a/src/gl-journal.h
+++ b/src/gl-journal.h
@@ -75,7 +75,7 @@ void gl_journal_set_matches (GlJournal *journal, GPtrArray *matches);
 void gl_journal_set_start_position (GlJournal *journal, guint64 until_timestamp);
 GArray * gl_journal_get_boot_ids (GlJournal *journal);
 GlJournalEntry * gl_journal_previous (GlJournal *journal);
-GlJournal * gl_journal_new (void);
+GlJournal * gl_journal_new (GPtrArray *files);
 gchar * gl_journal_get_boot_time (GlJournal *journal,
                                   const gchar *boot_match);
 
diff --git a/src/gl-window.c b/src/gl-window.c
index 3b3716a..2ebd758 100644
--- a/src/gl-window.c
+++ b/src/gl-window.c
@@ -383,21 +383,52 @@ enable_export (GlWindow *window)
     g_simple_action_set_enabled (G_SIMPLE_ACTION (action_export), TRUE);
 }
 
+void
+gl_window_load_journal (GlWindow *window,
+                        GlJournal *journal)
+{
+    gchar *boot_match;
+    GAction *action_view_boot;
+    GArray *boot_ids;
+    GVariant *variant;
+    GlJournalBootID *boot_id;
+    GlEventViewList *event_list;
+    GlEventToolbar *toolbar;
+    GlJournalModel *journal_model;
+    GlWindowPrivate *priv;
+
+    priv = gl_window_get_instance_private (window);
+    toolbar = GL_EVENT_TOOLBAR (priv->event_toolbar);
+    event_list = GL_EVENT_VIEW_LIST (priv->event_list);
+
+    journal_model = gl_event_view_list_get_journal_model (event_list);
+    gl_journal_model_load_journal (journal_model, journal);
+
+    boot_ids = gl_event_view_list_get_boot_ids (event_list);
+    gl_event_toolbar_add_boots (toolbar, boot_ids);
+
+    if (boot_ids->len > 0)
+    {
+        boot_id = &g_array_index (boot_ids, GlJournalBootID,
+                                  boot_ids->len - 1);
+        boot_match = boot_id->boot_match;
+
+        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);
+    }
+}
+
 static void
 gl_window_init (GlWindow *window)
 {
     GtkCssProvider *provider;
     GdkScreen *screen;
     GlWindowPrivate *priv;
-    GlEventToolbar *toolbar;
     GlEventViewList *event_list;
     GtkWidget *categories;
-    GAction *action_view_boot;
-    GArray *boot_ids;
     GlJournalStorage storage_type;
-    GlJournalBootID *boot_id;
-    gchar *boot_match;
-    GVariant *variant;
     GSettings *settings;
     gboolean ignore;
     GlJournalModel *model;
@@ -413,27 +444,10 @@ gl_window_init (GlWindow *window)
 
     priv = gl_window_get_instance_private (window);
     event_list = GL_EVENT_VIEW_LIST (priv->event_list);
-    toolbar = GL_EVENT_TOOLBAR (priv->event_toolbar);
-
-    boot_ids = gl_event_view_list_get_boot_ids (event_list);
 
     g_action_map_add_action_entries (G_ACTION_MAP (window), actions,
                                      G_N_ELEMENTS (actions), window);
 
-    gl_event_toolbar_add_boots (toolbar, boot_ids);
-
-    if (boot_ids->len > 0)
-    {
-        boot_id = &g_array_index (boot_ids, GlJournalBootID,
-                                  boot_ids->len - 1);
-        boot_match = boot_id->boot_match;
-
-        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);
-    }
-
     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);
diff --git a/src/gl-window.h b/src/gl-window.h
index 4744569..f8cffda 100644
--- a/src/gl-window.h
+++ b/src/gl-window.h
@@ -22,12 +22,14 @@
 #include <gtk/gtk.h>
 
 #include "gl-application.h"
+#include "gl-journal-model.h"
 
 G_BEGIN_DECLS
 
 #define GL_TYPE_WINDOW (gl_window_get_type ())
 G_DECLARE_FINAL_TYPE (GlWindow, gl_window, GL, WINDOW, GtkApplicationWindow)
 
+void gl_window_load_journal (GlWindow *window, GlJournal *journal);
 GtkWidget * gl_window_new (GtkApplication *application);
 void gl_window_set_sort_order (GlWindow *window, GlSortOrder sort_order);
 void disable_export (GlWindow *window);


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