qulogic/pidgin

f02878f30f91
Parents 998b44b2c5f1
Children 25d1b656d792
Create a full widget for the new instant message window

This now uses AdwMessageDialog and is self contained but PidginApplication
manages a singleton of it.

Previously this used the request api. I'm not sure why, as the request fields
were created by the ui itself.

Testing Done:
Created an im with `Echo` on a `demo` account and was able to send and receive messages.

Reviewed at https://reviews.imfreedom.org/r/2896/
--- a/ChangeLog.API Tue Jan 02 00:33:16 2024 -0600
+++ b/ChangeLog.API Tue Jan 02 00:36:32 2024 -0600
@@ -1067,6 +1067,7 @@
* pidgin_dialogs_alias_chat
* pidgin_dialogs_alias_contact
* pidgin_dialogs_destroy_all
+ * pidgin_dialogs_im
* pidgin_dialogs_log
* pidgin_dialogs_merge_groups
* pidgin_dialogs_remove_buddy
--- a/pidgin/gtkdialogs.c Tue Jan 02 00:33:16 2024 -0600
+++ b/pidgin/gtkdialogs.c Tue Jan 02 00:36:32 2024 -0600
@@ -31,81 +31,6 @@
#include "gtkutils.h"
#include "pidgincore.h"
-static void
-pidgin_dialogs_im_cb(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
- PurpleAccount *account;
- const char *username;
-
- account = purple_request_page_get_account(page, "account");
- username = purple_request_page_get_string(page, "screenname");
-
- pidgin_dialogs_im_with_user(account, username);
-}
-
-static gboolean
-pidgin_dialogs_im_name_validator(PurpleRequestField *field, char **errmsg,
- gpointer data)
-{
- PurpleRequestFieldAccount *account_field = data;
- PurpleAccount *account;
- PurpleProtocol *protocol;
- const char *username;
- gboolean valid = FALSE;
-
- account = purple_request_field_account_get_value(account_field);
- protocol = purple_account_get_protocol(account);
- username = purple_request_field_string_get_value(PURPLE_REQUEST_FIELD_STRING(field));
-
- if (username) {
- valid = purple_validate(protocol, username);
- }
-
- if (errmsg && !valid)
- *errmsg = g_strdup(_("Invalid username"));
-
- return valid;
-}
-
-void
-pidgin_dialogs_im(void)
-{
- PurpleRequestPage *page;
- PurpleRequestGroup *group;
- PurpleRequestField *username_field = NULL;
- PurpleRequestField *account_field = NULL;
-
- page = purple_request_page_new();
-
- group = purple_request_group_new(NULL);
- purple_request_page_add_group(page, group);
-
- account_field = purple_request_field_account_new("account", _("_Account"),
- NULL);
- purple_request_field_set_type_hint(account_field, "account");
- purple_request_field_set_visible(account_field,
- (purple_connections_get_all() != NULL &&
- purple_connections_get_all()->next != NULL));
- purple_request_field_set_required(account_field, TRUE);
- purple_request_group_add_field(group, account_field);
-
- purple_request_field_set_validator(username_field,
- pidgin_dialogs_im_name_validator,
- account_field, NULL);
-
- username_field = purple_request_field_string_new("screenname", _("_Name"),
- NULL, FALSE);
- purple_request_field_set_type_hint(username_field, "screenname");
- purple_request_field_set_required(username_field, TRUE);
- purple_request_group_add_field(group, username_field);
-
- purple_request_fields(
- purple_blist_get_default(), _("New Instant Message"), NULL,
- _("Please enter the username or alias of the person "
- "you would like to IM."),
- page, _("OK"), G_CALLBACK(pidgin_dialogs_im_cb), _("Cancel"),
- NULL, NULL, NULL);
-}
-
void
pidgin_dialogs_im_with_user(PurpleAccount *account, const char *username)
{
--- a/pidgin/gtkdialogs.h Tue Jan 02 00:33:16 2024 -0600
+++ b/pidgin/gtkdialogs.h Tue Jan 02 00:36:32 2024 -0600
@@ -33,9 +33,6 @@
G_BEGIN_DECLS
PIDGIN_AVAILABLE_IN_ALL
-void pidgin_dialogs_im(void);
-
-PIDGIN_AVAILABLE_IN_ALL
void pidgin_dialogs_im_with_user(PurpleAccount *account, const char *username);
PIDGIN_AVAILABLE_IN_ALL
--- a/pidgin/meson.build Tue Jan 02 00:33:16 2024 -0600
+++ b/pidgin/meson.build Tue Jan 02 00:36:32 2024 -0600
@@ -37,6 +37,7 @@
'pidgindisplayitem.c',
'pidgindisplaywindow.c',
'pidginiconname.c',
+ 'pidginimwindow.c',
'pidgininfopane.c',
'pidgininvitedialog.c',
'pidginkeypad.c',
@@ -94,6 +95,7 @@
'pidgindisplaywindow.h',
'pidgindebug.h',
'pidginiconname.h',
+ 'pidginimwindow.h',
'pidgininfopane.h',
'pidgininvitedialog.h',
'pidginkeypad.h',
--- a/pidgin/pidginapplication.c Tue Jan 02 00:33:16 2024 -0600
+++ b/pidgin/pidginapplication.c Tue Jan 02 00:36:32 2024 -0600
@@ -44,6 +44,7 @@
#include "pidgincore.h"
#include "pidgindebug.h"
#include "pidgindisplaywindow.h"
+#include "pidginimwindow.h"
#include "pidginpluginsdialog.h"
#include "pidginpluginsmenu.h"
#include "pidginprefs.h"
@@ -447,9 +448,18 @@
static void
pidgin_application_new_message(G_GNUC_UNUSED GSimpleAction *simple,
G_GNUC_UNUSED GVariant *parameter,
- G_GNUC_UNUSED gpointer data)
+ gpointer data)
{
- pidgin_dialogs_im();
+ PidginApplication *application = data;
+ static GtkWidget *dialog = NULL;
+
+ if(!PIDGIN_IS_IM_WINDOW(dialog)) {
+ dialog = pidgin_im_window_new();
+ g_object_add_weak_pointer(G_OBJECT(dialog), (gpointer)&dialog);
+ }
+
+ pidgin_application_present_transient_window(application,
+ GTK_WINDOW(dialog));
}
static void
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginimwindow.c Tue Jan 02 00:36:32 2024 -0600
@@ -0,0 +1,143 @@
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include <purple.h>
+
+#include "pidginimwindow.h"
+
+#include "pidginaccountrow.h"
+
+struct _PidginIMWindow {
+ AdwMessageDialog parent;
+
+ GtkCustomFilter *filter;
+
+ GtkWidget *account;
+ GtkWidget *username;
+};
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static gboolean
+pidgin_im_window_filter_accounts(gpointer item, G_GNUC_UNUSED gpointer data) {
+ if(PURPLE_IS_ACCOUNT(item)) {
+ PurpleAccount *account = PURPLE_ACCOUNT(item);
+ PurpleProtocol *protocol = purple_account_get_protocol(account);
+
+ if(PURPLE_IS_PROTOCOL(protocol)) {
+ return PURPLE_PROTOCOL_IMPLEMENTS(protocol, CONVERSATION,
+ send_message_async);
+ }
+ }
+
+ return FALSE;
+
+}
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+static void
+pidgin_im_window_username_changed_cb(GtkEditable *self, gpointer data) {
+ const char *text = NULL;
+ gboolean enabled = FALSE;
+
+ text = gtk_editable_get_text(self);
+ enabled = !purple_strempty(text);
+
+ adw_message_dialog_set_response_enabled(data, "okay", enabled);
+}
+
+static void
+pidgin_im_window_response_cb(AdwMessageDialog *self,
+ const char *response,
+ G_GNUC_UNUSED gpointer data)
+{
+ PidginIMWindow *window = PIDGIN_IM_WINDOW(self);
+ PurpleAccount *account = NULL;
+ PurpleConversation *im = NULL;
+ PurpleConversationManager *manager = NULL;
+ const char *username = NULL;
+
+ if(!purple_strequal(response, "okay")) {
+ return;
+ }
+
+ account = pidgin_account_row_get_account(PIDGIN_ACCOUNT_ROW(window->account)) ;
+ username = gtk_editable_get_text(GTK_EDITABLE(window->username));
+
+ manager = purple_conversation_manager_get_default();
+ im = purple_conversation_manager_find_im(manager, account, username);
+
+ if(!PURPLE_IS_IM_CONVERSATION(im)) {
+ /* This constructor automagically registers the conversation with the
+ * manager.
+ */
+ purple_im_conversation_new(account, username);
+ }
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_TYPE(PidginIMWindow, pidgin_im_window, ADW_TYPE_MESSAGE_DIALOG)
+
+static void
+pidgin_im_window_init(PidginIMWindow *window) {
+ gtk_widget_init_template(GTK_WIDGET(window));
+
+ gtk_custom_filter_set_filter_func(window->filter,
+ pidgin_im_window_filter_accounts,
+ NULL, NULL);
+}
+
+static void
+pidgin_im_window_class_init(PidginIMWindowClass *klass) {
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+
+ gtk_widget_class_set_template_from_resource(
+ widget_class,
+ "/im/pidgin/Pidgin3/imwindow.ui"
+ );
+
+ gtk_widget_class_bind_template_child(widget_class, PidginIMWindow,
+ filter);
+
+ gtk_widget_class_bind_template_child(widget_class, PidginIMWindow,
+ account);
+ gtk_widget_class_bind_template_child(widget_class, PidginIMWindow,
+ username);
+
+ gtk_widget_class_bind_template_callback(widget_class,
+ pidgin_im_window_username_changed_cb);
+ gtk_widget_class_bind_template_callback(widget_class,
+ pidgin_im_window_response_cb);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+GtkWidget *
+pidgin_im_window_new(void) {
+ return g_object_new(PIDGIN_TYPE_IM_WINDOW, NULL);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginimwindow.h Tue Jan 02 00:36:32 2024 -0600
@@ -0,0 +1,65 @@
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined(PIDGIN_GLOBAL_HEADER_INSIDE) && !defined(PIDGIN_COMPILATION)
+# error "only <pidgin.h> may be included directly"
+#endif
+
+#ifndef PIDGIN_IM_WINDOW_H
+#define PIDGIN_IM_WINDOW_H
+
+#include <glib.h>
+
+#include <gtk/gtk.h>
+
+#include <adwaita.h>
+
+#include "pidginversion.h"
+
+G_BEGIN_DECLS
+
+/**
+ * PidginIMWindow:
+ *
+ * A window used to start a new direct message.
+ *
+ * Since: 3.0.0
+ */
+
+#define PIDGIN_TYPE_IM_WINDOW (pidgin_im_window_get_type())
+
+PIDGIN_AVAILABLE_IN_3_0
+G_DECLARE_FINAL_TYPE(PidginIMWindow, pidgin_im_window,
+ PIDGIN, IM_WINDOW, AdwMessageDialog)
+
+/**
+ * pidgin_im_window_new:
+ *
+ * Creates a new #PidginIMWindow instance.
+ *
+ * Returns: (transfer full): The new #PidginIMWindow instance.
+ */
+GtkWidget *pidgin_im_window_new(void);
+
+G_END_DECLS
+
+#endif /* PIDGIN_IM_WINDOW_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/resources/imwindow.ui Tue Jan 02 00:36:32 2024 -0600
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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 library; if not, see <https://www.gnu.org/licenses/>.
+-->
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <!-- interface-license-type gplv2 -->
+ <!-- interface-name Pidgin -->
+ <!-- interface-description Internet Messenger -->
+ <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+ <template class="PidginIMWindow" parent="AdwMessageDialog">
+ <property name="heading" translatable="yes">New Instant Message</property>
+ <property name="body" translatable="yes">Please enter the username or alias of the person you would like to IM.</property>
+ <property name="extra-child">
+ <object class="AdwPreferencesGroup">
+ <property name="vexpand">true</property>
+ <property name="hexpand">true</property>
+ <child>
+ <object class="PidginAccountRow" id="account">
+ <property name="filter">
+ <object class="GtkEveryFilter">
+ <child>
+ <object class="GtkCustomFilter" id="filter"/>
+ </child>
+ <child>
+ <object class="PidginAccountFilterConnected"/>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwEntryRow" id="username">
+ <property name="focusable">no</property>
+ <property name="title" translatable="yes">_Username</property>
+ <property name="use-underline">yes</property>
+ <property name="activates-default">yes</property>
+ <signal name="changed" handler="pidgin_im_window_username_changed_cb"/>
+ </object>
+ </child>
+ </object>
+ </property>
+ <property name="default-response">okay</property>
+ <property name="close-response">cancel</property>
+ <responses>
+ <response id="cancel" translatable="yes">_Cancel</response>
+ <response id="okay" translatable="yes" appearance="suggested" enabled="false">_Okay</response>
+ </responses>
+ <signal name="response" handler="pidgin_im_window_response_cb"/>
+ </template>
+</interface>
--- a/pidgin/resources/pidgin.gresource.xml Tue Jan 02 00:33:16 2024 -0600
+++ b/pidgin/resources/pidgin.gresource.xml Tue Jan 02 00:36:32 2024 -0600
@@ -43,6 +43,7 @@
<file compressed="true" preprocess="xml-stripblanks">channeljoindialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks">contactlistitem.ui</file>
<file compressed="true" preprocess="xml-stripblanks">conversationmemberlistitem.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks">imwindow.ui</file>
<file compressed="true" preprocess="xml-stripblanks">presenceicon.ui</file>
<file>icons/16x16/status/pidgin-user-available.png</file>
<file>icons/16x16/status/pidgin-user-away.png</file>