diff --git a/libpurple/purpleaccountmanager.h b/libpurple/purpleaccountmanager.h
--- a/libpurple/purpleaccountmanager.h
+++ b/libpurple/purpleaccountmanager.h
@@ -126,6 +126,19 @@
 GList *purple_account_manager_get_active(PurpleAccountManager *manager);
 
 /**
+ * purple_account_manager_get_inactive:
+ * @manager: The account manager instance.
+ *
+ * Gets the list of all inactive accounts.
+ *
+ * Returns: (transfer container) (element-type PurpleAccount): The list of all
+ *          inactive accounts.
+ *
+ * Since: 3.0.0
+ */
+GList *purple_account_manager_get_inactive(PurpleAccountManager *manager);
+
+/**
  * purple_account_manager_find_by_id:
  * @manager: The account manager instance.
  * @id: The id of the account.
# HG changeset patch
# Node ID d0c53135a30f
# Parent  84e92cf6f64a
diff --git a/libpurple/purpleaccountmanager.c b/libpurple/purpleaccountmanager.c
--- a/libpurple/purpleaccountmanager.c
+++ b/libpurple/purpleaccountmanager.c
@@ -205,6 +205,24 @@
 	return active;
 }
 
+GList *
+purple_account_manager_get_inactive(PurpleAccountManager *manager) {
+	GList *inactive = NULL, *l = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_ACCOUNT_MANAGER(manager), NULL);
+
+	for(l = manager->accounts; l != NULL; l = l->next) {
+		PurpleAccount *account = l->data;
+
+		if(!purple_account_get_enabled(account, purple_core_get_ui())) {
+			inactive = g_list_append(inactive, account);
+		}
+	}
+
+	return inactive;
+}
+
+
 void
 purple_account_manager_reorder(PurpleAccountManager *manager,
                                PurpleAccount *account,
diff --git a/pidgin/meson.build b/pidgin/meson.build
--- a/pidgin/meson.build
+++ b/pidgin/meson.build
@@ -23,7 +23,6 @@
 	'pidginaccountchooser.c',
 	'pidginaccountfilterconnected.c',
 	'pidginaccountfilterprotocol.c',
-	'pidginaccountsdisabledmenu.c',
 	'pidginaccountsenabledmenu.c',
 	'pidginaccountsmenu.c',
 	'pidginaccountstore.c',
@@ -42,6 +41,7 @@
 	'pidgindialog.c',
 	'pidgingdkpixbuf.c',
 	'pidginiconname.c',
+	'pidgininactiveaccountsmenu.c',
 	'pidgininfopane.c',
 	'pidgininvitedialog.c',
 	'pidginmessage.c',
@@ -87,7 +87,6 @@
 	'pidginaccountchooser.h',
 	'pidginaccountfilterconnected.h',
 	'pidginaccountfilterprotocol.h',
-	'pidginaccountsdisabledmenu.h',
 	'pidginaccountsenabledmenu.h',
 	'pidginaccountsmenu.h',
 	'pidginaccountstore.h',
@@ -106,6 +105,7 @@
 	'pidgindebug.h',
 	'pidgingdkpixbuf.h',
 	'pidginiconname.h',
+	'pidgininactiveaccountsmenu.h',
 	'pidgininfopane.h',
 	'pidgininvitedialog.h',
 	'pidginmessage.h',
diff --git a/pidgin/pidginaccountsdisabledmenu.h b/pidgin/pidgininactiveaccountsmenu.h
rename from pidgin/pidginaccountsdisabledmenu.h
rename to pidgin/pidgininactiveaccountsmenu.h
--- a/pidgin/pidginaccountsdisabledmenu.h
+++ b/pidgin/pidgininactiveaccountsmenu.h
@@ -24,8 +24,8 @@
 # error "only <pidgin.h> may be included directly"
 #endif
 
-#ifndef PIDGIN_ACCOUNTS_DISABLED_MENU_H
-#define PIDGIN_ACCOUNTS_DISABLED_MENU_H
+#ifndef PIDGIN_INACTIVE_ACCOUNTS_MENU_H
+#define PIDGIN_INACTIVE_ACCOUNTS_MENU_H
 
 #include <glib.h>
 #include <gio/gio.h>
@@ -34,18 +34,22 @@
 
 G_BEGIN_DECLS
 
+#define PIDGIN_TYPE_INACTIVE_ACCOUNTS_MENU (pidgin_inactive_accounts_menu_get_type())
+G_DECLARE_FINAL_TYPE(PidginInactiveAccountsMenu, pidgin_inactive_accounts_menu,
+                     PIDGIN, INACTIVE_ACCOUNTS_MENU, GMenuModel)
+
 /**
- * pidgin_accounts_disabled_menu_new:
+ * pidgin_inactive_accounts_menu_new:
  *
- * Creates a [class@Gio.Menu] that will automatically update itself to include
- * accounts that are disabled in libpurple.
+ * Creates a menu that will automatically update itself to include accounts
+ * that are inactive in libpurple.
  *
  * Returns: (transfer full): The new menu instance.
  *
  * Since: 3.0.0
  */
-GMenu *pidgin_accounts_disabled_menu_new(void);
+GMenuModel *pidgin_inactive_accounts_menu_new(void);
 
 G_END_DECLS
 
-#endif /* PIDGIN_ACCOUNTS_DISABLED_MENU_H */
\ No newline at end of file
+#endif /* PIDGIN_INACTIVE_ACCOUNTS_MENU_H */
\ No newline at end of file
diff --git a/pidgin/pidginaccountsdisabledmenu.c b/pidgin/pidgininactiveaccountsmenu.c
rename from pidgin/pidginaccountsdisabledmenu.c
rename to pidgin/pidgininactiveaccountsmenu.c
--- a/pidgin/pidginaccountsdisabledmenu.c
+++ b/pidgin/pidgininactiveaccountsmenu.c
@@ -22,105 +22,196 @@
 
 #include <glib/gi18n.h>
 
-#include "pidginaccountsdisabledmenu.h"
-
-#include "pidgincore.h"
+#include "pidgininactiveaccountsmenu.h"
 
-/******************************************************************************
- * Helpers
- *****************************************************************************/
-static void
-pidgin_accounts_disabled_menu_refresh_helper(PurpleAccount *account,
-                                             gpointer data)
-{
-	GMenu *menu = data;
-
-	if(!purple_account_get_enabled(account, PIDGIN_UI)) {
-		gchar *label = NULL, *action = NULL;
-		const gchar *account_name = purple_account_get_username(account);
-		const gchar *protocol_name = purple_account_get_protocol_name(account);
+struct _PidginInactiveAccountsMenu {
+	GMenuModel parent;
 
-		/* translators: This format string is intended to contain the account
-		 * name followed by the protocol name to uniquely identify a specific
-		 * account.
-		 */
-		label = g_strdup_printf(_("%s (%s)"), account_name, protocol_name);
-		action = g_strdup_printf("app.enable-account::%s",
-		                         purple_account_get_id(account));
-
-		g_menu_append(menu, label, action);
-
-		g_free(label);
-		g_free(action);
-	}
-}
+	GList *accounts;
+};
 
-static void
-pidgin_accounts_disabled_menu_refresh(GMenu *menu) {
-	PurpleAccountManager *manager = NULL;
-
-	g_menu_remove_all(menu);
-
-	manager = purple_account_manager_get_default();
-	purple_account_manager_foreach(manager,
-	                               pidgin_accounts_disabled_menu_refresh_helper,
-	                               menu);
-
-	if(g_menu_model_get_n_items(G_MENU_MODEL(menu)) == 0) {
-		g_menu_append(menu, _("No disabled accounts"), "disabled");
-	}
-}
+G_DEFINE_TYPE(PidginInactiveAccountsMenu, pidgin_inactive_accounts_menu,
+              G_TYPE_MENU_MODEL)
 
 /******************************************************************************
  * Callbacks
  *****************************************************************************/
 static void
-pidgin_accounts_disabled_menu_enabled_cb(G_GNUC_UNUSED PurpleAccount *account,
+pidgin_inactive_accounts_menu_refresh(PidginInactiveAccountsMenu *menu) {
+	PurpleAccountManager *manager = NULL;
+	gint removed = 0, added = 0;
+
+	/* When refreshing we're always removing at least 1 item because of the
+	 * "no disabled accounts" item that we put in place when all accounts
+	 * are enabled.
+	 */
+	removed = MAX(1, g_list_length(menu->accounts));
+
+	/* Grab the manager and get all the disabled accounts. */
+	manager = purple_account_manager_get_default();
+	g_list_free(menu->accounts);
+	menu->accounts = purple_account_manager_get_inactive(manager);
+
+	/* Similar to the aboved note about removed items, if every account is
+	 * enabled, we add an item saying "no disabled accounts".
+	 */
+	added = MAX(1, g_list_length(menu->accounts));
+
+	/* Tell any listeners that our menu has changed. */
+	g_menu_model_items_changed(G_MENU_MODEL(menu), 0, removed, added);
+}
+
+static void
+pidgin_inactive_accounts_menu_changed_cb(G_GNUC_UNUSED PurpleAccount *account,
                                          gpointer data)
 {
-	pidgin_accounts_disabled_menu_refresh(data);
+	PidginInactiveAccountsMenu *menu = data;
+
+	pidgin_inactive_accounts_menu_refresh(menu);
+}
+
+/******************************************************************************
+ * GMenuModel Implementation
+ *****************************************************************************/
+static gboolean
+pidgin_inactive_accounts_menu_is_mutable(GMenuModel *model) {
+	return TRUE;
+}
+
+static gboolean
+pidgin_inactive_accounts_menu_get_n_items(GMenuModel *model) {
+	PidginInactiveAccountsMenu *menu = NULL;
+
+	menu = PIDGIN_INACTIVE_ACCOUNTS_MENU(model);
+
+	if(menu->accounts == NULL) {
+		return 1;
+	}
+
+	return g_list_length(menu->accounts);
 }
 
 static void
-pidgin_accounts_disabled_menu_disabled_cb(G_GNUC_UNUSED PurpleAccount *account,
-                                          gpointer data)
+pidgin_inactive_accounts_menu_get_item_attributes(GMenuModel *model,
+                                                  gint index,
+                                                  GHashTable **attributes)
 {
-	pidgin_accounts_disabled_menu_refresh(data);
+	PidginInactiveAccountsMenu *menu = NULL;
+	PurpleAccount *account = NULL;
+	PurpleProtocol *protocol = NULL;
+	GVariant *value = NULL;
+	const gchar *account_name = NULL, *protocol_name = NULL;
+
+	menu = PIDGIN_INACTIVE_ACCOUNTS_MENU(model);
+
+	/* Create our hash table of attributes to return. */
+	*attributes = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+	                                    (GDestroyNotify)g_variant_unref);
+
+	/* If we don't have any disabled accounts, just return a single item,
+	 * stating as much.
+	 */
+	if(menu->accounts == NULL) {
+		value = g_variant_new_string(_("No disabled accounts"));
+		g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_LABEL,
+		                    g_variant_ref_sink(value));
+
+		value = g_variant_new_string("disabled");
+		g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_ACTION,
+		                    g_variant_ref_sink(value));
+
+		return;
+	}
+
+	account = g_list_nth_data(menu->accounts, index);
+	if(account == NULL) {
+		return;
+	}
+
+	account_name = purple_account_get_username(account);
+	protocol_name = purple_account_get_protocol_name(account);
+
+	/* translators: This format string is intended to contain the account
+	 * name followed by the protocol name to uniquely identify a specific
+	 * account.
+	 */
+	value = g_variant_new_printf(_("%s (%s)"), account_name, protocol_name);
+	g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_LABEL,
+	                    g_variant_ref_sink(value));
+
+	value = g_variant_new_string("app.enable-account");
+	g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_ACTION,
+	                    g_variant_ref_sink(value));
+
+	value = g_variant_new_printf("%s", purple_account_get_id(account));
+	g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_TARGET,
+	                    g_variant_ref_sink(value));
+
+	protocol = purple_account_get_protocol(account);
+	if(protocol != NULL) {
+		value = g_variant_new_printf("%s", purple_protocol_get_icon_name(protocol));
+		g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_ICON,
+		                    g_variant_ref_sink(value));
+	}
 }
 
 static void
-pidgin_accounts_disabled_menu_weak_notify_cb(G_GNUC_UNUSED gpointer data,
-                                             GObject *obj)
+pidgin_inactive_accounts_menu_get_item_links(GMenuModel *model, gint index,
+                                             GHashTable **links)
 {
+	*links = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+	                               g_object_unref);
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+static void
+pidgin_inactive_accounts_menu_dispose(GObject *obj) {
 	purple_signals_disconnect_by_handle(obj);
+
+	G_OBJECT_CLASS(pidgin_inactive_accounts_menu_parent_class)->dispose(obj);
+}
+
+static void
+pidgin_inactive_accounts_menu_constructed(GObject *obj) {
+	G_OBJECT_CLASS(pidgin_inactive_accounts_menu_parent_class)->constructed(obj);
+
+	pidgin_inactive_accounts_menu_refresh(PIDGIN_INACTIVE_ACCOUNTS_MENU(obj));
+}
+
+static void
+pidgin_inactive_accounts_menu_init(PidginInactiveAccountsMenu *menu) {
+	gpointer handle = NULL;
+
+	/* Wire up the purple signals we care about. */
+	handle = purple_accounts_get_handle();
+	purple_signal_connect(handle, "account-enabled", menu,
+	                      G_CALLBACK(pidgin_inactive_accounts_menu_changed_cb),
+	                      menu);
+	purple_signal_connect(handle, "account-disabled", menu,
+	                      G_CALLBACK(pidgin_inactive_accounts_menu_changed_cb),
+	                      menu);
+}
+
+static void
+pidgin_inactive_accounts_menu_class_init(PidginInactiveAccountsMenuClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	GMenuModelClass *model_class = G_MENU_MODEL_CLASS(klass);
+
+	obj_class->constructed = pidgin_inactive_accounts_menu_constructed;
+	obj_class->dispose = pidgin_inactive_accounts_menu_dispose;
+
+	model_class->is_mutable = pidgin_inactive_accounts_menu_is_mutable;
+	model_class->get_n_items = pidgin_inactive_accounts_menu_get_n_items;
+	model_class->get_item_attributes = pidgin_inactive_accounts_menu_get_item_attributes;
+	model_class->get_item_links = pidgin_inactive_accounts_menu_get_item_links;
 }
 
 /******************************************************************************
  * Public API
  *****************************************************************************/
-GMenu *
-pidgin_accounts_disabled_menu_new(void) {
-	GMenu *menu = NULL;
-	gpointer handle = NULL;
-
-	/* Create the menu and set our instance as data on it so it'll be freed
-	 * when the menu is destroyed.
-	 */
-	menu = g_menu_new();
-	g_object_weak_ref(G_OBJECT(menu),
-	                  pidgin_accounts_disabled_menu_weak_notify_cb, NULL);
-
-	/* Populate ourselves with any accounts that are already disabled. */
-	pidgin_accounts_disabled_menu_refresh(menu);
-
-	/* Wire up the purple signals we care about. */
-	handle = purple_accounts_get_handle();
-	purple_signal_connect(handle, "account-enabled", menu,
-	                      G_CALLBACK(pidgin_accounts_disabled_menu_enabled_cb),
-	                      menu);
-	purple_signal_connect(handle, "account-disabled", menu,
-	                      G_CALLBACK(pidgin_accounts_disabled_menu_disabled_cb),
-	                      menu);
-
-	return menu;
+GMenuModel *
+pidgin_inactive_accounts_menu_new(void) {
+	return g_object_new(PIDGIN_TYPE_INACTIVE_ACCOUNTS_MENU, NULL);
 }
diff --git a/pidgin/pidginapplication.c b/pidgin/pidginapplication.c
--- a/pidgin/pidginapplication.c
+++ b/pidgin/pidginapplication.c
@@ -42,11 +42,11 @@
 #include "gtkroomlist.h"
 #include "gtkxfer.h"
 #include "pidginabout.h"
-#include "pidginaccountsdisabledmenu.h"
 #include "pidginaccountsenabledmenu.h"
 #include "pidginconversationwindow.h"
 #include "pidgincore.h"
 #include "pidgindebug.h"
+#include "pidgininactiveaccountsmenu.h"
 #include "pidginmooddialog.h"
 #include "pidgin/pidginpluginsdialog.h"
 #include "pidgin/pidginstatusmanager.h"
@@ -130,12 +130,13 @@
 static void
 pidgin_application_populate_dynamic_menus(PidginApplication *application) {
 	GMenu *source = NULL, *target = NULL;
+	GMenuModel *model = NULL;
 
 	/* Link the AccountsDisabledMenu into its proper location. */
-	source = pidgin_accounts_disabled_menu_new();
+	model = pidgin_inactive_accounts_menu_new();
 	target = gtk_application_get_menu_by_id(GTK_APPLICATION(application),
-	                                        "disabled-accounts");
-	g_menu_append_section(target, NULL, G_MENU_MODEL(source));
+	                                        "inactive-accounts");
+	g_menu_append_section(target, NULL, model);
 
 	/* Link the AccountsEnabledMenu into its proper location. */
 	source = pidgin_accounts_enabled_menu_new();
diff --git a/pidgin/resources/gtk/menus.ui b/pidgin/resources/gtk/menus.ui
--- a/pidgin/resources/gtk/menus.ui
+++ b/pidgin/resources/gtk/menus.ui
@@ -184,7 +184,7 @@
         <submenu>
           <attribute name="label" translatable="yes">_Enable Account</attribute>
 
-          <section id="disabled-accounts"/>
+          <section id="inactive-accounts"/>
         </submenu>
       </section>
       <section id="enabled-accounts"/>
diff --git a/po/POTFILES.in b/po/POTFILES.in
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -336,7 +336,6 @@
 pidgin/pidginaccountchooser.c
 pidgin/pidginaccountfilterconnected.c
 pidgin/pidginaccountfilterprotocol.c
-pidgin/pidginaccountsdisabledmenu.c
 pidgin/pidginaccountsenabledmenu.c
 pidgin/pidginaccountsmenu.c
 pidgin/pidginaccountstore.c
@@ -357,6 +356,7 @@
 pidgin/pidgindnd.c
 pidgin/pidgingdkpixbuf.c
 pidgin/pidginiconname.c
+pidgin/pidgininactiveaccountsmenu.c
 pidgin/pidgininfopane.c
 pidgin/pidgininvitedialog.c
 pidgin/pidginmessage.c
