pidgin/pidgin

Make PidginInfoPane generic

3 months ago, Gary Kramlich
ddaa27826ccc
Parents c035e2eba80d
Children 4be05f181669
Make PidginInfoPane generic

This removes the conversation property and replaces it with title and subtitle
properties.

It also adds a child property so that user can add custom widgets.

Testing Done:
Opened some conversations and verified everything still worked as expected without any warnings or errors.

Reviewed at https://reviews.imfreedom.org/r/2909/
--- a/pidgin/pidgininfopane.c Fri Jan 12 01:16:53 2024 -0600
+++ b/pidgin/pidgininfopane.c Fri Jan 12 01:47:00 2024 -0600
@@ -25,14 +25,17 @@
struct _PidginInfoPane {
GtkBox parent;
- PurpleConversation *conversation;
+ char *title;
+ char *subtitle;
- GtkWidget *topic;
+ GtkWidget *child;
};
enum {
PROP_0,
- PROP_CONVERSATION,
+ PROP_TITLE,
+ PROP_SUBTITLE,
+ PROP_CHILD,
N_PROPERTIES,
};
static GParamSpec *properties[N_PROPERTIES] = {NULL, };
@@ -43,14 +46,15 @@
* Callbacks
*****************************************************************************/
static char *
-pidgin_info_pane_linkify_text_cb(GObject *self, const char *topic,
+pidgin_info_pane_linkify_text_cb(GObject *self, const char *subtitle,
G_GNUC_UNUSED gpointer data)
{
- PidginInfoPane *pane = PIDGIN_INFO_PANE(self);
+ GtkWidget *label = GTK_WIDGET(self);
char *ret = NULL;
- ret = purple_markup_linkify(topic);
- gtk_widget_set_visible(pane->topic, !purple_strempty(ret));
+ ret = purple_markup_linkify(subtitle);
+
+ gtk_widget_set_visible(label, !purple_strempty(ret));
return ret;
}
@@ -65,8 +69,14 @@
PidginInfoPane *pane = PIDGIN_INFO_PANE(obj);
switch(param_id) {
- case PROP_CONVERSATION:
- g_value_set_object(value, pidgin_info_pane_get_conversation(pane));
+ case PROP_TITLE:
+ g_value_set_string(value, pidgin_info_pane_get_title(pane));
+ break;
+ case PROP_SUBTITLE:
+ g_value_set_string(value, pidgin_info_pane_get_subtitle(pane));
+ break;
+ case PROP_CHILD:
+ g_value_set_object(value, pidgin_info_pane_get_child(pane));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -81,8 +91,14 @@
PidginInfoPane *pane = PIDGIN_INFO_PANE(obj);
switch(param_id) {
- case PROP_CONVERSATION:
- pidgin_info_pane_set_conversation(pane, g_value_get_object(value));
+ case PROP_TITLE:
+ pidgin_info_pane_set_title(pane, g_value_get_string(value));
+ break;
+ case PROP_SUBTITLE:
+ pidgin_info_pane_set_subtitle(pane, g_value_get_string(value));
+ break;
+ case PROP_CHILD:
+ pidgin_info_pane_set_child(pane, g_value_get_object(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -91,12 +107,13 @@
}
static void
-pidgin_info_pane_dispose(GObject *obj) {
+pidgin_info_pane_finalize(GObject *obj) {
PidginInfoPane *pane = PIDGIN_INFO_PANE(obj);
- g_clear_object(&pane->conversation);
+ g_clear_pointer(&pane->title, g_free);
+ g_clear_pointer(&pane->subtitle, g_free);
- G_OBJECT_CLASS(pidgin_info_pane_parent_class)->dispose(obj);
+ G_OBJECT_CLASS(pidgin_info_pane_parent_class)->finalize(obj);
}
static void
@@ -109,29 +126,53 @@
GObjectClass *obj_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+ obj_class->finalize = pidgin_info_pane_finalize;
obj_class->get_property = pidgin_info_pane_get_property;
obj_class->set_property = pidgin_info_pane_set_property;
- obj_class->dispose = pidgin_info_pane_dispose;
+
+ /**
+ * PidginInfoPane:title:
+ *
+ * The title to display.
+ *
+ * Since: 3.0
+ */
+ properties[PROP_TITLE] = g_param_spec_string(
+ "title", "title",
+ "The title for the info pane.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
- * PidginInfoPane:conversation
+ * PidginInfoPane:subtitle:
*
- * The #PurpleConversation whose information will be displayed.
+ * The sub title to display.
+ *
+ * Since: 3.0
*/
- properties[PROP_CONVERSATION] = g_param_spec_object(
- "conversation", "conversation",
- "The PurpleConversation instance",
- PURPLE_TYPE_CONVERSATION,
+ properties[PROP_SUBTITLE] = g_param_spec_string(
+ "subtitle", "subtitle",
+ "The subtitle for the info pane.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PidginInfoPane:child:
+ *
+ * The child widget to display at the end of the info pane.
+ *
+ * Since: 3.0
+ */
+ properties[PROP_CHILD] = g_param_spec_object(
+ "child", "child",
+ "A child widget to display at the end of the info pane.",
+ GTK_TYPE_WIDGET,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
- gtk_widget_class_set_template_from_resource(
- widget_class,
- "/im/pidgin/Pidgin3/Conversations/infopane.ui"
- );
-
- gtk_widget_class_bind_template_child(widget_class, PidginInfoPane, topic);
+ gtk_widget_class_set_template_from_resource(widget_class,
+ "/im/pidgin/Pidgin3/infopane.ui");
gtk_widget_class_bind_template_callback(widget_class,
pidgin_info_pane_linkify_text_cb);
@@ -141,29 +182,75 @@
* API
*****************************************************************************/
GtkWidget *
-pidgin_info_pane_new(PurpleConversation *conversation) {
- return GTK_WIDGET(g_object_new(
- PIDGIN_TYPE_INFO_PANE,
- "conversation", conversation,
- NULL));
+pidgin_info_pane_new(void) {
+ return g_object_new(PIDGIN_TYPE_INFO_PANE, NULL);
+}
+
+const char *
+pidgin_info_pane_get_title(PidginInfoPane *pane) {
+ g_return_val_if_fail(PIDGIN_IS_INFO_PANE(pane), NULL);
+
+ return pane->title;
}
-PurpleConversation *
-pidgin_info_pane_get_conversation(PidginInfoPane *pane) {
+void
+pidgin_info_pane_set_title(PidginInfoPane *pane, const char *title) {
+ g_return_if_fail(PIDGIN_IS_INFO_PANE(pane));
+
+ if(!purple_strequal(pane->title, title)) {
+ g_free(pane->title);
+ pane->title = g_strdup(title);
+
+ g_object_notify_by_pspec(G_OBJECT(pane), properties[PROP_TITLE]);
+ }
+}
+
+const char *
+pidgin_info_pane_get_subtitle(PidginInfoPane *pane) {
g_return_val_if_fail(PIDGIN_IS_INFO_PANE(pane), NULL);
- return pane->conversation;
+ return pane->subtitle;
}
void
-pidgin_info_pane_set_conversation(PidginInfoPane *pane,
- PurpleConversation *conversation)
-{
+pidgin_info_pane_set_subtitle(PidginInfoPane *pane, const char *subtitle) {
g_return_if_fail(PIDGIN_IS_INFO_PANE(pane));
- if(!g_set_object(&pane->conversation, conversation)) {
+ if(!purple_strequal(pane->subtitle, subtitle)) {
+ g_free(pane->subtitle);
+ pane->subtitle = g_strdup(subtitle);
+
+ g_object_notify_by_pspec(G_OBJECT(pane), properties[PROP_SUBTITLE]);
+ }
+}
+
+GtkWidget *
+pidgin_info_pane_get_child(PidginInfoPane *pane) {
+ g_return_val_if_fail(PIDGIN_IS_INFO_PANE(pane), NULL);
+
+ return pane->child;
+}
+
+void
+pidgin_info_pane_set_child(PidginInfoPane *pane, GtkWidget *widget) {
+ g_return_if_fail(PIDGIN_IS_INFO_PANE(pane));
+ g_return_if_fail(widget == NULL || gtk_widget_get_parent(widget) == NULL);
+
+ if(pane->child == widget) {
return;
}
- g_object_notify_by_pspec(G_OBJECT(pane), properties[PROP_CONVERSATION]);
+ g_clear_object(&pane->child);
+
+ if(GTK_IS_WIDGET(widget)) {
+ pane->child = g_object_ref_sink(widget);
+ gtk_box_append(GTK_BOX(pane), pane->child);
+
+ /* This might not be the best place for this, but this helps keep the
+ * user interface consistent and doesn't force users to do it.
+ */
+ gtk_widget_set_margin_end(pane->child, 6);
+ }
+
+ g_object_notify_by_pspec(G_OBJECT(pane), properties[PROP_CHILD]);
}
--- a/pidgin/pidgininfopane.h Fri Jan 12 01:16:53 2024 -0600
+++ b/pidgin/pidgininfopane.h Fri Jan 12 01:47:00 2024 -0600
@@ -43,7 +43,7 @@
* #PidginInfoPane is a widget that displays information above
* #PidginConversations.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
#define PIDGIN_TYPE_INFO_PANE (pidgin_info_pane_get_type())
@@ -54,44 +54,90 @@
/**
* pidgin_info_pane_new:
- * @conversation: The #PurpleConversation instance.
*
- * Creates a new #PidginInfoPane instance that will display information about
- * @conversation.
+ * Creates a new #PidginInfoPane instance.
*
* Returns: (transfer full): The new #PidginInfoPane instance.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
PIDGIN_AVAILABLE_IN_3_0
-GtkWidget *pidgin_info_pane_new(PurpleConversation *conversation);
+GtkWidget *pidgin_info_pane_new(void);
/**
- * pidgin_info_pane_get_conversation:
+ * pidgin_info_pane_get_title:
* @pane: The #PidginInfoPane instance.
*
- * Gets the #PurpleConversation that @pane is displaying information for.
+ * Gets the title of @pane.
+ *
+ * Returns: (transfer none) (nullable): The title or %NULL.
*
- * Returns: (transfer none): The #PurpleConversation displayed by @pane.
+ * Since: 3.0
+ */
+PIDGIN_AVAILABLE_IN_3_0
+const char *pidgin_info_pane_get_title(PidginInfoPane *pane);
+
+/**
+ * pidgin_info_pane_set_title:
+ * @pane: The instance.
+ * @title: (nullable): The new title.
*
- * Since: 3.0.0
+ * Sets the title of @pane.
+ *
+ * Since: 3.0
*/
PIDGIN_AVAILABLE_IN_3_0
-PurpleConversation *pidgin_info_pane_get_conversation(PidginInfoPane *pane);
+void pidgin_info_pane_set_title(PidginInfoPane *pane, const char *title);
+
+/**
+ * pidgin_info_pane_get_subtitle:
+ * @pane: The #PidginInfoPane instance.
+ *
+ * Gets the subtitle of @pane.
+ *
+ * Returns: (transfer none) (nullable): The subtitle or %NULL.
+ *
+ * Since: 3.0
+ */
+PIDGIN_AVAILABLE_IN_3_0
+const char *pidgin_info_pane_get_subtitle(PidginInfoPane *pane);
/**
- * pidgin_info_pane_set_conversation:
+ * pidgin_info_pane_set_subtitle:
* @pane: The instance.
- * @conversation: (nullable): The [class@Purple.Conversation] to use.
+ * @subtitle: (nullable): The new subtitle.
*
- * Sets the conversation that @pane uses to get its values.
+ * Sets the subtitle of @pane.
*
- * Typically this is only necessary for the conversation instance itself.
- *
- * Since: 3.0.0
+ * Since: 3.0
*/
PIDGIN_AVAILABLE_IN_3_0
-void pidgin_info_pane_set_conversation(PidginInfoPane *pane, PurpleConversation *conversation);
+void pidgin_info_pane_set_subtitle(PidginInfoPane *pane, const char *subtitle);
+
+/**
+ * pidgin_info_pane_get_child:
+ * @pane: The instance.
+ *
+ * Gets the widget that is being displayed at the end of @pane.
+ *
+ * Returns: (nullable): The child widget or %NULL if one is not set.
+ *
+ * Since: 3.0
+ */
+PIDGIN_AVAILABLE_IN_3_0
+GtkWidget *pidgin_info_pane_get_child(PidginInfoPane *pane);
+
+/**
+ * pidgin_info_pane_set_child:
+ * @pane: The instance.
+ * @widget: (nullable): The new child.
+ *
+ * Sets the child widget of @pane to @widget.
+ *
+ * Since: 3.0
+ */
+PIDGIN_AVAILABLE_IN_3_0
+void pidgin_info_pane_set_child(PidginInfoPane *pane, GtkWidget *widget);
G_END_DECLS
--- a/pidgin/resources/Conversations/conversation.ui Fri Jan 12 01:16:53 2024 -0600
+++ b/pidgin/resources/Conversations/conversation.ui Fri Jan 12 01:47:00 2024 -0600
@@ -31,15 +31,27 @@
<child>
<object class="PidginInfoPane" id="info_pane">
<property name="hexpand">1</property>
- <binding name="conversation">
- <lookup name="conversation">PidginConversation</lookup>
+ <binding name="title">
+ <lookup name="title" type="PurpleConversation">
+ <lookup name="conversation">PidginConversation</lookup>
+ </lookup>
+ </binding>
+ <binding name="subtitle">
+ <lookup name="topic" type="PurpleConversation">
+ <lookup name="conversation">PidginConversation</lookup>
+ </lookup>
</binding>
- </object>
- </child>
- <child>
- <object class="GtkToggleButton" id="toggle_flap">
- <property name="icon-name">view-dual-symbolic</property>
- <property name="valign">center</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GtkToggleButton" id="toggle_flap">
+ <property name="icon-name">view-dual-symbolic</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </property>
</object>
</child>
</object>
--- a/pidgin/resources/Conversations/infopane.ui Fri Jan 12 01:16:53 2024 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-<?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"/>
- <requires lib="pidgin" version="3.0"/>
- <!-- interface-license-type gplv2 -->
- <!-- interface-name Pidgin -->
- <!-- interface-description Internet Messenger -->
- <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
- <template class="PidginInfoPane" parent="GtkBox">
- <child>
- <object class="GtkBox">
- <property name="spacing">6</property>
- <child>
- <object class="PidginAvatar">
- <binding name="conversation">
- <lookup name="conversation">PidginInfoPane</lookup>
- </binding>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="hexpand">1</property>
- <property name="orientation">vertical</property>
- <property name="valign">center</property>
- <child>
- <object class="GtkLabel" id="name">
- <binding name="label">
- <lookup name="name" type="PurpleConversation">
- <lookup name="conversation">PidginInfoPane</lookup>
- </lookup>
- </binding>
- <property name="xalign">0</property>
- <style>
- <class name="title-2"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkLabel" id="topic">
- <binding name="label">
- <closure type="gchararray" function="pidgin_info_pane_linkify_text_cb">
- <lookup name="topic" type="PurpleConversation">
- <lookup name="conversation">PidginInfoPane</lookup>
- </lookup>
- </closure>
- </binding>
- <property name="ellipsize">end</property>
- <property name="lines">2</property>
- <property name="use-markup">yes</property>
- <property name="wrap">yes</property>
- <property name="wrap-mode">word-char</property>
- <property name="xalign">0</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </template>
-</interface>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/resources/infopane.ui Fri Jan 12 01:47:00 2024 -0600
@@ -0,0 +1,69 @@
+<?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"/>
+ <requires lib="pidgin" version="3.0"/>
+ <!-- interface-license-type gplv2 -->
+ <!-- interface-name Pidgin -->
+ <!-- interface-description Internet Messenger -->
+ <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+ <template class="PidginInfoPane" parent="GtkBox">
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="PidginAvatar"></object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">1</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkLabel" id="title">
+ <binding name="label">
+ <lookup name="title">PidginInfoPane</lookup>
+ </binding>
+ <property name="xalign">0</property>
+ <style>
+ <class name="title-2"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="subtitle_label">
+ <binding name="label">
+ <closure type="gchararray" function="pidgin_info_pane_linkify_text_cb" object="subtitle_label">
+ <lookup name="subtitle">PidginInfoPane</lookup>
+ </closure>
+ </binding>
+ <property name="ellipsize">end</property>
+ <property name="lines">2</property>
+ <property name="use-markup">yes</property>
+ <property name="wrap">yes</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
--- a/pidgin/resources/pidgin.gresource.xml Fri Jan 12 01:16:53 2024 -0600
+++ b/pidgin/resources/pidgin.gresource.xml Fri Jan 12 01:47:00 2024 -0600
@@ -10,7 +10,6 @@
<file compressed="true" preprocess="xml-stripblanks">Accounts/manager-row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">avatar.ui</file>
<file compressed="true" preprocess="xml-stripblanks">Conversations/conversation.ui</file>
- <file compressed="true" preprocess="xml-stripblanks">Conversations/infopane.ui</file>
<file compressed="true" preprocess="xml-stripblanks">Conversations/invite_dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks">Conversations/message.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ContactList/widget.ui</file>
@@ -44,6 +43,7 @@
<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">infopane.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>
--- a/po/POTFILES.in Fri Jan 12 01:16:53 2024 -0600
+++ b/po/POTFILES.in Fri Jan 12 01:47:00 2024 -0600
@@ -292,7 +292,6 @@
pidgin/resources/Accounts/manager.ui
pidgin/resources/Accounts/manager-row.ui
pidgin/resources/avatar.ui
-pidgin/resources/Conversations/infopane.ui
pidgin/resources/Conversations/invite_dialog.ui
pidgin/resources/Debug/debug.ui
pidgin/resources/Dialogs/addbuddy.ui
@@ -315,6 +314,7 @@
pidgin/resources/gtk/menus.ui
pidgin/resources/account-row.ui
pidgin/resources/contactlistitem.ui
+pidgin/resources/infopane.ui
pidgin/win32/gtkwin32dep.c
pidgin/win32/winpidgin.c
purple-history/purplehistorycore.c