pidgin/pidgin

4adf517478fc
Parents 330cfcc1404d
Children c82a353713f6
Create new widget and store for choosing status primitives

Also port the status and substatus editors to the new widget and store.

Testing Done:
Messed around with the status and substatus editor a lot, seems to be okay.

Reviewed at https://reviews.imfreedom.org/r/1218/
--- a/pidgin/glade/pidgin3.xml.in Mon Feb 07 23:54:15 2022 -0600
+++ b/pidgin/glade/pidgin3.xml.in Thu Feb 10 20:17:10 2022 -0600
@@ -19,6 +19,8 @@
<glade-widget-class name="PidginProtocolStore" generic-name="protocol_store" title="ProtocolStore"/>
<glade-widget-class name="PidginScrollBook" generic-name="scroll_book" title="ScrollBook"/>
<glade-widget-class name="PidginStatusBox" generic-name="status_box" title="StatusBox"/>
+ <glade-widget-class name="PidginStatusPrimitiveChooser" generic-name="status_primitive_chooser" title="StatusPrimitiveChooser"/>
+ <glade-widget-class name="PidginStatusPrimitiveStore" generic-name="status_primitive_store" title="StatusPrimitiveStore"/>
</glade-widget-classes>
<glade-widget-group name="pidgin" title="Pidgin">
<glade-widget-class-ref name="PidginAccountChooser"/>
@@ -39,5 +41,7 @@
<glade-widget-class-ref name="PidginProtocolStore"/>
<glade-widget-class-ref name="PidginScrollBook"/>
<glade-widget-class-ref name="PidginStatusBox"/>
+ <glade-widget-class-ref name="PidginStatusPrimitiveChooser"/>
+ <glade-widget-class-ref name="PidginStatusPrimitiveStore"/>
</glade-widget-group>
</glade-catalog>
--- a/pidgin/gtksavedstatuses.c Mon Feb 07 23:54:15 2022 -0600
+++ b/pidgin/gtksavedstatuses.c Thu Feb 10 20:17:10 2022 -0600
@@ -32,6 +32,9 @@
#include "pidgindialog.h"
#include "pidginiconname.h"
+#include "pidginstatusprimitivechooser.h"
+#include "pidginstatusprimitivestore.h"
+
/*
* TODO: Should attach to the account-deleted and account-added signals
* and update the GtkListStores in any StatusEditor windows that
@@ -128,7 +131,6 @@
PurpleAccount *account;
GtkWidget *window;
- GtkListStore *model;
GtkComboBox *box;
GtkWidget *message_view;
GtkTextBuffer *message_buffer;
@@ -805,61 +807,6 @@
gtk_widget_set_sensitive(GTK_WIDGET(dialog->save_button), (*text != '\0'));
}
-static GtkWidget *
-create_status_type_menu(PurpleStatusPrimitive type)
-{
- int i;
- GtkWidget *dropdown;
- GtkListStore *store;
- GtkTreeIter iter;
- GtkCellRenderer *renderer;
-
- store = gtk_list_store_new(STATUS_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
-
- for (i = PURPLE_STATUS_UNSET + 1; i < PURPLE_STATUS_NUM_PRIMITIVES; i++)
- {
- /* Someone should fix this for 3.0.0. The independent boolean
- * should probably be set on the status type, not the status.
- * I guess that would prevent third party plugins from creating
- * independent statuses?
- */
- if (i == PURPLE_STATUS_MOBILE ||
- i == PURPLE_STATUS_MOOD ||
- i == PURPLE_STATUS_TUNE)
- /*
- * Special-case these. They're intended to be independent
- * status types, so don't show them in the list.
- */
- continue;
-
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter,
- STATUS_COLUMN_ICON, pidgin_icon_name_from_status_primitive(i, NULL),
- STATUS_COLUMN_STATUS_ID, purple_primitive_get_id_from_type(i),
- STATUS_COLUMN_STATUS_NAME, purple_primitive_get_name_from_type(i),
- -1);
- }
-
- dropdown = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
-
- renderer = gtk_cell_renderer_pixbuf_new();
- gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, FALSE);
- gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer,
- "icon-name", STATUS_COLUMN_ICON,
- NULL);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, TRUE);
- gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer,
- "text", STATUS_COLUMN_STATUS_NAME,
- NULL);
-
- gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown),
- type - (PURPLE_STATUS_UNSET + 1));
-
- return dropdown;
-}
-
static void edit_substatus(StatusEditor *status_editor, PurpleAccount *account);
static void
@@ -1066,6 +1013,8 @@
GtkWidget *hbox;
GtkWidget *vbox;
GtkWidget *win;
+ GtkListStore *store;
+ PurpleStatusPrimitive primitive = PURPLE_STATUS_AWAY;
if (edit)
{
@@ -1122,11 +1071,16 @@
pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Title:"), sg, entry, TRUE, NULL);
/* Status type */
- if (saved_status != NULL)
- dropdown = create_status_type_menu(purple_savedstatus_get_primitive_type(saved_status));
- else
- dropdown = create_status_type_menu(PURPLE_STATUS_AWAY);
+ if (saved_status != NULL) {
+ primitive = purple_savedstatus_get_primitive_type(saved_status);
+ }
+
+ store = pidgin_status_primitive_store_new();
+ dropdown = pidgin_status_primitive_chooser_new();
dialog->type = GTK_COMBO_BOX(dropdown);
+ gtk_combo_box_set_model(GTK_COMBO_BOX(dropdown), GTK_TREE_MODEL(store));
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(dropdown),
+ purple_primitive_get_id_from_type(primitive));
pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Status:"), sg, dropdown, TRUE, NULL);
/* Status message */
@@ -1215,24 +1169,26 @@
substatus_selection_changed_cb(GtkComboBox *box, gpointer user_data)
{
SubStatusEditor *select = user_data;
- GtkTreeIter iter;
- char *id;
PurpleStatusType *type;
+ PurpleStatusPrimitive primitive;
+ const gchar *id;
- if (!gtk_combo_box_get_active_iter(box, &iter))
+ id = gtk_combo_box_get_active_id(box);
+ if(id == NULL) {
return;
- gtk_tree_model_get(GTK_TREE_MODEL(select->model), &iter,
- STATUS_COLUMN_STATUS_ID, &id,
- -1);
- type = purple_account_get_status_type(select->account, id);
- g_free(id);
+ }
+
+ primitive = purple_primitive_get_type_from_id(id);
+ if(primitive == PURPLE_STATUS_UNSET) {
+ return;
+ }
- if (purple_status_type_get_attr(type, "message") == NULL)
- {
+ type = purple_account_get_status_type_with_primitive(select->account,
+ primitive);
+
+ if(purple_status_type_get_attr(type, "message") == NULL) {
gtk_widget_set_sensitive(select->message_view, FALSE);
- }
- else
- {
+ } else {
gtk_widget_set_sensitive(select->message_view, TRUE);
}
}
@@ -1298,25 +1254,30 @@
StatusEditor *status_editor;
GtkTreeIter iter;
PurpleStatusType *type;
- char *id = NULL;
+ PurpleStatusPrimitive primitive;
+ const char *id = NULL;
char *message = NULL;
const gchar *name = NULL, *icon_name = NULL;
- if (!gtk_combo_box_get_active_iter(dialog->box, &iter))
- {
+ id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(dialog->box));
+ if(id == NULL) {
gtk_widget_destroy(dialog->window);
return;
}
- gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter,
- STATUS_COLUMN_STATUS_ID, &id,
- -1);
- type = purple_account_get_status_type(dialog->account, id);
+ primitive = purple_primitive_get_type_from_id(id);
+ if(primitive == PURPLE_STATUS_UNSET) {
+ gtk_widget_destroy(dialog->window);
+ return;
+ }
+
+ type = purple_account_get_status_type_with_primitive(dialog->account,
+ primitive);
if (purple_status_type_get_attr(type, "message") != NULL) {
message = talkatu_markup_get_html(dialog->message_buffer, NULL);
}
name = purple_status_type_get_name(type);
- icon_name = pidgin_icon_name_from_status_primitive(purple_status_type_get_primitive(type), NULL);
+ icon_name = pidgin_icon_name_from_status_primitive(primitive, NULL);
status_editor = dialog->status_editor;
@@ -1333,7 +1294,6 @@
}
gtk_widget_destroy(dialog->window);
- g_free(id);
g_free(message);
}
@@ -1368,12 +1328,11 @@
GtkWidget *vbox;
GtkWidget *win;
GtkTreeIter iter;
- GtkCellRenderer *rend;
char *status_id = NULL;
char *message = NULL;
gboolean parent_dialog_has_substatus = FALSE;
- GList *list;
- gboolean select = FALSE;
+ GtkListStore *store;
+ PurpleStatusPrimitive primitive = PURPLE_STATUS_AWAY;
g_return_if_fail(status_editor != NULL);
g_return_if_fail(account != NULL);
@@ -1419,23 +1378,13 @@
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_size_group_add_widget(sg, label);
- dialog->model = gtk_list_store_new(STATUS_NUM_COLUMNS,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_STRING);
- combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(dialog->model));
+ store = pidgin_status_primitive_store_new();
+ pidgin_status_primitive_store_set_account(PIDGIN_STATUS_PRIMITIVE_STORE(store),
+ account);
+ combo = pidgin_status_primitive_chooser_new();
+ gtk_combo_box_set_model(GTK_COMBO_BOX(combo), GTK_TREE_MODEL(store));
dialog->box = GTK_COMBO_BOX(combo);
- rend = GTK_CELL_RENDERER(gtk_cell_renderer_pixbuf_new());
- gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), rend, FALSE);
- gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), rend,
- "icon-name", STATUS_COLUMN_ICON, NULL);
-
- rend = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
- gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), rend, TRUE);
- gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), rend,
- "text", STATUS_COLUMN_STATUS_NAME, NULL);
-
g_signal_connect(G_OBJECT(combo), "changed",
G_CALLBACK(substatus_selection_changed_cb), dialog);
@@ -1484,46 +1433,20 @@
}
/* TODO: Else get the generic status type from our parent */
+ if(status_id != NULL) {
+ PurpleStatus *status = purple_account_get_status(account, status_id);
+ PurpleStatusType *type = purple_status_get_status_type(status);
+
+ primitive = purple_status_type_get_primitive(type);
+ }
+
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo),
+ purple_primitive_get_id_from_type(primitive));
+
if (message) {
talkatu_markup_set_html(TALKATU_BUFFER(dialog->message_buffer), message, -1);
}
- for (list = purple_account_get_status_types(account); list; list = list->next)
- {
- PurpleStatusType *status_type;
- const char *id, *name;
- PurpleStatusPrimitive prim;
-
- status_type = list->data;
-
- /*
- * Only allow users to select statuses that are flagged as
- * "user settable" and that aren't independent.
- */
- if (!purple_status_type_is_user_settable(status_type) ||
- purple_status_type_is_independent(status_type))
- continue;
-
- id = purple_status_type_get_id(status_type);
- prim = purple_status_type_get_primitive(status_type);
- name = purple_status_type_get_name(status_type);
-
- gtk_list_store_append(dialog->model, &iter);
- gtk_list_store_set(dialog->model, &iter,
- STATUS_COLUMN_ICON, pidgin_icon_name_from_status_primitive(prim, NULL),
- STATUS_COLUMN_STATUS_ID, id,
- STATUS_COLUMN_STATUS_NAME, name,
- -1);
- if ((status_id != NULL) && purple_strequal(status_id, id))
- {
- gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo), &iter);
- select = TRUE;
- }
- }
-
- if (!select)
- gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
-
if (parent_dialog_has_substatus) {
/* These two were gotten from the parent tree model, so they need to be freed */
g_free(status_id);
--- a/pidgin/meson.build Mon Feb 07 23:54:15 2022 -0600
+++ b/pidgin/meson.build Thu Feb 10 20:17:10 2022 -0600
@@ -51,6 +51,8 @@
'pidginprotocolchooser.c',
'pidginprotocolstore.c',
'pidginscrollbook.c',
+ 'pidginstatusprimitivechooser.c',
+ 'pidginstatusprimitivestore.c',
'pidginstylecontext.c',
'pidgintalkatu.c',
'prefs/pidginprefs.c',
@@ -110,6 +112,8 @@
'pidginprotocolchooser.h',
'pidginprotocolstore.h',
'pidginscrollbook.h',
+ 'pidginstatusprimitivechooser.h',
+ 'pidginstatusprimitivestore.h',
'pidginstylecontext.h',
'pidgintalkatu.h',
]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginstatusprimitivechooser.c Thu Feb 10 20:17:10 2022 -0600
@@ -0,0 +1,56 @@
+/*
+ * 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 <pidgin/pidginstatusprimitivechooser.h>
+
+struct _PidginStatusPrimitiveChooser {
+ GtkComboBox parent;
+};
+
+G_DEFINE_TYPE(PidginStatusPrimitiveChooser, pidgin_status_primitive_chooser,
+ GTK_TYPE_COMBO_BOX)
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+
+static void
+pidgin_status_primitive_chooser_init(PidginStatusPrimitiveChooser *chooser) {
+ gtk_widget_init_template(GTK_WIDGET(chooser));
+}
+
+static void
+pidgin_status_primitive_chooser_class_init(PidginStatusPrimitiveChooserClass *klass) {
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+
+ /* Widget template */
+ gtk_widget_class_set_template_from_resource(
+ widget_class, "/im/pidgin/Pidgin3/statusprimitivechooser.ui");
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+GtkWidget *
+pidgin_status_primitive_chooser_new(void) {
+ return g_object_new(PIDGIN_TYPE_STATUS_PRIMITIVE_CHOOSER, NULL);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginstatusprimitivechooser.h Thu Feb 10 20:17:10 2022 -0600
@@ -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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef PIDGIN_STATUS_PRIMITIVE_CHOOSER_H
+#define PIDGIN_STATUS_PRIMITIVE_CHOOSER_H
+
+#include <gtk/gtk.h>
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+/**
+ * PidginStatusPrimitiveChooser:
+ *
+ * A [class@Gtk.Combobox] for presenting [class@Purple.StatusPrimitive]'s to a
+ * user.
+ *
+ * Since: 3.0.0
+ */
+
+#define PIDGIN_TYPE_STATUS_PRIMITIVE_CHOOSER (pidgin_status_primitive_chooser_get_type())
+G_DECLARE_FINAL_TYPE(PidginStatusPrimitiveChooser,
+ pidgin_status_primitive_chooser, PIDGIN,
+ STATUS_PRIMITIVE_CHOOSER, GtkComboBox)
+
+/**
+ * pidgin_status_primitive_chooser_new:
+ *
+ * Creates a new combo box that contains all of the available status
+ * primitives in purple.
+ *
+ * Returns: (transfer full): The new combo box.
+ *
+ * Since: 3.0.0
+ */
+GtkWidget *pidgin_status_primitive_chooser_new(void);
+
+G_END_DECLS
+
+#endif /* PIDGIN_STATUS_PRIMITIVE_CHOOSER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginstatusprimitivestore.c Thu Feb 10 20:17:10 2022 -0600
@@ -0,0 +1,254 @@
+/*
+ * 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 <pidgin/pidginstatusprimitivestore.h>
+
+#include <pidgin/pidginiconname.h>
+
+struct _PidginStatusPrimitiveStore {
+ GtkListStore parent;
+
+ PurpleAccount *account;
+};
+
+enum {
+ PROP_0,
+ PROP_ACCOUNT,
+ N_PROPERTIES,
+};
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+enum {
+ COL_ID,
+ COL_ICON,
+ COL_TEXT,
+ N_COLUMNS,
+};
+
+G_DEFINE_TYPE(PidginStatusPrimitiveStore, pidgin_status_primitive_store,
+ GTK_TYPE_LIST_STORE)
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static GList *
+pidgin_status_primitive_store_get_primitives_from_account(PidginStatusPrimitiveStore *store)
+{
+ GList *primitives = NULL;
+ GList *list = purple_account_get_status_types(store->account);
+
+ while(list != NULL) {
+ PurpleStatusType *type = (PurpleStatusType *)list->data;
+ PurpleStatusPrimitive primitive;
+ gboolean user_settable = FALSE, independent = FALSE;
+
+ /* iterate to the next item as we already have the data in type. */
+ list = list->next;
+
+ user_settable = purple_status_type_is_user_settable(type);
+ independent = purple_status_type_is_independent(type);
+ if(!user_settable || independent) {
+ continue;
+ }
+
+ primitive = purple_status_type_get_primitive(type);
+
+ primitives = g_list_append(primitives, GINT_TO_POINTER(primitive));
+ }
+
+ return primitives;
+}
+
+static GList *
+pidgin_status_primitive_store_get_primitives(PidginStatusPrimitiveStore *store)
+{
+ GList *primitives = NULL;
+
+ primitives = g_list_append(primitives,
+ GINT_TO_POINTER(PURPLE_STATUS_OFFLINE));
+ primitives = g_list_append(primitives,
+ GINT_TO_POINTER(PURPLE_STATUS_AVAILABLE));
+ primitives = g_list_append(primitives,
+ GINT_TO_POINTER(PURPLE_STATUS_UNAVAILABLE));
+ primitives = g_list_append(primitives,
+ GINT_TO_POINTER(PURPLE_STATUS_INVISIBLE));
+ primitives = g_list_append(primitives,
+ GINT_TO_POINTER(PURPLE_STATUS_AWAY));
+ primitives = g_list_append(primitives,
+ GINT_TO_POINTER(PURPLE_STATUS_EXTENDED_AWAY));
+
+ return primitives;
+}
+
+static void
+pidgin_status_primitive_store_populate(PidginStatusPrimitiveStore *store) {
+ GList *primitives = NULL;
+
+ /* clear out the list */
+ gtk_list_store_clear(GTK_LIST_STORE(store));
+
+ /* Get all the primitives and add them. */
+ if(PURPLE_IS_ACCOUNT(store->account)) {
+ primitives = pidgin_status_primitive_store_get_primitives_from_account(store);
+ } else {
+ primitives = pidgin_status_primitive_store_get_primitives(store);
+ }
+
+ while(primitives != NULL) {
+ PurpleStatusPrimitive primitive = GPOINTER_TO_INT(primitives->data);
+ GtkTreeIter iter;
+
+ gtk_list_store_append(GTK_LIST_STORE(store), &iter);
+ /* clang-format off */
+ gtk_list_store_set(
+ GTK_LIST_STORE(store), &iter,
+ COL_ID, purple_primitive_get_id_from_type(primitive),
+ COL_ICON, pidgin_icon_name_from_status_primitive(primitive, NULL),
+ COL_TEXT, purple_primitive_get_name_from_type(primitive),
+ -1);
+ /* clang-format on */
+
+ primitives = g_list_delete_link(primitives, primitives);
+ }
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+
+static void
+pidgin_status_primitive_store_get_property(GObject *obj, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ PidginStatusPrimitiveStore *store = PIDGIN_STATUS_PRIMITIVE_STORE(obj);
+
+ switch(param_id) {
+ case PROP_ACCOUNT:
+ g_value_set_object(value,
+ pidgin_status_primitive_store_get_account(store));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+pidgin_status_primitive_store_set_property(GObject *obj, guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PidginStatusPrimitiveStore *store = PIDGIN_STATUS_PRIMITIVE_STORE(obj);
+
+ switch(param_id) {
+ case PROP_ACCOUNT:
+ pidgin_status_primitive_store_set_account(store,
+ g_value_get_object(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+pidgin_status_primitive_store_dispose(GObject *obj) {
+ PidginStatusPrimitiveStore *store = PIDGIN_STATUS_PRIMITIVE_STORE(obj);
+
+ g_clear_object(&store->account);
+
+ G_OBJECT_CLASS(pidgin_status_primitive_store_parent_class)->dispose(obj);
+}
+
+static void
+pidgin_status_primitive_store_constructed(GObject *obj) {
+ PidginStatusPrimitiveStore *store = PIDGIN_STATUS_PRIMITIVE_STORE(obj);
+
+ G_OBJECT_CLASS(pidgin_status_primitive_store_parent_class)->constructed(obj);
+
+ /* This exists to populate the store if it was created without a value for
+ * the account property.
+ */
+ pidgin_status_primitive_store_populate(store);
+}
+
+static void
+pidgin_status_primitive_store_init(PidginStatusPrimitiveStore *store) {
+ GType types[N_COLUMNS] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING };
+
+ gtk_list_store_set_column_types(GTK_LIST_STORE(store), N_COLUMNS, types);
+}
+
+static void
+pidgin_status_primitive_store_class_init(PidginStatusPrimitiveStoreClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ obj_class->get_property = pidgin_status_primitive_store_get_property;
+ obj_class->set_property = pidgin_status_primitive_store_set_property;
+ obj_class->constructed = pidgin_status_primitive_store_constructed;
+ obj_class->dispose = pidgin_status_primitive_store_dispose;
+
+ /**
+ * PidginStatusPrimitiveStore::account:
+ *
+ * The account whose statuses to display.
+ *
+ * Since: 3.0.0
+ */
+ /* clang-format off */
+ properties[PROP_ACCOUNT] = g_param_spec_object(
+ "account", "account",
+ "The account whose statuses to display",
+ PURPLE_TYPE_ACCOUNT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ /* clang-format on */
+
+ g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+GtkListStore *
+pidgin_status_primitive_store_new(void) {
+ return g_object_new(PIDGIN_TYPE_STATUS_PRIMITIVE_STORE, NULL);
+}
+
+void
+pidgin_status_primitive_store_set_account(PidginStatusPrimitiveStore *store,
+ PurpleAccount *account)
+{
+ g_return_if_fail(PIDGIN_IS_STATUS_PRIMITIVE_STORE(store));
+
+ if(g_set_object(&store->account, account)) {
+ pidgin_status_primitive_store_populate(store);
+
+ g_object_notify_by_pspec(G_OBJECT(store), properties[PROP_ACCOUNT]);
+ }
+}
+
+PurpleAccount *
+pidgin_status_primitive_store_get_account(PidginStatusPrimitiveStore *store) {
+ g_return_val_if_fail(PIDGIN_IS_STATUS_PRIMITIVE_STORE(store), NULL);
+
+ return store->account;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginstatusprimitivestore.h Thu Feb 10 20:17:10 2022 -0600
@@ -0,0 +1,82 @@
+/*
+ * 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/>.
+ */
+
+#ifndef PIDGIN_STATUS_PRIMITIVE_STORE_H
+#define PIDGIN_STATUS_PRIMITIVE_STORE_H
+
+#include <gtk/gtk.h>
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+/**
+ * PidginStatusPrimitiveStore:
+ *
+ * A [class@Gtk.ListStore] for use with [class@PidginStatusPrimitiveChooser].
+ *
+ * Since: 3.0.0
+ */
+
+#define PIDGIN_TYPE_STATUS_PRIMITIVE_STORE (pidgin_status_primitive_store_get_type())
+G_DECLARE_FINAL_TYPE(PidginStatusPrimitiveStore, pidgin_status_primitive_store,
+ PIDGIN, STATUS_PRIMITIVE_STORE, GtkListStore)
+
+/**
+ * pidgin_status_primitive_store_new:
+ *
+ * Creates a new [class@Gtk.ListStore] that contains status primitives in
+ * purple.
+ *
+ * Returns: (transfer full): The new list store.
+ *
+ * Since: 3.0.0
+ */
+GtkListStore *pidgin_status_primitive_store_new(void);
+
+/**
+ * pidgin_status_primitive_store_set_account:
+ * @store: The status primitive store instance.
+ * @account: (nullable): The account to use.
+ *
+ * Sets the [class@Purple.Account] whose status primitives to show. If %NULL,
+ * all status primitives will be displayed.
+ *
+ * Since: 3.0.0
+ */
+void pidgin_status_primitive_store_set_account(PidginStatusPrimitiveStore *store, PurpleAccount *account);
+
+/**
+ * pidgin_status_primitive_store_get_account:
+ * @store: The store instance.
+ *
+ * Gets the [class@Purple.Account] that's associated with @store.
+ *
+ * Returns: (transfer none): The account of %NULL.
+ *
+ * Since: 3.0.0
+ */
+PurpleAccount *pidgin_status_primitive_store_get_account(PidginStatusPrimitiveStore *store);
+
+G_END_DECLS
+
+#endif /* PIDGIN_STATUS_PRIMITIVE_STORE_H */
--- a/pidgin/resources/pidgin.gresource.xml Mon Feb 07 23:54:15 2022 -0600
+++ b/pidgin/resources/pidgin.gresource.xml Thu Feb 10 20:17:10 2022 -0600
@@ -34,6 +34,7 @@
<file compressed="true">Xfer/xfer.ui</file>
<file compressed="true">closebutton.ui</file>
<file compressed="true">gtk/menus.ui</file>
+ <file compressed="true">statusprimitivechooser.ui</file>
<file>icons/16x16/status/pidgin-user-available.png</file>
<file>icons/16x16/status/pidgin-user-away.png</file>
<file>icons/16x16/status/pidgin-user-busy.png</file>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/resources/statusprimitivechooser.ui Thu Feb 10 20:17:10 2022 -0600
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2
+
+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, see <https://www.gnu.org/licenses/>.
+
+-->
+<interface>
+ <requires lib="gtk+" version="3.24"/>
+ <!-- interface-license-type gplv2 -->
+ <!-- interface-name Pidgin -->
+ <!-- interface-description Internet Messenger -->
+ <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+ <template class="PidginStatusPrimitiveChooser" parent="GtkComboBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="id-column">0</property>
+ <child>
+ <object class="GtkCellRendererPixbuf"/>
+ <attributes>
+ <attribute name="icon-name">1</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="markup">2</attribute>
+ </attributes>
+ </child>
+ </template>
+</interface>
--- a/po/POTFILES.in Mon Feb 07 23:54:15 2022 -0600
+++ b/po/POTFILES.in Thu Feb 10 20:17:10 2022 -0600
@@ -365,6 +365,8 @@
pidgin/pidginprotocolchooser.c
pidgin/pidginprotocolstore.c
pidgin/pidginscrollbook.c
+pidgin/pidginstatusprimitivechooser.c
+pidgin/pidginstatusprimitivestore.c
pidgin/pidginstylecontext.c
pidgin/pidgintalkatu.c
pidgin/plugins/disco/gtkdisco.c