[epiphany] bookmarks: Split list model functionality into separate class
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] bookmarks: Split list model functionality into separate class
- Date: Tue, 1 Nov 2016 23:11:53 +0000 (UTC)
commit feacce23897127e0eb13bf93b75e753d8e18767b
Author: Michael Catanzaro <mcatanzaro gnome org>
Date: Tue Nov 1 18:00:36 2016 -0500
bookmarks: Split list model functionality into separate class
This is much less efficient, but it also makes the code much simpler and
more robust. Using EphyBookmarksManager as the list model was a good
choice at the time, when we were not thinking about smart bookmarks, but
now that we need to handle both it doesn't work so well. My initial
implementation was complex and buggy. Simplify this.
src/Makefile.am | 2 +
src/bookmarks/ephy-bookmarks-list-model.c | 193 +++++++++++++++++++++++++++++
src/bookmarks/ephy-bookmarks-list-model.h | 36 ++++++
src/bookmarks/ephy-bookmarks-manager.c | 54 +--------
src/bookmarks/ephy-bookmarks-popover.c | 20 +++-
src/ephy-location-controller.c | 2 +
6 files changed, 251 insertions(+), 56 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index ec8a1db..6310e62 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,8 @@ libephymain_la_SOURCES = \
bookmarks/ephy-bookmark-properties-grid.h \
bookmarks/ephy-bookmark-row.c \
bookmarks/ephy-bookmark-row.h \
+ bookmarks/ephy-bookmarks-list-model.c \
+ bookmarks/ephy-bookmarks-list-model.h \
bookmarks/ephy-bookmarks-manager.c \
bookmarks/ephy-bookmarks-manager.h \
bookmarks/ephy-bookmarks-popover.c \
diff --git a/src/bookmarks/ephy-bookmarks-list-model.c b/src/bookmarks/ephy-bookmarks-list-model.c
new file mode 100644
index 0000000..d3145dc
--- /dev/null
+++ b/src/bookmarks/ephy-bookmarks-list-model.c
@@ -0,0 +1,193 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2016 Igalia S.L.
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "ephy-bookmarks-list-model.h"
+
+struct _EphyBookmarksListModel {
+ GObject parent_instance;
+
+ EphyBookmarksManager *bookmarks_manager;
+ GList *dumb_bookmarks;
+};
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EphyBookmarksListModel, ephy_bookmarks_list_model, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+enum {
+ PROP_0,
+ PROP_BOOKMARKS_MANAGER,
+ LAST_PROP
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+static void
+maybe_add_bookmark (EphyBookmark *bookmark,
+ EphyBookmarksListModel *self)
+{
+ if (!ephy_bookmark_is_smart (bookmark))
+ self->dumb_bookmarks = g_list_append (self->dumb_bookmarks, g_object_ref (bookmark));
+}
+
+static void
+refresh_bookmarks_list (EphyBookmarksListModel *self)
+{
+ GSequence *bookmarks;
+ guint previous_length = 0;
+
+ if (self->dumb_bookmarks != NULL) {
+ previous_length = g_list_length (self->dumb_bookmarks);
+ g_list_free_full (self->dumb_bookmarks, g_object_unref);
+ self->dumb_bookmarks = NULL;
+ }
+
+ bookmarks = ephy_bookmarks_manager_get_bookmarks (self->bookmarks_manager);
+ g_sequence_foreach (bookmarks, (GFunc)maybe_add_bookmark, self);
+
+ g_list_model_items_changed (G_LIST_MODEL (self),
+ 0,
+ previous_length,
+ g_list_length (self->dumb_bookmarks));
+}
+
+static void
+bookmarks_modified_cb (EphyBookmarksManager *manager,
+ EphyBookmark *bookmark,
+ EphyBookmarksListModel *self)
+{
+ if (!ephy_bookmark_is_smart (bookmark))
+ refresh_bookmarks_list (self);
+}
+
+static GType
+ephy_bookmarks_list_model_list_model_get_item_type (GListModel *model)
+{
+ return EPHY_TYPE_BOOKMARK;
+}
+
+static guint
+ephy_bookmarks_list_model_list_model_get_n_items (GListModel *model)
+{
+ EphyBookmarksListModel *self = EPHY_BOOKMARKS_LIST_MODEL (model);
+
+ return g_list_length (self->dumb_bookmarks);
+}
+
+static gpointer
+ephy_bookmarks_list_model_list_model_get_item (GListModel *model,
+ guint position)
+{
+ EphyBookmarksListModel *self = EPHY_BOOKMARKS_LIST_MODEL (model);
+
+ return g_object_ref (g_list_nth_data (self->dumb_bookmarks, position));
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+ iface->get_item_type = ephy_bookmarks_list_model_list_model_get_item_type;
+ iface->get_n_items = ephy_bookmarks_list_model_list_model_get_n_items;
+ iface->get_item = ephy_bookmarks_list_model_list_model_get_item;
+}
+
+static void
+ephy_bookmarks_list_model_dispose (GObject *object)
+{
+ EphyBookmarksListModel *self = EPHY_BOOKMARKS_LIST_MODEL (object);
+
+ if (self->dumb_bookmarks != NULL) {
+ g_list_free_full (self->dumb_bookmarks, g_object_unref);
+ self->dumb_bookmarks = NULL;
+ }
+
+ G_OBJECT_CLASS (ephy_bookmarks_list_model_parent_class)->dispose (object);
+}
+
+static void
+ephy_bookmarks_list_model_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyBookmarksListModel *self = EPHY_BOOKMARKS_LIST_MODEL (object);
+
+ switch (prop_id) {
+ case PROP_BOOKMARKS_MANAGER:
+ self->bookmarks_manager = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_bookmarks_list_model_constructed (GObject *object)
+{
+ EphyBookmarksListModel *self = EPHY_BOOKMARKS_LIST_MODEL (object);
+
+ G_OBJECT_CLASS (ephy_bookmarks_list_model_parent_class)->constructed (object);
+
+ refresh_bookmarks_list (self);
+
+ g_signal_connect_object (self->bookmarks_manager, "bookmark-added",
+ G_CALLBACK (bookmarks_modified_cb), self, 0);
+ g_signal_connect_object (self->bookmarks_manager, "bookmark-removed",
+ G_CALLBACK (bookmarks_modified_cb), self, 0);
+ g_signal_connect_object (self->bookmarks_manager, "bookmark-title-changed",
+ G_CALLBACK (bookmarks_modified_cb), self, 0);
+ g_signal_connect_object (self->bookmarks_manager, "bookmark-url-changed",
+ G_CALLBACK (bookmarks_modified_cb), self, 0);
+}
+
+static void
+ephy_bookmarks_list_model_class_init (EphyBookmarksListModelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = ephy_bookmarks_list_model_constructed;
+ object_class->dispose = ephy_bookmarks_list_model_dispose;
+ object_class->set_property = ephy_bookmarks_list_model_set_property;
+
+ obj_properties[PROP_BOOKMARKS_MANAGER] =
+ g_param_spec_object ("bookmarks-manager",
+ "The bookmarks manager",
+ "The bookmarks manager",
+ EPHY_TYPE_BOOKMARKS_MANAGER,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+}
+
+static void
+ephy_bookmarks_list_model_init (EphyBookmarksListModel *self)
+{
+}
+
+EphyBookmarksListModel *
+ephy_bookmarks_list_model_new (EphyBookmarksManager *manager)
+{
+ return EPHY_BOOKMARKS_LIST_MODEL (g_object_new (EPHY_TYPE_BOOKMARKS_LIST_MODEL,
+ "bookmarks-manager", manager,
+ NULL));
+}
diff --git a/src/bookmarks/ephy-bookmarks-list-model.h b/src/bookmarks/ephy-bookmarks-list-model.h
new file mode 100644
index 0000000..adee3cc
--- /dev/null
+++ b/src/bookmarks/ephy-bookmarks-list-model.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2016 Igalia S.L.
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "ephy-bookmark.h"
+#include "ephy-bookmarks-manager.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_BOOKMARKS_LIST_MODEL (ephy_bookmarks_list_model_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyBookmarksListModel, ephy_bookmarks_list_model, EPHY, BOOKMARKS_LIST_MODEL, GObject)
+
+EphyBookmarksListModel *ephy_bookmarks_list_model_new (EphyBookmarksManager *manager);
+
+G_END_DECLS
diff --git a/src/bookmarks/ephy-bookmarks-manager.c b/src/bookmarks/ephy-bookmarks-manager.c
index f768b83..a630189 100644
--- a/src/bookmarks/ephy-bookmarks-manager.c
+++ b/src/bookmarks/ephy-bookmarks-manager.c
@@ -38,10 +38,7 @@ struct _EphyBookmarksManager {
gchar *gvdb_filename;
};
-static void list_model_iface_init (GListModelInterface *iface);
-
-G_DEFINE_TYPE_EXTENDED (EphyBookmarksManager, ephy_bookmarks_manager, G_TYPE_OBJECT, 0,
- G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+G_DEFINE_TYPE (EphyBookmarksManager, ephy_bookmarks_manager, G_TYPE_OBJECT)
enum {
BOOKMARK_ADDED,
@@ -245,48 +242,6 @@ count_smart_bookmarks_prior_to (EphyBookmarksManager *self,
return count;
}
-static GType
-ephy_bookmarks_manager_list_model_get_item_type (GListModel *model)
-{
- return EPHY_TYPE_BOOKMARK;
-}
-
-static guint
-ephy_bookmarks_manager_list_model_get_n_items (GListModel *model)
-{
- EphyBookmarksManager *self = EPHY_BOOKMARKS_MANAGER (model);
- guint length = g_sequence_get_length (self->bookmarks);
-
- return length - count_smart_bookmarks_prior_to (self, length);
-}
-
-static gpointer
-ephy_bookmarks_manager_list_model_get_item (GListModel *model,
- guint position)
-{
- EphyBookmarksManager *self = EPHY_BOOKMARKS_MANAGER (model);
- GSequenceIter *iter = g_sequence_get_begin_iter (self->bookmarks);
- EphyBookmark *bookmark = NULL;
- guint i = 0;
-
- do {
- bookmark = g_sequence_get (iter);
- if (!ephy_bookmark_is_smart (bookmark))
- i++;
- iter = g_sequence_iter_next (iter);
- } while (i < position); //FIXME: should be <= right?
-
- return bookmark ? g_object_ref (bookmark) : NULL;
-}
-
-static void
-list_model_iface_init (GListModelInterface *iface)
-{
- iface->get_item_type = ephy_bookmarks_manager_list_model_get_item_type;
- iface->get_n_items = ephy_bookmarks_manager_list_model_get_n_items;
- iface->get_item = ephy_bookmarks_manager_list_model_get_item;
-}
-
static void
bookmark_title_changed_cb (EphyBookmark *bookmark,
GParamSpec *pspec,
@@ -327,9 +282,6 @@ ephy_bookmarks_manager_add_bookmark (EphyBookmarksManager *self,
/* Update list */
position = g_sequence_iter_get_position (iter);
- g_list_model_items_changed (G_LIST_MODEL (self),
- position - count_smart_bookmarks_prior_to (self, position) - 1,
- 0, 1);
g_signal_emit (self, signals[BOOKMARK_ADDED], 0, bookmark);
@@ -338,7 +290,6 @@ ephy_bookmarks_manager_add_bookmark (EphyBookmarksManager *self,
NULL);
}
- // FIXME: Need g_list_model_items_changed if a bookmark's smartness changes
g_signal_connect_object (bookmark, "notify::title",
G_CALLBACK (bookmark_title_changed_cb), self, 0);
g_signal_connect_object (bookmark, "notify::url",
@@ -397,9 +348,6 @@ ephy_bookmarks_manager_remove_bookmark (EphyBookmarksManager *self,
position = g_sequence_iter_get_position (iter);
g_sequence_remove (iter);
- g_list_model_items_changed (G_LIST_MODEL (self),
- position - count_smart_bookmarks_prior_to (self, position),
- 1, 0);
ephy_bookmarks_manager_save_to_file_async (self, NULL,
(GAsyncReadyCallback)ephy_bookmarks_manager_save_to_file_warn_on_error_cb,
diff --git a/src/bookmarks/ephy-bookmarks-popover.c b/src/bookmarks/ephy-bookmarks-popover.c
index 0b89d28..5f61e0c 100644
--- a/src/bookmarks/ephy-bookmarks-popover.c
+++ b/src/bookmarks/ephy-bookmarks-popover.c
@@ -24,6 +24,7 @@
#include "ephy-bookmark.h"
#include "ephy-bookmark-row.h"
+#include "ephy-bookmarks-list-model.h"
#include "ephy-bookmarks-manager.h"
#include "ephy-debug.h"
#include "ephy-shell.h"
@@ -40,8 +41,9 @@ struct _EphyBookmarksPopover {
GtkWidget *tag_detail_back_button;
GtkWidget *tag_detail_label;
- EphyBookmarksManager *manager;
- EphyWindow *window;
+ EphyBookmarksManager *manager;
+ EphyBookmarksListModel *list_model;
+ EphyWindow *window;
};
G_DEFINE_TYPE (EphyBookmarksPopover, ephy_bookmarks_popover, GTK_TYPE_POPOVER)
@@ -413,6 +415,16 @@ ephy_bookmarks_popover_list_box_row_activated_cb (EphyBookmarksPopover *self,
}
static void
+ephy_bookmarks_popover_dispose (GObject *object)
+{
+ EphyBookmarksPopover *self = EPHY_BOOKMARKS_POPOVER (object);
+
+ g_clear_object (&self->list_model);
+
+ G_OBJECT_CLASS (ephy_bookmarks_popover_parent_class)->dispose (object);
+}
+
+static void
ephy_bookmarks_popover_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -435,6 +447,7 @@ ephy_bookmarks_popover_class_init (EphyBookmarksPopoverClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ object_class->dispose = ephy_bookmarks_popover_dispose;
object_class->set_property = ephy_bookmarks_popover_set_property;
obj_properties[PROP_WINDOW] =
@@ -470,6 +483,7 @@ ephy_bookmarks_popover_init (EphyBookmarksPopover *self)
gtk_widget_init_template (GTK_WIDGET (self));
self->manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
+ self->list_model = ephy_bookmarks_list_model_new (self->manager);
group = g_simple_action_group_new ();
g_action_map_add_action_entries (G_ACTION_MAP (group), entries,
@@ -479,7 +493,7 @@ ephy_bookmarks_popover_init (EphyBookmarksPopover *self)
g_object_unref (group);
gtk_list_box_bind_model (GTK_LIST_BOX (self->bookmarks_list_box),
- G_LIST_MODEL (self->manager),
+ G_LIST_MODEL (self->list_model),
create_bookmark_row,
self, NULL);
diff --git a/src/ephy-location-controller.c b/src/ephy-location-controller.c
index 1670e55..958906f 100644
--- a/src/ephy-location-controller.c
+++ b/src/ephy-location-controller.c
@@ -23,6 +23,7 @@
#include "ephy-location-controller.h"
#include "ephy-bookmark.h"
+#include "ephy-bookmarks-list-model.h"
#include "ephy-bookmarks-manager.h"
#include "ephy-completion-model.h"
#include "ephy-debug.h"
@@ -52,6 +53,7 @@ struct _EphyLocationController {
EphyWindow *window;
EphyTitleWidget *title_widget;
EphyBookmarksManager *bookmarks_manager;
+ EphyBookmarksListModel *list_model;
GSequence *smart_bookmarks;
char *address;
guint editable : 1;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]