pidgin/pidgin

Merged in default (pull request #670)

2020-02-21, Gary Kramlich
0a01f2c891c2
Merged in default (pull request #670)

move PidginProtocolOptionMenu to its own widget

Approved-by: Elliott Sales de Andrade
--- a/ChangeLog.API Fri Feb 14 22:55:41 2020 +0000
+++ b/ChangeLog.API Fri Feb 21 02:45:13 2020 +0000
@@ -439,6 +439,7 @@
* purple_presence_new_for_buddy
* purple_print_utf8_to_console
* PurplePluginProtocolInfo
+ * pidgin_protocol_option_menu_new
* purple_proxy_connect_socks5
* purple_quotedp_decode. See the GMime library if needed.
* purple_request_certificate
--- a/pidgin/gtkaccount.c Fri Feb 14 22:55:41 2020 +0000
+++ b/pidgin/gtkaccount.c Fri Feb 21 02:45:13 2020 +0000
@@ -42,6 +42,7 @@
#include "gtkstatusbox.h"
#include "pidginstock.h"
#include "minidialog.h"
+#include "pidginprotocolchooser.h"
enum
{
@@ -224,41 +225,34 @@
}
static void
-set_account_protocol_cb(GtkWidget *widget, const char *id,
- AccountPrefsDialog *dialog)
-{
- PurpleProtocol *new_protocol;
-
- new_protocol = purple_protocols_find(id);
-
- dialog->protocol = new_protocol;
-
- if (dialog->protocol != NULL)
- {
- PurpleProtocol *old_protocol = NULL;
-
- if (dialog->protocol_id)
- old_protocol = purple_protocols_find(dialog->protocol_id);
-
- if (old_protocol != new_protocol) {
- g_free(dialog->protocol_id);
- dialog->protocol_id = g_strdup(purple_protocol_get_id(dialog->protocol));
- }
+set_account_protocol_cb(GtkWidget *widget, AccountPrefsDialog *dialog) {
+ PidginProtocolChooser *chooser = PIDGIN_PROTOCOL_CHOOSER(widget);
+ PurpleProtocol *protocol = pidgin_protocol_chooser_get_selected(chooser);
+
+ if(g_set_object(&dialog->protocol, protocol)) {
+ g_clear_pointer(&dialog->protocol_id, g_free);
}
-
- if (dialog->account != NULL)
+ g_object_unref(G_OBJECT(protocol));
+
+ if(PURPLE_IS_PROTOCOL(dialog->protocol)) {
+ dialog->protocol_id = g_strdup(purple_protocol_get_id(dialog->protocol));
+ }
+
+ if (dialog->account != NULL) {
purple_account_clear_settings(dialog->account);
-
- add_login_options(dialog, dialog->top_vbox);
- add_user_options(dialog, dialog->top_vbox);
+ }
+
+ add_login_options(dialog, dialog->top_vbox);
+ add_user_options(dialog, dialog->top_vbox);
add_account_options(dialog);
add_voice_options(dialog);
gtk_widget_grab_focus(dialog->protocol_menu);
- if (!dialog->protocol || !PURPLE_PROTOCOL_IMPLEMENTS(dialog->protocol, SERVER, register_user)) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
- dialog->register_button), FALSE);
+ if (!dialog->protocol ||
+ !PURPLE_PROTOCOL_IMPLEMENTS(dialog->protocol, SERVER, register_user))
+ {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->register_button), FALSE);
gtk_widget_hide(dialog->register_button);
} else {
if (purple_protocol_get_options(dialog->protocol) &
@@ -478,10 +472,12 @@
gtk_widget_show(vbox);
/* Protocol */
- if (dialog->protocol_menu == NULL)
- {
- dialog->protocol_menu = pidgin_protocol_option_menu_new(
- dialog->protocol_id, G_CALLBACK(set_account_protocol_cb), dialog);
+ if(dialog->protocol_menu == NULL) {
+ dialog->protocol_menu = pidgin_protocol_chooser_new();
+ gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->protocol_menu), 0);
+ g_signal_connect(G_OBJECT(dialog->protocol_menu), "changed",
+ G_CALLBACK(set_account_protocol_cb), dialog);
+ gtk_widget_show(dialog->protocol_menu);
g_object_ref(G_OBJECT(dialog->protocol_menu));
}
--- a/pidgin/gtkutils.c Fri Feb 14 22:55:41 2020 +0000
+++ b/pidgin/gtkutils.c Fri Feb 21 02:45:13 2020 +0000
@@ -440,25 +440,7 @@
return data;
}
-static void
-aop_menu_cb(GtkWidget *optmenu, GCallback cb)
-{
- if (cb != NULL) {
- ((void (*)(GtkWidget *, gpointer, gpointer))cb)(optmenu,
- aop_option_menu_get_selected(optmenu),
- g_object_get_data(G_OBJECT(optmenu), "user_data"));
- }
-}
-
-static void
-aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu)
-{
- gtk_combo_box_set_model(GTK_COMBO_BOX(optmenu), new_aop_menu->model);
- gtk_combo_box_set_active(GTK_COMBO_BOX(optmenu), new_aop_menu->default_item);
- g_free(new_aop_menu);
-}
-
-static GdkPixbuf *
+GdkPixbuf *
pidgin_create_icon_from_protocol(PurpleProtocol *protocol, PidginProtocolIconSize size, PurpleAccount *account)
{
const char *protoname = NULL;
@@ -490,27 +472,6 @@
return pixbuf;
}
-static GtkWidget *
-aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data)
-{
- GtkWidget *optmenu = NULL;
- GtkCellRenderer *cr = NULL;
-
- optmenu = gtk_combo_box_new();
- gtk_widget_show(optmenu);
- gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_pixbuf_new(), FALSE);
- gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "pixbuf", AOP_ICON_COLUMN);
- gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_text_new(), TRUE);
- gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "text", AOP_NAME_COLUMN);
-
- aop_option_menu_replace_menu(optmenu, aop_menu);
- g_object_set_data(G_OBJECT(optmenu), "user_data", user_data);
-
- g_signal_connect(G_OBJECT(optmenu), "changed", G_CALLBACK(aop_menu_cb), cb);
-
- return optmenu;
-}
-
static void
aop_option_menu_select_by_data(GtkWidget *optmenu, gpointer data)
{
@@ -529,58 +490,6 @@
}
}
-static AopMenu *
-create_protocols_menu(const char *default_proto_id)
-{
- AopMenu *aop_menu = NULL;
- PurpleProtocol *protocol;
- GdkPixbuf *pixbuf = NULL;
- GtkTreeIter iter;
- GtkListStore *ls;
- GList *list, *p;
- int i;
-
- ls = gtk_list_store_new(AOP_COLUMN_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
-
- aop_menu = g_malloc0(sizeof(AopMenu));
- aop_menu->default_item = 0;
- aop_menu->model = GTK_TREE_MODEL(ls);
-
- list = purple_protocols_get_all();
-
- for (p = list, i = 0;
- p != NULL;
- p = p->next, i++) {
-
- protocol = PURPLE_PROTOCOL(p->data);
-
- pixbuf = pidgin_create_icon_from_protocol(protocol, PIDGIN_PROTOCOL_ICON_SMALL, NULL);
-
- gtk_list_store_append(ls, &iter);
- gtk_list_store_set(ls, &iter,
- AOP_ICON_COLUMN, pixbuf,
- AOP_NAME_COLUMN, purple_protocol_get_name(protocol),
- AOP_DATA_COLUMN, purple_protocol_get_id(protocol),
- -1);
-
- if (pixbuf)
- g_object_unref(pixbuf);
-
- if (default_proto_id != NULL && purple_strequal(purple_protocol_get_id(protocol), default_proto_id))
- aop_menu->default_item = i;
- }
- g_list_free(list);
-
- return aop_menu;
-}
-
-GtkWidget *
-pidgin_protocol_option_menu_new(const char *id, GCallback cb,
- gpointer user_data)
-{
- return aop_option_menu_new(create_protocols_menu(id), cb, user_data);
-}
-
const char *
pidgin_protocol_option_menu_get_selected(GtkWidget *optmenu)
{
--- a/pidgin/gtkutils.h Fri Feb 14 22:55:41 2020 +0000
+++ b/pidgin/gtkutils.h Fri Feb 21 02:45:13 2020 +0000
@@ -259,20 +259,6 @@
GtkWidget *pidgin_make_frame(GtkWidget *parent, const char *title);
/**
- * pidgin_protocol_option_menu_new:
- * @id: The protocol to select by default.
- * @cb: (scope call): The callback to call when a protocol is selected.
- * @user_data: Data to pass to the callback function.
- *
- * Creates a drop-down option menu filled with protocols.
- *
- * Returns: (transfer full): The drop-down option menu.
- */
-GtkWidget *pidgin_protocol_option_menu_new(const char *id,
- GCallback cb,
- gpointer user_data);
-
-/**
* pidgin_protocol_option_menu_get_selected:
* @optmenu: The drop-down option menu created by
* pidgin_protocol_option_menu_new().
@@ -457,6 +443,27 @@
GdkPixbuf *pidgin_create_protocol_icon(PurpleAccount *account, PidginProtocolIconSize size);
/**
+ * pidgin_create_icon_from_protocol:
+ * @protocol: The #PurpleProtocol instance.
+ * @size: The size of the icon to return.
+ * @account: (nullable): An optional #PurpleAccount to use.
+ *
+ * Returns the base image to represent @protocol based on the currently
+ * selected theme. If @account is not %NULL then the returned icon will
+ * represent the account.
+ *
+ * Returns: (transfer full): A newly-created pixbuf with a reference count of 1,
+ * or NULL if any of several error conditions occurred:
+ * the file could not be opened, there was no loader
+ * for the file's format, there was not enough memory
+ * to allocate the image buffer, or the image file
+ * contained invalid data.
+ *
+ * Since: 3.0.0
+ */
+GdkPixbuf *pidgin_create_icon_from_protocol(PurpleProtocol *protocol, PidginProtocolIconSize size, PurpleAccount *account);
+
+/**
* pidgin_create_status_icon:
* @primitive: The status primitive
* @w: The widget to render this
--- a/pidgin/meson.build Fri Feb 14 22:55:41 2020 +0000
+++ b/pidgin/meson.build Fri Feb 21 02:45:13 2020 +0000
@@ -44,6 +44,8 @@
'pidginmessage.c',
'pidginplugininfo.c',
'pidginpluginsdialog.c',
+ 'pidginprotocolchooser.c',
+ 'pidginprotocolstore.c',
'pidgintalkatu.c',
'pidgintooltip.c',
]
@@ -96,6 +98,8 @@
'pidginmessage.h',
'pidginplugininfo.h',
'pidginpluginsdialog.h',
+ 'pidginprotocolchooser.h',
+ 'pidginprotocolstore.h',
'pidgintalkatu.h',
'pidgintooltip.h',
'pidgin.h',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginprotocolchooser.c Fri Feb 21 02:45:13 2020 +0000
@@ -0,0 +1,128 @@
+/*
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#include "pidginprotocolchooser.h"
+
+#include "pidginprotocolstore.h"
+
+/******************************************************************************
+ * Structs
+ *****************************************************************************/
+
+struct _PidginProtocolChooser {
+ GtkComboBox parent;
+
+ GtkListStore *model;
+};
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_TYPE(PidginProtocolChooser, pidgin_protocol_chooser,
+ GTK_TYPE_COMBO_BOX)
+
+static void
+pidgin_protocol_chooser_class_init(PidginProtocolChooserClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+
+ gtk_widget_class_set_template_from_resource(widget_class,
+ "/im/pidgin/Pidgin/Protocols/chooser.ui");
+
+ gtk_widget_class_bind_template_child(widget_class, PidginProtocolChooser,
+ model);
+}
+
+static void
+pidgin_protocol_chooser_init(PidginProtocolChooser *chooser) {
+ gtk_widget_init_template(GTK_WIDGET(chooser));
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+GtkWidget *
+pidgin_protocol_chooser_new(void) {
+ return GTK_WIDGET(g_object_new(PIDGIN_TYPE_PROTOCOL_CHOOSER, NULL));
+}
+
+PurpleProtocol *
+pidgin_protocol_chooser_get_selected(PidginProtocolChooser *chooser) {
+ GtkTreeIter iter;
+ PurpleProtocol *protocol = NULL;
+
+ g_return_val_if_fail(PIDGIN_IS_PROTOCOL_CHOOSER(chooser), NULL);
+
+ if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(chooser), &iter)) {
+ gtk_tree_model_get(GTK_TREE_MODEL(chooser->model), &iter,
+ PIDGIN_PROTOCOL_STORE_COLUMN_PROTOCOL, &protocol,
+ -1);
+ }
+
+ return protocol;
+}
+
+gchar *
+pidgin_protocol_chooser_get_selected_name(PidginProtocolChooser *chooser) {
+ GtkTreeIter iter;
+ gchar *name = NULL;
+
+ g_return_val_if_fail(PIDGIN_IS_PROTOCOL_CHOOSER(chooser), NULL);
+
+ if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(chooser), &iter)) {
+ gtk_tree_model_get(GTK_TREE_MODEL(chooser->model), &iter,
+ PIDGIN_PROTOCOL_STORE_COLUMN_NAME, &name,
+ -1);
+ }
+
+ return name;
+}
+
+void
+pidgin_protocol_chooser_set_selected_name(PidginProtocolChooser *chooser,
+ const gchar *name)
+{
+ GtkTreeIter iter;
+ gchar *iter_name = NULL;
+
+ g_return_if_fail(PIDGIN_IS_PROTOCOL_CHOOSER(chooser));
+
+ if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(chooser->model), &iter)) {
+ do {
+ gtk_tree_model_get(GTK_TREE_MODEL(chooser->model), &iter,
+ PIDGIN_PROTOCOL_STORE_COLUMN_NAME, &iter_name,
+ -1);
+
+ if(purple_strequal(iter_name, name)) {
+ gtk_combo_box_set_active_iter(GTK_COMBO_BOX(chooser), &iter);
+
+ g_free(iter_name);
+
+ return;
+ }
+
+ g_free(iter_name);
+ } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(chooser->model),
+ &iter));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginprotocolchooser.h Fri Feb 21 02:45:13 2020 +0000
@@ -0,0 +1,95 @@
+/*
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#ifndef PIDGIN_PROTOCOL_CHOOSER_H
+#define PIDGIN_PROTOCOL_CHOOSER_H
+
+/**
+ * SECTION:pidginprotocolchooser
+ * @section_id: pidgin-protocol-chooser
+ * @short_description: A #GtkComboBox for choosing protocols
+ * @title: Pidgin Protocol Chooser Combo Box Widget
+ */
+
+#include <gtk/gtk.h>
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+#define PIDGIN_TYPE_PROTOCOL_CHOOSER (pidgin_protocol_chooser_get_type())
+
+G_DECLARE_FINAL_TYPE(PidginProtocolChooser, pidgin_protocol_chooser, PIDGIN,
+ PROTOCOL_CHOOSER, GtkComboBox)
+
+/**
+ * pidgin_protocol_chooser_new:
+ *
+ * Creates a combo box for a user to select a protocol from.
+ *
+ * Returns: (transfer full): The protocol chooser combo box.
+ *
+ * Since: 3.0.0
+ */
+GtkWidget *pidgin_protocol_chooser_new(void);
+
+/**
+ * pidgin_protocol_chooser_get_selected:
+ * @chooser: The #PidginProtocolChooser instance.
+ *
+ * Gets the currently selected protocol from @chooser.
+ *
+ * Returns: (transfer full): The selected #PurpleProtocol or %NULL if nothing
+ * is selected
+ *
+ * Since: 3.0.0
+ */
+PurpleProtocol *pidgin_protocol_chooser_get_selected(PidginProtocolChooser *chooser);
+
+/**
+ * pidgin_protocol_chooser_get_selected_name:
+ * @chooser: The #PidginProtocolChooser instance.
+ *
+ * Gets the name of the currently selected protocol from @chooser.
+ *
+ * Returns: (transfer full): The selected #PurpleProtocol or %NULL if nothing
+ * is selected
+ *
+ * Since: 3.0.0
+ */
+gchar *pidgin_protocol_chooser_get_selected_name(PidginProtocolChooser *chooser);
+
+/**
+ * pidgin_protocol_chooser_set_selected_name:
+ * @chooser: The #PidginProtocolChooser instance.
+ * @name: The name of the protocol to select.
+ *
+ * Sets the currently selected protocol of @chooser to @protocol.
+ *
+ * Since: 3.0.0
+ */
+void pidgin_protocol_chooser_set_selected_name(PidginProtocolChooser *chooser, const gchar *name);
+
+G_END_DECLS
+
+#endif /* PIDGIN_PROTOCOL_CHOOSER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginprotocolstore.c Fri Feb 21 02:45:13 2020 +0000
@@ -0,0 +1,176 @@
+/*
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#include "pidgin/pidginprotocolstore.h"
+
+#include "gtkutils.h"
+
+struct _PidginProtocolStore {
+ GtkListStore parent;
+};
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+pidgin_protocol_store_add_protocol(PidginProtocolStore *store,
+ PurpleProtocol *protocol)
+{
+ GtkTreeIter iter;
+ GdkPixbuf *pixbuf = NULL;
+
+ pixbuf = pidgin_create_icon_from_protocol(protocol,
+ PIDGIN_PROTOCOL_ICON_SMALL, NULL);
+
+ gtk_list_store_append(GTK_LIST_STORE(store), &iter);
+ gtk_list_store_set(
+ GTK_LIST_STORE(store),
+ &iter,
+ PIDGIN_PROTOCOL_STORE_COLUMN_PROTOCOL, protocol,
+ PIDGIN_PROTOCOL_STORE_COLUMN_NAME, purple_protocol_get_name(protocol),
+ PIDGIN_PROTOCOL_STORE_COLUMN_ICON, pixbuf,
+ -1
+ );
+
+ g_clear_object(&pixbuf);
+}
+
+static void
+pidgin_protocol_store_add_protocol_helper(gpointer data, gpointer user_data) {
+ if(PURPLE_IS_PROTOCOL(data)) {
+ pidgin_protocol_store_add_protocol(PIDGIN_PROTOCOL_STORE(user_data),
+ PURPLE_PROTOCOL(data));
+ }
+}
+
+static void
+pidgin_protocol_store_add_protocols(PidginProtocolStore *store) {
+ g_list_foreach(purple_protocols_get_all(),
+ pidgin_protocol_store_add_protocol_helper, store);
+}
+
+static void
+pidgin_protocol_store_remove_protocol(PidginProtocolStore *store,
+ PurpleProtocol *protocol)
+{
+ GtkTreeIter iter;
+
+ if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) == FALSE) {
+ purple_debug_warning("protocol-store",
+ "protocol %s was removed but not in the store",
+ purple_protocol_get_name(protocol));
+ return;
+ }
+
+ /* walk through the store and look for the protocol to remove */
+ do {
+ PurpleProtocol *prpl = NULL;
+
+ gtk_tree_model_get(
+ GTK_TREE_MODEL(store),
+ &iter,
+ PIDGIN_PROTOCOL_STORE_COLUMN_PROTOCOL, &prpl,
+ -1
+ );
+
+ if(prpl == protocol) {
+ g_object_unref(G_OBJECT(prpl));
+
+ 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_protocol_store_protocol_added_cb(PurpleProtocol *protocol,
+ gpointer data)
+{
+ pidgin_protocol_store_add_protocol(PIDGIN_PROTOCOL_STORE(data), protocol);
+}
+
+static void
+pidgin_protocol_store_protocol_removed_cb(PurpleProtocol *protocol,
+ gpointer data)
+{
+ pidgin_protocol_store_remove_protocol(PIDGIN_PROTOCOL_STORE(data), protocol);
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_TYPE(PidginProtocolStore, pidgin_protocol_store, GTK_TYPE_LIST_STORE)
+
+static void
+pidgin_protocol_store_init(PidginProtocolStore *store) {
+ gpointer protocols_handle = NULL;
+ GType types[PIDGIN_PROTOCOL_STORE_N_COLUMNS] = {
+ PURPLE_TYPE_PROTOCOL,
+ G_TYPE_STRING,
+ GDK_TYPE_PIXBUF,
+ };
+
+ gtk_list_store_set_column_types(
+ GTK_LIST_STORE(store),
+ PIDGIN_PROTOCOL_STORE_N_COLUMNS,
+ types
+ );
+
+ /* add the known protocols */
+ pidgin_protocol_store_add_protocols(store);
+
+ /* add the signal handlers to dynamically add/remove protocols */
+ protocols_handle = purple_protocols_get_handle();
+ purple_signal_connect(protocols_handle, "protocol-added", store,
+ G_CALLBACK(pidgin_protocol_store_protocol_added_cb),
+ store);
+ purple_signal_connect(protocols_handle, "protocol-removed", store,
+ G_CALLBACK(pidgin_protocol_store_protocol_removed_cb),
+ store);
+}
+
+static void
+pidgin_protocol_store_finalize(GObject *obj) {
+ purple_signals_disconnect_by_handle(obj);
+
+ G_OBJECT_CLASS(pidgin_protocol_store_parent_class)->finalize(obj);
+}
+
+static void
+pidgin_protocol_store_class_init(PidginProtocolStoreClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ obj_class->finalize = pidgin_protocol_store_finalize;
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GtkListStore *
+pidgin_protocol_store_new(void) {
+ return GTK_LIST_STORE(g_object_new(PIDGIN_TYPE_PROTOCOL_STORE, NULL));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginprotocolstore.h Fri Feb 21 02:45:13 2020 +0000
@@ -0,0 +1,68 @@
+/* pidgin
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#ifndef PIDGIN_PROTOCOL_STORE_H
+#define PIDGIN_PROTOCOL_STORE_H
+
+/**
+ * SECTION:pidginprotocolstore
+ * @section_id: pidgin-protocol-store
+ * @short_description: A GtkListStore that keeps track of protocols
+ * @title: Protocol Store
+ *
+ * #PidginProtocolStore is a #GtkListStore that automatically keeps track of
+ * what protocols are currently available in libpurple. It's intended to be
+ * used any time that you need to present a protocol selection to the user.
+ */
+
+#include <gtk/gtk.h>
+
+#include <purple.h>
+
+typedef enum {
+ PIDGIN_PROTOCOL_STORE_COLUMN_PROTOCOL,
+ PIDGIN_PROTOCOL_STORE_COLUMN_NAME,
+ PIDGIN_PROTOCOL_STORE_COLUMN_ICON,
+ PIDGIN_PROTOCOL_STORE_N_COLUMNS,
+} PidginProtocolStoreColumn;
+
+G_BEGIN_DECLS
+
+#define PIDGIN_TYPE_PROTOCOL_STORE pidgin_protocol_store_get_type()
+
+G_DECLARE_FINAL_TYPE(PidginProtocolStore, pidgin_protocol_store, PIDGIN,
+ PROTOCOL_STORE, GtkListStore)
+
+/**
+ * pidgin_protocol_store_new:
+ *
+ * Creates a new #PidginProtocolStore that can be used anywhere a #GtkListStore
+ * can be used.
+ *
+ * Returns: (transfer full): The new #PidginProtocolStore instance.
+ *
+ * Since: 3.0.0
+ */
+GtkListStore *pidgin_protocol_store_new(void);
+
+G_END_DECLS
+
+#endif /* PIDGIN_PROTOCOL_STORE_H */
--- a/pidgin/plugins/meson.build Fri Feb 14 22:55:41 2020 +0000
+++ b/pidgin/plugins/meson.build Fri Feb 21 02:45:13 2020 +0000
@@ -85,4 +85,5 @@
name_prefix : '',
install : true, install_dir : PIDGIN_PLUGINDIR)
endif
+
endif # PLUGINS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/resources/Protocols/chooser.ui Fri Feb 21 02:45:13 2020 +0000
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1
+
+Pidgin - Internet Messenger
+Copyright (C) Pidgin Developers <devel@pidgin.im>
+
+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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+-->
+<interface domain="pidgin">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- interface-license-type gplv2 -->
+ <!-- interface-name Pidgin -->
+ <!-- interface-description Internet Messenger -->
+ <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+ <template class="PidginProtocolChooser" parent="GtkComboBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="icon"/>
+ <attributes>
+ <attribute name="pixbuf">2</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="name"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </template>
+ <object class="PidginProtocolStore" id="model"/>
+</interface>
--- a/pidgin/resources/pidgin.gresource.xml Fri Feb 14 22:55:41 2020 +0000
+++ b/pidgin/resources/pidgin.gresource.xml Fri Feb 21 02:45:13 2020 +0000
@@ -14,6 +14,7 @@
<file compressed="true">Prefs/prefs.ui</file>
<file compressed="true">Prefs/vv.ui</file>
<file compressed="true">Privacy/dialog.ui</file>
+ <file compressed="true">Protocols/chooser.ui</file>
<file compressed="true">Roomlist/roomlist.ui</file>
<file compressed="true">Whiteboard/whiteboard.ui</file>
<file compressed="true">Xfer/xfer.ui</file>