[gnome-system-log] all: rework UI to a more modern style



commit 180cb46ae5f16626875c5f97d8be292c8d1183d2
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Fri Jun 29 02:09:43 2012 -0400

    all: rework UI to a more modern style
    
    Remove the menubar and the statusbar, and add a toolbar with a gear
    menu. Take this as an occasion to port the menu to GMenuModel.

 data/gnome-system-log.desktop.in.in |    2 +-
 po/POTFILES.in                      |    1 +
 src/Makefile.am                     |    4 +-
 src/gd-main-toolbar.c               |  405 ++++++++++++++++
 src/gd-main-toolbar.h               |   96 ++++
 src/logview-app-menu.ui             |    7 +
 src/logview-app.c                   |   22 +-
 src/logview-findbar.c               |  160 ++-----
 src/logview-findbar.h               |    3 -
 src/logview-gear-menu.ui            |   51 ++
 src/logview-loglist.c               |    8 +-
 src/logview-manager.c               |    4 +-
 src/logview-menubar.xml             |   30 --
 src/logview-utils.c                 |   99 +++--
 src/logview-utils.h                 |    5 +-
 src/logview-window.c                |  883 ++++++++++++++++-------------------
 src/logview.gresource.xml           |    2 +-
 src/tests/test-reader.c             |    2 +-
 18 files changed, 1109 insertions(+), 675 deletions(-)
---
diff --git a/data/gnome-system-log.desktop.in.in b/data/gnome-system-log.desktop.in.in
index 1375969..c66d2b0 100644
--- a/data/gnome-system-log.desktop.in.in
+++ b/data/gnome-system-log.desktop.in.in
@@ -1,5 +1,5 @@
 [Desktop Entry]
-_Name=Log File Viewer
+_Name=System Log
 _Comment=View or monitor system log files
 Exec=gnome-system-log
 Icon=logview
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5f3a0b0..c747e94 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,6 +7,7 @@ src/logview-app.c
 [type: gettext/glade]src/logview-app-menu.ui
 src/logview-filter-manager.c
 [type: gettext/glade]src/logview-filter.ui
+[type: gettext/glade]src/logview-gear-menu.ui
 src/logview-findbar.c
 src/logview-log.c
 src/logview-loglist.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 8b1f0ed..32d983b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,7 +12,7 @@ bin_PROGRAMS = gnome-system-log
 ui_files = \
 	logview-app-menu.ui	\
 	logview-filter.ui	\
-	logview-menubar.xml
+	logview-gear-menu.ui
 
 logview-resources.c: logview.gresource.xml $(ui_files)
 	$(AM_V_GEN)glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name logview $(srcdir)/logview.gresource.xml
@@ -25,6 +25,8 @@ BUILT_SOURCES = 		\
 	logview-resources.h
 
 gnome_system_log_SOURCES = 	\
+	gd-main-toolbar.c	\
+	gd-main-toolbar.h	\
 	logview-app.c		\
 	logview-app.h		\
 	logview-main.c		\
diff --git a/src/gd-main-toolbar.c b/src/gd-main-toolbar.c
new file mode 100644
index 0000000..e1995ba
--- /dev/null
+++ b/src/gd-main-toolbar.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by 
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#include "gd-main-toolbar.h"
+
+#include <math.h>
+#include <glib/gi18n.h>
+
+G_DEFINE_TYPE (GdMainToolbar, gd_main_toolbar, GTK_TYPE_TOOLBAR)
+
+typedef enum {
+  CHILD_NORMAL = 0,
+  CHILD_TOGGLE = 1,
+  CHILD_MENU = 2,
+} ChildType;
+
+struct _GdMainToolbarPrivate {
+  GtkSizeGroup *size_group;
+  GtkSizeGroup *vertical_size_group;
+
+  GtkToolItem *left_group;
+  GtkToolItem *center_group;
+  GtkToolItem *right_group;
+
+  GtkWidget *left_grid;
+
+  GtkWidget *title_label;
+  GtkWidget *detail_label;
+
+  GtkWidget *right_grid;
+};
+
+static void
+gd_main_toolbar_dispose (GObject *obj)
+{
+  GdMainToolbar *self = GD_MAIN_TOOLBAR (obj);
+
+  g_clear_object (&self->priv->size_group);
+  g_clear_object (&self->priv->vertical_size_group);
+
+  G_OBJECT_CLASS (gd_main_toolbar_parent_class)->dispose (obj);
+}
+
+static gint
+get_icon_margin (void)
+{
+  gint toolbar_size, menu_size;
+
+  gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &menu_size, NULL);
+  gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &toolbar_size, NULL);
+  return (gint) floor ((toolbar_size - menu_size) / 2.0);
+}
+
+static GtkSizeGroup *
+get_vertical_size_group (void)
+{
+  GtkSizeGroup *retval;
+  GtkWidget *w, *dummy;
+  gint icon_margin;
+
+  icon_margin = get_icon_margin ();
+
+  dummy = gtk_toggle_button_new ();
+  w = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
+  g_object_set (w, "margin", icon_margin, NULL);
+  gtk_container_add (GTK_CONTAINER (dummy), w);
+  gtk_widget_show_all (dummy);
+
+  retval = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+  gtk_size_group_add_widget (retval, dummy);
+
+  return retval;
+}
+
+static GtkWidget *
+get_empty_button (ChildType type)
+{
+  GtkWidget *button;
+
+  switch (type)
+    {
+    case CHILD_MENU:
+      button = gtk_menu_button_new ();
+      break;
+    case CHILD_TOGGLE:
+      button = gtk_toggle_button_new ();
+      break;
+    case CHILD_NORMAL:
+    default:
+      button = gtk_button_new ();
+      break;
+    }
+
+  return button;
+}
+
+static GtkWidget *
+get_symbolic_button (const gchar *icon_name,
+                     ChildType    type)
+{
+  GtkWidget *button, *w;
+
+  switch (type)
+    {
+    case CHILD_MENU:
+      button = gtk_menu_button_new ();
+      gtk_widget_destroy (gtk_bin_get_child (GTK_BIN (button)));
+      break;
+    case CHILD_TOGGLE:
+      button = gtk_toggle_button_new ();
+      break;
+    case CHILD_NORMAL:
+    default:
+      button = gtk_button_new ();
+      break;
+    }
+
+  gtk_style_context_add_class (gtk_widget_get_style_context (button), "raised");
+
+  w = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
+  g_object_set (w, "margin", get_icon_margin (), NULL);
+  gtk_widget_show (w);
+  gtk_container_add (GTK_CONTAINER (button), w);
+
+  return button;
+}
+
+static GtkWidget *
+get_text_button (const gchar *label,
+                 ChildType    type)
+{
+  GtkWidget *button, *w;
+
+  switch (type)
+    {
+    case CHILD_MENU:
+      button = gtk_menu_button_new ();
+      gtk_widget_destroy (gtk_bin_get_child (GTK_BIN (button)));
+
+      w = gtk_label_new (label);
+      gtk_widget_show (w);
+      gtk_container_add (GTK_CONTAINER (button), w);
+      break;
+    case CHILD_TOGGLE:
+      button = gtk_toggle_button_new_with_label (label);
+      break;
+    case CHILD_NORMAL:
+    default:
+      button = gtk_button_new_with_label (label);
+      break;
+    }
+
+  gtk_widget_set_vexpand (button, TRUE);
+  gtk_style_context_add_class (gtk_widget_get_style_context (button), "raised");
+
+  return button;
+}
+
+static void
+gd_main_toolbar_constructed (GObject *obj)
+{
+  GdMainToolbar *self = GD_MAIN_TOOLBAR (obj);
+  GtkToolbar *tb = GTK_TOOLBAR (obj);
+  GtkWidget *grid;
+
+  G_OBJECT_CLASS (gd_main_toolbar_parent_class)->constructed (obj);
+
+  self->priv->vertical_size_group = get_vertical_size_group ();
+
+  /* left section */
+  self->priv->left_group = gtk_tool_item_new ();
+  gtk_widget_set_margin_right (GTK_WIDGET (self->priv->left_group), 12);
+  gtk_toolbar_insert (tb, self->priv->left_group, -1);
+  gtk_size_group_add_widget (self->priv->vertical_size_group,
+                             GTK_WIDGET (self->priv->left_group));
+
+  /* left button group */
+  self->priv->left_grid = gtk_grid_new ();
+  gtk_grid_set_column_spacing (GTK_GRID (self->priv->left_grid), 12);
+  gtk_container_add (GTK_CONTAINER (self->priv->left_group), self->priv->left_grid);
+
+  /* center section */
+  self->priv->center_group = gtk_tool_item_new ();
+  gtk_tool_item_set_expand (self->priv->center_group, TRUE);
+  gtk_toolbar_insert (tb, self->priv->center_group, -1);
+  gtk_size_group_add_widget (self->priv->vertical_size_group,
+                             GTK_WIDGET (self->priv->center_group));
+
+  /* centered label group */
+  grid = gtk_grid_new ();
+  gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
+  gtk_widget_set_valign (grid, GTK_ALIGN_CENTER);
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+  gtk_container_add (GTK_CONTAINER (self->priv->center_group), grid);
+
+  self->priv->title_label = gtk_label_new (NULL);
+  gtk_label_set_ellipsize (GTK_LABEL (self->priv->title_label), PANGO_ELLIPSIZE_END);
+  gtk_container_add (GTK_CONTAINER (grid), self->priv->title_label);
+
+  self->priv->detail_label = gtk_label_new (NULL);
+  gtk_widget_set_no_show_all (self->priv->detail_label, TRUE);
+  gtk_style_context_add_class (gtk_widget_get_style_context (self->priv->detail_label), "dim-label");
+  gtk_container_add (GTK_CONTAINER (grid), self->priv->detail_label);
+
+  /* right section */
+  self->priv->right_group = gtk_tool_item_new ();
+  gtk_widget_set_margin_left (GTK_WIDGET (self->priv->right_group), 12);
+  gtk_toolbar_insert (tb, self->priv->right_group, -1);
+  gtk_size_group_add_widget (self->priv->vertical_size_group,
+                             GTK_WIDGET (self->priv->right_group));
+
+  self->priv->right_grid = gtk_grid_new ();
+  gtk_grid_set_column_spacing (GTK_GRID (self->priv->right_grid), 12);
+  gtk_container_add (GTK_CONTAINER (self->priv->right_group), self->priv->right_grid);
+
+  self->priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+  gtk_size_group_add_widget (self->priv->size_group, GTK_WIDGET (self->priv->left_group));
+  gtk_size_group_add_widget (self->priv->size_group, GTK_WIDGET (self->priv->right_group));
+}
+
+static void
+gd_main_toolbar_init (GdMainToolbar *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_MAIN_TOOLBAR, GdMainToolbarPrivate);
+}
+
+static void
+gd_main_toolbar_class_init (GdMainToolbarClass *klass)
+{
+  GObjectClass *oclass;
+
+  oclass = G_OBJECT_CLASS (klass);
+  oclass->constructed = gd_main_toolbar_constructed;
+  oclass->dispose = gd_main_toolbar_dispose;
+
+  g_type_class_add_private (klass, sizeof (GdMainToolbarPrivate));
+}
+
+void
+gd_main_toolbar_clear (GdMainToolbar *self)
+{
+  /* reset labels */
+  gtk_label_set_text (GTK_LABEL (self->priv->title_label), "");
+  gtk_label_set_text (GTK_LABEL (self->priv->detail_label), "");
+
+  /* clear all added buttons */
+  gtk_container_foreach (GTK_CONTAINER (self->priv->left_grid),
+                         (GtkCallback) gtk_widget_destroy, self);
+  gtk_container_foreach (GTK_CONTAINER (self->priv->right_grid), 
+                         (GtkCallback) gtk_widget_destroy, self);
+}
+
+/**
+ * gd_main_toolbar_set_labels:
+ * @self:
+ * @primary: (allow-none):
+ * @detail: (allow-none):
+ *
+ */
+void
+gd_main_toolbar_set_labels (GdMainToolbar *self,
+                            const gchar *primary,
+                            const gchar *detail)
+{
+  gchar *real_primary = NULL;
+
+  if (primary != NULL)
+    real_primary = g_markup_printf_escaped ("<b>%s</b>", primary);
+
+  if (real_primary == NULL)
+    {
+      gtk_label_set_markup (GTK_LABEL (self->priv->title_label), "");
+      gtk_widget_hide (self->priv->title_label);
+    }
+  else
+    {
+      gtk_label_set_markup (GTK_LABEL (self->priv->title_label), real_primary);
+      gtk_widget_show (self->priv->title_label);
+    }
+
+  if (detail == NULL)
+    {
+      gtk_label_set_text (GTK_LABEL (self->priv->detail_label), "");
+      gtk_widget_hide (self->priv->detail_label);
+    }
+  else
+    {
+      gtk_label_set_text (GTK_LABEL (self->priv->detail_label), detail);
+      gtk_widget_show (self->priv->detail_label);
+    }
+
+  g_free (real_primary);
+}
+
+GtkWidget *
+gd_main_toolbar_new (void)
+{
+  return g_object_new (GD_TYPE_MAIN_TOOLBAR, NULL);
+}
+
+static GtkWidget *
+add_button_internal (GdMainToolbar *self,
+                     const gchar *icon_name,
+                     const gchar *label,
+                     gboolean pack_start,
+                     ChildType type)
+{
+  GtkWidget *button;
+
+  if (icon_name != NULL)
+    {
+      button = get_symbolic_button (icon_name, type);
+      if (label != NULL)
+        gtk_widget_set_tooltip_text (button, label);
+    }
+  else if (label != NULL)
+    {
+      button = get_text_button (label, type);
+    }
+  else
+    {
+      button = get_empty_button (type);
+    }
+
+  if (pack_start)
+    gtk_container_add (GTK_CONTAINER (self->priv->left_grid), button);
+  else
+    gtk_container_add (GTK_CONTAINER (self->priv->right_grid), button);    
+
+  gtk_widget_show_all (button);
+
+  return button;
+}
+
+/**
+ * gd_main_toolbar_add_button:
+ * @self:
+ * @icon_name: (allow-none):
+ * @label: (allow-none):
+ * @pack_start:
+ *
+ * Returns: (transfer none):
+ */
+GtkWidget *
+gd_main_toolbar_add_button (GdMainToolbar *self,
+                            const gchar *icon_name,
+                            const gchar *label,
+                            gboolean pack_start)
+{
+  return add_button_internal (self, icon_name, label, pack_start, CHILD_NORMAL);
+}
+
+/**
+ * gd_main_toolbar_add_menu:
+ * @self:
+ * @icon_name: (allow-none):
+ * @label: (allow-none):
+ * @pack_start:
+ *
+ * Returns: (transfer none):
+ */
+GtkWidget *
+gd_main_toolbar_add_menu (GdMainToolbar *self,
+                          const gchar *icon_name,
+                          const gchar *label,
+                          gboolean pack_start)
+{
+  return add_button_internal (self, icon_name, label, pack_start, CHILD_MENU);
+}
+
+/**
+ * gd_main_toolbar_add_menu:
+ * @self:
+ * @icon_name: (allow-none):
+ * @label: (allow-none):
+ * @pack_start:
+ *
+ * Returns: (transfer none):
+ */
+GtkWidget *
+gd_main_toolbar_add_toggle (GdMainToolbar *self,
+                            const gchar *icon_name,
+                            const gchar *label,
+                            gboolean pack_start)
+{
+  return add_button_internal (self, icon_name, label, pack_start, CHILD_TOGGLE);
+}
diff --git a/src/gd-main-toolbar.h b/src/gd-main-toolbar.h
new file mode 100644
index 0000000..5d4c7e7
--- /dev/null
+++ b/src/gd-main-toolbar.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by 
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef __GD_MAIN_TOOLBAR_H__
+#define __GD_MAIN_TOOLBAR_H__
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_MAIN_TOOLBAR gd_main_toolbar_get_type()
+
+#define GD_MAIN_TOOLBAR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   GD_TYPE_MAIN_TOOLBAR, GdMainToolbar))
+
+#define GD_MAIN_TOOLBAR_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   GD_TYPE_MAIN_TOOLBAR, GdMainToolbarClass))
+
+#define GD_IS_MAIN_TOOLBAR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   GD_TYPE_MAIN_TOOLBAR))
+
+#define GD_IS_MAIN_TOOLBAR_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   GD_TYPE_MAIN_TOOLBAR))
+
+#define GD_MAIN_TOOLBAR_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+   GD_TYPE_MAIN_TOOLBAR, GdMainToolbarClass))
+
+typedef struct _GdMainToolbar GdMainToolbar;
+typedef struct _GdMainToolbarClass GdMainToolbarClass;
+typedef struct _GdMainToolbarPrivate GdMainToolbarPrivate;
+
+struct _GdMainToolbar
+{
+  GtkToolbar parent;
+
+  GdMainToolbarPrivate *priv;
+};
+
+struct _GdMainToolbarClass
+{
+  GtkToolbarClass parent_class;
+};
+
+GType gd_main_toolbar_get_type (void) G_GNUC_CONST;
+
+GtkWidget     *gd_main_toolbar_new (void);
+
+void        gd_main_toolbar_set_labels (GdMainToolbar *self,
+                                        const gchar *primary,
+                                        const gchar *detail);
+
+void        gd_main_toolbar_clear (GdMainToolbar *self);
+
+GtkWidget * gd_main_toolbar_add_button (GdMainToolbar *self,
+                                        const gchar *icon_name,
+                                        const gchar *label,
+                                        gboolean pack_start);
+
+GtkWidget * gd_main_toolbar_add_toggle (GdMainToolbar *self,
+                                        const gchar *icon_name,
+                                        const gchar *label,
+                                        gboolean pack_start);
+
+GtkWidget * gd_main_toolbar_add_menu (GdMainToolbar *self,
+                                      const gchar *icon_name,
+                                      const gchar *label,
+                                      gboolean pack_start);
+
+G_END_DECLS
+
+#endif /* __GD_MAIN_TOOLBAR_H__ */
diff --git a/src/logview-app-menu.ui b/src/logview-app-menu.ui
index 837b7d2..6e023fa 100644
--- a/src/logview-app-menu.ui
+++ b/src/logview-app-menu.ui
@@ -2,6 +2,13 @@
   <menu id="app-menu">
     <section>
       <item>
+        <attribute name="action">win.autoscroll</attribute>
+        <attribute name="label" translatable="yes">Auto Scroll</attribute>
+        <attribute name="accel">F8</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
         <attribute name="action">app.about</attribute>
         <attribute name="label" translatable="yes">About System Log</attribute>
       </item>
diff --git a/src/logview-app.c b/src/logview-app.c
index dd36b84..1a1927a 100644
--- a/src/logview-app.c
+++ b/src/logview-app.c
@@ -332,8 +332,11 @@ static GActionEntry action_entries[] = {
   { "quit", action_quit, NULL, NULL, NULL }
 };
 
+#define SIMPLE_ACCEL(app, accel, action) \
+  (gtk_application_add_accelerator (GTK_APPLICATION (app), accel, action, NULL))
+
 static void
-logview_app_init_menus (LogviewApp *app)
+logview_app_init_actions (LogviewApp *app)
 {
   GtkBuilder *builder = gtk_builder_new ();
   GMenuModel *app_menu;
@@ -345,6 +348,21 @@ logview_app_init_menus (LogviewApp *app)
   app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "app-menu"));
   gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
 
+  /* action accels */
+  SIMPLE_ACCEL (app, "<Control>f", "win.search");
+  SIMPLE_ACCEL (app, "<Control>o", "win.open");
+  SIMPLE_ACCEL (app, "<Control>w", "win.close");
+  SIMPLE_ACCEL (app, "<Control>c", "win.copy");
+  SIMPLE_ACCEL (app, "<Control>a", "win.select_all");
+  SIMPLE_ACCEL (app, "<Control>plus", "win.zoom_in");
+  SIMPLE_ACCEL (app, "<Control>minus", "win.zoom_out");
+  SIMPLE_ACCEL (app, "<Control>0", "win.zoom_normal");
+
+  /* additional zoom accels */
+  SIMPLE_ACCEL (app, "<Control>KP_Add", "win.zoom_in");
+  SIMPLE_ACCEL (app, "<Control>KP_Subtract", "win.zoom_out");
+  SIMPLE_ACCEL (app, "<Control>KP_0", "win.zoom_normal");
+
   g_object_unref (builder);
   g_object_unref (app_menu);
 }
@@ -357,7 +375,7 @@ logview_app_startup (GApplication *application)
   G_APPLICATION_CLASS (logview_app_parent_class)->startup (application);
 
   app->priv->window = logview_window_new (GTK_APPLICATION (app));
-  logview_app_init_menus (app);
+  logview_app_init_actions (app);
 }
 
 static void
diff --git a/src/logview-findbar.c b/src/logview-findbar.c
index 0257a67..73cf81a 100644
--- a/src/logview-findbar.c
+++ b/src/logview-findbar.c
@@ -26,22 +26,17 @@
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
+#include <math.h>
 
 #include "logview-findbar.h"
 
 struct _LogviewFindbarPrivate {
   GtkWidget *entry;
-  GtkWidget *message;
 
-  GtkToolItem *clear_button;
-  GtkToolItem *back_button;
-  GtkToolItem *forward_button;
-  GtkToolItem *status_item;
-  GtkToolItem *separator;
+  GtkWidget *back_button;
+  GtkWidget *forward_button;
   
   char *string;
-
-  guint status_bold_id;
 };
 
 enum {
@@ -78,16 +73,6 @@ forward_button_clicked_cb (GtkToolButton *button,
 }
 
 static void
-clear_button_clicked_cb (GtkToolButton *button,
-                         gpointer user_data)
-{
-  LogviewFindbar *findbar = user_data;
-
-  logview_findbar_set_message (findbar, NULL);
-  gtk_entry_set_text (GTK_ENTRY (findbar->priv->entry), "");
-}
-
-static void
 entry_activate_cb (GtkWidget *entry,
                    gpointer user_data)
 {
@@ -105,10 +90,6 @@ entry_changed_cb (GtkEditable *editable,
 
   text = gtk_entry_get_text (GTK_ENTRY (editable));
 
-  if (g_strcmp0 (text, "") == 0) {
-    return;
-  }
-
   if (g_strcmp0 (findbar->priv->string, text) != 0) {
     g_free (findbar->priv->string);
     findbar->priv->string = g_strdup (text);
@@ -132,25 +113,20 @@ entry_key_press_event_cb (GtkWidget *entry,
   return FALSE;
 }
 
-static gboolean
-unbold_timeout_cb (gpointer user_data)
+static gint
+get_icon_margin (void)
 {
-  LogviewFindbar *findbar = user_data;
-  PangoFontDescription *desc;
-
-  desc = pango_font_description_new ();
-  gtk_widget_modify_font (findbar->priv->message, desc);
-  pango_font_description_free (desc);
-
-  findbar->priv->status_bold_id = 0;
+  gint toolbar_size, menu_size;
 
-  return FALSE;
+  gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &menu_size, NULL);
+  gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &toolbar_size, NULL);
+  return (gint) floor ((toolbar_size - menu_size) / 2.0);
 }
 
 static void 
 logview_findbar_init (LogviewFindbar *findbar)
 {
-  GtkWidget *label, *w, *box;
+  GtkWidget *w, *box;
   GtkToolbar *gtoolbar;
   GtkToolItem *item;
   LogviewFindbarPrivate *priv;
@@ -161,65 +137,45 @@ logview_findbar_init (LogviewFindbar *findbar)
 
   gtk_toolbar_set_style (gtoolbar, GTK_TOOLBAR_BOTH_HORIZ);
 
-  priv->status_bold_id = 0;
-
-  /* Find: |_______| */
-  w = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
-  gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 2, 2);
-
-  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-  gtk_container_add (GTK_CONTAINER (w), box);
-
-  label = gtk_label_new_with_mnemonic (_("_Find:"));
-  gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
-
-  priv->entry = gtk_entry_new ();
-  gtk_entry_set_width_chars (GTK_ENTRY (priv->entry), 32);
-  gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->entry);
-  gtk_box_pack_start (GTK_BOX (box), priv->entry, TRUE, TRUE, 0);
+  priv->entry = gtk_search_entry_new ();
 
   item = gtk_tool_item_new ();
-  gtk_container_add (GTK_CONTAINER (item), w);
+  gtk_tool_item_set_expand (GTK_TOOL_ITEM (item), TRUE);
+  gtk_container_add (GTK_CONTAINER (item), priv->entry);
   gtk_toolbar_insert (gtoolbar, item, -1);
   gtk_widget_show_all (GTK_WIDGET (item));
 
+  item = gtk_separator_tool_item_new ();
+  gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (item), FALSE);
+  gtk_toolbar_insert (gtoolbar, item, -1);
+  gtk_widget_show (GTK_WIDGET (item));
+
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_style_context_add_class (gtk_widget_get_style_context (box), "linked");
+
   /* "Previous" and "Next" buttons */
-  w = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE);
-  priv->back_button = gtk_tool_button_new (w, _("Find Previous"));
-  gtk_tool_item_set_is_important (priv->back_button, TRUE);
-  gtk_tool_item_set_tooltip_text (priv->back_button,
-                                 _("Find previous occurrence of the search string"));
-  gtk_toolbar_insert (gtoolbar, priv->back_button, -1);
+  priv->back_button = gtk_button_new ();
+  w = gtk_image_new_from_icon_name ("go-up-symbolic", GTK_ICON_SIZE_MENU);
+  g_object_set (w, "margin", get_icon_margin (), NULL);
+  gtk_container_add (GTK_CONTAINER (priv->back_button), w);
+  gtk_container_add (GTK_CONTAINER (box), priv->back_button);
+  gtk_widget_set_tooltip_text (priv->back_button,
+                               _("Find previous occurrence of the search string"));
   gtk_widget_show_all (GTK_WIDGET (priv->back_button));
 
-  w = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
-  priv->forward_button = gtk_tool_button_new (w, _("Find Next"));
-  gtk_tool_item_set_is_important (priv->forward_button, TRUE);
-  gtk_tool_item_set_tooltip_text (priv->forward_button,
-                                 _("Find next occurrence of the search string"));
-  gtk_toolbar_insert (gtoolbar, priv->forward_button, -1);
+  priv->forward_button = gtk_button_new ();
+  w = gtk_image_new_from_icon_name ("go-down-symbolic", GTK_ICON_SIZE_MENU);
+  g_object_set (w, "margin", get_icon_margin (), NULL);
+  gtk_container_add (GTK_CONTAINER (priv->forward_button), w);
+  gtk_container_add (GTK_CONTAINER (box), priv->forward_button);
+  gtk_widget_set_tooltip_text (priv->forward_button,
+                               _("Find next occurrence of the search string"));
   gtk_widget_show_all (GTK_WIDGET (priv->forward_button));
 
-  /* clear button */
-  priv->clear_button = gtk_tool_button_new_from_stock (GTK_STOCK_CLEAR);
-  gtk_tool_item_set_tooltip_text (priv->clear_button,
-                                 _("Clear the search string"));
-  gtk_toolbar_insert (gtoolbar, priv->clear_button, -1);
-  gtk_widget_show_all (GTK_WIDGET (priv->clear_button));
-
-  /* separator */
-  priv->separator = gtk_separator_tool_item_new ();
-  gtk_toolbar_insert (gtoolbar, priv->separator, -1);
-
-  /* message */
-  priv->status_item = gtk_tool_item_new ();
-  gtk_tool_item_set_expand (priv->status_item, TRUE);
-  priv->message = gtk_label_new ("");
-  gtk_label_set_use_markup (GTK_LABEL (priv->message), TRUE);
-  gtk_misc_set_alignment (GTK_MISC (priv->message), 0.0, 0.5);
-  gtk_container_add (GTK_CONTAINER (priv->status_item), priv->message);
-  gtk_widget_show (priv->message);
-  gtk_toolbar_insert (gtoolbar, priv->status_item, -1);
+  item = gtk_tool_item_new ();
+  gtk_container_add (GTK_CONTAINER (item), box);
+  gtk_toolbar_insert (gtoolbar, item, -1);
+  gtk_widget_show_all (GTK_WIDGET (item));
 
   priv->string = NULL;
 
@@ -228,8 +184,6 @@ logview_findbar_init (LogviewFindbar *findbar)
                     G_CALLBACK (back_button_clicked_cb), findbar);
   g_signal_connect (priv->forward_button, "clicked",
                     G_CALLBACK (forward_button_clicked_cb), findbar);
-  g_signal_connect (priv->clear_button, "clicked",
-                    G_CALLBACK (clear_button_clicked_cb), findbar);
   g_signal_connect (priv->entry, "activate",
                     G_CALLBACK (entry_activate_cb), findbar);
   g_signal_connect (priv->entry, "changed",
@@ -306,18 +260,7 @@ logview_findbar_class_init (LogviewFindbarClass *klass)
 GtkWidget *
 logview_findbar_new (void)
 {
-  GtkWidget *widget;
-  widget = g_object_new (LOGVIEW_TYPE_FINDBAR, NULL);
-  return widget;
-}
-
-void
-logview_findbar_open (LogviewFindbar *findbar)
-{
-  g_assert (LOGVIEW_IS_FINDBAR (findbar));
-
-  gtk_widget_show (GTK_WIDGET (findbar));
-  gtk_widget_grab_focus (GTK_WIDGET (findbar));
+  return g_object_new (LOGVIEW_TYPE_FINDBAR, NULL);
 }
 
 const char *
@@ -327,26 +270,3 @@ logview_findbar_get_text (LogviewFindbar *findbar)
 
   return findbar->priv->string;
 }
-
-void
-logview_findbar_set_message (LogviewFindbar *findbar,
-                             const char *text)
-{
-  PangoFontDescription *desc;
-
-  g_assert (LOGVIEW_IS_FINDBAR (findbar));
-
-  if (text) {
-    desc = pango_font_description_new ();
-    pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
-    gtk_widget_modify_font (findbar->priv->message, desc);
-    pango_font_description_free (desc);
-    
-    findbar->priv->status_bold_id = g_timeout_add (600, unbold_timeout_cb, findbar);
-  }
-
-  gtk_label_set_text (GTK_LABEL (findbar->priv->message), 
-                      text != NULL ? text : "");
-  g_object_set (findbar->priv->separator, "visible", text != NULL, NULL);
-  g_object_set (findbar->priv->status_item, "visible", text != NULL, NULL);
-}
diff --git a/src/logview-findbar.h b/src/logview-findbar.h
index 792d065..8ffbb88 100644
--- a/src/logview-findbar.h
+++ b/src/logview-findbar.h
@@ -62,10 +62,7 @@ GType logview_findbar_get_type (void);
 
 /* public methods */
 GtkWidget *  logview_findbar_new         (void);
-void         logview_findbar_open        (LogviewFindbar *findbar);
 const char * logview_findbar_get_text    (LogviewFindbar *findbar);
-void         logview_findbar_set_message (LogviewFindbar *findbar,
-                                          const char *message);
 
 G_END_DECLS
 
diff --git a/src/logview-gear-menu.ui b/src/logview-gear-menu.ui
new file mode 100644
index 0000000..7abac42
--- /dev/null
+++ b/src/logview-gear-menu.ui
@@ -0,0 +1,51 @@
+<interface>
+  <menu id="gear-menu">
+    <section>
+      <item>
+        <attribute name="action">win.open</attribute>
+        <attribute name="label" translatable="yes">Open...</attribute>
+      </item>
+      <item>
+        <attribute name="action">win.close</attribute>
+        <attribute name="label" translatable="yes">Close</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="action">win.copy</attribute>
+        <attribute name="label" translatable="yes">Copy</attribute>
+      </item>
+      <item>
+        <attribute name="action">win.select_all</attribute>
+        <attribute name="label" translatable="yes">Select All</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="action">win.zoom_in</attribute>
+        <attribute name="label" translatable="yes">Zoom In</attribute>
+      </item>
+      <item>
+        <attribute name="action">win.zoom_out</attribute>
+        <attribute name="label" translatable="yes">Zoom Out</attribute>
+      </item>
+      <item>
+        <attribute name="action">win.zoom_normal</attribute>
+        <attribute name="label" translatable="yes">Normal Size</attribute>
+      </item>
+    </section>
+    <submenu>
+      <attribute name="label" translatable="yes">Filters</attribute>
+      <section id="filters-placeholder">
+      </section>
+      <item>
+        <attribute name="action">win.filters_match</attribute>
+        <attribute name="label" translatable="yes">Show Matches Only</attribute>
+      </item>
+      <item>
+        <attribute name="action">win.filters_manage</attribute>
+        <attribute name="label" translatable="yes">Manage Filters...</attribute>
+      </item>
+    </submenu>
+  </menu>
+</interface>
diff --git a/src/logview-loglist.c b/src/logview-loglist.c
index 52e2034..f73163b 100644
--- a/src/logview-loglist.c
+++ b/src/logview-loglist.c
@@ -79,7 +79,7 @@ update_days_and_lines_for_log (LogviewLoglist *loglist,
   GtkTreeIter iter, dummy;
   GSList *l;
   int i;
-  char date[200];
+  gchar *date;
   Day *day;
 
   /* if we have some days, we can't remove all the items immediately, otherwise,
@@ -101,13 +101,14 @@ update_days_and_lines_for_log (LogviewLoglist *loglist,
   for (i = 1, l = days; l; l = l->next) {
     /* now insert all the days */
     day = l->data;
-
-    g_date_strftime (date, 200, "%A, %e %b", day->date);
+    date = logview_utils_format_date (day->date);
 
     gtk_tree_store_insert (GTK_TREE_STORE (loglist->priv->model),
                            &iter, log, i);
     gtk_tree_store_set (GTK_TREE_STORE (loglist->priv->model),
                         &iter, LOG_NAME, date, LOG_DAY, day, -1);
+    g_free (date);
+
     i++;
   }
 
@@ -152,7 +153,6 @@ log_changed_cb (LogviewLog *log,
   active = logview_manager_get_active_log (list->priv->manager);
 
   if (log == active) {
-    g_object_unref (active);
     return;
   }
 
diff --git a/src/logview-manager.c b/src/logview-manager.c
index dd48f14..29dcba9 100644
--- a/src/logview-manager.c
+++ b/src/logview-manager.c
@@ -312,9 +312,7 @@ logview_manager_get_active_log (LogviewManager *manager)
 {
   g_assert (LOGVIEW_IS_MANAGER (manager));
 
-  return (manager->priv->active_log != NULL) ?
-    g_object_ref (manager->priv->active_log) :
-    NULL;
+  return manager->priv->active_log;
 }
 
 void
diff --git a/src/logview-utils.c b/src/logview-utils.c
index 82070b1..675d6e4 100644
--- a/src/logview-utils.c
+++ b/src/logview-utils.c
@@ -30,6 +30,7 @@
 #include <math.h>
 
 #include <glib.h>
+#include <glib/gi18n.h>
 
 #include "logview-utils.h"
 
@@ -40,7 +41,7 @@ logview_utils_day_free (Day *day)
     return;
   }
 
-  g_date_free (day->date);
+  g_date_time_unref (day->date);
   g_slice_free (Day, day);
 }
 
@@ -50,7 +51,7 @@ logview_utils_day_copy (Day *day)
   Day *retval;
 
   retval = g_slice_new0 (Day);
-  retval->date = g_date_new_julian (g_date_get_julian (day->date));
+  retval->date = g_date_time_new_from_unix_utc (g_date_time_to_unix (day->date));
   retval->first_line = day->first_line;
   retval->last_line = day->last_line;
   retval->timestamp_len = day->timestamp_len;
@@ -75,15 +76,21 @@ days_compare (gconstpointer a, gconstpointer b)
 {
   const Day *day1 = a, *day2 = b;
 
-  return g_date_compare (day1->date, day2->date);
+  return - g_date_time_compare (day1->date, day2->date);
 }
 
-static GDate *
-string_get_date (const char *line, char **time_string, int *timestamp_len)
+static GDateTime *
+string_get_date (const char *line, time_t current, char **time_string, int *timestamp_len)
 {
-  GDate *date = NULL;
+  GDateTime *date = NULL;
   struct tm tp;
   char *cp = NULL, *timestamp = NULL;
+  gint current_year;
+  gboolean has_year = FALSE;
+
+  localtime_r (&current, &tp);
+  current_year = tp.tm_year + 1900;
+  memset (&tp, 0, sizeof (struct tm));
   
   /* it's safe to assume that if strptime returns NULL, it's
    * because of an error (format unmatched). being a log file, it's very
@@ -103,13 +110,17 @@ string_get_date (const char *line, char **time_string, int *timestamp_len)
   /* this parses the YYYY-MM-DD format */
   cp = strptime (line, "%F", &tp);
   if (cp) {
+    has_year = TRUE;
     goto out;
   }
 
 out:
   if (cp) {
-    /* the year doesn't matter to us now */
-    date = g_date_new_dmy (tp.tm_mday, tp.tm_mon + 1, 1);
+    if (has_year)
+      current_year = tp.tm_year + 1900;
+
+    date = g_date_time_new_local (current_year, tp.tm_mon + 1, tp.tm_mday,
+                                  0, 0, 0);
     *time_string = g_strndup (line, cp - line);
 
     timestamp = strptime (cp, "%X", &tp);
@@ -138,11 +149,10 @@ out:
 GSList *
 log_read_dates (const char **buffer_lines, time_t current)
 {
-  int current_year, offsetyear, i, n, rangemin, rangemax, timestamp_len = 0;
+  int offsetyear, i, n, rangemin, rangemax, timestamp_len = 0;
   GSList *days = NULL;
-  GDate *date = NULL;
-  GDate *newdate;
-  struct tm *tmptm;
+  GDateTime *date = NULL;
+  GDateTime *newdate, *tmp;
   char *date_string;
   Day *day;
   gboolean done = FALSE;
@@ -150,14 +160,11 @@ log_read_dates (const char **buffer_lines, time_t current)
   g_return_val_if_fail (buffer_lines != NULL, NULL);
 
   n = g_strv_length ((char **) buffer_lines);
-
-  tmptm = localtime (&current);
-  current_year = tmptm->tm_year + 1900;
   offsetyear = 0;
 
   /* find the first line with a date we're able to parse */
   for (i = 0; buffer_lines[i]; i++) {
-    if ((date = string_get_date (buffer_lines[i], &date_string, &timestamp_len)) != NULL)
+    if ((date = string_get_date (buffer_lines[i], current, &date_string, &timestamp_len)) != NULL)
       break;
   }
 
@@ -166,14 +173,6 @@ log_read_dates (const char **buffer_lines, time_t current)
     return NULL;
   }
 
-  if (!g_date_valid (date)) {
-    g_date_free (date);
-    g_free (date_string);
-    return NULL;
-  }
-
-  g_date_set_year (date, current_year);
-
   day = g_slice_new0 (Day);
   days = g_slist_append (days, day);
 
@@ -230,7 +229,7 @@ log_read_dates (const char **buffer_lines, time_t current)
       newdate = NULL;
       
       for (i = day->last_line + 1; buffer_lines[i]; i++) {
-        if ((newdate = string_get_date (buffer_lines[i], &date_string, &timestamp_len)) != NULL)
+        if ((newdate = string_get_date (buffer_lines[i], current, &date_string, &timestamp_len)) != NULL)
         break;
       }
 
@@ -247,17 +246,10 @@ log_read_dates (const char **buffer_lines, time_t current)
       if (newdate) {
         /* append a new day to the list */
 
-        g_date_set_year (newdate, current_year + offsetyear);
+        tmp = g_date_time_add_years (newdate, offsetyear);
+        g_date_time_unref (newdate);
+        date = tmp;
 
-        if (g_date_compare (newdate, date) < 1) {
-          /* this isn't possible, as we're reading the log forward.
-           * so it means that newdate is the next year.
-           */
-          g_date_add_years (newdate, 1);
-          offsetyear++;
-        }
-
-        date = newdate;
         day = g_slice_new0 (Day);
         days = g_slist_prepend (days, day);
 
@@ -280,3 +272,40 @@ log_read_dates (const char **buffer_lines, time_t current)
 
   return days;
 }
+
+gchar *
+logview_utils_format_date (GDateTime *date)
+{
+  GString *format;
+  GDateTime *now;
+  gboolean same_year;
+  gint day_date, day_now;
+  gchar *date_string;
+
+  now = g_date_time_new_now_local ();
+  same_year = (g_date_time_get_year (now) == g_date_time_get_year (date));
+  format = g_string_new (NULL);
+
+  if (same_year) {
+    day_now = g_date_time_get_day_of_year (now);
+    day_date = g_date_time_get_day_of_year (date);
+
+    if (day_now == day_date)
+      g_string_append (format, _("today"));
+    else if (day_now == (day_date + 1))
+      g_string_append (format, _("yesterday"));
+    else if (g_date_time_get_month (now) ==
+             g_date_time_get_month (date))
+      g_string_append (format, " %a %e");
+    else
+      g_string_append (format, " %a %b %e");
+  } else {
+      g_string_append (format, " %a %b %e %Y");
+  }
+
+  date_string = g_date_time_format (date, format->str);
+  g_string_free (format, TRUE);
+  g_date_time_unref (now);
+
+  return date_string;
+}
diff --git a/src/logview-utils.h b/src/logview-utils.h
index 2724291..f4d4877 100644
--- a/src/logview-utils.h
+++ b/src/logview-utils.h
@@ -24,7 +24,7 @@
 #include <glib.h>
 
 typedef struct {
-  GDate *date;
+  GDateTime *date;
   int first_line;
   int last_line;
   int timestamp_len;
@@ -36,5 +36,6 @@ void     logview_utils_day_free (Day *day);
 Day *    logview_utils_day_copy (Day *day);
 GSList * logview_utils_day_list_copy (GSList *days);
 
+gchar * logview_utils_format_date (GDateTime *date);
 
-#endif /* __LOGVIEW_UTILS_H__ */
\ No newline at end of file
+#endif /* __LOGVIEW_UTILS_H__ */
diff --git a/src/logview-window.c b/src/logview-window.c
index 603bfd5..c34cfec 100644
--- a/src/logview-window.c
+++ b/src/logview-window.c
@@ -28,36 +28,32 @@
 
 #include "logview-window.h"
 
+#include "gd-main-toolbar.h"
 #include "logview-loglist.h"
 #include "logview-findbar.h"
 #include "logview-prefs.h"
 #include "logview-manager.h"
 #include "logview-filter-manager.h"
 
-#define APP_NAME _("System Log Viewer")
 #define SEARCH_START_MARK "lw-search-start-mark"
 #define SEARCH_END_MARK "lw-search-end-mark"
 
 struct _LogviewWindowPrivate {
-  GtkUIManager *ui_manager;
-  GtkActionGroup *action_group;
-  GtkActionGroup *filter_action_group;
-
   PangoFontDescription *monospace_description;
 
   GtkWidget *find_bar;
   GtkWidget *loglist;
-  GtkWidget *sidebar; 
-  GtkWidget *version_bar;
-  GtkWidget *version_selector;
+  GtkWidget *sidebar;
   GtkWidget *hpaned;
   GtkWidget *text_view;
-  GtkWidget *statusbar;
+  GtkWidget *toolbar;
 
   GtkWidget *message_area;
   GtkWidget *message_primary;
   GtkWidget *message_secondary;
 
+  GMenuModel *filters_placeholder;
+
   GtkTextTagTable *tag_table;
 
   int original_fontsize, fontsize;
@@ -87,42 +83,6 @@ static void read_new_lines_cb (LogviewLog *log,
                                GError *error,
                                gpointer user_data);
 
-/* private functions */
-
-static void
-logview_version_selector_changed (GtkComboBox *version_selector, gpointer user_data)
-{
-
-}
-#if 0
-	LogviewWindow *logview = user_data;
-	Log *log = logview->curlog;
-	int selected;
-
-    g_assert (LOGVIEW_IS_WINDOW (logview));
-
-	selected = gtk_combo_box_get_active (version_selector);
-
-	if (selected == log->current_version)
-		return;
-
-	/* select a new version */
-	if (selected == 0) {
-		logview_select_log (logview, log->parent_log);
-	} else {
-		Log *new;
-		if (log->parent_log) {
-			new = log->parent_log->older_logs[selected];
-		} else {
-			new = log->older_logs[selected];
-		}
-
-		logview_select_log (logview, new);
-	}
-}
-
-#endif
-
 /* private helpers */
 
 static void
@@ -199,36 +159,62 @@ _gtk_text_buffer_apply_tag_to_rectangle (GtkTextBuffer *buffer, int line_start,
 }
 
 static void
-logview_update_statusbar (LogviewWindow *logview, LogviewLog *active)
+logview_update_toolbar (LogviewWindow *logview, 
+                        LogviewLog *active,
+                        Day *selected_day)
 {
-  char *statusbar_text;
-  char *size, *modified, *timestring_utf8;
+  GString *string;
+  GDateTime *log_time;
+  gchar *text;
   time_t timestamp;
-  char timestring[255];
 
   if (active == NULL) {
-    gtk_statusbar_pop (GTK_STATUSBAR (logview->priv->statusbar), 0);
+    gd_main_toolbar_set_labels (GD_MAIN_TOOLBAR (logview->priv->toolbar),
+                                NULL, NULL);
+    return;
+  }
+
+  if (gtk_widget_get_visible (logview->priv->find_bar)) {
+    text = g_strdup_printf ("Search in \"%s\"",
+                            logview_log_get_display_name (active));
+    gd_main_toolbar_set_labels (GD_MAIN_TOOLBAR (logview->priv->toolbar),
+                                text, NULL);
+    g_free (text);
+    return;
+  }
+
+  if (selected_day != NULL) {
+    text = logview_utils_format_date (selected_day->date);
+    gd_main_toolbar_set_labels (GD_MAIN_TOOLBAR (logview->priv->toolbar),
+                                logview_log_get_display_name (active), text);
+    g_free (text);
+
     return;
   }
 
   timestamp = logview_log_get_timestamp (active);
-  strftime (timestring, sizeof (timestring), "%a %b %e %T %Y", localtime (&timestamp));
-  timestring_utf8 = g_locale_to_utf8 (timestring, -1, NULL, NULL, NULL);
+  log_time = g_date_time_new_from_unix_local (timestamp);
 
-  modified = g_strdup_printf (_("last update: %s"), timestring_utf8);
+  text = logview_utils_format_date (log_time);
 
-  size = g_format_size (logview_log_get_file_size (active));
-  statusbar_text = g_strdup_printf (_("%d lines (%s) - %s"), 
-                                    logview_log_get_cached_lines_number (active),
-                                    size, modified);
+  /* translators: this is part of a label composed with
+   * a date string, for example "updated today 23:54"
+   */
+  string = g_string_new (_("updated"));
+  g_string_append (string, " ");
+  g_string_append (string, text);
+  g_free (text);
 
-  gtk_statusbar_pop (GTK_STATUSBAR (logview->priv->statusbar), 0);
-  gtk_statusbar_push (GTK_STATUSBAR (logview->priv->statusbar), 0, statusbar_text);
-  
-  g_free (size);
-  g_free (timestring_utf8);
-  g_free (modified);
-  g_free (statusbar_text);
+  text = g_date_time_format (log_time, "%X");
+  g_string_append (string, " ");
+  g_string_append (string, text);
+  g_free (text);
+
+  gd_main_toolbar_set_labels (GD_MAIN_TOOLBAR (logview->priv->toolbar),
+                              logview_log_get_display_name (active), string->str);
+
+  g_string_free (string, TRUE);
+  g_date_time_unref (log_time);
 }
 
 #define DEFAULT_LOGVIEW_FONT "Monospace 10"
@@ -268,145 +254,13 @@ logview_set_fontsize (LogviewWindow *logview, gboolean store)
 }
 
 static void
-logview_set_window_title (LogviewWindow *logview, const char * log_name)
-{
-  char *window_title;
-
-  if (log_name) {
-    window_title = g_strdup_printf ("%s - %s", log_name, APP_NAME);
-  } else {
-    window_title = g_strdup_printf (APP_NAME);
-  }
-
-  gtk_window_set_title (GTK_WINDOW (logview), window_title);
-
-  g_free (window_title);
-}
-
-/* actions callbacks */
-
-static void
-open_file_selected_cb (GtkWidget *chooser, gint response, LogviewWindow *logview)
-{
-  GFile *f;
-  char *file_uri;
-  LogviewLog *log;
-
-  gtk_widget_hide (GTK_WIDGET (chooser));
-  if (response != GTK_RESPONSE_OK) {
-	  return;
-  }
-
-  f = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (chooser));
-  file_uri = g_file_get_uri (f);
-
-  log = logview_manager_get_if_loaded (logview->priv->manager, file_uri);
-
-  g_free (file_uri);
-
-  if (log) {
-    logview_manager_set_active_log (logview->priv->manager, log);
-    g_object_unref (log);
-    goto out;
-  }
-
-  logview_manager_add_log_from_gfile (logview->priv->manager, f, TRUE);
-
-out:
-  g_object_unref (f);
-}
-
-static void
-logview_open_log (GtkAction *action, LogviewWindow *logview)
-{
-  static GtkWidget *chooser = NULL;
-  char *active;
-
-  if (chooser == NULL) {
-    chooser = gtk_file_chooser_dialog_new (_("Open Log"),
-                                           GTK_WINDOW (logview),
-                                           GTK_FILE_CHOOSER_ACTION_OPEN,
-                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                           GTK_STOCK_OPEN, GTK_RESPONSE_OK,
-                                           NULL);
-    gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
-    gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
-    g_signal_connect (chooser, "response",
-                      G_CALLBACK (open_file_selected_cb), logview);
-    g_signal_connect (chooser, "destroy",
-                      G_CALLBACK (gtk_widget_destroyed), &chooser);
-    active = logview_prefs_get_active_logfile (logview->priv->prefs);
-    if (active != NULL) {
-      gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), active);
-      g_free (active);
-    }
-  }
-
-  gtk_window_present (GTK_WINDOW (chooser));
-}
-
-static void
-logview_close_log (GtkAction *action, LogviewWindow *logview)
-{
-  findbar_close_cb (LOGVIEW_FINDBAR (logview->priv->find_bar), logview);
-  logview_manager_close_active_log (logview->priv->manager);
-}
-
-static void
-logview_bigger_text (GtkAction *action, LogviewWindow *logview)
-{
-  logview->priv->fontsize = MIN (logview->priv->fontsize + 1, 24);
-  logview_set_fontsize (logview, TRUE);
-}	
-
-static void
-logview_smaller_text (GtkAction *action, LogviewWindow *logview)
-{
-  logview->priv->fontsize = MAX (logview->priv->fontsize-1, 6);
-  logview_set_fontsize (logview, TRUE);
-}	
-
-static void
-logview_normal_text (GtkAction *action, LogviewWindow *logview)
-{
-  logview->priv->fontsize = logview->priv->original_fontsize;
-  logview_set_fontsize (logview, TRUE);
-}
-
-static void
-logview_select_all (GtkAction *action, LogviewWindow *logview)
-{
-  GtkTextIter start, end;
-  GtkTextBuffer *buffer;
-
-  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
-
-  gtk_text_buffer_get_bounds (buffer, &start, &end);
-  gtk_text_buffer_select_range (buffer, &start, &end);
-
-  gtk_widget_grab_focus (GTK_WIDGET (logview->priv->text_view));
-}
-
-static void
-logview_copy (GtkAction *action, LogviewWindow *logview)
-{
-  GtkTextBuffer *buffer;
-  GtkClipboard *clipboard;
-
-  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
-  clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
-
-  gtk_text_buffer_copy_clipboard (buffer, clipboard);
-
-  gtk_widget_grab_focus (GTK_WIDGET (logview->priv->text_view));
-}
-
-static void
 findbar_close_cb (LogviewFindbar *findbar,
                   gpointer user_data)
 {
-  gtk_widget_hide (GTK_WIDGET (findbar));
-  logview_findbar_set_message (findbar, NULL);
+  LogviewWindow *window = user_data;
+
+  g_action_group_change_action_state (G_ACTION_GROUP (window), "search",
+                                      g_variant_new_boolean (FALSE));
 }
 
 static void
@@ -415,8 +269,10 @@ logview_search_text (LogviewWindow *logview, gboolean forward)
   GtkTextBuffer *buffer;
   GtkTextMark *search_start, *search_end;
   GtkTextIter search, start_m, end_m;
-  const char *text;
+  const char *text, *secondary;
   gboolean res, wrapped;
+  gchar *primary;
+  LogviewLog *active_log;
 
   wrapped = FALSE;
 
@@ -430,6 +286,8 @@ logview_search_text (LogviewWindow *logview, gboolean forward)
   search_start = gtk_text_buffer_get_mark (buffer, SEARCH_START_MARK);
   search_end = gtk_text_buffer_get_mark (buffer, SEARCH_END_MARK);
 
+  secondary = primary = NULL;
+
   if (!search_start) {
     /* this is our first search on the buffer, create a new search mark */
     gtk_text_buffer_get_start_iter (buffer, &search);
@@ -461,7 +319,7 @@ wrap:
     gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW (logview->priv->text_view), search_end);
 
     if (wrapped) {
-      logview_findbar_set_message (LOGVIEW_FINDBAR (logview->priv->find_bar), _("Wrapped"));
+      secondary = _("Wrapped");
     }
   } else {
     if (wrapped) {
@@ -476,7 +334,7 @@ wrap:
         gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &iter);
       }
 
-      logview_findbar_set_message (LOGVIEW_FINDBAR (logview->priv->find_bar), _("Not found"));
+      secondary = _("No matches found");
     } else {
       if (forward) {
         gtk_text_buffer_get_start_iter (buffer, &search);
@@ -488,6 +346,16 @@ wrap:
       goto wrap;
     }
   }
+
+  active_log = logview_manager_get_active_log (logview_manager_get ());
+  if (!active_log)
+    return;
+
+  primary = g_strdup_printf ("Search in \"%s\"",
+                             logview_log_get_display_name (active_log));
+  gd_main_toolbar_set_labels (GD_MAIN_TOOLBAR (logview->priv->toolbar), primary, secondary);
+
+  g_free (primary);
 }
 
 static void
@@ -529,8 +397,6 @@ text_changed_timeout_cb (gpointer user_data)
     gtk_text_buffer_move_mark (buffer, search_end, &start);
   }
 
-  logview_findbar_set_message (LOGVIEW_FINDBAR (logview->priv->find_bar), NULL);
-
   logview_search_text (logview, TRUE);
 
   return FALSE;
@@ -550,12 +416,6 @@ findbar_text_changed_cb (LogviewFindbar *findbar,
 }
 
 static void
-logview_search (GtkAction *action, LogviewWindow *logview)
-{
-  logview_findbar_open (LOGVIEW_FINDBAR (logview->priv->find_bar));
-}
-
-static void
 filter_buffer (LogviewWindow *logview, gint start_line)
 {
   GtkTextBuffer *buffer;
@@ -618,19 +478,29 @@ filter_remove (LogviewWindow *logview, LogviewFilter *filter)
 }
 
 static void
-on_filter_toggled (GtkToggleAction *action, LogviewWindow *logview)
+filter_activate (GSimpleAction *action,
+                 GVariant *parameter,
+                 gpointer user_data)
 {
-  LogviewWindowPrivate *priv = GET_PRIVATE (logview);
-  const gchar* name;
+  LogviewWindow *logview = user_data;
+  LogviewWindowPrivate *priv = logview->priv;
+  const gchar* action_name, *name;
   LogviewFilter *filter;
+  GVariant *state_variant;
+  gboolean new_state;
 
-  name = gtk_action_get_name (GTK_ACTION (action));
-  
-  if (gtk_toggle_action_get_active (action)) {
+  state_variant = g_action_get_state (G_ACTION (action));
+  new_state = !g_variant_get_boolean (state_variant);
+  g_variant_unref (state_variant);
+
+  action_name = g_action_get_name (G_ACTION (action));
+  name = action_name + strlen ("filter_");
+
+  if (new_state) {
     priv->active_filters = g_list_append (priv->active_filters,
                                           logview_prefs_get_filter (priv->prefs,
                                                                     name));
-    filter_buffer(logview, 0);
+    filter_buffer (logview, 0);
   } else {
     filter = logview_prefs_get_filter (priv->prefs, name);
     priv->active_filters = g_list_remove (priv->active_filters,
@@ -638,182 +508,66 @@ on_filter_toggled (GtkToggleAction *action, LogviewWindow *logview)
 
     filter_remove (logview, filter);
   }
+
+  g_simple_action_set_state (action, g_variant_new_boolean (new_state));
 }
 
-#define FILTER_PLACEHOLDER "/LogviewMenu/FilterMenu/PlaceholderFilters"
 static void
 update_filter_menu (LogviewWindow *window)
 {
-  LogviewWindowPrivate *priv;
-  GtkUIManager* ui;
-  GList *actions, *l;
-  guint id;
-  GList *filters;
+  LogviewWindowPrivate *priv = window->priv;
+  GVariant *variant;
   GtkTextTagTable *table;
   GtkTextTag *tag;
-  GtkToggleAction *action;
-  gchar* name;
-
-  priv = GET_PRIVATE (window);
-  ui = priv->ui_manager;
-
-  g_return_if_fail (priv->filter_action_group != NULL);
+  gint idx;
+  gchar *name, *action_name, *menu_action_name;
+  GList *filters, *l;
+  GSimpleAction *action;
 
   table = priv->tag_table;
 
-  if (priv->filter_merge_id != 0) {
-    gtk_ui_manager_remove_ui (ui,
-                              priv->filter_merge_id);
-  }
+  for (idx = g_menu_model_get_n_items (window->priv->filters_placeholder); idx > 0; idx--)
+    {
+      variant = g_menu_model_get_item_attribute_value (window->priv->filters_placeholder,
+                                                       idx - 1, G_MENU_ATTRIBUTE_ACTION, NULL);
+      name = (gchar *) g_variant_get_string (variant, NULL) + strlen ("win.filter_");
+      action_name = (gchar *) g_variant_get_string (variant, NULL) + strlen ("win.");
 
-  actions = gtk_action_group_list_actions (priv->filter_action_group);
+      tag = gtk_text_tag_table_lookup (table, name);
+      gtk_text_tag_table_remove (table, tag);
 
-  for (l = actions; l != NULL; l = g_list_next (l)) {
-    tag = gtk_text_tag_table_lookup (table, gtk_action_get_name (GTK_ACTION (l->data)));
-    gtk_text_tag_table_remove (table, tag);
+      g_menu_remove (G_MENU (window->priv->filters_placeholder), idx - 1);
+      g_action_map_remove_action (G_ACTION_MAP (window), action_name);
 
-    g_signal_handlers_disconnect_by_func (GTK_ACTION (l->data),
-                                          G_CALLBACK (on_filter_toggled),
-                                          window);
-    gtk_action_group_remove_action (priv->filter_action_group,
-                                    GTK_ACTION (l->data));
-  }
+      g_variant_unref (variant);
+    }
 
-  g_list_free (actions);
-  
   filters = logview_prefs_get_filters (logview_prefs_get ());
 
-  id = (g_list_length (filters) > 0) ? gtk_ui_manager_new_merge_id (ui) : 0;
-
   for (l = filters; l != NULL; l = g_list_next (l)) {
     g_object_get (l->data, "name", &name, NULL);
+    action_name = g_strconcat ("filter_", name, NULL);
 
-    action = gtk_toggle_action_new (name, name, NULL, NULL);
-    gtk_action_group_add_action (priv->filter_action_group,
-                                 GTK_ACTION (action));
+    action = g_simple_action_new_stateful (action_name, NULL, g_variant_new_boolean (FALSE));
+    g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
 
-    g_signal_connect (action,
-                      "toggled",
-                      G_CALLBACK (on_filter_toggled),
-                      window);
+    menu_action_name = g_strconcat ("win.", action_name, NULL);
+    g_menu_append (G_MENU (window->priv->filters_placeholder), name, menu_action_name);
+    g_signal_connect (action, "activate",
+                      G_CALLBACK (filter_activate), window);
 
-    gtk_ui_manager_add_ui (ui, id, FILTER_PLACEHOLDER,
-                           name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
     gtk_text_tag_table_add (table, 
                             logview_filter_get_tag (LOGVIEW_FILTER (l->data)));
 
     g_object_unref (action);
-    g_free(name);
+    g_free (name);
+    g_free (action_name);
+    g_free (menu_action_name);
   }
 
   g_list_free (filters);
-
-  priv->filter_merge_id = id;
-}
-
-static void
-on_logview_filter_manager_response (GtkDialog *dialog, 
-                                    gint response,
-                                    LogviewWindow *logview)
-{
-  update_filter_menu (logview);
-
-  g_list_free (logview->priv->active_filters);
-  logview->priv->active_filters = NULL;
-}
-
-static void
-logview_manage_filters (GtkAction *action, LogviewWindow *logview)
-{
-  GtkWidget *manager;
-
-  manager = logview_filter_manager_new ();
-
-  g_signal_connect (manager, "response", 
-                    G_CALLBACK (on_logview_filter_manager_response),
-                    logview);
-  
-  gtk_window_set_transient_for (GTK_WINDOW (manager),
-                                GTK_WINDOW (logview));
-  gtk_widget_show (GTK_WIDGET (manager));
-}
-
-static void
-logview_toggle_statusbar (GtkAction *action, LogviewWindow *logview)
-{
-  if (gtk_widget_get_visible (logview->priv->statusbar))
-    gtk_widget_hide (logview->priv->statusbar);
-  else
-    gtk_widget_show (logview->priv->statusbar);
-}
-
-static void
-logview_toggle_sidebar (GtkAction *action, LogviewWindow *logview)
-{
-  if (gtk_widget_get_visible (logview->priv->sidebar))
-    gtk_widget_hide (logview->priv->sidebar);
-  else
-    gtk_widget_show (logview->priv->sidebar);
 }
 
-static void
-logview_toggle_match_filters (GtkToggleAction *action, LogviewWindow *logview)
-{
-  logview->priv->matches_only = gtk_toggle_action_get_active (action);
-  filter_buffer (logview, 0);
-}
-
-static void
-logview_toggle_autoscroll (GtkToggleAction *action, LogviewWindow *logview)
-{
-  logview->priv->auto_scroll = gtk_toggle_action_get_active (action);
-}
-
-/* GObject functions */
-
-/* Menus */
-
-static GtkActionEntry entries[] = {
-    { "FileMenu", NULL, N_("_File"), NULL, NULL, NULL },
-    { "EditMenu", NULL, N_("_Edit"), NULL, NULL, NULL },
-    { "ViewMenu", NULL, N_("_View"), NULL, NULL, NULL },
-    { "FilterMenu", NULL, N_("_Filters"), NULL, NULL, NULL },  
-    { "HelpMenu", NULL, N_("_Help"), NULL, NULL, NULL },
-
-    { "OpenLog", GTK_STOCK_OPEN, N_("_Open..."), "<control>O", N_("Open a log from file"), 
-      G_CALLBACK (logview_open_log) },
-    { "CloseLog", GTK_STOCK_CLOSE, N_("_Close"), "<control>W", N_("Close this log"), 
-      G_CALLBACK (logview_close_log) },
-
-    { "Copy", GTK_STOCK_COPY, N_("_Copy"), "<control>C", N_("Copy the selection"),
-      G_CALLBACK (logview_copy) },
-    { "SelectAll", NULL, N_("Select _All"), "<Control>A", N_("Select the entire log"),
-      G_CALLBACK (logview_select_all) },
-    { "Search", GTK_STOCK_FIND, N_("_Find..."), "<control>F", N_("Find a word or phrase in the log"),
-      G_CALLBACK (logview_search) },
-
-    { "ViewZoomIn", GTK_STOCK_ZOOM_IN, NULL, "<control>plus", N_("Bigger text size"),
-      G_CALLBACK (logview_bigger_text)},
-    { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus", N_("Smaller text size"),
-      G_CALLBACK (logview_smaller_text)},
-    { "ViewZoom100", GTK_STOCK_ZOOM_100, NULL, "<control>0", N_("Normal text size"),
-      G_CALLBACK (logview_normal_text)},
-
-    { "FilterManage", NULL, N_("Manage Filters"), NULL, N_("Manage filters"),
-      G_CALLBACK (logview_manage_filters)},
-};
-
-static GtkToggleActionEntry toggle_entries[] = {
-    { "ShowStatusBar", NULL, N_("_Statusbar"), NULL, N_("Show Status Bar"),
-      G_CALLBACK (logview_toggle_statusbar), TRUE },
-    { "ShowSidebar", NULL, N_("Side _Pane"), "F9", N_("Show Side Pane"), 
-      G_CALLBACK (logview_toggle_sidebar), TRUE }, 
-    { "FilterMatchOnly", NULL, N_("Show matches only"), NULL, N_("Only show lines that match one of the given filters"),
-      G_CALLBACK (logview_toggle_match_filters), FALSE },
-    { "AutoScroll", NULL, N_("_Auto Scroll"), "F8", N_("Automatically scroll down when new lines appear"),
-      G_CALLBACK (logview_toggle_autoscroll), TRUE }
-};
-
 static gboolean 
 window_size_changed_cb (GtkWidget *widget, GdkEventConfigure *event, 
                         gpointer data)
@@ -828,7 +582,7 @@ window_size_changed_cb (GtkWidget *widget, GdkEventConfigure *event,
 
 static void
 real_select_day (LogviewWindow *logview,
-                 GDate *date, int first_line, int last_line)
+                 int first_line, int last_line)
 {
   GtkTextBuffer *buffer;
   GtkTextIter start_iter, end_iter, start_vis, end_vis;
@@ -862,8 +616,10 @@ loglist_day_selected_cb (LogviewLoglist *loglist,
                          gpointer user_data)
 {
   LogviewWindow *logview = user_data;
+  LogviewLog *active_log = logview_manager_get_active_log (logview_manager_get ());
 
-  real_select_day (logview, day->date, day->first_line, day->last_line);
+  real_select_day (logview, day->first_line, day->last_line);
+  logview_update_toolbar (logview, active_log, day);
 }
 
 static void
@@ -873,6 +629,7 @@ loglist_day_cleared_cb (LogviewLoglist *loglist,
   LogviewWindow *logview = user_data;
   GtkTextBuffer *buffer;
   GtkTextIter start, end;
+  LogviewLog *active_log = logview_manager_get_active_log (logview_manager_get ());
 
   buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
   gtk_text_buffer_get_bounds (buffer, &start, &end);
@@ -880,6 +637,8 @@ loglist_day_cleared_cb (LogviewLoglist *loglist,
   /* clear all previous invisible tags */
   gtk_text_buffer_remove_tag_by_name (buffer, "invisible",
                                       &start, &end);
+
+  logview_update_toolbar (logview, active_log, NULL);
 }
 
 static void
@@ -986,7 +745,7 @@ read_new_lines_cb (LogviewLog *log,
                                                  G_CALLBACK (log_monitor_changed_cb), window);
   }
 
-  logview_update_statusbar (window, log);
+  logview_update_toolbar (window, log, NULL);
   logview_loglist_update_lines (LOGVIEW_LOGLIST (window->priv->loglist), log);
 }
 
@@ -1003,7 +762,7 @@ active_log_changed_cb (LogviewManager *manager,
   findbar_close_cb (LOGVIEW_FINDBAR (window->priv->find_bar),
                     window);
 
-  logview_set_window_title (window, logview_log_get_display_name (log));
+  logview_update_toolbar (window, log, NULL);
 
   if (window->priv->monitor_id) {
     g_signal_handler_disconnect (old_log, window->priv->monitor_id);
@@ -1058,42 +817,6 @@ font_changed_cb (LogviewPrefs *prefs,
   logview_set_font (window, font_name);
 }
 
-static const struct {
-  guint keyval;
-  GdkModifierType modifier;
-  const gchar *action;
-} extra_keybindings [] = {
-  { GDK_KEY_KP_Add,      GDK_CONTROL_MASK, "ViewZoomIn" },
-  { GDK_KEY_KP_Subtract, GDK_CONTROL_MASK, "ViewZoomOut" },
-  { GDK_KEY_KP_0,        GDK_CONTROL_MASK, "ViewZoom100" }
-};
-
-static gboolean
-key_press_event_cb (GtkWidget *widget,
-                    GdkEventKey *event,
-                    gpointer user_data)
-{
-  LogviewWindow *window = user_data;
-  guint modifier = event->state & gtk_accelerator_get_default_mod_mask ();
-  GtkAction *action;
-  int i;
-
-  /* handle accelerators that we want bound, but aren't associated with
-   * an action */
-  for (i = 0; i < G_N_ELEMENTS (extra_keybindings); i++) {
-    if (event->keyval == extra_keybindings[i].keyval &&
-        modifier == extra_keybindings[i].modifier) {
-
-      action = gtk_action_group_get_action (window->priv->action_group,
-                                            extra_keybindings[i].action);
-      gtk_action_activate (action);
-      return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
 /* adapted from GEdit */
 
 static void
@@ -1183,30 +906,278 @@ logview_window_finalize (GObject *object)
 {
   LogviewWindow *logview = LOGVIEW_WINDOW (object);
 
-  g_object_unref (logview->priv->ui_manager);
+  g_clear_object (&logview->priv->filters_placeholder);
   pango_font_description_free (logview->priv->monospace_description);
 
   G_OBJECT_CLASS (logview_window_parent_class)->finalize (object);
 }
 
 static void
+action_matches_only_change_state (GSimpleAction *action,
+                                  GVariant *state,
+                                  gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  logview->priv->matches_only = g_variant_get_boolean (state);
+  filter_buffer (logview, 0);
+
+  g_simple_action_set_state (action, state);
+}
+
+static void
+filter_manager_response_cb (GtkDialog *dialog, 
+                            gint response,
+                            LogviewWindow *logview)
+{
+  update_filter_menu (logview);
+
+  g_list_free (logview->priv->active_filters);
+  logview->priv->active_filters = NULL;
+}
+
+static void
+action_filters_manage (GSimpleAction *action,
+                       GVariant *parameter,
+                       gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  GtkWidget *manager;
+
+  manager = logview_filter_manager_new ();
+  g_signal_connect (manager, "response", 
+                    G_CALLBACK (filter_manager_response_cb), logview);
+
+  gtk_window_set_transient_for (GTK_WINDOW (manager),
+                                GTK_WINDOW (logview));
+  gtk_widget_show (GTK_WIDGET (manager));
+}
+
+static void
+action_zoom_in (GSimpleAction *action,
+                GVariant *parameter,
+                gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  logview->priv->fontsize = MIN (logview->priv->fontsize + 1, 24);
+  logview_set_fontsize (logview, TRUE);
+}	
+
+static void
+action_zoom_out (GSimpleAction *action,
+                 GVariant *parameter,
+                 gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  logview->priv->fontsize = MAX (logview->priv->fontsize - 1, 6);
+  logview_set_fontsize (logview, TRUE);
+}	
+
+static void
+action_zoom_normal (GSimpleAction *action,
+                    GVariant *parameter,
+                    gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  logview->priv->fontsize = logview->priv->original_fontsize;
+  logview_set_fontsize (logview, TRUE);
+}
+
+static void
+action_select_all (GSimpleAction *action,
+                   GVariant *parameter,
+                   gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  GtkTextIter start, end;
+  GtkTextBuffer *buffer;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+
+  gtk_text_buffer_get_bounds (buffer, &start, &end);
+  gtk_text_buffer_select_range (buffer, &start, &end);
+
+  gtk_widget_grab_focus (GTK_WIDGET (logview->priv->text_view));
+}
+
+static void
+action_copy (GSimpleAction *action,
+             GVariant *parameter,
+             gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  GtkTextBuffer *buffer;
+  GtkClipboard *clipboard;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
+  clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+
+  gtk_text_buffer_copy_clipboard (buffer, clipboard);
+
+  gtk_widget_grab_focus (GTK_WIDGET (logview->priv->text_view));
+}
+
+static void
+action_close (GSimpleAction *action,
+              GVariant *parameter,
+              gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+
+  findbar_close_cb (LOGVIEW_FINDBAR (logview->priv->find_bar), logview);
+  logview_manager_close_active_log (logview->priv->manager);
+}
+
+static void
+open_file_selected_cb (GtkWidget *chooser,
+                       gint response,
+                       LogviewWindow *logview)
+{
+  GFile *f;
+  char *file_uri;
+  LogviewLog *log;
+
+  gtk_widget_hide (GTK_WIDGET (chooser));
+  if (response != GTK_RESPONSE_OK) {
+	  return;
+  }
+
+  f = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (chooser));
+  file_uri = g_file_get_uri (f);
+
+  log = logview_manager_get_if_loaded (logview->priv->manager, file_uri);
+
+  g_free (file_uri);
+
+  if (log) {
+    logview_manager_set_active_log (logview->priv->manager, log);
+    g_object_unref (log);
+    goto out;
+  }
+
+  logview_manager_add_log_from_gfile (logview->priv->manager, f, TRUE);
+
+out:
+  g_object_unref (f);
+}
+
+static void
+action_open (GSimpleAction *action,
+             GVariant *parameter,
+             gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  static GtkWidget *chooser = NULL;
+  char *active;
+
+  if (chooser == NULL) {
+    chooser = gtk_file_chooser_dialog_new (_("Open Log"),
+                                           GTK_WINDOW (logview),
+                                           GTK_FILE_CHOOSER_ACTION_OPEN,
+                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                           GTK_STOCK_OPEN, GTK_RESPONSE_OK,
+                                           NULL);
+    gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
+    gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
+    g_signal_connect (chooser, "response",
+                      G_CALLBACK (open_file_selected_cb), logview);
+    g_signal_connect (chooser, "destroy",
+                      G_CALLBACK (gtk_widget_destroyed), &chooser);
+    active = logview_prefs_get_active_logfile (logview->priv->prefs);
+    if (active != NULL) {
+      gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), active);
+      g_free (active);
+    }
+  }
+
+  gtk_window_present (GTK_WINDOW (chooser));
+}
+
+static void
+action_search_change_state (GSimpleAction *action,
+                            GVariant *state,
+                            gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  gboolean open = g_variant_get_boolean (state);
+  LogviewLog *active_log = logview_manager_get_active_log (logview_manager_get ());
+
+  if (open) {
+    gtk_widget_show (logview->priv->find_bar);
+    gtk_widget_grab_focus (logview->priv->find_bar);
+  } else {
+    gtk_widget_hide (logview->priv->find_bar);
+  }
+
+  logview_update_toolbar (logview, active_log, NULL);
+
+  g_simple_action_set_state (action, state);
+}
+
+static void
+action_autoscroll_change_state (GSimpleAction *action,
+                                GVariant *state,
+                                gpointer user_data)
+{
+  LogviewWindow *logview = user_data;
+  logview->priv->auto_scroll = g_variant_get_boolean (state);
+  g_simple_action_set_state (action, state);
+}
+
+static void
+action_toggle (GSimpleAction *action,
+               GVariant *parameter,
+               gpointer user_data)
+{
+  GVariant *state;
+
+  state = g_action_get_state (G_ACTION (action));
+  g_action_change_state (G_ACTION (action), g_variant_new_boolean (!g_variant_get_boolean (state)));
+  g_variant_unref (state);
+}
+
+static GActionEntry action_entries[] = {
+  { "autoscroll", action_toggle, NULL, "true", action_autoscroll_change_state },
+  { "search", action_toggle, NULL, "false", action_search_change_state },
+  { "open", action_open, NULL, NULL, NULL },
+  { "close", action_close, NULL, NULL, NULL },
+  { "copy", action_copy, NULL, NULL, NULL },
+  { "select_all", action_select_all, NULL, NULL, NULL },
+  { "zoom_in", action_zoom_in, NULL, NULL, NULL },
+  { "zoom_out", action_zoom_out, NULL, NULL, NULL },
+  { "zoom_normal", action_zoom_normal, NULL, NULL, NULL },
+  { "filters_match", action_toggle, NULL, "false", action_matches_only_change_state },
+  { "filters_manage", action_filters_manage, NULL, NULL, NULL }
+};
+
+static void
+logview_window_init_actions (LogviewWindow *window)
+{
+  g_action_map_add_action_entries (G_ACTION_MAP (window), action_entries,
+                                   G_N_ELEMENTS (action_entries), window);
+  window->priv->auto_scroll = TRUE;
+}
+
+static void
 logview_window_init (LogviewWindow *logview)
 {
-  GtkActionGroup *action_group;
-  GtkAccelGroup *accel_group;
-  GError *error = NULL;
   GtkWidget *hpaned, *main_view, *vbox, *w;
   gchar *monospace_font_name;
   LogviewWindowPrivate *priv;
   int width, height;
-  gboolean res;
+  GtkBuilder *builder;
+  GMenuModel *menu;
 
   priv = logview->priv = GET_PRIVATE (logview);
   priv->prefs = logview_prefs_get ();
   priv->manager = logview_manager_get ();
   priv->monitor_id = 0;
 
+  logview_window_init_actions (logview);
+
+  gtk_window_set_title (GTK_WINDOW (logview), _("System Log"));
   gtk_window_set_icon_name (GTK_WINDOW (logview), "logview");
+  gtk_window_set_hide_titlebar_when_maximized (GTK_WINDOW (logview), TRUE);
 
   logview_prefs_get_stored_window_size (priv->prefs, &width, &height);
   gtk_window_set_default_size (GTK_WINDOW (logview), width, height);
@@ -1214,33 +1185,40 @@ logview_window_init (LogviewWindow *logview)
   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
   gtk_container_add (GTK_CONTAINER (logview), vbox);
 
-  /* create menus */
-  action_group = gtk_action_group_new ("LogviewMenuActions");
-  gtk_action_group_set_translation_domain (action_group, NULL);
-  gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), logview);
-  gtk_action_group_add_toggle_actions (action_group, toggle_entries, G_N_ELEMENTS (toggle_entries), logview);
-  priv->action_group = action_group;
-  priv->auto_scroll = TRUE;
+  /* create toolbar and menus */
+  priv->toolbar = gd_main_toolbar_new ();
+  gtk_style_context_add_class (gtk_widget_get_style_context (priv->toolbar),
+                               "menubar");
+  gtk_box_pack_start (GTK_BOX (vbox), priv->toolbar, FALSE, FALSE, 0);
+  gtk_widget_show_all (priv->toolbar);
 
-  priv->ui_manager = gtk_ui_manager_new ();
+  w = gd_main_toolbar_add_toggle (GD_MAIN_TOOLBAR (priv->toolbar),
+                                  "edit-find-symbolic", NULL, FALSE);
+  gtk_actionable_set_action_name (GTK_ACTIONABLE (w), "win.search");
 
-  gtk_ui_manager_insert_action_group (priv->ui_manager, action_group, 0);
-  accel_group = gtk_ui_manager_get_accel_group (priv->ui_manager);
-  gtk_window_add_accel_group (GTK_WINDOW (logview), accel_group);
+  w = gd_main_toolbar_add_menu (GD_MAIN_TOOLBAR (priv->toolbar),
+                                "emblem-system-symbolic", NULL, FALSE);
+  gtk_widget_show (w);
 
-  res = gtk_ui_manager_add_ui_from_resource (priv->ui_manager,
-                                             "/org/gnome/logview/logview-menubar.xml",
-                                             &error);
+  builder = gtk_builder_new ();
+  gtk_builder_add_from_resource (builder, "/org/gnome/logview/logview-gear-menu.ui", NULL);
+  menu = G_MENU_MODEL (gtk_builder_get_object (builder, "gear-menu"));
+  gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (w), menu);
 
-  if (res == FALSE) {
-    g_critical ("Can't load the UI description: %s", error->message);
-    g_error_free (error);
-    return;
-  }
+  priv->filters_placeholder = G_MENU_MODEL (gtk_builder_get_object (builder, "filters-placeholder"));
+  g_object_unref (builder);
 
-  w = gtk_ui_manager_get_widget (priv->ui_manager, "/LogviewMenu");
-  gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
-  gtk_widget_show (w);
+  priv->find_bar = logview_findbar_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), priv->find_bar, FALSE, FALSE, 0);
+
+  g_signal_connect (priv->find_bar, "previous",
+                    G_CALLBACK (findbar_previous_cb), logview);
+  g_signal_connect (priv->find_bar, "next",
+                    G_CALLBACK (findbar_next_cb), logview);
+  g_signal_connect (priv->find_bar, "text_changed",
+                    G_CALLBACK (findbar_text_changed_cb), logview);
+  g_signal_connect (priv->find_bar, "close",
+                    G_CALLBACK (findbar_close_cb), logview);
   
   /* panes */
   hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
@@ -1308,37 +1286,10 @@ logview_window_init (LogviewWindow *logview)
   /* restore saved zoom */
   priv->fontsize = logview_prefs_get_stored_fontsize (priv->prefs);
 
-  if (priv->fontsize <= 0) {
-    /* restore the default */
-    logview_normal_text (NULL, logview);
-  } else {
+  if (priv->fontsize > 0) {
     logview_set_fontsize (logview, FALSE);
   }
 
-  /* version selector */
-  priv->version_bar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-  gtk_container_set_border_width (GTK_CONTAINER (priv->version_bar), 3);
-  priv->version_selector = gtk_combo_box_text_new ();
-  g_signal_connect (priv->version_selector, "changed",
-                    G_CALLBACK (logview_version_selector_changed), logview);
-  w = gtk_label_new (_("Version: "));
-
-  gtk_box_pack_end (GTK_BOX (priv->version_bar), priv->version_selector, FALSE, FALSE, 0);
-  gtk_box_pack_end (GTK_BOX (priv->version_bar), w, FALSE, FALSE, 0);
-  gtk_box_pack_end (GTK_BOX (main_view), priv->version_bar, FALSE, FALSE, 0);
-
-  priv->find_bar = logview_findbar_new ();
-  gtk_box_pack_end (GTK_BOX (main_view), priv->find_bar, FALSE, FALSE, 0);
-
-  g_signal_connect (priv->find_bar, "previous",
-                    G_CALLBACK (findbar_previous_cb), logview);
-  g_signal_connect (priv->find_bar, "next",
-                    G_CALLBACK (findbar_next_cb), logview);
-  g_signal_connect (priv->find_bar, "text_changed",
-                    G_CALLBACK (findbar_text_changed_cb), logview);
-  g_signal_connect (priv->find_bar, "close",
-                    G_CALLBACK (findbar_close_cb), logview);
-
   /* signal handlers
    * - first is used to remember/restore the window size on quit.
    */
@@ -1348,19 +1299,7 @@ logview_window_init (LogviewWindow *logview)
                     G_CALLBACK (font_changed_cb), logview);
   g_signal_connect (priv->manager, "active-changed",
                     G_CALLBACK (active_log_changed_cb), logview);
-  g_signal_connect (logview, "key-press-event",
-                    G_CALLBACK (key_press_event_cb), logview);
-
-  /* status area at bottom */
-  priv->statusbar = gtk_statusbar_new ();
-  gtk_box_pack_start (GTK_BOX (vbox), priv->statusbar, FALSE, FALSE, 0);
-  gtk_widget_show (priv->statusbar);
-
-  /* Filter menu */
-  priv->filter_action_group = gtk_action_group_new ("ActionGroupFilter");
-  gtk_ui_manager_insert_action_group (priv->ui_manager, priv->filter_action_group,
-                                      1);
-  priv->active_filters = NULL;
+
   update_filter_menu (logview);
   
   gtk_widget_show (vbox);
diff --git a/src/logview.gresource.xml b/src/logview.gresource.xml
index 224b31a..28d1273 100644
--- a/src/logview.gresource.xml
+++ b/src/logview.gresource.xml
@@ -2,7 +2,7 @@
 <gresources>
   <gresource prefix="/org/gnome/logview">
     <file preprocess="xml-stripblanks">logview-app-menu.ui</file>
+    <file preprocess="xml-stripblanks">logview-gear-menu.ui</file>
     <file preprocess="xml-stripblanks">logview-filter.ui</file>
-    <file preprocess="xml-stripblanks">logview-menubar.xml</file>
   </gresource>
 </gresources>
diff --git a/src/tests/test-reader.c b/src/tests/test-reader.c
index 5e6e8b7..77cc64e 100644
--- a/src/tests/test-reader.c
+++ b/src/tests/test-reader.c
@@ -31,7 +31,7 @@ new_lines_cb (LogviewLog *log,
 
   for (l = days; l; l = l->next) {
     day_s = l->data;
-    g_print ("\nday %u month %u\n", g_date_get_day (day_s->date), g_date_get_month (day_s->date));
+    g_print ("\nday %u month %u\n", g_date_time_get_day_of_month (day_s->date), g_date_time_get_month (day_s->date));
   }
 
   g_object_unref (log);



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