pidgin/pidgin

Parents 8f6c0247f9f2
Children 65fd2cd524e5
Move the mood api to it's own files and remove the remaining bits of the old menu bar from gtkblist
--- a/doc/reference/pidgin/pidgin-docs.xml Tue Apr 07 01:20:01 2020 -0500
+++ b/doc/reference/pidgin/pidgin-docs.xml Tue Apr 07 02:27:08 2020 -0500
@@ -65,6 +65,7 @@
<xi:include href="xml/pidginlog.xml" />
<xi:include href="xml/pidginmenutray.xml" />
<xi:include href="xml/pidginmessage.xml" />
+ <xi:include href="xml/pidginmooddialog.xml" />
<xi:include href="xml/pidginplugininfo.xml" />
<xi:include href="xml/pidginpluginsdialog.xml" />
<xi:include href="xml/pidginpluginsmenu.xml" />
--- a/pidgin/gtkblist.c Tue Apr 07 01:20:01 2020 -0500
+++ b/pidgin/gtkblist.c Tue Apr 07 02:27:08 2020 -0500
@@ -60,6 +60,7 @@
#include "pidgin/pidgindebug.h"
#include "pidgin/pidgingdkpixbuf.h"
#include "pidgin/pidginlog.h"
+#include "pidgin/pidginmooddialog.h"
#include "pidgin/pidginplugininfo.h"
#include "pidgin/pidgintooltip.h"
#include "pidginmenutray.h"
@@ -3249,287 +3250,6 @@
return FALSE;
}
-static char *get_mood_icon_path(const char *mood)
-{
- char *path;
-
- if (purple_strequal(mood, "busy")) {
- path = g_build_filename(PURPLE_DATADIR, "pidgin", "icons",
- "hicolor", "16x16", "status", "user-busy.png", NULL);
- } else if (purple_strequal(mood, "hiptop")) {
- path = g_build_filename(PURPLE_DATADIR, "pidgin", "icons",
- "hicolor", "16x16", "emblems", "emblem-hiptop.png",
- NULL);
- } else {
- char *filename = g_strdup_printf("%s.png", mood);
- path = g_build_filename(PURPLE_DATADIR, "pixmaps", "pidgin",
- "emotes", "small", filename, NULL);
- g_free(filename);
- }
- return path;
-}
-
-static void
-update_status_with_mood(PurpleAccount *account, const gchar *mood,
- const gchar *text)
-{
- if (mood && *mood) {
- if (text) {
- purple_account_set_status(account, "mood", TRUE,
- PURPLE_MOOD_NAME, mood,
- PURPLE_MOOD_COMMENT, text,
- NULL);
- } else {
- purple_account_set_status(account, "mood", TRUE,
- PURPLE_MOOD_NAME, mood,
- NULL);
- }
- } else {
- purple_account_set_status(account, "mood", FALSE, NULL);
- }
-}
-
-static void
-edit_mood_cb(PurpleConnection *gc, PurpleRequestFields *fields)
-{
- PurpleRequestField *mood_field;
- GList *l;
-
- mood_field = purple_request_fields_get_field(fields, "mood");
- l = purple_request_field_list_get_selected(mood_field);
-
- if (l) {
- const char *mood = purple_request_field_list_get_data(mood_field, l->data);
-
- if (gc) {
- const char *text;
- PurpleAccount *account = purple_connection_get_account(gc);
-
- if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES) {
- PurpleRequestField *text_field;
- text_field = purple_request_fields_get_field(fields, "text");
- text = purple_request_field_string_get_value(text_field);
- } else {
- text = NULL;
- }
-
- update_status_with_mood(account, mood, text);
- } else {
- GList *accounts = purple_accounts_get_all_active();
-
- for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
- PurpleAccount *account = (PurpleAccount *) accounts->data;
- PurpleConnection *gc = purple_account_get_connection(account);
-
- if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) {
- update_status_with_mood(account, mood, NULL);
- }
- }
- }
- }
-}
-
-static void
-global_moods_for_each(gpointer key, gpointer value, gpointer user_data)
-{
- GList **out_moods = (GList **) user_data;
- PurpleMood *mood = (PurpleMood *) value;
-
- *out_moods = g_list_append(*out_moods, mood);
-}
-
-static PurpleMood *
-get_global_moods(void)
-{
- GHashTable *global_moods =
- g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
- GHashTable *mood_counts =
- g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
- GList *accounts = purple_accounts_get_all_active();
- PurpleMood *result = NULL;
- GList *out_moods = NULL;
- int i = 0;
- int num_accounts = 0;
-
- for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
- PurpleAccount *account = (PurpleAccount *) accounts->data;
- if (purple_account_is_connected(account)) {
- PurpleConnection *gc = purple_account_get_connection(account);
-
- if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS) {
- PurpleProtocol *protocol = purple_connection_get_protocol(gc);
- PurpleMood *mood = NULL;
-
- for (mood = purple_protocol_client_iface_get_moods(protocol, account) ;
- mood->mood != NULL ; mood++) {
- int mood_count =
- GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood));
-
- if (!g_hash_table_lookup(global_moods, mood->mood)) {
- g_hash_table_insert(global_moods, (gpointer)mood->mood, mood);
- }
- g_hash_table_insert(mood_counts, (gpointer)mood->mood,
- GINT_TO_POINTER(mood_count + 1));
- }
-
- num_accounts++;
- }
- }
- }
-
- g_hash_table_foreach(global_moods, global_moods_for_each, &out_moods);
- result = g_new0(PurpleMood, g_hash_table_size(global_moods) + 1);
-
- while (out_moods) {
- PurpleMood *mood = (PurpleMood *) out_moods->data;
- int in_num_accounts =
- GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood));
-
- if (in_num_accounts == num_accounts) {
- /* mood is present in all accounts supporting moods */
- result[i].mood = mood->mood;
- result[i].description = mood->description;
- i++;
- }
- out_moods = g_list_delete_link(out_moods, out_moods);
- }
-
- g_hash_table_destroy(global_moods);
- g_hash_table_destroy(mood_counts);
-
- return result;
-}
-
-/* get current set mood for all mood-supporting accounts, or NULL if not set
- or not set to the same on all */
-static const gchar *
-get_global_mood_status(void)
-{
- GList *accounts = purple_accounts_get_all_active();
- const gchar *found_mood = NULL;
-
- for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
- PurpleAccount *account = (PurpleAccount *) accounts->data;
-
- if (purple_account_is_connected(account) &&
- (purple_connection_get_flags(purple_account_get_connection(account)) &
- PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) {
- PurplePresence *presence = purple_account_get_presence(account);
- PurpleStatus *status = purple_presence_get_status(presence, "mood");
- const gchar *curr_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
-
- if (found_mood != NULL && !purple_strequal(curr_mood, found_mood)) {
- /* found a different mood */
- found_mood = NULL;
- break;
- } else {
- found_mood = curr_mood;
- }
- }
- }
-
- return found_mood;
-}
-
-static void
-set_mood_cb(GtkWidget *widget, PurpleAccount *account)
-{
- const char *current_mood;
- PurpleRequestFields *fields;
- PurpleRequestFieldGroup *g;
- PurpleRequestField *f;
- PurpleConnection *gc = NULL;
- PurpleProtocol *protocol = NULL;
- PurpleMood *mood;
- PurpleMood *global_moods = NULL;
-
- if (account) {
- PurplePresence *presence = purple_account_get_presence(account);
- PurpleStatus *status = purple_presence_get_status(presence, "mood");
- gc = purple_account_get_connection(account);
- g_return_if_fail(purple_connection_get_protocol(gc) != NULL);
- protocol = purple_connection_get_protocol(gc);
- current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
- } else {
- current_mood = get_global_mood_status();
- }
-
- fields = purple_request_fields_new();
- g = purple_request_field_group_new(NULL);
- f = purple_request_field_list_new("mood", _("Please select your mood from the list"));
-
- purple_request_field_list_add_icon(f, _("None"), NULL, "");
- if (current_mood == NULL)
- purple_request_field_list_add_selected(f, _("None"));
-
- /* TODO: rlaager wants this sorted. */
- /* TODO: darkrain wants it sorted post-translation */
- if (account && PURPLE_PROTOCOL_IMPLEMENTS(protocol, CLIENT, get_moods)) {
- mood = purple_protocol_client_iface_get_moods(protocol, account);
- } else {
- mood = global_moods = get_global_moods();
- }
- for ( ; mood->mood != NULL ; mood++) {
- char *path;
-
- if (mood->description == NULL) {
- continue;
- }
-
- path = get_mood_icon_path(mood->mood);
- purple_request_field_list_add_icon(f, _(mood->description),
- path, (gpointer)mood->mood);
- g_free(path);
-
- if (current_mood && purple_strequal(current_mood, mood->mood))
- purple_request_field_list_add_selected(f, _(mood->description));
- }
- purple_request_field_group_add_field(g, f);
-
- purple_request_fields_add_group(fields, g);
-
- /* if the connection allows setting a mood message */
- if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES)) {
- g = purple_request_field_group_new(NULL);
- f = purple_request_field_string_new("text",
- _("Message (optional)"), NULL, FALSE);
- purple_request_field_group_add_field(g, f);
- purple_request_fields_add_group(fields, g);
- }
-
- purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"),
- NULL, fields,
- _("OK"), G_CALLBACK(edit_mood_cb),
- _("Cancel"), NULL,
- purple_request_cpar_from_connection(gc), gc);
-
- g_free(global_moods);
-}
-
-static void
-set_mood_show(void)
-{
- set_mood_cb(NULL, NULL);
-}
-
-/***************************************************
- * Crap *
- ***************************************************/
-static const GtkActionEntry blist_menu_entries[] = {
- /* Tools */
- { "ToolsMenu", NULL, N_("_Tools"), NULL, NULL, NULL },
- { "SetMood", NULL, N_("Set _Mood"), "<control>D", NULL, set_mood_show },
-};
-
-static const char *blist_menu =
-"<ui>"
- "<menubar name='BList'>"
- "<menu action='ToolsMenu'>"
- "<menuitem action='SetMood'/>"
- "</menu>"
- "</menubar>"
-"</ui>";
-
/*********************************************************
* Private Utility functions *
*********************************************************/
@@ -3928,7 +3648,7 @@
if (!(name && *name))
return NULL;
- path = get_mood_icon_path(name);
+ path = pidgin_mood_get_icon_path(name);
} else {
filename = g_strdup_printf("emblem-%s.png", name);
path = g_build_filename(PURPLE_DATADIR, "pidgin", "icons",
@@ -5429,7 +5149,6 @@
void *handle;
GSimpleActionGroup *actions;
GtkTreeViewColumn *column;
- GtkWidget *menu;
GtkWidget *sep;
GtkWidget *infobar;
GtkWidget *content_area;
@@ -5437,9 +5156,6 @@
GtkWidget *close;
gchar *text;
const char *theme_name;
- GtkActionGroup *action_group;
- GError *error;
- GtkAccelGroup *accel_group;
GtkTreeSelection *selection;
GtkTargetEntry dte[] = {{"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW},
{"application/x-im-contact", 0, DRAG_BUDDY},
@@ -5496,38 +5212,11 @@
gtk_widget_insert_action_group(gtkblist->window, "blist",
G_ACTION_GROUP(actions));
- action_group = gtk_action_group_new("BListActions");
- gtk_action_group_set_translation_domain(action_group, PACKAGE);
- gtk_action_group_add_actions(action_group,
- blist_menu_entries,
- G_N_ELEMENTS(blist_menu_entries),
- GTK_WINDOW(gtkblist->window));
-
- gtkblist->ui = gtk_ui_manager_new();
- gtk_ui_manager_insert_action_group(gtkblist->ui, action_group, 0);
-
- accel_group = gtk_ui_manager_get_accel_group(gtkblist->ui);
- gtk_window_add_accel_group(GTK_WINDOW(gtkblist->window), accel_group);
- pidgin_load_accels();
- g_signal_connect(G_OBJECT(accel_group), "accel-changed", G_CALLBACK(pidgin_save_accels_cb), NULL);
-
- error = NULL;
- if (!gtk_ui_manager_add_ui_from_string(gtkblist->ui, blist_menu, -1, &error))
- {
- g_message("building menus failed: %s", error->message);
- g_error_free(error);
- exit(EXIT_FAILURE);
- }
-
- menu = gtk_ui_manager_get_widget(gtkblist->ui, "/BList");
- gtk_widget_show(menu);
- gtk_box_pack_start(GTK_BOX(gtkblist->main_vbox), menu, FALSE, FALSE, 0);
-
gtkblist->menu = pidgin_buddy_list_menu_new();
gtk_box_pack_start(GTK_BOX(gtkblist->main_vbox), gtkblist->menu, FALSE,
FALSE, 0);
- gtkblist->menutray = pidgin_buddy_list_menu_get_menu_tray(gtkblist->menu);
+ gtkblist->menutray = pidgin_buddy_list_menu_get_menu_tray(PIDGIN_BUDDY_LIST_MENU(gtkblist->menu));
/****************************** Notebook *************************************/
gtkblist->notebook = gtk_notebook_new();
@@ -7214,7 +6903,6 @@
gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL;
g_clear_object(&gtkblist->treemodel);
- g_object_unref(G_OBJECT(gtkblist->ui));
g_object_unref(G_OBJECT(gtkblist->empty_avatar));
g_clear_object(&priv->current_theme);
@@ -7572,7 +7260,7 @@
GMenu *menu = NULL;
GList *l;
- if ((gtkblist == NULL) || (gtkblist->ui == NULL))
+ if(gtkblist == NULL)
return;
/* create the gmenu */
--- a/pidgin/gtkblist.h Tue Apr 07 01:20:01 2020 -0500
+++ b/pidgin/gtkblist.h Tue Apr 07 02:27:08 2020 -0500
@@ -119,7 +119,6 @@
GtkCellRenderer *text_rend;
- GtkUIManager *ui;
GtkWidget *menu;
GtkWidget *menutray;
GtkWidget *menutrayicon;
--- a/pidgin/meson.build Tue Apr 07 01:20:01 2020 -0500
+++ b/pidgin/meson.build Tue Apr 07 02:27:08 2020 -0500
@@ -46,6 +46,7 @@
'pidginlog.c',
'pidginmenutray.c',
'pidginmessage.c',
+ 'pidginmooddialog.c',
'pidginplugininfo.c',
'pidginpluginsdialog.c',
'pidginpluginsmenu.c',
@@ -105,6 +106,7 @@
'pidginlog.h',
'pidginmenutray.h',
'pidginmessage.h',
+ 'pidginmooddialog.h',
'pidginplugininfo.h',
'pidginpluginsdialog.h',
'pidginpluginsmenu.h',
--- a/pidgin/pidginaccountactionsmenu.c Tue Apr 07 01:20:01 2020 -0500
+++ b/pidgin/pidginaccountactionsmenu.c Tue Apr 07 02:27:08 2020 -0500
@@ -26,8 +26,9 @@
#include "internal.h"
+#include "pidgin/gtkaccount.h"
#include "pidgin/pidgin.h"
-#include "pidgin/gtkaccount.h"
+#include "pidgin/pidginmooddialog.h"
struct _PidginAccountActionsMenu {
GtkMenu parent;
@@ -64,7 +65,9 @@
static void
pidgin_account_actions_menu_set_mood_cb(GtkMenuItem *item, gpointer data) {
- g_warning("open the mood dialog");
+ PidginAccountActionsMenu *menu = PIDGIN_ACCOUNT_ACTIONS_MENU(data);
+
+ pidgin_mood_dialog_show(menu->account);
}
static void
--- a/pidgin/pidginactiongroup.c Tue Apr 07 01:20:01 2020 -0500
+++ b/pidgin/pidginactiongroup.c Tue Apr 07 02:27:08 2020 -0500
@@ -36,6 +36,7 @@
#include "pidgin/gtkxfer.h"
#include "pidgin/pidginabout.h"
#include "pidgin/pidginlog.h"
+#include "pidgin/pidginmooddialog.h"
struct _PidginActionGroup {
GSimpleActionGroup parent;
@@ -56,6 +57,7 @@
PIDGIN_ACTION_GET_USER_INFO,
PIDGIN_ACTION_NEW_MESSAGE,
PIDGIN_ACTION_PRIVACY,
+ PIDGIN_ACTION_SET_MOOD,
};
static const gchar *pidgin_action_group_chat_actions[] = {
@@ -604,6 +606,13 @@
}
static void
+pidgin_action_group_set_mood(GSimpleAction *simple, GVariant *parameter,
+ gpointer data)
+{
+ pidgin_mood_dialog_show(NULL);
+}
+
+static void
pidgin_action_group_show_buddy_icons(GSimpleAction *action, GVariant *value,
gpointer data)
{
@@ -731,6 +740,9 @@
.name = PIDGIN_ACTION_ROOM_LIST,
.activate = pidgin_action_group_room_list,
}, {
+ .name = PIDGIN_ACTION_SET_MOOD,
+ .activate = pidgin_action_group_set_mood,
+ }, {
.name = PIDGIN_ACTION_SHOW_BUDDY_ICONS,
.state = "false",
.change_state = pidgin_action_group_show_buddy_icons,
--- a/pidgin/pidginactiongroup.h Tue Apr 07 01:20:01 2020 -0500
+++ b/pidgin/pidginactiongroup.h Tue Apr 07 02:27:08 2020 -0500
@@ -152,6 +152,13 @@
#define PIDGIN_ACTION_ROOM_LIST ("room-list")
/**
+ * PIDGIN_ACTION_SET_MOOD:
+ *
+ * A constant that represents the set-mood action.
+ */
+#define PIDGIN_ACTION_SET_MOOD ("set-mood")
+
+/**
* PIDGIN_ACTION_SHOW_BUDDY_ICONS:
*
* A constant that represents the show-buddy-icons action.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginmooddialog.c Tue Apr 07 02:27:08 2020 -0500
@@ -0,0 +1,316 @@
+/*
+ * 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
+ */
+
+#include "pidgin/pidginmooddialog.h"
+
+#include "internal.h"
+
+/*< private >
+ * pidgin_mood_update_status:
+ * @account: The #PurpleAccount instance.
+ * @mood: The id of the new mood.
+ * @text: The new status text.
+ *
+ * Updates the current status for @account with the given @mood and @text.
+ */
+static void
+update_status_with_mood(PurpleAccount *account, const gchar *mood,
+ const gchar *text)
+{
+ if (mood && *mood) {
+ if (text) {
+ purple_account_set_status(account, "mood", TRUE,
+ PURPLE_MOOD_NAME, mood,
+ PURPLE_MOOD_COMMENT, text,
+ NULL);
+ } else {
+ purple_account_set_status(account, "mood", TRUE,
+ PURPLE_MOOD_NAME, mood,
+ NULL);
+ }
+ } else {
+ purple_account_set_status(account, "mood", FALSE, NULL);
+ }
+}
+
+/*< private
+ * pidgin_mood_edit_cb:
+ * @gc: The #PurpleConnection instance.
+ * @fields: The #PurpleRequestFields
+ *
+ * This a callback function for when the request dialog has been accepted.
+ */
+static void
+pidgin_mood_dialog_edit_cb(PurpleConnection *gc, PurpleRequestFields *fields) {
+ PurpleRequestField *mood_field;
+ GList *l;
+ const gchar *mood = NULL;
+
+ mood_field = purple_request_fields_get_field(fields, "mood");
+ l = purple_request_field_list_get_selected(mood_field);
+
+ if(l == NULL) {
+ return;
+ }
+
+ mood = purple_request_field_list_get_data(mood_field, l->data);
+
+ if (gc) {
+ const gchar *text;
+ PurpleAccount *account = purple_connection_get_account(gc);
+
+ if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES) {
+ PurpleRequestField *text_field;
+ text_field = purple_request_fields_get_field(fields, "text");
+ text = purple_request_field_string_get_value(text_field);
+ } else {
+ text = NULL;
+ }
+
+ update_status_with_mood(account, mood, text);
+ } else {
+ GList *accounts = purple_accounts_get_all_active();
+
+ for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
+ PurpleAccount *account = (PurpleAccount *) accounts->data;
+ PurpleConnection *gc = purple_account_get_connection(account);
+
+ if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) {
+ update_status_with_mood(account, mood, NULL);
+ }
+ }
+ }
+}
+
+/*< private >
+ * pidgin_mood_get_global_moods:
+ *
+ * Returns an array of all global moods.
+ *
+ * This function should be in libpurple, and it needs a lot of cleanup. It
+ * should probably also be returning a GList of moods as that's easier to deal
+ * with.
+ *
+ * Also, there is non-deterministic behavior here that the return mood depends
+ * purely on the order that the accounts where connected in. This is probably
+ * okay, but we should look at fixing that somehow.
+ *
+ * Returns: (transfer container): A list of all global moods.
+ */
+static PurpleMood *
+pidgin_mood_get_global_moods(void) {
+ GHashTable *global_moods = NULL;
+ GHashTable *mood_counts = NULL;
+ GList *accounts = NULL;
+ PurpleMood *result = NULL;
+ GList *out_moods = NULL;
+ int i = 0;
+ int num_accounts = 0;
+
+ global_moods = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+ mood_counts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+
+ accounts = purple_accounts_get_all_active();
+ for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
+ PurpleAccount *account = (PurpleAccount *) accounts->data;
+ if (purple_account_is_connected(account)) {
+ PurpleConnection *gc = purple_account_get_connection(account);
+
+ if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS) {
+ PurpleProtocol *protocol = purple_connection_get_protocol(gc);
+ PurpleMood *mood = NULL;
+
+ for (mood = purple_protocol_client_iface_get_moods(protocol, account) ;
+ mood->mood != NULL ; mood++) {
+ int mood_count =
+ GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood));
+
+ if (!g_hash_table_lookup(global_moods, mood->mood)) {
+ g_hash_table_insert(global_moods, (gpointer)mood->mood, mood);
+ }
+ g_hash_table_insert(mood_counts, (gpointer)mood->mood,
+ GINT_TO_POINTER(mood_count + 1));
+ }
+
+ num_accounts++;
+ }
+ }
+ }
+
+ result = g_new0(PurpleMood, g_hash_table_size(global_moods) + 1);
+
+ out_moods = g_hash_table_get_values(global_moods);
+ while (out_moods) {
+ PurpleMood *mood = (PurpleMood *) out_moods->data;
+ int in_num_accounts =
+ GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood));
+
+ if (in_num_accounts == num_accounts) {
+ /* mood is present in all accounts supporting moods */
+ result[i].mood = mood->mood;
+ result[i].description = mood->description;
+ i++;
+ }
+ out_moods = g_list_delete_link(out_moods, out_moods);
+ }
+
+ g_hash_table_destroy(global_moods);
+ g_hash_table_destroy(mood_counts);
+
+ return result;
+}
+
+/*< private >
+ * pidgin_mood_get_global_status:
+ *
+ * Get the currently selected mood name for all mood support accounts. If no
+ * mood is set, or accounts have different moods then %NULL is returned.
+ *
+ * Returns: The currently selected mood name or %NULL if a mood is not set, or
+ * accounts are using different moods.
+ */
+static const gchar *
+pidgin_mood_get_global_status(void) {
+ GList *accounts = purple_accounts_get_all_active();
+ const gchar *found_mood = NULL;
+
+ for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
+ PurpleAccount *account = (PurpleAccount *) accounts->data;
+
+ if (purple_account_is_connected(account) &&
+ (purple_connection_get_flags(purple_account_get_connection(account)) &
+ PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) {
+ PurplePresence *presence = purple_account_get_presence(account);
+ PurpleStatus *status = purple_presence_get_status(presence, "mood");
+ const gchar *curr_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
+
+ if (found_mood != NULL && !purple_strequal(curr_mood, found_mood)) {
+ /* found a different mood */
+ found_mood = NULL;
+ break;
+ } else {
+ found_mood = curr_mood;
+ }
+ }
+ }
+
+ return found_mood;
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+void
+pidgin_mood_dialog_show(PurpleAccount *account) {
+ const gchar *current_mood;
+ PurpleRequestFields *fields;
+ PurpleRequestFieldGroup *g;
+ PurpleRequestField *f;
+ PurpleConnection *gc = NULL;
+ PurpleProtocol *protocol = NULL;
+ PurpleMood *mood;
+ PurpleMood *global_moods = NULL;
+
+ if (account) {
+ PurplePresence *presence = purple_account_get_presence(account);
+ PurpleStatus *status = purple_presence_get_status(presence, "mood");
+ gc = purple_account_get_connection(account);
+ g_return_if_fail(purple_connection_get_protocol(gc) != NULL);
+ protocol = purple_connection_get_protocol(gc);
+ current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
+ } else {
+ current_mood = pidgin_mood_get_global_status();
+ }
+
+ fields = purple_request_fields_new();
+ g = purple_request_field_group_new(NULL);
+ f = purple_request_field_list_new("mood", _("Please select your mood from the list"));
+
+ purple_request_field_list_add_icon(f, _("None"), NULL, "");
+ if (current_mood == NULL)
+ purple_request_field_list_add_selected(f, _("None"));
+
+ /* TODO: rlaager wants this sorted. */
+ /* TODO: darkrain wants it sorted post-translation */
+ if (account && PURPLE_PROTOCOL_IMPLEMENTS(protocol, CLIENT, get_moods)) {
+ mood = purple_protocol_client_iface_get_moods(protocol, account);
+ } else {
+ mood = global_moods = pidgin_mood_get_global_moods();
+ }
+ for ( ; mood->mood != NULL ; mood++) {
+ char *path;
+
+ if (mood->description == NULL) {
+ continue;
+ }
+
+ path = pidgin_mood_get_icon_path(mood->mood);
+ purple_request_field_list_add_icon(f, _(mood->description),
+ path, (gpointer)mood->mood);
+ g_free(path);
+
+ if (current_mood && purple_strequal(current_mood, mood->mood))
+ purple_request_field_list_add_selected(f, _(mood->description));
+ }
+ purple_request_field_group_add_field(g, f);
+
+ purple_request_fields_add_group(fields, g);
+
+ /* if the connection allows setting a mood message */
+ if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES)) {
+ g = purple_request_field_group_new(NULL);
+ f = purple_request_field_string_new("text",
+ _("Message (optional)"), NULL, FALSE);
+ purple_request_field_group_add_field(g, f);
+ purple_request_fields_add_group(fields, g);
+ }
+
+ purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"),
+ NULL, fields,
+ _("OK"), G_CALLBACK(pidgin_mood_dialog_edit_cb),
+ _("Cancel"), NULL,
+ purple_request_cpar_from_connection(gc), gc);
+
+ g_free(global_moods);
+}
+
+gchar *
+pidgin_mood_get_icon_path(const gchar *mood) {
+ gchar *path;
+
+ if(purple_strequal(mood, "busy")) {
+ path = g_build_filename(PURPLE_DATADIR, "pidgin", "icons",
+ "hicolor", "16x16", "status", "user-busy.png", NULL);
+ } else if(purple_strequal(mood, "hiptop")) {
+ path = g_build_filename(PURPLE_DATADIR, "pidgin", "icons",
+ "hicolor", "16x16", "emblems", "emblem-hiptop.png",
+ NULL);
+ } else {
+ gchar *filename = g_strdup_printf("%s.png", mood);
+ path = g_build_filename(PURPLE_DATADIR, "pixmaps", "pidgin",
+ "emotes", "small", filename, NULL);
+ g_free(filename);
+ }
+
+ return path;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginmooddialog.h Tue Apr 07 02:27:08 2020 -0500
@@ -0,0 +1,66 @@
+/*
+ * 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_MOOD_DIALOG_H
+#define PIDGIN_MOOD_DIALOG_H
+
+/**
+ * SECTION:pidginmooddialog
+ * @section_id: pidgin-mood-dialog
+ * @short_description: A dialog for selecting moods
+ * @title: Mood Dialog
+ *
+ * A simple dialog for selecting a global mood as well as a per account mood.
+ */
+
+#include <glib.h>
+
+#include <gtk/gtk.h>
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+/**
+ * pidgin_mood_dialog_show:
+ * @account: (nullable): The #PurpleAccount who's mood to set, or %NULL for the
+ * global mood.
+ *
+ * Presents a dialog to select the mood for @account or the global mood if
+ * @account is %NULL.
+ */
+void pidgin_mood_dialog_show(PurpleAccount *account);
+
+/**
+ * pidgin_mood_get_icon_path:
+ * @mood: The id of the mood.
+ *``
+ * Gets the path to the icon for @mood.
+ *
+ * Returns: (transfer full): The location of the icon for @mood.
+ */
+gchar *pidgin_mood_get_icon_path(const gchar *mood);
+
+G_END_DECLS
+
+#endif /* PIDGIN_MOOD_DIALOG_H */
+