[gnome-builder] recent-projects: implement GListModel



commit e4914e8970ead39d7a5b6ef7c7a031d2d48bde19
Author: Christian Hergert <christian hergert me>
Date:   Wed Apr 22 14:52:15 2015 -0700

    recent-projects: implement GListModel
    
    Implement GListModel from IdeRecentProjects. This simplifies the code
    in IdeProjectSelector a bit to remove the list management details.

 libide/ide-recent-projects.c     |   93 ++++++++++++++++++++++++-------------
 src/dialogs/gb-projects-dialog.c |   87 +++++++-----------------------------
 2 files changed, 76 insertions(+), 104 deletions(-)
---
diff --git a/libide/ide-recent-projects.c b/libide/ide-recent-projects.c
index b996781..dcba064 100644
--- a/libide/ide-recent-projects.c
+++ b/libide/ide-recent-projects.c
@@ -28,7 +28,7 @@ struct _IdeRecentProjects
 
   GCancellable *cancellable;
   GPtrArray    *miners;
-  GPtrArray    *projects;
+  GSequence    *projects;
   GHashTable   *recent_uris;
 
   gint          active;
@@ -36,14 +36,11 @@ struct _IdeRecentProjects
   guint         discovered : 1;
 };
 
-G_DEFINE_TYPE (IdeRecentProjects, ide_recent_projects, G_TYPE_OBJECT)
+static void list_model_iface_init (GListModelInterface *iface);
 
-enum {
-  ADDED,
-  LAST_SIGNAL
-};
-
-static guint gSignals [LAST_SIGNAL];
+G_DEFINE_TYPE_WITH_CODE (IdeRecentProjects, ide_recent_projects, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
+                                                list_model_iface_init))
 
 IdeRecentProjects *
 ide_recent_projects_new (void)
@@ -66,8 +63,15 @@ ide_recent_projects_added (IdeRecentProjects *self,
 
   if (!g_hash_table_contains (self->recent_uris, uri))
     {
-      g_ptr_array_add (self->projects, g_object_ref (project_info));
-      g_signal_emit (self, gSignals [ADDED], 0, project_info);
+      GSequenceIter *iter;
+      gint position;
+
+      iter = g_sequence_insert_sorted (self->projects,
+                                       g_object_ref (project_info),
+                                       (GCompareDataFunc)ide_project_info_compare,
+                                       NULL);
+      position = g_sequence_iter_get_position (iter);
+      g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
     }
 }
 
@@ -178,13 +182,44 @@ ide_recent_projects_load_recent (IdeRecentProjects *self,
   g_list_free_full (list, (GDestroyNotify)gtk_recent_info_unref);
 }
 
+static GType
+ide_recent_projects_get_item_type (GListModel *model)
+{
+  return IDE_TYPE_PROJECT_INFO;
+}
+
+static guint
+ide_recent_projects_get_n_items (GListModel *model)
+{
+  IdeRecentProjects *self = (IdeRecentProjects *)model;
+
+  g_assert (IDE_IS_RECENT_PROJECTS (self));
+
+  return g_sequence_get_length (self->projects);
+}
+
+static gpointer
+ide_recent_projects_get_item (GListModel *model,
+                              guint       position)
+{
+  IdeRecentProjects *self = (IdeRecentProjects *)model;
+  GSequenceIter *iter;
+
+  g_assert (IDE_IS_RECENT_PROJECTS (self));
+
+  if ((iter = g_sequence_get_iter_at_pos (self->projects, position)))
+    return g_object_ref (g_sequence_get (iter));
+
+  return NULL;
+}
+
 static void
 ide_recent_projects_finalize (GObject *object)
 {
   IdeRecentProjects *self = (IdeRecentProjects *)object;
 
   g_clear_pointer (&self->miners, g_ptr_array_unref);
-  g_clear_pointer (&self->projects, g_ptr_array_unref);
+  g_clear_pointer (&self->projects, g_sequence_free);
   g_clear_pointer (&self->recent_uris, g_hash_table_unref);
   g_clear_object (&self->cancellable);
 
@@ -192,29 +227,19 @@ ide_recent_projects_finalize (GObject *object)
 }
 
 static void
+list_model_iface_init (GListModelInterface *iface)
+{
+  iface->get_item_type = ide_recent_projects_get_item_type;
+  iface->get_n_items = ide_recent_projects_get_n_items;
+  iface->get_item = ide_recent_projects_get_item;
+}
+
+static void
 ide_recent_projects_class_init (IdeRecentProjectsClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   object_class->finalize = ide_recent_projects_finalize;
-
-  /**
-   * IdeRecentProjects::added:
-   * @self: An #IdeRecentProjects
-   * @project_info: An #IdeProjectInfo.
-   *
-   * The "added" signal is emitted when a new #IdeProjectInfo has been discovered.
-   */
-  gSignals [ADDED] =
-    g_signal_new ("added",
-                  G_TYPE_FROM_CLASS (klass),
-                  G_SIGNAL_RUN_LAST,
-                  0,
-                  NULL, NULL,
-                  g_cclosure_marshal_VOID__OBJECT,
-                  G_TYPE_NONE,
-                  1,
-                  IDE_TYPE_PROJECT_INFO);
 }
 
 static void
@@ -223,7 +248,7 @@ ide_recent_projects_init (IdeRecentProjects *self)
   GIOExtensionPoint *extension_point;
   GList *extensions;
 
-  self->projects = g_ptr_array_new_with_free_func (g_object_unref);
+  self->projects = g_sequence_new (g_object_unref);
   self->miners = g_ptr_array_new_with_free_func (g_object_unref);
   self->cancellable = g_cancellable_new ();
   self->recent_uris = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -261,18 +286,20 @@ ide_recent_projects_init (IdeRecentProjects *self)
 GPtrArray *
 ide_recent_projects_get_projects (IdeRecentProjects *self)
 {
+  GSequenceIter *iter;
   GPtrArray *ret;
-  gsize i;
 
   g_return_val_if_fail (IDE_IS_RECENT_PROJECTS (self), NULL);
 
   ret = g_ptr_array_new_with_free_func (g_object_unref);
 
-  for (i = 0; i < self->projects->len; i++)
+  for (iter = g_sequence_get_begin_iter (self->projects);
+       !g_sequence_iter_is_end (iter);
+       g_sequence_iter_next (iter))
     {
       IdeProjectInfo *project_info;
 
-      project_info = g_ptr_array_index (self->projects, i);
+      project_info = g_sequence_get (iter);
       g_ptr_array_add (ret, g_object_ref (project_info));
     }
 
diff --git a/src/dialogs/gb-projects-dialog.c b/src/dialogs/gb-projects-dialog.c
index 36ea900..9ebefc5 100644
--- a/src/dialogs/gb-projects-dialog.c
+++ b/src/dialogs/gb-projects-dialog.c
@@ -16,10 +16,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
 #define G_LOG_DOMAIN "gb-projects-dialog"
 
 #include <glib/gi18n.h>
@@ -138,16 +134,16 @@ gb_projects_dialog__listbox_row_activated_cb (GbProjectsDialog *self,
                                      g_object_ref (self));
 }
 
-static void
-gb_projects_dialog__recent_projects_added (GbProjectsDialog  *self,
-                                           IdeProjectInfo    *project_info,
-                                           IdeRecentProjects *recent_projects)
+static GtkWidget *
+create_project_row (gpointer item,
+                    gpointer user_data)
 {
+  IdeProjectInfo *project_info = item;
+  GbProjectsDialog *self = user_data;
   GtkWidget *row;
 
-  g_assert (GB_IS_PROJECTS_DIALOG (self));
   g_assert (IDE_IS_PROJECT_INFO (project_info));
-  g_assert (IDE_IS_RECENT_PROJECTS (recent_projects));
+  g_assert (GB_IS_PROJECTS_DIALOG (self));
 
   row = g_object_new (GB_TYPE_RECENT_PROJECT_ROW,
                       "project-info", project_info,
@@ -158,9 +154,11 @@ gb_projects_dialog__recent_projects_added (GbProjectsDialog  *self,
                            G_CALLBACK (gb_projects_dialog_update_delete_sensitivity),
                            self,
                            G_CONNECT_SWAPPED);
-  g_object_bind_property (self->select_button, "active", row, "selection-mode",
+  g_object_bind_property (self->select_button, "active",
+                          row, "selection-mode",
                           G_BINDING_SYNC_CREATE);
-  gtk_container_add (GTK_CONTAINER (self->listbox), row);
+
+  return row;
 }
 
 static void
@@ -202,55 +200,6 @@ gb_projects_dialog__listbox_header_cb (GtkListBoxRow *row,
     }
 }
 
-static gint
-gb_projects_dialog__listbox_sort_cb (GtkListBoxRow *row1,
-                                     GtkListBoxRow *row2,
-                                     gpointer       user_data)
-{
-  IdeProjectInfo *info1;
-  IdeProjectInfo *info2;
-  const gchar *name1;
-  const gchar *name2;
-  GDateTime *dt1;
-  GDateTime *dt2;
-  gint ret;
-  gint prio1;
-  gint prio2;
-
-  g_assert (GB_IS_RECENT_PROJECT_ROW (row1));
-  g_assert (GB_IS_RECENT_PROJECT_ROW (row2));
-
-  info1 = gb_recent_project_row_get_project_info (GB_RECENT_PROJECT_ROW (row1));
-  info2 = gb_recent_project_row_get_project_info (GB_RECENT_PROJECT_ROW (row2));
-
-  g_assert (IDE_IS_PROJECT_INFO (info1));
-  g_assert (IDE_IS_PROJECT_INFO (info2));
-
-  prio1 = ide_project_info_get_priority (info1);
-  prio2 = ide_project_info_get_priority (info2);
-
-  if (prio1 != prio2)
-    return prio1 - prio2;
-
-  dt1 = ide_project_info_get_last_modified_at (info1);
-  dt2 = ide_project_info_get_last_modified_at (info2);
-
-  ret = g_date_time_compare (dt2, dt1);
-
-  if (ret != 0)
-    return ret;
-
-  name1 = ide_project_info_get_name (info1);
-  name2 = ide_project_info_get_name (info2);
-
-  if (name1 == NULL)
-    return 1;
-  else if (name2 == NULL)
-    return -1;
-  else
-    return strcasecmp (name1, name2);
-}
-
 static gboolean
 gb_projects_dialog__listbox_filter_cb (GtkListBoxRow *row,
                                        gpointer       user_data)
@@ -482,12 +431,6 @@ gb_projects_dialog_constructed (GObject *object)
                            self,
                            G_CONNECT_SWAPPED);
 
-  g_signal_connect_object (self->recent_projects,
-                           "added",
-                           G_CALLBACK (gb_projects_dialog__recent_projects_added),
-                           self,
-                           G_CONNECT_SWAPPED);
-
   g_object_bind_property (self->search_button, "active",
                           self->search_bar, "search-mode-enabled",
                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
@@ -526,14 +469,16 @@ gb_projects_dialog_constructed (GObject *object)
                                 gb_projects_dialog__listbox_header_cb,
                                 NULL, NULL);
 
-  gtk_list_box_set_sort_func (self->listbox,
-                              gb_projects_dialog__listbox_sort_cb,
-                              NULL, NULL);
-
   gtk_list_box_set_filter_func (self->listbox,
                                 gb_projects_dialog__listbox_filter_cb,
                                 self, NULL);
 
+  gtk_list_box_bind_model (self->listbox,
+                           G_LIST_MODEL (self->recent_projects),
+                           create_project_row,
+                           self,
+                           NULL);
+
   ide_recent_projects_discover_async (self->recent_projects,
                                       NULL, /* TODO: cancellable */
                                       gb_projects_dialog__recent_projects_discover_cb,


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