--- a/pidgin/plugins/xmppconsole/console.ui Wed May 25 23:52:44 2022 -0500
+++ b/pidgin/plugins/xmppconsole/console.ui Wed May 25 23:52:44 2022 -0500
@@ -26,7 +26,7 @@
<!-- interface-description Internet Messenger -->
<!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
<object class="GtkTextBuffer" id="entry_buffer">
- <signal name="changed" handler="entry_changed_cb" swapped="no"/>
+ <signal name="changed" handler="entry_changed_cb" object="PidginXmppConsole" swapped="no"/> <object class="GtkAdjustment" id="presence.priority_adjustment">
<property name="lower">-128</property>
@@ -82,15 +82,11 @@
<object class="GtkTextBuffer" id="buffer">
<property name="tag_table">tags.table</property>
- <object class="GtkWindow" id="PidginXmppConsole">
+ <template parent="GtkWindow" class="PidginXmppConsole"> <property name="can_focus">False</property>
<property name="title" translatable="yes">XMPP Console</property>
<property name="default_width">580</property>
<property name="default_height">400</property>
- <signal name="destroy" handler="console_destroy" swapped="no"/>
<property name="visible">True</property>
@@ -118,7 +114,7 @@
<object class="GtkComboBoxText" id="dropdown">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <signal name="changed" handler="dropdown_changed_cb" swapped="no"/>
+ <signal name="changed" handler="dropdown_changed_cb" object="PidginXmppConsole" swapped="no"/> <property name="expand">True</property>
@@ -225,7 +221,7 @@
<object class="GtkPopover" id="iq.popover">
<property name="can_focus">False</property>
<property name="relative_to">iq</property>
--- a/pidgin/plugins/xmppconsole/xmppconsole.c Wed May 25 23:52:44 2022 -0500
+++ b/pidgin/plugins/xmppconsole/xmppconsole.c Wed May 25 23:52:44 2022 -0500
@@ -1,5 +1,6 @@
* Purple - XMPP debugging tool
+ * 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
@@ -16,25 +17,25 @@
* 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
+ * along with this program; if not, see <https://www.gnu.org/licenses/>. #include <glib/gi18n-lib.h>
#include <gdk/gdkkeysyms.h>
+#include "xmppconsole.h" #define PLUGIN_ID "gtk-xmpp"
#define PLUGIN_DOMAIN (g_quark_from_static_string(PLUGIN_ID))
+struct _PidginXmppConsole {
@@ -77,14 +78,19 @@
-XmppConsole *console = NULL;
+G_DEFINE_DYNAMIC_TYPE(PidginXmppConsole, pidgin_xmpp_console, GTK_TYPE_WINDOW) +static PidginXmppConsole *console = NULL; static const gchar *xmpp_prpls[] = {
"prpl-jabber", "prpl-gtalk", NULL
+/****************************************************************************** + *****************************************************************************/ xmppconsole_is_xmpp_account(PurpleAccount *account)
@@ -104,7 +110,9 @@
-purple_xmlnode_append_to_buffer(PurpleXmlNode *node, gint indent_level, GtkTextIter *iter, GtkTextTag *tag)
+xmppconsole_append_xmlnode(PidginXmppConsole *console, PurpleXmlNode *node, + gint indent_level, GtkTextIter *iter, gboolean need_end = FALSE, pretty = TRUE;
@@ -170,7 +178,7 @@
for (c = node->child; c; c = c->next)
if (c->type == PURPLE_XMLNODE_TYPE_TAG) {
- purple_xmlnode_append_to_buffer(c, indent_level + 1, iter, tag);
+ xmppconsole_append_xmlnode(console, c, indent_level + 1, iter, tag); } else if (c->type == PURPLE_XMLNODE_TYPE_DATA && c->data_sz > 0) {
gtk_text_buffer_insert_with_tags(console->buffer, iter, c->data, c->data_sz,
@@ -207,11 +215,13 @@
- if (!console || console->gc != gc)
+ if (console == NULL || console->gc != gc) { gtk_text_buffer_get_end_iter(console->buffer, &iter);
- purple_xmlnode_append_to_buffer(*packet, 0, &iter, console->tags.incoming);
+ xmppconsole_append_xmlnode(console, *packet, 0, &iter, + console->tags.incoming); @@ -220,21 +230,23 @@
- if (!console || console->gc != gc)
+ if (console == NULL || console->gc != gc) { node = purple_xmlnode_from_str(*packet, -1);
gtk_text_buffer_get_end_iter(console->buffer, &iter);
- purple_xmlnode_append_to_buffer(node, 0, &iter, console->tags.outgoing);
+ xmppconsole_append_xmlnode(console, node, 0, &iter, + console->tags.outgoing); purple_xmlnode_free(node);
-message_send_cb(GtkWidget *widget, GdkEventKey *event, gpointer p)
+message_send_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) { + PidginXmppConsole *console = data; PurpleProtocol *protocol = NULL;
@@ -263,8 +275,8 @@
-entry_changed_cb(GtkTextBuffer *buffer, void *data)
+entry_changed_cb(GtkTextBuffer *buffer, gpointer data) { + PidginXmppConsole *console = data; @@ -320,7 +332,8 @@
-load_text_and_set_caret(const gchar *pre_text, const gchar *post_text)
+load_text_and_set_caret(PidginXmppConsole *console, const gchar *pre_text, + const gchar *post_text) @@ -360,7 +373,7 @@
iq_clicked_cb(GtkWidget *w, gpointer data)
- XmppConsole *console = (XmppConsole *)data;
+ PidginXmppConsole *console = data; @@ -369,7 +382,7 @@
"<iq %s%s%s id='console%x' type='%s'>", to && *to ? "to='" : "",
to && *to ? to : "", to && *to ? "'" : "", g_random_int(),
gtk_combo_box_text_get_active_text(console->iq.type));
- load_text_and_set_caret(stanza, "</iq>");
+ load_text_and_set_caret(console, stanza, "</iq>"); gtk_widget_grab_focus(console->entry);
@@ -382,7 +395,7 @@
presence_clicked_cb(GtkWidget *w, gpointer data)
- XmppConsole *console = (XmppConsole *)data;
+ PidginXmppConsole *console = data; const gchar *to, *status, *priority;
@@ -426,7 +439,7 @@
*priority ? priority : "",
*priority ? "</priority>" : "");
- load_text_and_set_caret(stanza, "</presence>");
+ load_text_and_set_caret(console, stanza, "</presence>"); gtk_widget_grab_focus(console->entry);
@@ -444,7 +457,7 @@
message_clicked_cb(GtkWidget *w, gpointer data)
- XmppConsole *console = (XmppConsole *)data;
+ PidginXmppConsole *console = data; const gchar *to, *body, *thread, *subject;
@@ -470,7 +483,7 @@
*thread ? "<thread>" : "", *thread ? thread : "",
*thread ? "</thread>" : "");
- load_text_and_set_caret(stanza, "</message>");
+ load_text_and_set_caret(console, stanza, "</message>"); gtk_widget_grab_focus(console->entry);
@@ -488,8 +501,9 @@
account = purple_connection_get_account(gc);
if (!xmppconsole_is_xmpp_account(account))
@@ -513,8 +527,9 @@
i = g_list_index(console->accounts, gc);
@@ -534,49 +549,128 @@
-console_destroy(GtkWidget *window, gpointer nul)
- g_list_free(console->accounts);
+dropdown_changed_cb(GtkComboBox *widget, gpointer data) { + PidginXmppConsole *console = data; + console->gc = g_list_nth_data(console->accounts, + gtk_combo_box_get_active(widget)); + gtk_text_buffer_set_text(console->buffer, "", 0); +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +pidgin_xmpp_console_finalize(GObject *obj) { + PidginXmppConsole *console = PIDGIN_XMPP_CONSOLE(obj); + g_clear_pointer(&console->accounts, g_list_free); + G_OBJECT_CLASS(pidgin_xmpp_console_parent_class)->finalize(obj); +pidgin_xmpp_console_class_finalize(PidginXmppConsoleClass *klass) { -dropdown_changed_cb(GtkComboBox *widget, gpointer nul)
+pidgin_xmpp_console_class_init(PidginXmppConsoleClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + obj_class->finalize = pidgin_xmpp_console_finalize; + gtk_widget_class_set_template_from_resource( + "/im/pidgin/Pidgin3/Plugin/XMPPConsole/console.ui" + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_callback(widget_class, dropdown_changed_cb); + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_callback(widget_class, + toggle_button_toggled_cb); + gtk_widget_class_bind_template_callback(widget_class, popover_closed_cb); - console->gc = g_list_nth_data(console->accounts, gtk_combo_box_get_active(GTK_COMBO_BOX(console->dropdown)));
- gtk_text_buffer_set_text(console->buffer, "", 0);
+ /* Popover for <iq/> button. */ + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_callback(widget_class, iq_clicked_cb); + /* Popover for <presence/> button. */ + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_callback(widget_class, presence_clicked_cb); + /* Popover for <message/> button. */ + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_callback(widget_class, message_clicked_cb); + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, + gtk_widget_class_bind_template_callback(widget_class, message_send_cb); + gtk_widget_class_bind_template_child(widget_class, PidginXmppConsole, sw); + gtk_widget_class_bind_template_callback(widget_class, entry_changed_cb); -create_console(PurplePluginAction *action)
+pidgin_xmpp_console_init(PidginXmppConsole *console) { GtkCssProvider *entry_css;
GtkStyleContext *context;
- gtk_window_present(GTK_WINDOW(console->window));
- console = g_new0(XmppConsole, 1);
+ gtk_widget_init_template(GTK_WIDGET(console)); - builder = gtk_builder_new_from_resource(
- "/im/pidgin/Pidgin3/Plugin/XMPPConsole/console.ui");
- gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE);
- console->window = GTK_WIDGET(
- gtk_builder_get_object(builder, "PidginXmppConsole"));
- gtk_builder_add_callback_symbol(builder, "console_destroy",
- G_CALLBACK(console_destroy));
- console->hbox = GTK_WIDGET(gtk_builder_get_object(builder, "hbox"));
- GTK_WIDGET(gtk_builder_get_object(builder, "dropdown"));
for (connections = purple_connections_get_all(); connections; connections = connections->next) {
PurpleConnection *gc = connections->data;
if (xmppconsole_is_xmpp_account(purple_connection_get_account(gc))) {
@@ -589,27 +683,6 @@
gtk_combo_box_set_active(GTK_COMBO_BOX(console->dropdown), 0);
- gtk_builder_add_callback_symbol(builder, "dropdown_changed_cb",
- G_CALLBACK(dropdown_changed_cb));
- GTK_TEXT_BUFFER(gtk_builder_get_object(builder, "buffer"));
- GTK_TEXT_TAG(gtk_builder_get_object(builder, "tags.info"));
- console->tags.incoming =
- GTK_TEXT_TAG(gtk_builder_get_object(builder, "tags.incoming"));
- console->tags.outgoing =
- GTK_TEXT_TAG(gtk_builder_get_object(builder, "tags.outgoing"));
- console->tags.bracket =
- GTK_TEXT_TAG(gtk_builder_get_object(builder, "tags.bracket"));
- GTK_TEXT_TAG(gtk_builder_get_object(builder, "tags.tag"));
- GTK_TEXT_TAG(gtk_builder_get_object(builder, "tags.attr"));
- GTK_TEXT_TAG(gtk_builder_get_object(builder, "tags.value"));
- GTK_TEXT_TAG(gtk_builder_get_object(builder, "tags.xmlns"));
if (console->count == 0) {
@@ -618,50 +691,6 @@
gtk_text_buffer_apply_tag(console->buffer, console->tags.info, &start, &end);
- /* Popover for <iq/> button. */
- GTK_POPOVER(gtk_builder_get_object(builder, "iq.popover"));
- console->iq.to = GTK_ENTRY(gtk_builder_get_object(builder, "iq.to"));
- GTK_COMBO_BOX_TEXT(gtk_builder_get_object(builder, "iq.type"));
- /* Popover for <presence/> button. */
- console->presence.popover = GTK_POPOVER(
- gtk_builder_get_object(builder, "presence.popover"));
- GTK_ENTRY(gtk_builder_get_object(builder, "presence.to"));
- console->presence.type = GTK_COMBO_BOX_TEXT(
- gtk_builder_get_object(builder, "presence.type"));
- console->presence.show = GTK_COMBO_BOX_TEXT(
- gtk_builder_get_object(builder, "presence.show"));
- console->presence.status =
- GTK_ENTRY(gtk_builder_get_object(builder, "presence.status"));
- console->presence.priority =
- GTK_ENTRY(gtk_builder_get_object(builder, "presence.priority"));
- /* Popover for <message/> button. */
- console->message.popover =
- GTK_POPOVER(gtk_builder_get_object(builder, "message.popover"));
- GTK_ENTRY(gtk_builder_get_object(builder, "message.to"));
- console->message.type = GTK_COMBO_BOX_TEXT(
- gtk_builder_get_object(builder, "message.type"));
- console->message.body =
- GTK_ENTRY(gtk_builder_get_object(builder, "message.body"));
- console->message.subject =
- GTK_ENTRY(gtk_builder_get_object(builder, "message.subject"));
- console->message.thread =
- GTK_ENTRY(gtk_builder_get_object(builder, "message.thread"));
- gtk_builder_add_callback_symbols(
- builder, "toggle_button_toggled_cb",
- G_CALLBACK(toggle_button_toggled_cb), "popover_closed_cb",
- G_CALLBACK(popover_closed_cb), "iq_clicked_cb",
- G_CALLBACK(iq_clicked_cb), "presence_clicked_cb",
- G_CALLBACK(presence_clicked_cb), "message_clicked_cb",
- G_CALLBACK(message_clicked_cb), NULL);
- console->entry = GTK_WIDGET(gtk_builder_get_object(builder, "entry"));
entry_css = gtk_css_provider_new();
gtk_css_provider_load_from_data(entry_css,
"textview." GTK_STYLE_CLASS_ERROR " text {background-color:#ffcece;}",
@@ -669,23 +698,28 @@
context = gtk_widget_get_style_context(console->entry);
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(entry_css),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
- console->entry_buffer = GTK_TEXT_BUFFER(
- gtk_builder_get_object(builder, "entry_buffer"));
- gtk_builder_add_callback_symbol(builder, "message_send_cb",
- G_CALLBACK(message_send_cb));
+ entry_changed_cb(console->entry_buffer, console); - console->sw = GTK_WIDGET(gtk_builder_get_object(builder, "sw"));
- gtk_builder_add_callback_symbol(builder, "entry_changed_cb",
- G_CALLBACK(entry_changed_cb));
+ if (console->count < 2) { + gtk_widget_hide(console->hbox); + gtk_widget_show(GTK_WIDGET(console)); - entry_changed_cb(console->entry_buffer, NULL);
+/****************************************************************************** + * Plugin implementation + *****************************************************************************/ +create_console(PurplePluginAction *action) + console = g_object_new(PIDGIN_TYPE_XMPP_CONSOLE, NULL); + g_object_add_weak_pointer(G_OBJECT(console), (gpointer)&console); - gtk_widget_show_all(console->window);
- if (console->count < 2)
- gtk_widget_hide(console->hbox);
- gtk_builder_connect_signals(builder, console);
- g_object_unref(builder);
+ gtk_window_present(GTK_WINDOW(console)); @@ -730,6 +764,8 @@
gboolean any_registered = FALSE;
+ pidgin_xmpp_console_register_type(G_TYPE_MODULE(plugin)); while (xmpp_prpls[i] != NULL) {
@@ -766,8 +802,9 @@
xmpp_console_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
- gtk_widget_destroy(console->window);
+ gtk_widget_destroy(GTK_WIDGET(console));