[gnome-logs/wip/larsu/listmodel: 18/18] Add GlJournalModel
- From: Lars Uebernickel <larsu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-logs/wip/larsu/listmodel: 18/18] Add GlJournalModel
- Date: Sat, 14 Feb 2015 18:48:56 +0000 (UTC)
commit a27b21f8f144c4b308defbc65607853c608a4ade
Author: Lars Uebernickel <lars uebernic de>
Date: Sat Feb 14 19:42:32 2015 +0100
Add GlJournalModel
A GListModel that contains all journal entries for a given set of
matches.
This let's us have a single listbox in GlEventViewList that is bound to
this model.
Makefile.am | 2 +
data/gl-eventviewlist.ui | 6 ++
src/gl-eventviewlist.c | 123 ++++++++---------------------
src/gl-journal-model.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++
src/gl-journal-model.h | 15 ++++
5 files changed, 249 insertions(+), 89 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index ec9deda..399ddf5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,6 +32,7 @@ gnome_logs_SOURCES = \
src/gl-eventviewlist.c \
src/gl-eventviewrow.c \
src/gl-journal.c \
+ src/gl-journal-model.c \
src/gl-main.c \
src/gl-util.c \
src/gl-window.c
@@ -60,6 +61,7 @@ noinst_gnome_logs_headers = \
src/gl-eventviewlist.h \
src/gl-eventviewrow.h \
src/gl-journal.h \
+ src/gl-journal-model.h \
src/gl-util.h \
src/gl-window.h
diff --git a/data/gl-eventviewlist.ui b/data/gl-eventviewlist.ui
index 78a4699..61dfa98 100644
--- a/data/gl-eventviewlist.ui
+++ b/data/gl-eventviewlist.ui
@@ -37,6 +37,12 @@
<object class="GtkScrolledWindow" id="event_scrolled">
<property name="visible">True</property>
<property name="expand">True</property>
+ <child>
+ <object class="GtkListBox" id="entries_box">
+ <property name="visible">True</property>
+ <property name="selection-mode">none</property>
+ </object>
+ </child>
</object>
</child>
</object>
diff --git a/src/gl-eventviewlist.c b/src/gl-eventviewlist.c
index 6602223..5c95cff 100644
--- a/src/gl-eventviewlist.c
+++ b/src/gl-eventviewlist.c
@@ -28,15 +28,15 @@
#include "gl-eventview.h"
#include "gl-eventviewdetail.h"
#include "gl-eventviewrow.h"
-#include "gl-journal.h"
+#include "gl-journal-model.h"
#include "gl-util.h"
typedef struct
{
- GlJournal *journal;
+ GlJournalModel *journal_model;
GlJournalEntry *entry;
GlUtilClockFormat clock_format;
- GtkListBox *active_listbox;
+ GtkListBox *entries_box;
GtkWidget *categories;
GtkWidget *event_search;
GtkWidget *event_scrolled;
@@ -44,12 +44,10 @@ typedef struct
gchar *search_text;
GlEventViewRowStyle current_row_style;
- guint insert_idle_id;
} GlEventViewListPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GlEventViewList, gl_event_view_list, GTK_TYPE_BOX)
-static const gssize N_RESULTS_IDLE = 5;
static const gchar DESKTOP_SCHEMA[] = "org.gnome.desktop.interface";
static const gchar SETTINGS_SCHEMA[] = "org.gnome.Logs";
static const gchar CLOCK_FORMAT[] = "clock-format";
@@ -301,56 +299,14 @@ gl_event_view_create_empty (G_GNUC_UNUSED GlEventViewList *view)
}
static GtkWidget *
-gl_event_view_list_box_new (GlEventViewList *view)
+gl_event_list_view_create_row_widget (gpointer item,
+ gpointer user_data)
{
- GtkWidget *listbox;
+ GlEventViewList *view = user_data;
- listbox = gtk_list_box_new ();
-
- gtk_list_box_set_filter_func (GTK_LIST_BOX (listbox),
- (GtkListBoxFilterFunc)listbox_search_filter_func,
- view, NULL);
- gtk_list_box_set_placeholder (GTK_LIST_BOX (listbox),
- gl_event_view_create_empty (view));
- gtk_list_box_set_selection_mode (GTK_LIST_BOX (listbox),
- GTK_SELECTION_NONE);
- g_signal_connect (listbox, "row-activated",
- G_CALLBACK (on_listbox_row_activated), GTK_BOX (view));
-
- return listbox;
-}
-
-static gboolean
-insert_idle (gpointer data)
-{
- GlEventViewList *view = data;
GlEventViewListPrivate *priv = gl_event_view_list_get_instance_private (view);
- gint i;
-
- for (i = 0; i < N_RESULTS_IDLE; i++)
- {
- GlJournalEntry *entry;
- GtkWidget *row;
-
- entry = gl_journal_previous (priv->journal);
- if (entry)
- {
- row = gl_event_view_row_new (entry,
- priv->current_row_style,
- priv->clock_format);
- gtk_container_add (GTK_CONTAINER (priv->active_listbox), row);
- gtk_widget_show_all (row);
-
- g_object_unref (entry);
- }
- else
- {
- priv->insert_idle_id = 0;
- return G_SOURCE_REMOVE;
- }
- }
- return G_SOURCE_CONTINUE;
+ return gl_event_view_row_new (item, priv->current_row_style, priv->clock_format);
}
static gchar *
@@ -385,23 +341,6 @@ on_notify_category (GlCategoryList *list,
priv = gl_event_view_list_get_instance_private (view);
filter = gl_category_list_get_category (list);
- if (priv->insert_idle_id)
- {
- g_source_remove (priv->insert_idle_id);
- priv->insert_idle_id = 0;
- }
-
- if (priv->active_listbox)
- {
- GtkWidget *child;
-
- child = gtk_bin_get_child (GTK_BIN (priv->event_scrolled));
- gtk_widget_destroy (child);
- }
-
- priv->active_listbox = GTK_LIST_BOX (gl_event_view_list_box_new (view));
- gtk_container_add (GTK_CONTAINER (priv->event_scrolled), GTK_WIDGET (priv->active_listbox));
-
switch (filter)
{
case GL_CATEGORY_LIST_FILTER_IMPORTANT:
@@ -410,7 +349,7 @@ on_notify_category (GlCategoryList *list,
const gchar * query[] = { "PRIORITY=0", "PRIORITY=1", "PRIORITY=2", "PRIORITY=3", NULL };
priv->current_row_style = GL_EVENT_VIEW_ROW_STYLE_CMDLINE;
- gl_journal_set_matches (priv->journal, query);
+ gl_journal_model_set_matches (priv->journal_model, query);
}
break;
@@ -419,7 +358,7 @@ on_notify_category (GlCategoryList *list,
const gchar *query[] = { NULL };
priv->current_row_style = GL_EVENT_VIEW_ROW_STYLE_CMDLINE;
- gl_journal_set_matches (priv->journal, query);
+ gl_journal_model_set_matches (priv->journal_model, query);
}
break;
@@ -437,7 +376,7 @@ on_notify_category (GlCategoryList *list,
priv->current_row_style = GL_EVENT_VIEW_ROW_STYLE_CMDLINE;
uid_str = create_uid_match_string ();
query[3] = uid_str;
- gl_journal_set_matches (priv->journal, query);
+ gl_journal_model_set_matches (priv->journal_model, query);
g_free (uid_str);
}
@@ -448,7 +387,7 @@ on_notify_category (GlCategoryList *list,
const gchar *query[] = { "_TRANSPORT=kernel", NULL };
priv->current_row_style = GL_EVENT_VIEW_ROW_STYLE_SIMPLE;
- gl_journal_set_matches (priv->journal, query);
+ gl_journal_model_set_matches (priv->journal_model, query);
}
break;
@@ -457,7 +396,7 @@ on_notify_category (GlCategoryList *list,
const gchar *query[] = { "_TRANSPORT=kernel", "_KERNEL_DEVICE", NULL };
priv->current_row_style = GL_EVENT_VIEW_ROW_STYLE_SIMPLE;
- gl_journal_set_matches (priv->journal, query);
+ gl_journal_model_set_matches (priv->journal_model, query);
}
break;
@@ -466,7 +405,7 @@ on_notify_category (GlCategoryList *list,
const gchar *query[] = { "_AUDIT_SESSION", NULL };
priv->current_row_style = GL_EVENT_VIEW_ROW_STYLE_CMDLINE;
- gl_journal_set_matches (priv->journal, query);
+ gl_journal_model_set_matches (priv->journal_model, query);
}
break;
@@ -474,10 +413,6 @@ on_notify_category (GlCategoryList *list,
g_assert_not_reached ();
}
- priv->insert_idle_id = g_idle_add (insert_idle, view);
-
- gtk_widget_show_all (GTK_WIDGET (priv->active_listbox));
-
settings = g_settings_new (SETTINGS_SCHEMA);
sort_order = g_settings_get_enum (settings, SORT_ORDER);
g_object_unref (settings);
@@ -553,12 +488,12 @@ gl_event_view_list_set_sort_order (GlEventViewList *view,
switch (sort_order)
{
case GL_SORT_ORDER_ASCENDING_TIME:
- gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->active_listbox),
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->entries_box),
(GtkListBoxSortFunc) gl_event_view_sort_by_ascending_time,
NULL, NULL);
break;
case GL_SORT_ORDER_DESCENDING_TIME:
- gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->active_listbox),
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->entries_box),
(GtkListBoxSortFunc) gl_event_view_sort_by_descending_time,
NULL, NULL);
break;
@@ -615,11 +550,7 @@ gl_event_view_list_finalize (GObject *object)
GlEventViewList *view = GL_EVENT_VIEW_LIST (object);
GlEventViewListPrivate *priv = gl_event_view_list_get_instance_private (view);
- if (priv->insert_idle_id)
- {
- g_source_remove (priv->insert_idle_id);
- }
-
+ g_clear_object (&priv->journal_model);
g_clear_pointer (&priv->search_text, g_free);
}
@@ -634,6 +565,8 @@ gl_event_view_list_class_init (GlEventViewListClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/Logs/gl-eventviewlist.ui");
gtk_widget_class_bind_template_child_private (widget_class, GlEventViewList,
+ entries_box);
+ gtk_widget_class_bind_template_child_private (widget_class, GlEventViewList,
categories);
gtk_widget_class_bind_template_child_private (widget_class, GlEventViewList,
event_search);
@@ -659,11 +592,23 @@ gl_event_view_list_init (GlEventViewList *view)
priv = gl_event_view_list_get_instance_private (view);
priv->search_text = NULL;
- priv->active_listbox = NULL;
- priv->insert_idle_id = 0;
- priv->journal = gl_journal_new ();
categories = GL_CATEGORY_LIST (priv->categories);
+ priv->journal_model = gl_journal_model_new ();
+
+ gtk_list_box_bind_model (GTK_LIST_BOX (priv->entries_box),
+ G_LIST_MODEL (priv->journal_model),
+ gl_event_list_view_create_row_widget,
+ view, NULL);
+
+ gtk_list_box_set_filter_func (GTK_LIST_BOX (priv->entries_box),
+ (GtkListBoxFilterFunc) listbox_search_filter_func,
+ view, NULL);
+ gtk_list_box_set_placeholder (GTK_LIST_BOX (priv->entries_box),
+ gl_event_view_create_empty (view));
+ g_signal_connect (priv->entries_box, "row-activated",
+ G_CALLBACK (on_listbox_row_activated), GTK_BOX (view));
+
/* TODO: Monitor and propagate any GSettings changes. */
settings = g_settings_new (DESKTOP_SCHEMA);
priv->clock_format = g_settings_get_enum (settings, CLOCK_FORMAT);
@@ -686,7 +631,7 @@ gl_event_view_list_search (GlEventViewList *view,
g_free (priv->search_text);
priv->search_text = g_strdup (needle);
- gtk_list_box_invalidate_filter (priv->active_listbox);
+ gtk_list_box_invalidate_filter (priv->entries_box);
}
GtkWidget *
diff --git a/src/gl-journal-model.c b/src/gl-journal-model.c
new file mode 100644
index 0000000..681fbe0
--- /dev/null
+++ b/src/gl-journal-model.c
@@ -0,0 +1,192 @@
+
+#include "gl-journal-model.h"
+#include "gl-journal.h"
+
+struct _GlJournalModel
+{
+ GObject parent_instance;
+
+ GlJournal *journal;
+ GPtrArray *entries;
+
+ guint idle_source;
+};
+
+static void gl_journal_model_interface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GlJournalModel, gl_journal_model, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gl_journal_model_interface_init))
+
+enum
+{
+ PROP_0,
+ PROP_MATCHES,
+ N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES];
+
+static gboolean
+gl_journal_model_fetch_entries (gpointer user_data)
+{
+ GlJournalModel *model = user_data;
+ guint last;
+ gint i;
+
+ last = model->entries->len;
+ for (i = 0; i < 5; i++)
+ {
+ GlJournalEntry *entry;
+
+ entry = gl_journal_previous (model->journal);
+ if (entry)
+ {
+ g_ptr_array_add (model->entries, entry);
+ }
+ else
+ {
+ model->idle_source = 0;
+ return G_SOURCE_REMOVE;
+ }
+ }
+
+ g_list_model_items_changed (G_LIST_MODEL (model), last, 0, i);
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+gl_journal_model_init (GlJournalModel *model)
+{
+ model->journal = gl_journal_new ();
+ model->entries = g_ptr_array_new_with_free_func (g_object_unref);
+ model->idle_source = g_idle_add_full (G_PRIORITY_LOW, gl_journal_model_fetch_entries, model, NULL);
+}
+
+static void
+gl_journal_model_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GlJournalModel *model = GL_JOURNAL_MODEL (object);
+
+ switch (property_id)
+ {
+ case PROP_MATCHES:
+ gl_journal_model_set_matches (model, g_value_get_boxed (value));
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+gl_journal_model_stop_idle (GlJournalModel *model)
+{
+ if (model->idle_source)
+ {
+ g_source_remove (model->idle_source);
+ model->idle_source = 0;
+ }
+}
+
+static void
+gl_journal_model_dispose (GObject *object)
+{
+ GlJournalModel *model = GL_JOURNAL_MODEL (object);
+
+ gl_journal_model_stop_idle (model);
+
+ if (model->entries)
+ {
+ g_ptr_array_free (model->entries, TRUE);
+ model->entries = NULL;
+ }
+
+ g_clear_object (&model->journal);
+
+ G_OBJECT_CLASS (gl_journal_model_parent_class)->dispose (object);
+}
+
+static GType
+gl_journal_model_get_item_type (GListModel *list)
+{
+ return GL_TYPE_JOURNAL_ENTRY;
+}
+
+static guint
+gl_journal_model_get_n_items (GListModel *list)
+{
+ GlJournalModel *model = GL_JOURNAL_MODEL (list);
+
+ return model->entries->len;
+}
+
+static gpointer
+gl_journal_model_get_item (GListModel *list,
+ guint position)
+{
+ GlJournalModel *model = GL_JOURNAL_MODEL (list);
+
+ if (position < model->entries->len)
+ return g_object_ref (g_ptr_array_index (model->entries, position));
+
+ return NULL;
+}
+
+static void
+gl_journal_model_class_init (GlJournalModelClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GParamFlags default_flags = G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY;
+
+ object_class->dispose = gl_journal_model_dispose;
+ object_class->set_property = gl_journal_model_set_property;
+
+ properties[PROP_MATCHES] = g_param_spec_boxed ("matches", "", "", G_TYPE_STRV,
+ G_PARAM_WRITABLE | default_flags);
+
+ g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static void
+gl_journal_model_interface_init (GListModelInterface *iface)
+{
+ iface->get_item_type = gl_journal_model_get_item_type;
+ iface->get_n_items = gl_journal_model_get_n_items;
+ iface->get_item = gl_journal_model_get_item;
+}
+
+GlJournalModel *
+gl_journal_model_new (void)
+{
+ return g_object_new (GL_TYPE_JOURNAL_MODEL, NULL);
+}
+
+/**
+ * gl_journal_model_set_matches:
+ * @model: a #GlJournalModel
+ * @matches: new matches
+ *
+ * Changes @model's filter matches to @matches. This resets all items in
+ * the model, as they have to be requeried from the journal.
+ */
+void
+gl_journal_model_set_matches (GlJournalModel *model,
+ const gchar * const *matches)
+{
+ g_return_if_fail (GL_IS_JOURNAL_MODEL (model));
+ g_return_if_fail (matches != NULL);
+
+ gl_journal_model_stop_idle (model);
+ if (model->entries->len > 0)
+ {
+ g_list_model_items_changed (G_LIST_MODEL (model), 0, model->entries->len, 0);
+ g_ptr_array_remove_range (model->entries, 0, model->entries->len);
+ }
+
+ gl_journal_set_matches (model->journal, matches);
+
+ model->idle_source = g_idle_add_full (G_PRIORITY_LOW, gl_journal_model_fetch_entries, model, NULL);
+}
diff --git a/src/gl-journal-model.h b/src/gl-journal-model.h
new file mode 100644
index 0000000..18b9bb8
--- /dev/null
+++ b/src/gl-journal-model.h
@@ -0,0 +1,15 @@
+
+#ifndef GL_JOURNAL_MODEL_H
+#define GL_JOURNAL_MODEL_H
+
+#include <gio/gio.h>
+
+#define GL_TYPE_JOURNAL_MODEL gl_journal_model_get_type()
+G_DECLARE_FINAL_TYPE (GlJournalModel, gl_journal_model, GL, JOURNAL_MODEL, GObject)
+
+GlJournalModel * gl_journal_model_new (void);
+
+void gl_journal_model_set_matches (GlJournalModel *model,
+ const gchar * const *matches);
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]