pidgin/pidgin

Parents b1921b17b683
Children af3eb87ac757
Separate the AccountChooser from its model and move options to filters

Create a store for accounts and a filter to only show connected accounts

Update everything to use the new PidginAccountStore and PidginAccountFilterConnected filter

Add a GtkTreeModelFilter for protocols by id

Testing Done:
Compiled and opened most of the dialogs to make sure they're still working the same. Was unable to test gevolution.

Reviewed at https://reviews.imfreedom.org/r/95/
--- a/doc/reference/pidgin/pidgin-docs.xml Tue Sep 15 20:26:57 2020 -0500
+++ b/doc/reference/pidgin/pidgin-docs.xml Tue Sep 15 21:54:10 2020 -0500
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
@@ -54,9 +54,12 @@
<xi:include href="xml/minidialog.xml" />
<xi:include href="xml/pidgin.xml" />
<xi:include href="xml/pidginabout.xml" />
+ <xi:include href="xml/pidginaccountactionsmenu.xml" />
<xi:include href="xml/pidginaccountchooser.xml" />
- <xi:include href="xml/pidginaccountactionsmenu.xml" />
+ <xi:include href="xml/pidginaccountfilterconnected.xml" />
+ <xi:include href="xml/pidginaccountfilterprotocol.xml" />
<xi:include href="xml/pidginaccountsmenu.xml" />
+ <xi:include href="xml/pidginaccountstore.xml" />
<xi:include href="xml/pidginactiongroup.xml" />
<xi:include href="xml/pidginattachment.xml" />
<xi:include href="xml/pidginbuddylistmenu.xml" />
--- a/pidgin/glade/pidgin3.xml.in Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/glade/pidgin3.xml.in Tue Sep 15 21:54:10 2020 -0500
@@ -3,6 +3,9 @@
<glade-widget-classes>
<glade-widget-class name="PidginAccountChooser" generic-name="account_chooser" title="AccountChooser"/>
<glade-widget-class name="PidginAccountsMenu" generic-name="accounts_menu" title="AccountsMenu"/>
+ <glade-widget-class name="PidginAccountStore" generic-name="account_store" title="AccountStore"/>
+ <glade-widget-class name="PidginAccountFilterConnected" generic-name="account_filter_connected" title="FilterConnected"/>
+ <glade-widget-class name="PidginAccountFilterProtocol" generic-name="account_filter_protocol" title="FilterProtocol"/>
<glade-widget-class name="PidginCloseButton" generic-name="close-button" title="CloseButton"/>
<glade-widget-class name="PidginDialog" generic-name="dialog" title="Dialog"/>
<glade-widget-class name="PidginInviteDialog" generic-name="invite_dialog" title="InviteDialog"/>
@@ -14,6 +17,9 @@
<glade-widget-group name="pidgin" title="Pidgin">
<glade-widget-class-ref name="PidginAccountChooser"/>
<glade-widget-class-ref name="PidginAccountsMenu"/>
+ <glade-widget-class-ref name="PidginAccountStore"/>
+ <glade-widget-class-ref name="PidginAccountFilterConnected"/>
+ <glade-widget-class-ref name="PidginAccountFilterProtocol"/>
<glade-widget-class-ref name="PidginCloseButton"/>
<glade-widget-class-ref name="PidginDialog"/>
<glade-widget-class-ref name="PidginInviteDialog"/>
--- a/pidgin/gtkblist.c Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/gtkblist.c Tue Sep 15 21:54:10 2020 -0500
@@ -44,6 +44,8 @@
#include "gtkutils.h"
#include "pidgin/minidialog.h"
#include "pidgin/pidginaccountchooser.h"
+#include "pidgin/pidginaccountfilterconnected.h"
+#include "pidgin/pidginaccountstore.h"
#include "pidgin/pidginactiongroup.h"
#include "pidgin/pidginbuddylistmenu.h"
#include "pidgin/pidginclosebutton.h"
@@ -967,6 +969,7 @@
GtkWidget *hbox;
GtkWidget *vbox;
GtkWindow *blist_window;
+ GtkTreeModel *model = NULL, *filter = NULL;
PidginBuddyList *gtkblist;
data->account = account;
@@ -1009,7 +1012,19 @@
data->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- data->account_menu = pidgin_account_chooser_new(account, FALSE);
+ model = GTK_TREE_MODEL(pidgin_account_store_new());
+ filter = pidgin_account_filter_connected_new(model, NULL);
+ g_object_unref(G_OBJECT(model));
+ data->account_menu = pidgin_account_chooser_new();
+ gtk_combo_box_set_model(GTK_COMBO_BOX(data->account_menu), filter);
+ g_object_unref(G_OBJECT(filter));
+ if(PURPLE_IS_ACCOUNT(account)) {
+ pidgin_account_chooser_set_selected(PIDGIN_ACCOUNT_CHOOSER(
+ data->account_menu), account);
+ } else {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(data->account_menu), 0);
+ }
+
pidgin_account_chooser_set_filter_func(
PIDGIN_ACCOUNT_CHOOSER(data->account_menu), filter_func);
pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("A_ccount"), data->sg, data->account_menu, TRUE, NULL);
@@ -1109,8 +1124,8 @@
static void
chat_select_account_cb(GObject *w, PidginChatData *data)
{
- PurpleAccount *account =
- pidgin_account_chooser_get_selected(GTK_WIDGET(w));
+ PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(w);
+ PurpleAccount *account = pidgin_account_chooser_get_selected(chooser);
g_return_if_fail(data != NULL);
g_return_if_fail(account != NULL);
@@ -1131,6 +1146,7 @@
pidgin_blist_joinchat_show(void)
{
PidginChatData *data = NULL;
+ PidginAccountChooser *chooser = NULL;
data = g_new0(PidginChatData, 1);
@@ -1147,8 +1163,9 @@
gtk_dialog_set_default_response(GTK_DIALOG(data->rq_data.window),
GTK_RESPONSE_OK);
data->default_chat_name = NULL;
- data->rq_data.account =
- pidgin_account_chooser_get_selected(data->rq_data.account_menu);
+
+ chooser = PIDGIN_ACCOUNT_CHOOSER(data->rq_data.account_menu);
+ data->rq_data.account = pidgin_account_chooser_get_selected(chooser);
rebuild_chat_entries(data, NULL);
@@ -6263,8 +6280,8 @@
static void
add_buddy_select_account_cb(GObject *w, PidginAddBuddyData *data)
{
- PurpleAccount *account =
- pidgin_account_chooser_get_selected(GTK_WIDGET(w));
+ PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(w);
+ PurpleAccount *account = pidgin_account_chooser_get_selected(chooser);
PurpleConnection *pc = NULL;
PurpleProtocol *protocol = NULL;
gboolean invite_enabled = TRUE;
@@ -6371,6 +6388,7 @@
const char *username, const char *group,
const char *alias)
{
+ PidginAccountChooser *chooser = NULL;
PidginAddBuddyData *data = g_new0(PidginAddBuddyData, 1);
PidginBlistRequestData *blist_req_data = &data->rq_data;
@@ -6434,8 +6452,8 @@
gtk_widget_show_all(data->rq_data.window);
/* Force update of invite message entry sensitivity */
- pidgin_account_chooser_set_selected(blist_req_data->account_menu,
- account);
+ chooser = PIDGIN_ACCOUNT_CHOOSER(blist_req_data->account_menu);
+ pidgin_account_chooser_set_selected(chooser, account);
}
static void
--- a/pidgin/gtkpounce.c Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/gtkpounce.c Tue Sep 15 21:54:10 2020 -0500
@@ -33,6 +33,7 @@
#include "pidginstock.h"
#include "gtkutils.h"
#include "pidginaccountchooser.h"
+#include "pidginaccountstore.h"
#include "pidgincore.h"
#include "pidgindialog.h"
#include "pidgintalkatu.h"
@@ -347,8 +348,9 @@
}
static void
-pounce_choose_cb(GtkWidget *chooser, PidginPounceDialog *dialog)
+pounce_choose_cb(GtkWidget *w, PidginPounceDialog *dialog)
{
+ PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(w);
dialog->account = pidgin_account_chooser_get_selected(chooser);
}
@@ -399,7 +401,8 @@
gtk_entry_set_text(GTK_ENTRY(dialog->buddy_entry), purple_buddy_get_name(buddy));
dialog->account = purple_buddy_get_account(buddy);
pidgin_account_chooser_set_selected(
- dialog->account_menu, purple_buddy_get_account(buddy));
+ PIDGIN_ACCOUNT_CHOOSER(dialog->account_menu),
+ purple_buddy_get_account(buddy));
gtk_drag_finish(dc, TRUE, (gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE), t);
}
@@ -425,7 +428,7 @@
gtk_entry_set_text(GTK_ENTRY(dialog->buddy_entry), username);
dialog->account = account;
pidgin_account_chooser_set_selected(
- dialog->account_menu, account);
+ PIDGIN_ACCOUNT_CHOOSER(dialog->account_menu), account);
}
}
@@ -445,8 +448,8 @@
static void
reset_send_msg_entry(PidginPounceDialog *dialog, GtkWidget *dontcare)
{
- PurpleAccount *account =
- pidgin_account_chooser_get_selected(dialog->account_menu);
+ PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(dialog->account_menu);
+ PurpleAccount *account = pidgin_account_chooser_get_selected(chooser);
if(GTK_IS_TEXT_BUFFER(dialog->send_msg_buffer)) {
g_object_unref(dialog->send_msg_buffer);
@@ -483,6 +486,7 @@
GtkWidget *grid;
GtkSizeGroup *sg;
GtkWidget *editor;
+ GtkTreeModel *model;
g_return_if_fail((cur_pounce != NULL) ||
(account != NULL) ||
@@ -547,8 +551,12 @@
gtk_widget_show(label);
gtk_size_group_add_widget(sg, label);
- dialog->account_menu =
- pidgin_account_chooser_new(dialog->account, TRUE);
+ dialog->account_menu = pidgin_account_chooser_new();
+ model = GTK_TREE_MODEL(pidgin_account_store_new());
+ gtk_combo_box_set_model(GTK_COMBO_BOX(dialog->account_menu), model);
+ g_object_unref(G_OBJECT(model));
+ pidgin_account_chooser_set_selected(
+ PIDGIN_ACCOUNT_CHOOSER(dialog->account_menu), dialog->account);
g_signal_connect(dialog->account_menu, "changed",
G_CALLBACK(pounce_choose_cb), dialog);
--- a/pidgin/gtkprivacy.c Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/gtkprivacy.c Tue Sep 15 21:54:10 2020 -0500
@@ -28,6 +28,7 @@
#include "gtkprivacy.h"
#include "gtkutils.h"
#include "pidginaccountchooser.h"
+#include "pidginaccountstore.h"
#define PIDGIN_TYPE_PRIVACY_DIALOG (pidgin_privacy_dialog_get_type())
G_DECLARE_FINAL_TYPE(PidginPrivacyDialog, pidgin_privacy_dialog, PIDGIN,
@@ -119,8 +120,8 @@
}
static void
-select_account_cb(GtkWidget *chooser, PidginPrivacyDialog *dialog)
-{
+select_account_cb(GtkWidget *w, PidginPrivacyDialog *dialog) {
+ PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(w);
PurpleAccount *account = pidgin_account_chooser_get_selected(chooser);
gsize i;
@@ -300,15 +301,15 @@
}
static void
-pidgin_privacy_dialog_init(PidginPrivacyDialog *dialog)
-{
+pidgin_privacy_dialog_init(PidginPrivacyDialog *dialog) {
+ PidginAccountChooser *chooser = NULL;
gssize selected = -1;
gsize i;
gtk_widget_init_template(GTK_WIDGET(dialog));
- dialog->account =
- pidgin_account_chooser_get_selected(dialog->account_chooser);
+ chooser = PIDGIN_ACCOUNT_CHOOSER(dialog->account_chooser);
+ dialog->account = pidgin_account_chooser_get_selected(chooser);
/* Add the drop-down list with the allow/block types. */
for (i = 0; i < menu_entry_count; i++) {
--- a/pidgin/gtkrequest.c Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/gtkrequest.c Tue Sep 15 21:54:10 2020 -0500
@@ -26,9 +26,11 @@
#include <purple.h>
#include "gtkrequest.h"
+#include "gtkblist.h"
#include "gtkutils.h"
-#include "gtkblist.h"
#include "pidginaccountchooser.h"
+#include "pidginaccountfilterconnected.h"
+#include "pidginaccountstore.h"
#include "pidgincore.h"
#include "pidgindialog.h"
#include "pidginstock.h"
@@ -262,8 +264,10 @@
static void
field_account_cb(GObject *w, PurpleRequestField *field)
{
+ PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(w);
+
purple_request_field_account_set_value(
- field, pidgin_account_chooser_get_selected(GTK_WIDGET(w)));
+ field, pidgin_account_chooser_get_selected(chooser));
}
static void
@@ -1325,10 +1329,32 @@
create_account_field(PurpleRequestField *field)
{
GtkWidget *widget;
-
- widget = pidgin_account_chooser_new(
- purple_request_field_account_get_default_value(field),
- purple_request_field_account_get_show_all(field));
+ PurpleAccount *account;
+
+ widget = pidgin_account_chooser_new();
+ account = purple_request_field_account_get_default_value(field);
+
+ if(purple_request_field_account_get_show_all(field)) {
+ GtkListStore *store = pidgin_account_store_new();
+
+ gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store));
+
+ g_object_unref(G_OBJECT(store));
+ } else {
+ GtkListStore *store = NULL;
+ GtkTreeModel *filter = NULL;
+
+ store = pidgin_account_store_new();
+ filter = pidgin_account_filter_connected_new(GTK_TREE_MODEL(store),
+ NULL);
+ g_object_unref(G_OBJECT(store));
+
+ gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(filter));
+ g_object_unref(G_OBJECT(filter));
+ }
+
+ pidgin_account_chooser_set_selected(PIDGIN_ACCOUNT_CHOOSER(widget),
+ account);
pidgin_account_chooser_set_filter_func(
PIDGIN_ACCOUNT_CHOOSER(widget),
purple_request_field_account_get_filter(field));
@@ -1338,6 +1364,7 @@
gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field));
g_signal_connect(widget, "changed",
G_CALLBACK(req_field_changed_cb), field);
+ gtk_widget_show(widget);
return widget;
}
--- a/pidgin/gtkroomlist.c Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/gtkroomlist.c Tue Sep 15 21:54:10 2020 -0500
@@ -110,8 +110,8 @@
}
static void
-dialog_select_account_cb(GtkWidget *chooser, PidginRoomlistDialog *dialog)
-{
+dialog_select_account_cb(GtkWidget *w, PidginRoomlistDialog *dialog) {
+ PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(w);
PurpleAccount *account = pidgin_account_chooser_get_selected(chooser);
gboolean change = (account != dialog->account);
dialog->account = account;
@@ -566,19 +566,20 @@
static PidginRoomlistDialog *
pidgin_roomlist_dialog_new_with_account(PurpleAccount *account)
{
- PidginRoomlistDialog *dialog;
+ PidginRoomlistDialog *dialog = NULL;
+ PidginAccountChooser *chooser = NULL;
dialog = g_object_new(PIDGIN_TYPE_ROOMLIST_DIALOG, NULL);
dialog->account = account;
+ chooser = PIDGIN_ACCOUNT_CHOOSER(dialog->account_widget);
+
if (!account) {
/* This is normally NULL, and we normally don't care what the
* first selected item is */
- dialog->account = pidgin_account_chooser_get_selected(
- dialog->account_widget);
+ dialog->account = pidgin_account_chooser_get_selected(chooser);
} else {
- pidgin_account_chooser_set_selected(dialog->account_widget,
- account);
+ pidgin_account_chooser_set_selected(chooser, account);
}
/* show the dialog window and return the dialog */
--- a/pidgin/meson.build Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/meson.build Tue Sep 15 21:54:10 2020 -0500
@@ -35,7 +35,10 @@
'pidginabout.c',
'pidginaccountactionsmenu.c',
'pidginaccountchooser.c',
+ 'pidginaccountfilterconnected.c',
+ 'pidginaccountfilterprotocol.c',
'pidginaccountsmenu.c',
+ 'pidginaccountstore.c',
'pidginactiongroup.c',
'pidginattachment.c',
'pidginbuddylistmenu.c',
@@ -97,7 +100,10 @@
'pidginabout.h',
'pidginaccountactionsmenu.h',
'pidginaccountchooser.h',
+ 'pidginaccountfilterconnected.h',
+ 'pidginaccountfilterprotocol.h',
'pidginaccountsmenu.h',
+ 'pidginaccountstore.h',
'pidginactiongroup.h',
'pidginattachment.h',
'pidginbuddylistmenu.h',
--- a/pidgin/pidginaccountchooser.c Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/pidginaccountchooser.c Tue Sep 15 21:54:10 2020 -0500
@@ -1,4 +1,6 @@
-/* pidgin
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
*
* Pidgin is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
@@ -20,196 +22,38 @@
*/
#include <gtk/gtk.h>
-#include "gtkutils.h"
#include "pidginaccountchooser.h"
-/******************************************************************************
- * Enums
- *****************************************************************************/
+#include "pidginaccountstore.h"
-enum
-{
- AOP_ICON_COLUMN,
- AOP_NAME_COLUMN,
- AOP_DATA_COLUMN,
- AOP_COLUMN_COUNT
+struct _PidginAccountChooser {
+ GtkComboBox parent;
+
+ PurpleFilterAccountFunc filter_func;
};
enum
{
PROP_0,
PROP_ACCOUNT,
- PROP_SHOW_ALL,
PROP_LAST
};
-/******************************************************************************
- * Structs
- *****************************************************************************/
-
-struct _PidginAccountChooser {
- GtkComboBox parent;
-
- GtkListStore *model;
-
- PurpleFilterAccountFunc filter_func;
- gboolean show_all;
-};
-
-/******************************************************************************
- * Code
- *****************************************************************************/
static GParamSpec *properties[PROP_LAST] = {NULL};
-G_DEFINE_TYPE(PidginAccountChooser, pidgin_account_chooser, GTK_TYPE_COMBO_BOX)
-
-static gpointer
-account_chooser_get_selected(PidginAccountChooser *chooser)
-{
- gpointer data = NULL;
- GtkTreeIter iter;
-
- if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(chooser), &iter)) {
- gtk_tree_model_get(
- gtk_combo_box_get_model(GTK_COMBO_BOX(chooser)), &iter,
- AOP_DATA_COLUMN, &data, -1);
- }
-
- return data;
-}
-
-static void
-account_chooser_select_by_data(GtkWidget *chooser, gpointer data)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- gpointer iter_data;
- model = gtk_combo_box_get_model(GTK_COMBO_BOX(chooser));
- if (gtk_tree_model_get_iter_first(model, &iter)) {
- do {
- gtk_tree_model_get(model, &iter, AOP_DATA_COLUMN,
- &iter_data, -1);
- if (iter_data == data) {
- gtk_combo_box_set_active_iter(
- GTK_COMBO_BOX(chooser), &iter);
- return;
- }
- } while (gtk_tree_model_iter_next(model, &iter));
- }
-}
-
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
static void
-set_account_menu(PidginAccountChooser *chooser, PurpleAccount *default_account)
-{
- PurpleAccount *account;
- GdkPixbuf *pixbuf = NULL;
- GList *list;
- GList *p;
- GtkTreeIter iter;
- gint default_item = 0;
- gint i;
- gchar buf[256];
-
- if (chooser->show_all) {
- list = purple_accounts_get_all();
- } else {
- list = purple_connections_get_all();
- }
-
- gtk_list_store_clear(chooser->model);
- for (p = list, i = 0; p != NULL; p = p->next, i++) {
- if (chooser->show_all) {
- account = (PurpleAccount *)p->data;
- } else {
- PurpleConnection *gc = (PurpleConnection *)p->data;
-
- account = purple_connection_get_account(gc);
- }
-
- if (chooser->filter_func && !chooser->filter_func(account)) {
- i--;
- continue;
- }
-
- pixbuf = pidgin_create_protocol_icon(
- account, PIDGIN_PROTOCOL_ICON_SMALL);
-
- if (pixbuf) {
- if (purple_account_is_disconnected(account) &&
- chooser->show_all && purple_connections_get_all()) {
- gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf,
- 0.0, FALSE);
- }
- }
-
- if (purple_account_get_private_alias(account)) {
- g_snprintf(buf, sizeof(buf), "%s (%s) (%s)",
- purple_account_get_username(account),
- purple_account_get_private_alias(account),
- purple_account_get_protocol_name(account));
- } else {
- g_snprintf(buf, sizeof(buf), "%s (%s)",
- purple_account_get_username(account),
- purple_account_get_protocol_name(account));
- }
-
- gtk_list_store_append(chooser->model, &iter);
- gtk_list_store_set(chooser->model, &iter, AOP_ICON_COLUMN,
- pixbuf, AOP_NAME_COLUMN, buf,
- AOP_DATA_COLUMN, account, -1);
-
- if (pixbuf) {
- g_object_unref(pixbuf);
- }
-
- if (default_account && account == default_account) {
- default_item = i;
- }
- }
-
- gtk_combo_box_set_active(GTK_COMBO_BOX(chooser), default_item);
-}
-
-static void
-regenerate_account_menu(PidginAccountChooser *chooser)
-{
- PurpleAccount *account;
-
- account = (PurpleAccount *)account_chooser_get_selected(chooser);
-
- set_account_menu(chooser, account);
-}
-
-static void
-account_menu_sign_on_off_cb(PurpleConnection *gc, PidginAccountChooser *chooser)
-{
- regenerate_account_menu(chooser);
-}
-
-static void
-account_menu_added_removed_cb(PurpleAccount *account,
- PidginAccountChooser *chooser)
-{
- regenerate_account_menu(chooser);
-}
-
-static gboolean
-account_menu_destroyed_cb(GtkWidget *chooser, GdkEvent *event, void *user_data)
-{
- purple_signals_disconnect_by_handle(chooser);
-
- return FALSE;
-}
-
-static void
-pidgin_account_chooser_changed_cb(GtkComboBox *widget, gpointer user_data)
-{
+pidgin_account_chooser_changed_cb(GtkComboBox *widget, gpointer user_data) {
g_object_notify_by_pspec(G_OBJECT(widget), properties[PROP_ACCOUNT]);
}
/******************************************************************************
* GObject implementation
*****************************************************************************/
+G_DEFINE_TYPE(PidginAccountChooser, pidgin_account_chooser, GTK_TYPE_COMBO_BOX)
+
static void
pidgin_account_chooser_get_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
@@ -218,10 +62,7 @@
switch (prop_id) {
case PROP_ACCOUNT:
- g_value_set_object(value, account_chooser_get_selected(chooser));
- break;
- case PROP_SHOW_ALL:
- g_value_set_boolean(value, chooser->show_all);
+ g_value_set_object(value, pidgin_account_chooser_get_selected(chooser));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -237,11 +78,8 @@
switch (prop_id) {
case PROP_ACCOUNT:
- account_chooser_select_by_data(GTK_WIDGET(chooser),
- g_value_get_object(value));
- break;
- case PROP_SHOW_ALL:
- chooser->show_all = g_value_get_boolean(value);
+ pidgin_account_chooser_set_selected(chooser,
+ g_value_get_object(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -263,61 +101,30 @@
"account", "Account", "The account that is currently selected.",
PURPLE_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- properties[PROP_SHOW_ALL] = g_param_spec_boolean(
- "show-all", "Show all",
- "Whether to show all accounts, or just online ones.", FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
-
g_object_class_install_properties(obj_class, PROP_LAST, properties);
/* Widget template */
-
gtk_widget_class_set_template_from_resource(
widget_class, "/im/pidgin/Pidgin/Accounts/chooser.ui");
-
- gtk_widget_class_bind_template_child(widget_class, PidginAccountChooser,
- model);
-
- gtk_widget_class_bind_template_callback(widget_class,
- account_menu_destroyed_cb);
}
static void
-pidgin_account_chooser_init(PidginAccountChooser *chooser)
-{
+pidgin_account_chooser_init(PidginAccountChooser *chooser) {
gtk_widget_init_template(GTK_WIDGET(chooser));
- set_account_menu(chooser, NULL);
-
+ /* this callback emits the notify for the account property */
g_signal_connect(chooser, "changed",
G_CALLBACK(pidgin_account_chooser_changed_cb), NULL);
-
- /* Register the purple sign on/off event callbacks. */
- purple_signal_connect(
- purple_connections_get_handle(), "signed-on", chooser,
- PURPLE_CALLBACK(account_menu_sign_on_off_cb), chooser);
- purple_signal_connect(
- purple_connections_get_handle(), "signed-off", chooser,
- PURPLE_CALLBACK(account_menu_sign_on_off_cb), chooser);
- purple_signal_connect(
- purple_accounts_get_handle(), "account-added", chooser,
- PURPLE_CALLBACK(account_menu_added_removed_cb), chooser);
- purple_signal_connect(
- purple_accounts_get_handle(), "account-removed", chooser,
- PURPLE_CALLBACK(account_menu_added_removed_cb), chooser);
}
/******************************************************************************
* Public API
*****************************************************************************/
GtkWidget *
-pidgin_account_chooser_new(PurpleAccount *default_account, gboolean show_all)
-{
+pidgin_account_chooser_new(void) {
PidginAccountChooser *chooser = NULL;
- chooser = g_object_new(PIDGIN_TYPE_ACCOUNT_CHOOSER, "account",
- default_account, "show-all", show_all, NULL);
+ chooser = g_object_new(PIDGIN_TYPE_ACCOUNT_CHOOSER, NULL);
return GTK_WIDGET(chooser);
}
@@ -329,32 +136,53 @@
g_return_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser));
chooser->filter_func = filter_func;
- regenerate_account_menu(chooser);
}
PurpleAccount *
-pidgin_account_chooser_get_selected(GtkWidget *chooser)
-{
+pidgin_account_chooser_get_selected(PidginAccountChooser *chooser) {
+ GtkTreeIter iter;
+ gpointer account = NULL;
+
g_return_val_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser), NULL);
- return (PurpleAccount *)account_chooser_get_selected(
- PIDGIN_ACCOUNT_CHOOSER(chooser));
+ if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(chooser), &iter)) {
+ GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(chooser));
+ gtk_tree_model_get(model, &iter,
+ PIDGIN_ACCOUNT_STORE_COLUMN_ACCOUNT, &account, -1);
+ }
+
+ return account;
}
void
-pidgin_account_chooser_set_selected(GtkWidget *chooser, PurpleAccount *account)
+pidgin_account_chooser_set_selected(PidginAccountChooser *chooser,
+ PurpleAccount *account)
{
+ GtkTreeModel *model = NULL;
+ GtkTreeIter iter;
+ PurpleAccount *acc = NULL;
+
g_return_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser));
- account_chooser_select_by_data(chooser, account);
+ model = gtk_combo_box_get_model(GTK_COMBO_BOX(chooser));
+ g_return_if_fail(GTK_IS_TREE_MODEL(model));
- /* NOTE: Property notification occurs in 'changed' signal callback. */
+ if(gtk_tree_model_get_iter_first(model, &iter)) {
+ do {
+ gtk_tree_model_get(model, &iter,
+ PIDGIN_ACCOUNT_STORE_COLUMN_ACCOUNT, &acc, -1);
+ if(acc == account) {
+ /* NOTE: Property notification occurs in 'changed' signal
+ * callback.
+ */
+ gtk_combo_box_set_active_iter(GTK_COMBO_BOX(chooser), &iter);
+
+ g_object_unref(G_OBJECT(acc));
+
+ return;
+ }
+ g_object_unref(G_OBJECT(acc));
+ } while(gtk_tree_model_iter_next(model, &iter));
+ }
}
-gboolean
-pidgin_account_chooser_get_show_all(GtkWidget *chooser)
-{
- g_return_val_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser), FALSE);
-
- return PIDGIN_ACCOUNT_CHOOSER(chooser)->show_all;
-}
--- a/pidgin/pidginaccountchooser.h Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/pidginaccountchooser.h Tue Sep 15 21:54:10 2020 -0500
@@ -45,8 +45,6 @@
/**
* pidgin_account_chooser_new:
- * @default_account: The account to select by default.
- * @show_all: Whether or not to show all accounts, or just active accounts.
*
* Creates a combo box filled with accounts.
*
@@ -54,8 +52,7 @@
*
* Since: 3.0.0
*/
-GtkWidget *pidgin_account_chooser_new(PurpleAccount *default_account,
- gboolean show_all);
+GtkWidget *pidgin_account_chooser_new(void);
/**
* pidgin_account_chooser_set_filter_func:
@@ -76,12 +73,12 @@
*
* Gets the currently selected account from an account combo box.
*
- * Returns: (transfer none): Returns the #PurpleAccount that is currently
+ * Returns: (transfer full): Returns the #PurpleAccount that is currently
* selected.
*
* Since: 3.0.0
*/
-PurpleAccount *pidgin_account_chooser_get_selected(GtkWidget *chooser);
+PurpleAccount *pidgin_account_chooser_get_selected(PidginAccountChooser *chooser);
/**
* pidgin_account_chooser_set_selected:
@@ -92,21 +89,9 @@
*
* Since: 3.0.0
*/
-void pidgin_account_chooser_set_selected(GtkWidget *chooser,
+void pidgin_account_chooser_set_selected(PidginAccountChooser *chooser,
PurpleAccount *account);
-/**
- * pidgin_account_chooser_get_show_all:
- * @chooser: The chooser created by pidgin_account_chooser_new().
- *
- * Returns whether to show all accounts.
- *
- * Returns: Whether or not to show all accounts, or just active accounts.
- *
- * Since: 3.0.0
- */
-gboolean pidgin_account_chooser_get_show_all(GtkWidget *chooser);
-
G_END_DECLS
#endif /* PIDGIN_ACCOUNT_CHOOSER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginaccountfilterconnected.c Tue Sep 15 21:54:10 2020 -0500
@@ -0,0 +1,123 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pidgin/pidginaccountfilterconnected.h"
+
+#include "pidgin/pidginaccountstore.h"
+
+#include <purple.h>
+
+struct _PidginAccountFilterConnected {
+ GtkTreeModelFilter parent;
+};
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+static void
+pidgin_account_filter_connected_changed(PurpleConnection *connection,
+ gpointer data)
+{
+ PidginAccountFilterConnected *filter = NULL;
+
+ filter = PIDGIN_ACCOUNT_FILTER_CONNECTED(data);
+
+ gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(filter));
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+static gboolean
+pidgin_account_filter_connected_func(GtkTreeModel *model, GtkTreeIter *iter,
+ gpointer data)
+{
+ PurpleAccount *account = NULL;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail(GTK_IS_TREE_MODEL(model), FALSE);
+ g_return_val_if_fail(iter != NULL, FALSE);
+
+ gtk_tree_model_get(model, iter, PIDGIN_ACCOUNT_STORE_COLUMN_ACCOUNT,
+ &account, -1);
+
+ if(!PURPLE_IS_ACCOUNT(account)) {
+ return FALSE;
+ }
+
+ ret = purple_account_is_connected(account);
+
+ g_object_unref(G_OBJECT(account));
+
+ return ret;
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_TYPE(PidginAccountFilterConnected, pidgin_account_filter_connected,
+ GTK_TYPE_TREE_MODEL_FILTER)
+
+static void
+pidgin_account_filter_connected_init(PidginAccountFilterConnected *filter) {
+ gpointer connections_handle = NULL;
+
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
+ pidgin_account_filter_connected_func,
+ NULL, NULL);
+
+ /* we connect to the connections signals to force a refresh of the filter */
+ connections_handle = purple_connections_get_handle();
+ purple_signal_connect(connections_handle, "signed-on", filter,
+ G_CALLBACK(pidgin_account_filter_connected_changed),
+ filter);
+ purple_signal_connect(connections_handle, "signed-off", filter,
+ G_CALLBACK(pidgin_account_filter_connected_changed),
+ filter);
+}
+
+static void
+pidgin_account_filter_connected_finalize(GObject *obj) {
+ purple_signals_disconnect_by_handle(obj);
+
+ G_OBJECT_CLASS(pidgin_account_filter_connected_parent_class)->finalize(obj);
+}
+
+static void
+pidgin_account_filter_connected_class_init(PidginAccountFilterConnectedClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ obj_class->finalize = pidgin_account_filter_connected_finalize;
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GtkTreeModel *
+pidgin_account_filter_connected_new(GtkTreeModel *child_model,
+ GtkTreePath *root)
+{
+ g_return_val_if_fail(GTK_IS_TREE_MODEL(child_model), NULL);
+
+ return g_object_new(PIDGIN_TYPE_ACCOUNT_FILTER_CONNECTED, "child-model",
+ child_model, "virtual-root", root, NULL);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginaccountfilterconnected.h Tue Sep 15 21:54:10 2020 -0500
@@ -0,0 +1,60 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PIDGIN_ACCOUNT_FILTER_CONNECTED_H
+#define PIDGIN_ACCOUNT_FILTER_CONNECTED_H
+
+/**
+ * SECTION:pidginaccountfilterconnected
+ * @section_id: pidgin-account-filter-connected
+ * @short_description: A GtkTreeModelFilter that displays connected accounts.
+ * @title: Account Connected Filter
+ *
+ * #PidginAccountFilterConnected is a #GtkTreeModelFilter that will only show
+ * accounts that are connected. It's intended to be used with
+ * #PidginAccountStore.
+ */
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define PIDGIN_TYPE_ACCOUNT_FILTER_CONNECTED pidgin_account_filter_connected_get_type()
+G_DECLARE_FINAL_TYPE(PidginAccountFilterConnected,
+ pidgin_account_filter_connected, PIDGIN,
+ ACCOUNT_FILTER_CONNECTED, GtkTreeModelFilter)
+
+/**
+ * pidgin_account_filter_connected_new:
+ *
+ * Creates a new #PidginAccountFilterConnected that should be used to filter
+ * only online accounts in a #PidginAccountStore.
+ *
+ * Returns: (transfer full): The new #PidginAccountFilterConnected instance.
+ *
+ * Since: 3.0.0
+ */
+GtkTreeModel *pidgin_account_filter_connected_new(GtkTreeModel *child_model, GtkTreePath *root);
+
+G_END_DECLS
+
+#endif /* PIDGIN_ACCOUNT_FILTER_CONNECTED_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginaccountfilterprotocol.c Tue Sep 15 21:54:10 2020 -0500
@@ -0,0 +1,183 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pidgin/pidginaccountfilterprotocol.h"
+
+#include "pidgin/pidginaccountstore.h"
+
+#include <purple.h>
+
+struct _PidginAccountFilterProtocol {
+ GtkTreeModelFilter parent;
+
+ gchar *protocol_id;
+};
+
+enum {
+ PROP_0,
+ PROP_PROTOCOL_ID,
+ N_PROPERTIES
+};
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+pidgin_account_filter_protocol_set_protocol_id(PidginAccountFilterProtocol *filter,
+ const gchar *protocol_id)
+{
+ g_free(filter->protocol_id);
+ filter->protocol_id = g_strdup(protocol_id);
+}
+
+static gboolean
+pidgin_account_filter_protocol_func(GtkTreeModel *model, GtkTreeIter *iter,
+ gpointer data)
+{
+ PidginAccountFilterProtocol *filter = NULL;
+ PurpleAccount *account = NULL;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail(PIDGIN_IS_ACCOUNT_FILTER_PROTOCOL(data), FALSE);
+ g_return_val_if_fail(GTK_IS_TREE_MODEL(model), FALSE);
+ g_return_val_if_fail(iter != NULL, FALSE);
+
+ filter = PIDGIN_ACCOUNT_FILTER_PROTOCOL(data);
+
+ gtk_tree_model_get(model, iter, PIDGIN_ACCOUNT_STORE_COLUMN_ACCOUNT,
+ &account, -1);
+
+ if(!PURPLE_IS_ACCOUNT(account)) {
+ return FALSE;
+ }
+
+ ret = purple_strequal(purple_account_get_protocol_id(account),
+ filter->protocol_id);
+
+ g_object_unref(G_OBJECT(account));
+
+ return ret;
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_TYPE(PidginAccountFilterProtocol, pidgin_account_filter_protocol,
+ GTK_TYPE_TREE_MODEL_FILTER)
+
+static void
+pidgin_account_filter_protocol_get_property(GObject *obj, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ PidginAccountFilterProtocol *filter = PIDGIN_ACCOUNT_FILTER_PROTOCOL(obj);
+
+ switch(param_id) {
+ case PROP_PROTOCOL_ID:
+ g_value_set_string(
+ value, pidgin_account_filter_protocol_get_protocol_id(filter));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+pidgin_account_filter_protocol_set_property(GObject *obj, guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PidginAccountFilterProtocol *filter = PIDGIN_ACCOUNT_FILTER_PROTOCOL(obj);
+
+ switch(param_id) {
+ case PROP_PROTOCOL_ID:
+ pidgin_account_filter_protocol_set_protocol_id(
+ filter, g_value_get_string(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+pidgin_account_filter_protocol_finalize(GObject *obj) {
+ PidginAccountFilterProtocol *filter = PIDGIN_ACCOUNT_FILTER_PROTOCOL(obj);
+
+ g_free(filter->protocol_id);
+
+ G_OBJECT_CLASS(pidgin_account_filter_protocol_parent_class)->finalize(obj);
+}
+
+static void
+pidgin_account_filter_protocol_init(PidginAccountFilterProtocol *filter) {
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
+ pidgin_account_filter_protocol_func,
+ filter, NULL);
+}
+
+static void
+pidgin_account_filter_protocol_class_init(PidginAccountFilterProtocolClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ obj_class->get_property = pidgin_account_filter_protocol_get_property;
+ obj_class->set_property = pidgin_account_filter_protocol_set_property;
+ obj_class->finalize = pidgin_account_filter_protocol_finalize;
+
+ /**
+ * PidginAccountFilterProtocol::protocol-id:
+ *
+ * The protocol id that will be filtered for.
+ */
+ properties[PROP_PROTOCOL_ID] = g_param_spec_string(
+ "protocol-id", "protocol-id", "The id of the protocol to filter",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GtkTreeModel *
+pidgin_account_filter_protocol_new(const gchar *protocol_id,
+ GtkTreeModel *child_model,
+ GtkTreePath *root)
+{
+ g_return_val_if_fail(GTK_IS_TREE_MODEL(child_model), NULL);
+
+ return g_object_new(
+ PIDGIN_TYPE_ACCOUNT_FILTER_PROTOCOL,
+ "protocol-id", protocol_id,
+ "child-model", child_model,
+ "virtual-root", root,
+ NULL);
+}
+
+const gchar *
+pidgin_account_filter_protocol_get_protocol_id(PidginAccountFilterProtocol *filter) {
+ g_return_val_if_fail(PIDGIN_IS_ACCOUNT_FILTER_PROTOCOL(filter), NULL);
+
+ return filter->protocol_id;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginaccountfilterprotocol.h Tue Sep 15 21:54:10 2020 -0500
@@ -0,0 +1,75 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PIDGIN_ACCOUNT_FILTER_PROTOCOL_H
+#define PIDGIN_ACCOUNT_FILTER_PROTOCOL_H
+
+/**
+ * SECTION:pidginaccountfilterprotocol
+ * @section_id: pidgin-account-filter-protocol
+ * @short_description: A GtkTreeModelFilter that displays the given protocol.
+ * @title: Account Protocol Filter
+ *
+ * #PidginAccountFilterProtocol is a #GtkTreeModelFilter that will only show
+ * accounts for the given protocol. It's intended to be used with
+ * #PidginAccountStore.
+ */
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define PIDGIN_TYPE_ACCOUNT_FILTER_PROTOCOL pidgin_account_filter_protocol_get_type()
+G_DECLARE_FINAL_TYPE(PidginAccountFilterProtocol,
+ pidgin_account_filter_protocol, PIDGIN,
+ ACCOUNT_FILTER_PROTOCOL, GtkTreeModelFilter)
+
+/**
+ * pidgin_account_filter_protocol_new:
+ * @protocol_id: The ID of the protocol to filter for.
+ * @child_model: The #GtkTreeModel that should be filtered.
+ * @root: The root path that should be filtered.
+ *
+ * Creates a new #PidginAccountFilterProtocol that should be used to filter
+ * only online accounts in a #PidginAccountStore.
+ *
+ * See gtk_tree_model_filter_new() for more information.
+ *
+ * Returns: (transfer full): The new #PidginAccountFilterProtocol instance.
+ *
+ * Since: 3.0.0
+ */
+GtkTreeModel *pidgin_account_filter_protocol_new(const gchar *protocol_id, GtkTreeModel *child_model, GtkTreePath *root);
+
+/**
+ * pidgin_account_filter_protocol_get_protocol_id:
+ * @filter: The #PidginAccountFilterProtocol instance.
+ *
+ * Gets the ID of the protocol that @filter is filtering for.
+ *
+ * Returns: The Protocol ID that @filter is filtering for.
+ */
+const gchar *pidgin_account_filter_protocol_get_protocol_id(PidginAccountFilterProtocol *filter);
+
+G_END_DECLS
+
+#endif /* PIDGIN_ACCOUNT_FILTER_PROTOCOL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginaccountstore.c Tue Sep 15 21:54:10 2020 -0500
@@ -0,0 +1,191 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n-lib.h>
+
+#include "pidgin/pidginaccountstore.h"
+
+#include "gtkutils.h"
+
+struct _PidginAccountStore {
+ GtkListStore parent;
+};
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+pidgin_account_store_add_account(PidginAccountStore *store,
+ PurpleAccount *account)
+{
+ GtkTreeIter iter;
+ GdkPixbuf *pixbuf = NULL;
+ gchar *markup = NULL;
+ const gchar *alias = NULL;
+
+ pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
+
+ alias = purple_account_get_private_alias(account);
+ if(alias != NULL) {
+ markup = g_strdup_printf(_("%s (%s) (%s)"),
+ purple_account_get_username(account),
+ alias,
+ purple_account_get_protocol_name(account));
+ } else {
+ markup = g_strdup_printf(_("%s (%s)"),
+ purple_account_get_username(account),
+ purple_account_get_protocol_name(account));
+ }
+
+ gtk_list_store_append(GTK_LIST_STORE(store), &iter);
+ gtk_list_store_set(
+ GTK_LIST_STORE(store),
+ &iter,
+ PIDGIN_ACCOUNT_STORE_COLUMN_ACCOUNT, account,
+ PIDGIN_ACCOUNT_STORE_COLUMN_MARKUP, markup,
+ PIDGIN_ACCOUNT_STORE_COLUMN_ICON, pixbuf,
+ -1
+ );
+
+ g_clear_object(&pixbuf);
+ g_free(markup);
+}
+
+static void
+pidgin_account_store_add_account_helper(gpointer data, gpointer user_data) {
+ if(PURPLE_IS_ACCOUNT(data)) {
+ pidgin_account_store_add_account(PIDGIN_ACCOUNT_STORE(user_data),
+ PURPLE_ACCOUNT(data));
+ }
+}
+
+static void
+pidgin_account_store_add_accounts(PidginAccountStore *store) {
+ g_list_foreach(purple_accounts_get_all(),
+ pidgin_account_store_add_account_helper, store);
+}
+
+static void
+pidgin_account_store_remove_account(PidginAccountStore *store,
+ PurpleAccount *account)
+{
+ GtkTreeIter iter;
+
+ if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) == FALSE) {
+ purple_debug_warning("account-store",
+ "account %s was removed but not in the store",
+ purple_account_get_username(account));
+ return;
+ }
+
+ /* walk through the store and look for the account to remove */
+ do {
+ PurpleAccount *found = NULL;
+
+ gtk_tree_model_get(
+ GTK_TREE_MODEL(store),
+ &iter,
+ PIDGIN_ACCOUNT_STORE_COLUMN_ACCOUNT, &found,
+ -1
+ );
+
+ if(found == account) {
+ g_object_unref(G_OBJECT(found));
+
+ gtk_list_store_remove(GTK_LIST_STORE(store), &iter);
+
+ return;
+ }
+ } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
+}
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+static void
+pidgin_account_store_account_added_cb(PurpleAccount *account,
+ gpointer data)
+{
+ pidgin_account_store_add_account(PIDGIN_ACCOUNT_STORE(data), account);
+}
+
+static void
+pidgin_account_store_account_removed_cb(PurpleAccount *account,
+ gpointer data)
+{
+ pidgin_account_store_remove_account(PIDGIN_ACCOUNT_STORE(data), account);
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_TYPE(PidginAccountStore, pidgin_account_store, GTK_TYPE_LIST_STORE)
+
+static void
+pidgin_account_store_init(PidginAccountStore *store) {
+ gpointer accounts_handle = NULL;
+ GType types[PIDGIN_ACCOUNT_STORE_N_COLUMNS] = {
+ PURPLE_TYPE_ACCOUNT,
+ G_TYPE_STRING,
+ GDK_TYPE_PIXBUF,
+ };
+
+ gtk_list_store_set_column_types(
+ GTK_LIST_STORE(store),
+ PIDGIN_ACCOUNT_STORE_N_COLUMNS,
+ types
+ );
+
+ /* add the known accounts */
+ pidgin_account_store_add_accounts(store);
+
+ /* add the signal handlers to dynamically add/remove accounts */
+ accounts_handle = purple_accounts_get_handle();
+ purple_signal_connect(accounts_handle, "account-added", store,
+ G_CALLBACK(pidgin_account_store_account_added_cb),
+ store);
+ purple_signal_connect(accounts_handle, "account-removed", store,
+ G_CALLBACK(pidgin_account_store_account_removed_cb),
+ store);
+}
+
+static void
+pidgin_account_store_finalize(GObject *obj) {
+ purple_signals_disconnect_by_handle(obj);
+
+ G_OBJECT_CLASS(pidgin_account_store_parent_class)->finalize(obj);
+}
+
+static void
+pidgin_account_store_class_init(PidginAccountStoreClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ obj_class->finalize = pidgin_account_store_finalize;
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GtkListStore *
+pidgin_account_store_new(void) {
+ return GTK_LIST_STORE(g_object_new(PIDGIN_TYPE_ACCOUNT_STORE, NULL));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginaccountstore.h Tue Sep 15 21:54:10 2020 -0500
@@ -0,0 +1,83 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PIDGIN_ACCOUNT_STORE_H
+#define PIDGIN_ACCOUNT_STORE_H
+
+/**
+ * SECTION:pidginaccountstore
+ * @section_id: pidgin-account-store
+ * @short_description: A GtkListStore that keeps track of accounts
+ * @title: Account Store
+ *
+ * #PidginAccountStore is a #GtkListStore that automatically keeps track of
+ * what accounts are currently available in libpurple. It's intended to be
+ * used any time that you need to present an account selection to the user.
+ */
+
+#include <gtk/gtk.h>
+
+#include <purple.h>
+
+typedef enum {
+ PIDGIN_ACCOUNT_STORE_COLUMN_ACCOUNT,
+ PIDGIN_ACCOUNT_STORE_COLUMN_MARKUP,
+ PIDGIN_ACCOUNT_STORE_COLUMN_ICON,
+ PIDGIN_ACCOUNT_STORE_N_COLUMNS,
+} PidginAccountStoreColumn;
+
+G_BEGIN_DECLS
+
+#define PIDGIN_TYPE_ACCOUNT_STORE pidgin_account_store_get_type()
+G_DECLARE_FINAL_TYPE(PidginAccountStore, pidgin_account_store, PIDGIN,
+ ACCOUNT_STORE, GtkListStore)
+
+/**
+ * pidgin_account_store_new:
+ *
+ * Creates a new #PidginAccountStore that can be used anywhere a #GtkListStore
+ * can be used.
+ *
+ * Returns: (transfer full): The new #PidginAccountStore instance.
+ *
+ * Since: 3.0.0
+ */
+GtkListStore *pidgin_account_store_new(void);
+
+/**
+ * pidgin_account_store_filter_connected:
+ * @model: The #GtkTreeModel that's being filtered.
+ * @iter: The #GtkTreeIter to check.
+ * @data: Userdata passed to gtk_tree_model_filter_set_visible_func().
+ *
+ * pidgin_account_store_filter_connected() is a #GtkTreeModelFilterVisibleFunc
+ * that can be set on a #GtkTreeModelFilter via
+ * gtk_tree_model_filter_set_visible_func(), to only show accounts that are
+ * currently connected.
+ *
+ * Returns: %TRUE if the account will be displayed, %FALSE otherwise.
+ */
+gboolean pidgin_account_store_filter_connected(GtkTreeModel *model, GtkTreeIter *iter, gpointer data);
+
+G_END_DECLS
+
+#endif /* PIDGIN_ACCOUNT_STORE_H */
--- a/pidgin/plugins/contact_priority.c Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/plugins/contact_priority.c Tue Sep 15 21:54:10 2020 -0500
@@ -29,17 +29,19 @@
#define CONTACT_PRIORITY_PLUGIN_ID "gtk-contact-priority"
static void
-select_account(GtkWidget *chooser, gpointer data)
+select_account(GtkWidget *widget, gpointer data)
{
+ PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(widget);
PurpleAccount *account = pidgin_account_chooser_get_selected(chooser);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(data),
(gdouble)purple_account_get_int(account, "score", 0));
}
static void
-account_update(GtkWidget *widget, GtkWidget *chooser)
+account_update(GtkWidget *widget, gpointer data)
{
PurpleAccount *account = NULL;
+ PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(data);
account = pidgin_account_chooser_get_selected(chooser);
purple_account_set_int(account, "score", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)));
@@ -79,6 +81,7 @@
GtkWidget *chooser = NULL;
GtkAdjustment *adj = NULL;
GtkSizeGroup *sg = NULL;
+ GtkListStore *store = NULL;
PurpleAccount *account = NULL;
int i;
@@ -145,12 +148,15 @@
adj = GTK_ADJUSTMENT(gtk_adjustment_new(0, -500, 500, 1, 1, 1));
spin = gtk_spin_button_new(adj, 1, 0);
- chooser = pidgin_account_chooser_new(NULL, TRUE);
+ store = pidgin_account_store_new();
+ chooser = pidgin_account_chooser_new();
+ gtk_combo_box_set_model(GTK_COMBO_BOX(chooser), GTK_TREE_MODEL(store));
+ g_object_unref(G_OBJECT(store));
gtk_box_pack_start(GTK_BOX(hbox), chooser, FALSE, FALSE, 0);
g_signal_connect(chooser, "changed", G_CALLBACK(select_account), spin);
/* this is where we set up the spin button we made above */
- account = pidgin_account_chooser_get_selected(chooser);
+ account = pidgin_account_chooser_get_selected(PIDGIN_ACCOUNT_CHOOSER(chooser));
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin),
(gdouble)purple_account_get_int(account, "score", 0));
gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(spin), GTK_ADJUSTMENT(adj));
--- a/pidgin/plugins/disco/gtkdisco.c Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/plugins/disco/gtkdisco.c Tue Sep 15 21:54:10 2020 -0500
@@ -145,7 +145,7 @@
static void
dialog_select_account_cb(GtkWidget *chooser, PidginDiscoDialog *dialog)
{
- PurpleAccount *account = pidgin_account_chooser_get_selected(chooser);
+ PurpleAccount *account = pidgin_account_chooser_get_selected(PIDGIN_ACCOUNT_CHOOSER(chooser));
gboolean change = (account != dialog->account);
dialog->account = account;
gtk_widget_set_sensitive(dialog->browse_button, account != NULL);
@@ -414,11 +414,6 @@
gtk_widget_destroy(GTK_WIDGET(dialog));
}
-static gboolean account_filter_func(PurpleAccount *account)
-{
- return purple_strequal(purple_account_get_protocol_id(account), XMPP_PROTOCOL_ID);
-}
-
static gboolean
disco_paint_tooltip(GtkWidget *tipwindow, cairo_t *cr, gpointer data)
{
@@ -520,6 +515,8 @@
PidginDiscoList *list = dialog->discolist;
if (list && list->pc == pc) {
+ PurpleAccount *account = NULL;
+
if (list->in_progress)
pidgin_disco_list_set_in_progress(list, FALSE);
@@ -528,10 +525,12 @@
pidgin_disco_list_unref(list);
dialog->discolist = NULL;
+ account = pidgin_account_chooser_get_selected(
+ PIDGIN_ACCOUNT_CHOOSER(dialog->account_chooser));
+
gtk_widget_set_sensitive(
dialog->browse_button,
- pidgin_account_chooser_get_selected(
- dialog->account_chooser) != NULL);
+ account != NULL);
gtk_widget_set_sensitive(dialog->register_button, FALSE);
gtk_widget_set_sensitive(dialog->add_button, FALSE);
@@ -609,11 +608,8 @@
gtk_widget_init_template(GTK_WIDGET(dialog));
/* accounts dropdown list */
- pidgin_account_chooser_set_filter_func(
- PIDGIN_ACCOUNT_CHOOSER(dialog->account_chooser),
- account_filter_func);
- dialog->account =
- pidgin_account_chooser_get_selected(dialog->account_chooser);
+ dialog->account = pidgin_account_chooser_get_selected(
+ PIDGIN_ACCOUNT_CHOOSER(dialog->account_chooser));
/* browse button */
gtk_widget_set_sensitive(dialog->browse_button, dialog->account != NULL);
--- a/pidgin/plugins/disco/resources/disco.ui Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/plugins/disco/resources/disco.ui Tue Sep 15 21:54:10 2020 -0500
@@ -26,6 +26,14 @@
<!-- interface-name Pidgin -->
<!-- interface-description Internet Messenger -->
<!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+ <object class="PidginAccountStore" id="accounts"/>
+ <object class="PidginAccountFilterConnected" id="accounts_connected">
+ <property name="child_model">accounts</property>
+ </object>
+ <object class="PidginAccountFilterProtocol" id="xmpp_accounts">
+ <property name="child_model">accounts_connected</property>
+ <property name="protocol_id">prpl-jabber</property>
+ </object>
<object class="GtkTreeStore" id="model">
<columns>
<!-- column-name pixbuf -->
@@ -168,6 +176,8 @@
<object class="PidginAccountChooser" id="account_chooser">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="model">xmpp_accounts</property>
+ <property name="active">0</property>
<signal name="changed" handler="dialog_select_account_cb" object="PidginDiscoDialog" swapped="no"/>
</object>
<packing>
--- a/pidgin/resources/Accounts/chooser.ui Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/resources/Accounts/chooser.ui Tue Sep 15 21:54:10 2020 -0500
@@ -25,25 +25,13 @@
<!-- interface-name Pidgin -->
<!-- interface-description Internet Messenger -->
<!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
- <object class="GtkListStore" id="model">
- <columns>
- <!-- column-name icon -->
- <column type="GdkPixbuf"/>
- <!-- column-name name -->
- <column type="gchararray"/>
- <!-- column-name account -->
- <column type="PurpleAccount"/>
- </columns>
- </object>
<template class="PidginAccountChooser" parent="GtkComboBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="model">model</property>
- <signal name="destroy" handler="account_menu_destroyed_cb" swapped="no"/>
<child>
<object class="GtkCellRendererPixbuf"/>
<attributes>
- <attribute name="pixbuf">0</attribute>
+ <attribute name="pixbuf">2</attribute>
</attributes>
</child>
<child>
--- a/pidgin/resources/Privacy/dialog.ui Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/resources/Privacy/dialog.ui Tue Sep 15 21:54:10 2020 -0500
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.1
+<!-- Generated with glade 3.22.1
Pidgin - Internet Messenger
Copyright (C) Pidgin Developers <devel@pidgin.im>
@@ -26,6 +26,10 @@
<!-- interface-name Pidgin -->
<!-- interface-description Internet Messenger -->
<!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+ <object class="PidginAccountStore" id="account_store"/>
+ <object class="PidginAccountFilterConnected" id="connected_account_store">
+ <property name="child_model">account_store</property>
+ </object>
<object class="GtkListStore" id="allow_store">
<columns>
<!-- column-name column1 -->
@@ -169,6 +173,8 @@
<object class="PidginAccountChooser" id="account_chooser">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="model">connected_account_store</property>
+ <property name="active">0</property>
<signal name="changed" handler="select_account_cb" object="PidginPrivacyDialog" swapped="no"/>
<accessibility>
<relation type="labelled-by" target="label1"/>
--- a/pidgin/resources/Roomlist/roomlist.ui Tue Sep 15 20:26:57 2020 -0500
+++ b/pidgin/resources/Roomlist/roomlist.ui Tue Sep 15 21:54:10 2020 -0500
@@ -26,6 +26,7 @@
<!-- interface-name Pidgin -->
<!-- interface-description Internet Messenger -->
<!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+ <object class="PidginAccountStore" id="accounts"/>
<object class="GtkImage" id="add_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -179,6 +180,8 @@
<object class="PidginAccountChooser" id="account_widget">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="model">accounts</property>
+ <property name="active">0</property>
<signal name="changed" handler="dialog_select_account_cb" object="PidginRoomlistDialog" swapped="no"/>
<accessibility>
<relation type="labelled-by" target="label1"/>
--- a/po/POTFILES.in Tue Sep 15 20:26:57 2020 -0500
+++ b/po/POTFILES.in Tue Sep 15 21:54:10 2020 -0500
@@ -344,6 +344,9 @@
pidgin/minidialog.c
pidgin/pidginabout.c
pidgin/pidgin.c
+pidgin/pidginaccountfilterconnected.c
+pidgin/pidginaccountfilterprotocol.c
+pidgin/pidginaccountstore.c
pidgin/pidginattachment.c
pidgin/pidginclosebutton.c
pidgin/pidgincontactcompletion.c