[gnome-logs] Output the shown logs in GtkListBox to file
- From: Jonathan Kang <jonathankang src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-logs] Output the shown logs in GtkListBox to file
- Date: Mon, 12 Oct 2015 09:05:52 +0000 (UTC)
commit a0b01ba05eaf1153a27a05a4eb7f926e34741bfe
Author: Jonathan Kang <jonathan121537 gmail com>
Date: Mon Oct 12 17:03:14 2015 +0800
Output the shown logs in GtkListBox to file
https://bugzilla.gnome.org/show_bug.cgi?id=727173
data/gl-eventtoolbar.ui | 21 +++++++++++
src/gl-eventtoolbar.c | 5 +++
src/gl-eventview.c | 12 ++++++
src/gl-eventview.h | 1 +
src/gl-eventviewlist.c | 53 +++++++++++++++++++++++++++
src/gl-eventviewlist.h | 1 +
src/gl-eventviewrow.c | 30 +++++++++++++++
src/gl-eventviewrow.h | 3 ++
src/gl-window.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 216 insertions(+), 0 deletions(-)
---
diff --git a/data/gl-eventtoolbar.ui b/data/gl-eventtoolbar.ui
index c42af57..8e3fc8d 100644
--- a/data/gl-eventtoolbar.ui
+++ b/data/gl-eventtoolbar.ui
@@ -20,6 +20,27 @@
</child>
</object>
</child>
+ <child>
+ <object class="GtkButton" id="output_button">
+ <property name="action-name">win.export</property>
+ <property name="tooltip-text" translatable="yes">Export logs to a file</property>
+ <property name="valign">center</property>
+ <property name="visible">True</property>
+ <style>
+ <class name="image-button" />
+ </style>
+ <child>
+ <object class="GtkImage" id="output_icon">
+ <property name="icon-name">send-to-symbolic</property>
+ <property name="icon-size">1</property>
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack-type">end</property>
+ </packing>
+ </child>
<child type="title">
<object class="GtkMenuButton" id="menu_button">
<property name="direction">none</property>
diff --git a/src/gl-eventtoolbar.c b/src/gl-eventtoolbar.c
index 951b320..072e838 100644
--- a/src/gl-eventtoolbar.c
+++ b/src/gl-eventtoolbar.c
@@ -42,6 +42,7 @@ typedef struct
{
GtkWidget *current_boot;
GtkWidget *back_button;
+ GtkWidget *output_button;
GtkWidget *menu_button;
GtkWidget *search_button;
GlEventToolbarMode mode;
@@ -164,11 +165,13 @@ on_notify_mode (GlEventToolbar *toolbar,
{
case GL_EVENT_TOOLBAR_MODE_LIST:
gtk_widget_hide (priv->back_button);
+ gtk_widget_show (priv->output_button);
gtk_widget_show (priv->menu_button);
gtk_widget_show (priv->search_button);
break;
case GL_EVENT_TOOLBAR_MODE_DETAIL:
gtk_widget_show (priv->back_button);
+ gtk_widget_hide (priv->output_button);
gtk_widget_hide (priv->menu_button);
gtk_widget_hide (priv->search_button);
break;
@@ -263,6 +266,8 @@ gl_event_toolbar_class_init (GlEventToolbarClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/Logs/gl-eventtoolbar.ui");
gtk_widget_class_bind_template_child_private (widget_class, GlEventToolbar,
+ output_button);
+ gtk_widget_class_bind_template_child_private (widget_class, GlEventToolbar,
back_button);
gtk_widget_class_bind_template_child_private (widget_class, GlEventToolbar,
menu_button);
diff --git a/src/gl-eventview.c b/src/gl-eventview.c
index 41c8a9e..df6c83d 100644
--- a/src/gl-eventview.c
+++ b/src/gl-eventview.c
@@ -59,6 +59,18 @@ static const gchar DESKTOP_SCHEMA[] = "org.gnome.desktop.interface";
static const gchar CLOCK_FORMAT[] = "clock-format";
gchar *
+gl_event_view_get_output_logs (GlEventView *view)
+{
+ 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_output_logs (events);
+}
+
+gchar *
gl_event_view_get_current_boot_time (GlEventView *view,
const gchar *boot_match)
{
diff --git a/src/gl-eventview.h b/src/gl-eventview.h
index eb02ad4..3e34c87 100644
--- a/src/gl-eventview.h
+++ b/src/gl-eventview.h
@@ -51,6 +51,7 @@ 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_output_logs (GlEventView *view);
gchar * gl_event_view_get_current_boot_time (GlEventView *view,
const gchar *boot_match);
diff --git a/src/gl-eventviewlist.c b/src/gl-eventviewlist.c
index 46f55e8..05dc4fe 100644
--- a/src/gl-eventviewlist.c
+++ b/src/gl-eventviewlist.c
@@ -69,6 +69,59 @@ static const gchar SETTINGS_SCHEMA[] = "org.gnome.Logs";
static const gchar CLOCK_FORMAT[] = "clock-format";
static const gchar SORT_ORDER[] = "sort-order";
+gchar *
+gl_event_view_list_get_output_logs (GlEventViewList *view)
+{
+ gchar *output_buf = NULL;
+ gint index = 0;
+ GOutputStream *stream;
+ GlEventViewListPrivate *priv;
+
+ priv = gl_event_view_list_get_instance_private (view);
+
+ stream = g_memory_output_stream_new_resizable ();
+
+ while (gtk_list_box_get_row_at_index (GTK_LIST_BOX (priv->entries_box),
+ index) != NULL)
+ {
+ const gchar *comm;
+ const gchar *message;
+ gchar *output_text;
+ gchar *time;
+ GDateTime *now;
+ guint64 timestamp;
+ GtkListBoxRow *row;
+
+ row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (priv->entries_box),
+ index);
+
+ comm = gl_event_view_row_get_command_line (GL_EVENT_VIEW_ROW (row));
+ message = gl_event_view_row_get_message (GL_EVENT_VIEW_ROW (row));
+ timestamp = gl_event_view_row_get_timestamp (GL_EVENT_VIEW_ROW (row));
+ now = g_date_time_new_now_local ();
+ time = gl_util_timestamp_to_display (timestamp, now,
+ priv->clock_format);
+
+ output_text = g_strconcat (time, " ",
+ comm ? comm : "kernel", ": ",
+ message, "\n", NULL);
+ index++;
+
+ g_output_stream_write (stream, output_text, strlen (output_text),
+ NULL, NULL);
+
+ g_date_time_unref (now);
+ g_free (time);
+ g_free (output_text);
+ }
+
+ output_buf = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (stream));
+
+ g_output_stream_close (stream, NULL, NULL);
+
+ return output_buf;
+}
+
static gboolean
gl_event_view_search_is_case_sensitive (GlEventViewList *view)
{
diff --git a/src/gl-eventviewlist.h b/src/gl-eventviewlist.h
index 3ba1083..df2cbd6 100644
--- a/src/gl-eventviewlist.h
+++ b/src/gl-eventviewlist.h
@@ -39,6 +39,7 @@ 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_output_logs (GlEventViewList *view);
gchar * gl_event_view_list_get_current_boot_time (GlEventViewList *view,
const gchar *boot_match);
diff --git a/src/gl-eventviewrow.c b/src/gl-eventviewrow.c
index 41de277..5765e5f 100644
--- a/src/gl-eventviewrow.c
+++ b/src/gl-eventviewrow.c
@@ -53,6 +53,36 @@ G_DEFINE_TYPE_WITH_PRIVATE (GlEventViewRow, gl_event_view_row, GTK_TYPE_LIST_BOX
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+const gchar *
+gl_event_view_row_get_command_line (GlEventViewRow *row)
+{
+ GlEventViewRowPrivate *priv;
+
+ priv = gl_event_view_row_get_instance_private (row);
+
+ return gl_journal_entry_get_command_line (priv->entry);
+}
+
+guint64
+gl_event_view_row_get_timestamp (GlEventViewRow *row)
+{
+ GlEventViewRowPrivate *priv;
+
+ priv = gl_event_view_row_get_instance_private (row);
+
+ return gl_journal_entry_get_timestamp (priv->entry);
+}
+
+const gchar *
+gl_event_view_row_get_message (GlEventViewRow *row)
+{
+ GlEventViewRowPrivate *priv;
+
+ priv = gl_event_view_row_get_instance_private (row);
+
+ return gl_journal_entry_get_message (priv->entry);
+}
+
GtkWidget *
gl_event_view_row_get_category_label (GlEventViewRow *row)
{
diff --git a/src/gl-eventviewrow.h b/src/gl-eventviewrow.h
index 4fbba00..63ffcd4 100644
--- a/src/gl-eventviewrow.h
+++ b/src/gl-eventviewrow.h
@@ -45,6 +45,9 @@ G_DECLARE_FINAL_TYPE (GlEventViewRow, gl_event_view_row, GL, EVENT_VIEW_ROW, Gtk
GtkWidget * gl_event_view_row_new (GlJournalEntry *entry, GlUtilClockFormat clock_format,
GlEventViewRowCategory category);
GlJournalEntry * gl_event_view_row_get_entry (GlEventViewRow *row);
+const gchar * gl_event_view_row_get_command_line (GlEventViewRow *row);
+const gchar * gl_event_view_row_get_message (GlEventViewRow *row);
+guint64 gl_event_view_row_get_timestamp (GlEventViewRow *row);
GtkWidget * gl_event_view_row_get_category_label (GlEventViewRow *row);
GtkWidget * gl_event_view_row_get_message_label (GlEventViewRow *row);
GtkWidget * gl_event_view_row_get_time_label (GlEventViewRow *row);
diff --git a/src/gl-window.c b/src/gl-window.c
index 8dfccad..0a06050 100644
--- a/src/gl-window.c
+++ b/src/gl-window.c
@@ -169,6 +169,95 @@ on_search (GSimpleAction *action,
}
static void
+on_export (GSimpleAction *action,
+ GVariant *variant,
+ gpointer user_data)
+{
+ GlWindowPrivate *priv;
+ GlEventView *event;
+ GtkFileChooser *file_chooser;
+ GtkWidget *dialog;
+ gint res;
+
+ priv = gl_window_get_instance_private (GL_WINDOW (user_data));
+ event = GL_EVENT_VIEW (priv->event);
+
+ dialog = gtk_file_chooser_dialog_new (_("Save logs"),
+ GTK_WINDOW (user_data),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Save"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ file_chooser = GTK_FILE_CHOOSER (dialog);
+ gtk_file_chooser_set_do_overwrite_confirmation (file_chooser, TRUE);
+ gtk_file_chooser_set_current_name (file_chooser, _("log messages"));
+
+ res = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (res == GTK_RESPONSE_ACCEPT)
+ {
+ gboolean have_error = FALSE;
+ gchar *file_content;
+ GFile *output_file;
+ GFileOutputStream *file_ostream;
+ GError *error = NULL;
+ GtkWidget *error_dialog;
+
+ file_content = gl_event_view_get_output_logs (event);
+ output_file = gtk_file_chooser_get_file (file_chooser);
+ file_ostream = g_file_replace (output_file, NULL, TRUE,
+ G_FILE_CREATE_NONE, NULL, &error);
+ if (error != NULL)
+ {
+ have_error = TRUE;
+
+ g_warning ("Error while replacing exported log messages file: %s",
+ error->message);
+ g_clear_error (&error);
+ }
+
+ g_output_stream_write (G_OUTPUT_STREAM (file_ostream), file_content,
+ strlen (file_content), NULL, &error);
+ if (error != NULL)
+ {
+ have_error = TRUE;
+
+ g_warning ("Error while replacing exported log messages file: %s",
+ error->message);
+ g_clear_error (&error);
+ }
+
+ g_output_stream_close (G_OUTPUT_STREAM (file_ostream), NULL, &error);
+ if (error != NULL)
+ {
+ have_error = TRUE;
+
+ g_warning ("Error while replacing exported log messages file: %s",
+ error->message);
+ g_clear_error (&error);
+ }
+
+ if (have_error == TRUE)
+ {
+ error_dialog = gtk_message_dialog_new (GTK_WINDOW (user_data),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "%s",
+ _("Unable to export log messages to a file"));
+ gtk_dialog_run (GTK_DIALOG (error_dialog));
+ gtk_widget_destroy (error_dialog);
+ }
+
+ g_free (file_content);
+ g_object_unref (file_ostream);
+ g_object_unref (output_file);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
on_view_boot (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
@@ -275,6 +364,7 @@ static GActionEntry actions[] = {
{ "toolbar-mode", on_action_radio, "s", "'list'", on_toolbar_mode },
{ "search", on_action_toggle, NULL, "false", on_search },
{ "view-boot", on_action_radio, "s", "''", on_view_boot },
+ { "export", on_export },
{ "close", on_close }
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]