diff --git a/libpurple/purplewhiteboardmanager.h b/libpurple/purplewhiteboardmanager.h
--- a/libpurple/purplewhiteboardmanager.h
+++ b/libpurple/purplewhiteboardmanager.h
@@ -53,17 +53,6 @@
                      PURPLE, WHITEBOARD_MANAGER, GObject)
 
 /**
- * PurpleWhiteboardManagerForeachFunc:
- * @whiteboard: The #PurpleWhiteboard instance.
- * @data: User supplied data.
- *
- * A function to be used as a callback with purple_whiteboard_manager_foreach().
- *
- * Since: 3.0.0
- */
-typedef void (*PurpleWhiteboardManagerForeachFunc)(PurpleWhiteboard *whiteboard, gpointer data);
-
-/**
  * purple_whiteboard_manager_get_default:
  *
  * Gets the default #PurpleWhiteboardManager instance.
@@ -75,6 +64,18 @@
 PurpleWhiteboardManager *purple_whiteboard_manager_get_default(void);
 
 /**
+ * purple_whiteboard_manager_get_default_as_model:
+ *
+ * Gets the default manager as a [iface@Gio.ListModel].
+ *
+ * Returns: (transfer none): The default manager cast to a
+ *          [iface@Gio.ListModel].
+ *
+ * Since: 3.0.0
+ */
+GListModel *purple_whiteboard_manager_get_default_as_model(void);
+
+/**
  * purple_whiteboard_manager_register:
  * @manager: The #PurpleWhiteboardManager instance.
  * @whiteboard: The #PurpleWhiteboard to register.
@@ -117,31 +118,6 @@
  */
 PurpleWhiteboard *purple_whiteboard_manager_find(PurpleWhiteboardManager *manager, const gchar *id);
 
-/**
- * purple_whiteboard_manager_foreach:
- * @manager: The #PurpleWhiteboardManager instance.
- * @func: (scope call): The #PurpleWhiteboardManagerForeachFunc to call.
- * @data: User data to pass to @func.
- *
- * Calls @func for each #PurpleWhiteboard that @manager knows about.
- *
- * Since: 3.0.0
- */
-void purple_whiteboard_manager_foreach(PurpleWhiteboardManager *manager, PurpleWhiteboardManagerForeachFunc func, gpointer data);
-
-/**
- * purple_whiteboard_manager_get_model:
- * @manager: The #PurpleWhiteboardManager instance.
- *
- * Gets the backing model of @manager as a #GListModel.
- *
- * Returns: (transfer none) (element-type PurpleWhiteboard): The #GListModel
- *          containing all of the #PurpleWhiteboards registered with @manager.
- *
- * Since: 3.0.0
- */
-GListModel *purple_whiteboard_manager_get_model(PurpleWhiteboardManager *manager);
-
 G_END_DECLS
 
 #endif /* PURPLE_WHITEBOARD_MANAGER_H */
# HG changeset patch
# Node ID 8c282dd01776
# Parent  0c3de459b1cc
diff --git a/libpurple/purplewhiteboardmanager.c b/libpurple/purplewhiteboardmanager.c
--- a/libpurple/purplewhiteboardmanager.c
+++ b/libpurple/purplewhiteboardmanager.c
@@ -31,31 +31,68 @@
 struct _PurpleWhiteboardManager {
 	GObject parent;
 
-	GListStore *store;
+	GPtrArray *whiteboards;
 };
 
-G_DEFINE_TYPE(PurpleWhiteboardManager, purple_whiteboard_manager,
-              G_TYPE_OBJECT);
-
 static PurpleWhiteboardManager *default_manager = NULL;
 
 /******************************************************************************
+ * GListModel Implementation
+ *****************************************************************************/
+static GType
+purple_whiteboard_manager_get_item_type(G_GNUC_UNUSED GListModel *list) {
+	return PURPLE_TYPE_WHITEBOARD;
+}
+
+static guint
+purple_whiteboard_manager_get_n_items(GListModel *list) {
+	PurpleWhiteboardManager *manager = PURPLE_WHITEBOARD_MANAGER(list);
+
+	return manager->whiteboards->len;
+}
+
+static gpointer
+purple_whiteboard_manager_get_item(GListModel *list, guint position) {
+	PurpleWhiteboardManager *manager = PURPLE_WHITEBOARD_MANAGER(list);
+	PurpleWhiteboard *whiteboard = NULL;
+
+	if(position < manager->whiteboards->len) {
+		whiteboard = g_ptr_array_index(manager->whiteboards, position);
+		g_object_ref(whiteboard);
+	}
+
+	return whiteboard;
+}
+
+static void
+purple_whiteboard_manager_list_model_init(GListModelInterface *iface) {
+	iface->get_item_type = purple_whiteboard_manager_get_item_type;
+	iface->get_n_items = purple_whiteboard_manager_get_n_items;
+	iface->get_item = purple_whiteboard_manager_get_item;
+}
+
+/******************************************************************************
  * GObject Implementation
  *****************************************************************************/
+G_DEFINE_TYPE_EXTENDED(PurpleWhiteboardManager, purple_whiteboard_manager,
+                       G_TYPE_OBJECT, G_TYPE_FLAG_FINAL,
+                       G_IMPLEMENT_INTERFACE(G_TYPE_LIST_MODEL, purple_whiteboard_manager_list_model_init));
+
 static void
 purple_whiteboard_manager_finalize(GObject *obj) {
 	PurpleWhiteboardManager *manager = NULL;
 
 	manager = PURPLE_WHITEBOARD_MANAGER(obj);
 
-	g_clear_object(&manager->store);
+	g_ptr_array_free(manager->whiteboards, TRUE);
+	manager->whiteboards = NULL;
 
 	G_OBJECT_CLASS(purple_whiteboard_manager_parent_class)->finalize(obj);
 }
 
 static void
 purple_whiteboard_manager_init(PurpleWhiteboardManager *manager) {
-	manager->store = g_list_store_new(PURPLE_TYPE_WHITEBOARD);
+	manager->whiteboards = g_ptr_array_new_full(0, g_object_unref);
 }
 
 static void
@@ -114,6 +151,8 @@
 purple_whiteboard_manager_startup(void) {
 	if(default_manager == NULL) {
 		default_manager = g_object_new(PURPLE_TYPE_WHITEBOARD_MANAGER, NULL);
+		g_object_add_weak_pointer(G_OBJECT(default_manager),
+		                          (gpointer *)&default_manager);
 	}
 }
 
@@ -130,6 +169,15 @@
 	return default_manager;
 }
 
+GListModel *
+purple_whiteboard_manager_get_default_as_model(void) {
+	if(PURPLE_IS_WHITEBOARD_MANAGER(default_manager)) {
+		return G_LIST_MODEL(default_manager);
+	}
+
+	return NULL;
+}
+
 gboolean
 purple_whiteboard_manager_register(PurpleWhiteboardManager *manager,
                                    PurpleWhiteboard *whiteboard,
@@ -140,9 +188,9 @@
 	g_return_val_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager), FALSE);
 	g_return_val_if_fail(PURPLE_IS_WHITEBOARD(whiteboard), FALSE);
 
-	found = g_list_store_find_with_equal_func(manager->store, whiteboard,
-	                                          (GEqualFunc)purple_whiteboard_equal,
-	                                          NULL);
+	found = g_ptr_array_find_with_equal_func(manager->whiteboards, whiteboard,
+	                                         (GEqualFunc)purple_whiteboard_equal,
+	                                         NULL);
 
 	if(found) {
 		g_set_error(error, PURPLE_WHITEBOARD_MANAGER_DOMAIN, 0,
@@ -152,9 +200,9 @@
 		return FALSE;
 	}
 
-	g_list_store_insert(manager->store, 0, whiteboard);
+	g_ptr_array_add(manager->whiteboards, g_object_ref(whiteboard));
 
-	g_signal_emit(G_OBJECT(manager), signals[SIG_REGISTERED], 0, whiteboard);
+	g_signal_emit(manager, signals[SIG_REGISTERED], 0, whiteboard);
 
 	return TRUE;
 }
@@ -164,15 +212,15 @@
                                      PurpleWhiteboard *whiteboard,
                                      GError **error)
 {
-	guint position = 0;
+	guint index = 0;
 	gboolean found = FALSE;
 
 	g_return_val_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager), FALSE);
 	g_return_val_if_fail(PURPLE_IS_WHITEBOARD(whiteboard), FALSE);
 
-	found = g_list_store_find_with_equal_func(manager->store, whiteboard,
-	                                          (GEqualFunc)purple_whiteboard_equal,
-	                                          &position);
+	found = g_ptr_array_find_with_equal_func(manager->whiteboards, whiteboard,
+	                                         (GEqualFunc)purple_whiteboard_equal,
+	                                         &index);
 
 	if(!found) {
 		g_set_error(error, PURPLE_WHITEBOARD_MANAGER_DOMAIN, 0,
@@ -185,13 +233,13 @@
 	/* Temporarily ref whiteboard so we can pass it along to the signal
 	 * callbacks.
 	 */
-	g_object_ref(G_OBJECT(whiteboard));
+	g_object_ref(whiteboard);
 
-	g_list_store_remove(manager->store, position);
+	g_ptr_array_remove_index(manager->whiteboards, index);
 
-	g_signal_emit(G_OBJECT(manager), signals[SIG_UNREGISTERED], 0, whiteboard);
+	g_signal_emit(manager, signals[SIG_UNREGISTERED], 0, whiteboard);
 
-	g_object_unref(G_OBJECT(whiteboard));
+	g_object_unref(whiteboard);
 
 	return TRUE;
 }
@@ -200,50 +248,24 @@
 purple_whiteboard_manager_find(PurpleWhiteboardManager *manager,
                                const gchar *id)
 {
-	guint idx, n;
+	PurpleWhiteboard *needle = NULL;
+	gboolean found = FALSE;
+	guint index = 0;
 
 	g_return_val_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager), NULL);
 	g_return_val_if_fail(id != NULL, NULL);
 
-	n = g_list_model_get_n_items(G_LIST_MODEL(manager->store));
-	for(idx = 0; idx < n; idx++) {
-		GObject *obj = NULL;
+	needle = g_object_new(PURPLE_TYPE_WHITEBOARD, "id", id, NULL);
 
-		obj = g_list_model_get_object(G_LIST_MODEL(manager->store), idx);
-		if(PURPLE_IS_WHITEBOARD(obj)) {
-			PurpleWhiteboard *whiteboard = PURPLE_WHITEBOARD(obj);
+	found = g_ptr_array_find_with_equal_func(manager->whiteboards, needle,
+	                                         (GEqualFunc)purple_whiteboard_equal,
+	                                         &index);
 
-			if(purple_strequal(id, purple_whiteboard_get_id(whiteboard))) {
-				return whiteboard;
-			}
-		}
-		g_clear_object(&obj);
+	g_clear_object(&needle);
+
+	if(found) {
+		return g_ptr_array_index(manager->whiteboards, index);
 	}
 
 	return NULL;
 }
-
-void
-purple_whiteboard_manager_foreach(PurpleWhiteboardManager *manager,
-                                  PurpleWhiteboardManagerForeachFunc func,
-                                  gpointer data)
-{
-	guint idx, n;
-
-	g_return_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager));
-	g_return_if_fail(func != NULL);
-
-	n = g_list_model_get_n_items(G_LIST_MODEL(manager->store));
-	for(idx = 0; idx < n; idx++) {
-		gpointer item = g_list_model_get_item(G_LIST_MODEL(manager->store), idx);
-		func(item, data);
-		g_object_unref(item);
-	}
-}
-
-GListModel *
-purple_whiteboard_manager_get_model(PurpleWhiteboardManager *manager) {
-	g_return_val_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager), NULL);
-
-	return G_LIST_MODEL(manager->store);
-}
