--- a/pidgin/pidginaccountmanager.c Tue Jan 17 02:27:41 2023 -0600 +++ b/pidgin/pidginaccountmanager.c Tue Jan 17 02:29:19 2023 -0600 @@ -29,167 +29,33 @@ #include "gtkaccount.h" #include "pidgincore.h" #include "pidginaccounteditor.h" +#include "pidginaccountrow.h" struct _PidginAccountManager { GtkDialog parent; - GtkListStore *model; - GtkTreeSelection *selection; - - GtkWidget *modify_button; - GtkWidget *remove_button; + GtkListBox *list_box; + GtkWidget *add; }; enum { RESPONSE_ADD, - RESPONSE_MODIFY, - RESPONSE_REMOVE, -}; - -enum { - COLUMN_ENABLED, - COLUMN_AVATAR, - COLUMN_USERNAME, - COLUMN_PROTOCOL_ICON, - COLUMN_PROTOCOL_NAME, - COLUMN_ACCOUNT }; G_DEFINE_TYPE(PidginAccountManager, pidgin_account_manager, GTK_TYPE_DIALOG) -static void pidgin_account_manager_account_notify_cb(GObject *obj, GParamSpec *pspec, gpointer data); - /****************************************************************************** * Helpers *****************************************************************************/ -static gboolean -pidgin_account_manager_find_account(PidginAccountManager *manager, - PurpleAccount *account, GtkTreeIter *iter) +static GtkWidget * +pidgin_account_manager_create_widget(gpointer item, + G_GNUC_UNUSED gpointer data) { - GtkTreeModel *model = GTK_TREE_MODEL(manager->model); - - if(!gtk_tree_model_get_iter_first(model, iter)) { - return FALSE; - } - - do { - PurpleAccount *current = NULL; - - gtk_tree_model_get(model, iter, - COLUMN_ACCOUNT, ¤t, - -1); - - if(current == account) { - g_clear_object(¤t); - - return TRUE; - } - - g_clear_object(¤t); - } while(gtk_tree_model_iter_next(model, iter)); - - return FALSE; -} - -static PurpleAccount * -pidgin_account_manager_get_selected_account(PidginAccountManager *manager) { - PurpleAccount *account = NULL; - GtkTreeIter iter; - - if(gtk_tree_selection_count_selected_rows(manager->selection) == 0) { + if(!PURPLE_IS_ACCOUNT(item)) { return NULL; } - gtk_tree_selection_get_selected(manager->selection, NULL, &iter); - - gtk_tree_model_get(GTK_TREE_MODEL(manager->model), &iter, - COLUMN_ACCOUNT, &account, - -1); - - return account; -} - -static void -pidgin_account_manager_refresh_account(PidginAccountManager *manager, - PurpleAccount *account, - GtkTreeIter *iter) -{ - PurpleContactInfo *info = NULL; - PurpleImage *image = NULL; - PurpleProtocol *protocol = NULL; - GdkPixbuf *avatar = NULL; - const gchar *protocol_icon = NULL, *protocol_name = NULL; - - /* Try to find the avatar for the account. */ - image = purple_buddy_icons_find_account_icon(account); - if(image != NULL) { - GdkPixbuf *raw = NULL; - - raw = purple_gdk_pixbuf_from_image(image); - g_object_unref(image); - - avatar = gdk_pixbuf_scale_simple(raw, 22, 22, GDK_INTERP_HYPER); - g_clear_object(&raw); - } - - /* Get the protocol fields. */ - protocol = purple_account_get_protocol(account); - if(PURPLE_IS_PROTOCOL(protocol)) { - protocol_name = purple_protocol_get_name(protocol); - protocol_icon = purple_protocol_get_icon_name(protocol); - } else { - protocol_name = _("Unknown"); - } - - info = PURPLE_CONTACT_INFO(account); - gtk_list_store_set(manager->model, iter, - COLUMN_ENABLED, purple_account_get_enabled(account), - COLUMN_AVATAR, avatar, - COLUMN_USERNAME, purple_contact_info_get_username(info), - COLUMN_PROTOCOL_ICON, protocol_icon, - COLUMN_PROTOCOL_NAME, protocol_name, - COLUMN_ACCOUNT, account, - -1); - - g_clear_object(&avatar); -} - -static void -pidgin_account_manager_update_account(PidginAccountManager *manager, - PurpleAccount *account) -{ - GtkTreeIter iter; - - if(pidgin_account_manager_find_account(manager, account, &iter)) { - pidgin_account_manager_refresh_account(manager, account, &iter); - } -} - -static void -pidgin_account_manager_add_account(PidginAccountManager *manager, - PurpleAccount *account) -{ - GtkTreeIter iter; - - gtk_list_store_append(manager->model, &iter); - - pidgin_account_manager_refresh_account(manager, account, &iter); - - g_signal_connect_object(account, "notify", - G_CALLBACK(pidgin_account_manager_account_notify_cb), - manager, 0); -} - -static void -pidgin_account_manager_populate_helper(PurpleAccount *account, gpointer data) { - pidgin_account_manager_add_account(PIDGIN_ACCOUNT_MANAGER(data), account); -} - -static void -pidgin_account_manager_populate(PidginAccountManager *manager) { - purple_account_manager_foreach(purple_account_manager_get_default(), - pidgin_account_manager_populate_helper, - manager); + return pidgin_account_row_new(PURPLE_ACCOUNT(item)); } static void @@ -200,51 +66,22 @@ gtk_window_present_with_time(GTK_WINDOW(editor), GDK_CURRENT_TIME); } -static void -pidgin_account_manager_edit_selected_account(PidginAccountManager *manager) { - PurpleAccount *account = NULL; - GtkWidget *editor = NULL; - - account = pidgin_account_manager_get_selected_account(manager); - - editor = pidgin_account_editor_new(account); - gtk_window_set_transient_for(GTK_WINDOW(editor), - GTK_WINDOW(manager)); - gtk_window_present_with_time(GTK_WINDOW(editor), GDK_CURRENT_TIME); - - g_clear_object(&account); -} - -static void -pidgin_account_manager_remove_selected_account(PidginAccountManager *manager) { - PurpleAccount *account = NULL; - PurpleNotificationManager *notification_manager = NULL; - - account = pidgin_account_manager_get_selected_account(manager); - - /* Remove all notifications including connection errors for the account. */ - notification_manager = purple_notification_manager_get_default(); - purple_notification_manager_remove_with_account(notification_manager, - account, TRUE); - - /* Delete the account. */ - purple_accounts_delete(account); - - g_clear_object(&account); -} - /****************************************************************************** * Callbacks *****************************************************************************/ + static void -pidgin_account_manager_account_notify_cb(GObject *obj, - G_GNUC_UNUSED GParamSpec *pspec, - gpointer data) +pidgin_account_manager_refresh_add_cb(GListModel *list, + G_GNUC_UNUSED guint position, + G_GNUC_UNUSED guint removed, + G_GNUC_UNUSED guint added, + gpointer data) { - PidginAccountManager *manager = PIDGIN_ACCOUNT_MANAGER(data); - PurpleAccount *account = PURPLE_ACCOUNT(obj); + PidginAccountManager *manager = data; - pidgin_account_manager_update_account(manager, account); + /* If there are no accounts, the placeholder is shown, which includes an + * Add button. So hide the one in the button box if that's the case. */ + gtk_widget_set_visible(manager->add, g_list_model_get_n_items(list) != 0); } static void @@ -257,12 +94,6 @@ case RESPONSE_ADD: pidgin_account_manager_create_account(manager); break; - case RESPONSE_MODIFY: - pidgin_account_manager_edit_selected_account(manager); - break; - case RESPONSE_REMOVE: - pidgin_account_manager_remove_selected_account(manager); - break; case GTK_RESPONSE_CLOSE: case GTK_RESPONSE_DELETE_EVENT: gtk_window_destroy(GTK_WINDOW(dialog)); @@ -273,100 +104,16 @@ } static void -pidgin_account_manager_selection_changed_cb(GtkTreeSelection *selection, - gpointer data) -{ - PidginAccountManager *manager = data; - gboolean sensitive = TRUE; - - if(gtk_tree_selection_count_selected_rows(selection) == 0) { - sensitive = FALSE; - } - - gtk_widget_set_sensitive(manager->modify_button, sensitive); - gtk_widget_set_sensitive(manager->remove_button, sensitive); -} - -static void -pidgin_account_manager_row_activated_cb(G_GNUC_UNUSED GtkTreeView *tree_view, - GtkTreePath *path, - G_GNUC_UNUSED GtkTreeViewColumn *column, - gpointer data) +pidgin_account_manager_row_activated_cb(G_GNUC_UNUSED GtkListBox *box, + GtkListBoxRow *row, + G_GNUC_UNUSED gpointer data) { - PidginAccountManager *manager = data; - GtkTreeIter iter; - - if(gtk_tree_model_get_iter(GTK_TREE_MODEL(manager->model), &iter, path)) { - GtkWidget *editor = NULL; - PurpleAccount *account = NULL; - - gtk_tree_model_get(GTK_TREE_MODEL(manager->model), &iter, - COLUMN_ACCOUNT, &account, - -1); - - editor = pidgin_account_editor_new(account); - gtk_widget_show(editor); - - g_clear_object(&account); - } -} - -static void -pidgin_account_manager_enable_toggled_cb(G_GNUC_UNUSED GtkCellRendererToggle *renderer, - gchar *path, gpointer data) -{ - PidginAccountManager *manager = data; - GtkTreeModel *model = GTK_TREE_MODEL(manager->model); - GtkTreeIter iter; + GtkWidget *editor = NULL; + PurpleAccount *account = NULL; - if(gtk_tree_model_get_iter_from_string(model, &iter, path)) { - PurpleAccount *account = NULL; - gboolean enabled = FALSE; - - /* The value of enabled in the model is the old value, so if enabled - * is currently set to TRUE, we are disabling the account and vice - * versa. - */ - gtk_tree_model_get(model, &iter, - COLUMN_ENABLED, &enabled, - COLUMN_ACCOUNT, &account, - -1); - - /* The account was just enabled, so set its status. */ - if(!enabled) { - PurpleSavedStatus *status = purple_savedstatus_get_current(); - purple_savedstatus_activate_for_account(status, account); - } - - purple_account_set_enabled(account, !enabled); - - /* We don't update the model here, as it's updated via the notify - * signal. - */ - } -} - -static void -pidgin_account_manager_account_added_cb(G_GNUC_UNUSED PurpleAccountManager *purple_manager, - PurpleAccount *account, - gpointer data) -{ - PidginAccountManager *manager = data; - - pidgin_account_manager_add_account(manager, account); -} - -static void -pidgin_account_manager_account_removed_cb(G_GNUC_UNUSED PurpleAccountManager *purple_manager, - PurpleAccount *account, - gpointer data) -{ - PidginAccountManager *manager = data; - GtkTreeIter iter; - - if(pidgin_account_manager_find_account(manager, account, &iter)) { - gtk_list_store_remove(manager->model, &iter); - } + account = pidgin_account_row_get_account(PIDGIN_ACCOUNT_ROW(row)); + editor = pidgin_account_editor_new(account); + gtk_widget_show(editor); } /****************************************************************************** @@ -374,19 +121,17 @@ *****************************************************************************/ static void pidgin_account_manager_init(PidginAccountManager *manager) { - PurpleAccountManager *purple_manager = NULL; + GListModel *purple_manager = NULL; gtk_widget_init_template(GTK_WIDGET(manager)); - pidgin_account_manager_populate(manager); - - purple_manager = purple_account_manager_get_default(); - g_signal_connect_object(purple_manager, "added", - G_CALLBACK(pidgin_account_manager_account_added_cb), + purple_manager = purple_account_manager_get_default_as_model(); + gtk_list_box_bind_model(manager->list_box, purple_manager, + pidgin_account_manager_create_widget, NULL, NULL); + g_signal_connect_object(purple_manager, "items-changed", + G_CALLBACK(pidgin_account_manager_refresh_add_cb), manager, 0); - g_signal_connect_object(purple_manager, "removed", - G_CALLBACK(pidgin_account_manager_account_removed_cb), - manager, 0); + pidgin_account_manager_refresh_add_cb(purple_manager, 0, 0, 0, manager); } static void @@ -399,23 +144,16 @@ ); gtk_widget_class_bind_template_child(widget_class, PidginAccountManager, - model); - gtk_widget_class_bind_template_child(widget_class, PidginAccountManager, - selection); - + list_box); gtk_widget_class_bind_template_child(widget_class, PidginAccountManager, - modify_button); - gtk_widget_class_bind_template_child(widget_class, PidginAccountManager, - remove_button); + add); gtk_widget_class_bind_template_callback(widget_class, - pidgin_account_manager_enable_toggled_cb); - gtk_widget_class_bind_template_callback(widget_class, pidgin_account_manager_response_cb); gtk_widget_class_bind_template_callback(widget_class, pidgin_account_manager_row_activated_cb); gtk_widget_class_bind_template_callback(widget_class, - pidgin_account_manager_selection_changed_cb); + pidgin_account_manager_create_account); } /******************************************************************************