--- a/pidgin/glade/pidgin3.xml.in Sat Nov 14 03:05:16 2020 -0600
+++ b/pidgin/glade/pidgin3.xml.in Sat Nov 14 03:15:43 2020 -0600
@@ -6,6 +6,7 @@
<glade-widget-class name="PidginAccountStore" generic-name="account_store" title="AccountStore"/>
<glade-widget-class name="PidginAccountFilterConnected" generic-name="account_filter_connected" title="FilterConnected"/>
<glade-widget-class name="PidginAccountFilterProtocol" generic-name="account_filter_protocol" title="FilterProtocol"/>
+ <glade-widget-class name="PidginBuddyListMenu" generic-name="buddy_list_menu" title="BuddyListMenu"/> <glade-widget-class name="PidginCloseButton" generic-name="close-button" title="CloseButton"/>
<glade-widget-class name="PidginConversationWindow" generic-name="conversation_window" title="ConversationWindow"/>
<glade-widget-class name="PidginDialog" generic-name="dialog" title="Dialog"/>
@@ -13,6 +14,7 @@
<glade-widget-class name="PidginMenuTray" generic-name="menu_tray" title="MenuTray"/>
<glade-widget-class name="PidginPluginsMenu" generic-name="plugins_menu" title="PluginsMenu"/>
<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="PidginWindow" generic-name="window" title="Window"/>
<glade-widget-group name="pidgin" title="Pidgin">
@@ -21,6 +23,7 @@
<glade-widget-class-ref name="PidginAccountStore"/>
<glade-widget-class-ref name="PidginAccountFilterConnected"/>
<glade-widget-class-ref name="PidginAccountFilterProtocol"/>
+ <glade-widget-class-ref name="PidginBuddyListMenu"/> <glade-widget-class-ref name="PidginCloseButton"/>
<glade-widget-class-ref name="PidginConversationWindow"/>
<glade-widget-class-ref name="PidginDialog"/>
@@ -28,6 +31,7 @@
<glade-widget-class-ref name="PidginMenuTray"/>
<glade-widget-class-ref name="PidginPluginsMenu"/>
<glade-widget-class-ref name="PidginScrollBook"/>
+ <glade-widget-class-ref name="PidginStatusBox"/> <glade-widget-class-ref name="PidginWindow"/>
--- a/pidgin/gtkblist.c Sat Nov 14 03:05:16 2020 -0600
+++ b/pidgin/gtkblist.c Sat Nov 14 03:15:43 2020 -0600
@@ -48,6 +48,7 @@
#include "pidgin/pidginbuddylistmenu.h"
#include "pidgin/pidgincellrendererexpander.h"
#include "pidgin/pidginclosebutton.h"
+#include "pidgin/pidgincontactlist.h" #include "pidgin/pidgincore.h"
#include "pidgin/pidgindebug.h"
#include "pidgin/pidgingdkpixbuf.h"
@@ -5225,15 +5226,16 @@
gtkblist->empty_avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
gdk_pixbuf_fill(gtkblist->empty_avatar, 0x00000000);
- gtkblist->window = pidgin_window_new(_("Buddy List"), 0, "buddy_list", TRUE);
+ gtkblist->window = pidgin_contact_list_new(); g_signal_connect(G_OBJECT(gtkblist->window), "focus-in-event",
G_CALLBACK(blist_focus_cb), gtkblist);
g_signal_connect(G_OBJECT(gtkblist->window), "focus-out-event",
G_CALLBACK(blist_focus_cb), gtkblist);
- gtkblist->main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_widget_show(gtkblist->main_vbox);
- gtk_container_add(GTK_CONTAINER(gtkblist->window), gtkblist->main_vbox);
+ /* the main vbox is already packed and shown via glade, we just need a + * reference to it to pack the rest of our widgets here. + gtkblist->main_vbox = pidgin_contact_list_get_vbox(PIDGIN_CONTACT_LIST(gtkblist->window)); g_signal_connect(G_OBJECT(gtkblist->window), "delete_event", G_CALLBACK(gtk_blist_delete_cb), NULL);
g_signal_connect(G_OBJECT(gtkblist->window), "hide",
@@ -5248,10 +5250,6 @@
gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK);
/******************************* Menu bar *************************************/
- actions = pidgin_action_group_new();
- gtk_widget_insert_action_group(gtkblist->window, "blist",
- G_ACTION_GROUP(actions));
gtkblist->menu = pidgin_buddy_list_menu_new();
gtk_box_pack_start(GTK_BOX(gtkblist->main_vbox), gtkblist->menu, FALSE,
--- a/pidgin/pidginactiongroup.c Sat Nov 14 03:05:16 2020 -0600
+++ b/pidgin/pidginactiongroup.c Sat Nov 14 03:15:43 2020 -0600
@@ -24,51 +24,13 @@
-#include "gtkroomlist.h"
-#include "gtksmiley-manager.h"
-#include "pidginabout.h"
-#include "pidginmooddialog.h"
struct _PidginActionGroup {
GSimpleActionGroup parent;
/******************************************************************************
- *****************************************************************************/
- * This list keeps track of which actions should only be enabled while online.
-static const gchar *pidgin_action_group_online_actions[] = {
- PIDGIN_ACTION_ADD_BUDDY,
- PIDGIN_ACTION_ADD_GROUP,
- PIDGIN_ACTION_GET_USER_INFO,
- PIDGIN_ACTION_NEW_MESSAGE,
- PIDGIN_ACTION_SET_MOOD,
-static const gchar *pidgin_action_group_chat_actions[] = {
- PIDGIN_ACTION_ADD_CHAT,
- PIDGIN_ACTION_JOIN_CHAT,
-static const gchar *pidgin_action_group_room_list_actions[] = {
- PIDGIN_ACTION_ROOM_LIST,
-/******************************************************************************
*****************************************************************************/
@@ -198,188 +160,6 @@
purple_prefs_connect_callback(group, pref_name, callback, group);
- * pidgin_action_group_actions_set_enable:
- * @group: The #PidginActionGroup instance.
- * @actions: The action names.
- * @n_actions: The number of @actions.
- * @enabled: Whether or not to enable the actions.
- * Sets the enabled property of the named actions to @enabled.
-pidgin_action_group_actions_set_enable(PidginActionGroup *group,
- const gchar *const *actions,
- for(i = 0; i < n_actions; i++) {
- GAction *action = NULL;
- const gchar *name = actions[i];
- action = g_action_map_lookup_action(G_ACTION_MAP(group), name);
- g_simple_action_set_enabled(G_SIMPLE_ACTION(action), enabled);
- g_warning("Failed to find action named %s", name);
- * pidgin_action_group_online_actions_set_enable:
- * @group: The #PidginActionGroup instance.
- * @enabled: %TRUE to enable the actions, %FALSE to disable them.
- * Enables/disables the actions that require being online to use.
-pidgin_action_group_online_actions_set_enable(PidginActionGroup *group,
- gint n_actions = G_N_ELEMENTS(pidgin_action_group_online_actions);
- pidgin_action_group_actions_set_enable(group,
- pidgin_action_group_online_actions,
- * pidgin_action_group_chat_actions_set_enable:
- * @group: The #PidginActionGroup instance.
- * @enabled: Whether or not to enable/disable the actions.
- * Sets the enabled state of the chat specific actions to the value of @enabled.
-pidgin_action_group_chat_actions_set_enable(PidginActionGroup *group,
- gint n_actions = G_N_ELEMENTS(pidgin_action_group_chat_actions);
- pidgin_action_group_actions_set_enable(group,
- pidgin_action_group_chat_actions,
- * pidgin_action_group_room_list_actions_set_enable:
- * @group: The #PidginActionGroup instance.
- * @enabled: Whether or not to enable/disable the actions.
- * Sets the enabled state of the room list specific actions to the value of
-pidgin_action_group_room_list_actions_set_enable(PidginActionGroup *group,
- gint n_actions = G_N_ELEMENTS(pidgin_action_group_room_list_actions);
- pidgin_action_group_actions_set_enable(group,
- pidgin_action_group_room_list_actions,
-/******************************************************************************
- * Purple Signal Callbacks
- *****************************************************************************/
-pidgin_action_group_online_cb(gpointer data) {
- pidgin_action_group_online_actions_set_enable(PIDGIN_ACTION_GROUP(data),
-pidgin_action_group_offline_cb(gpointer data) {
- pidgin_action_group_online_actions_set_enable(PIDGIN_ACTION_GROUP(data),
-pidgin_action_group_signed_on_cb(PurpleAccount *account, gpointer data) {
- PidginActionGroup *group = PIDGIN_ACTION_GROUP(data);
- PurpleProtocol *protocol = NULL;
- const gchar *protocol_id = NULL;
- gboolean should_enable_chat = FALSE, should_enable_room_list = FALSE;
- protocol_id = purple_account_get_protocol_id(account);
- protocol = purple_protocols_find(protocol_id);
- /* We assume that the current state is correct, so we don't bother changing
- * state unless the newly connected account implements the chat interface,
- * which would cause a state change.
- should_enable_chat = PURPLE_PROTOCOL_IMPLEMENTS(protocol, CHAT, info);
- if(should_enable_chat) {
- pidgin_action_group_chat_actions_set_enable(group, TRUE);
- /* likewise, for the room list, we only care about enabling in this
- should_enable_room_list = PURPLE_PROTOCOL_IMPLEMENTS(protocol, ROOMLIST,
- if(should_enable_room_list) {
- pidgin_action_group_room_list_actions_set_enable(group, TRUE);
-pidgin_action_group_signed_off_cb(PurpleAccount *account, gpointer data) {
- gboolean should_disable_chat = TRUE, should_disable_room_list = TRUE;
- GList *connections = NULL, *l = NULL;
- /* walk through all the connections, looking for online ones that implement
- * the chat interface. We don't bother checking the account that this
- * signal was emitted for, because it's already offline and will be
- * filtered out by the online check.
- connections = purple_connections_get_all();
- for(l = connections; l != NULL; l = l->next) {
- PurpleConnection *connection = PURPLE_CONNECTION(l->data);
- PurpleProtocol *protocol = NULL;
- /* if the connection isn't online, we don't care about it */
- if(!PURPLE_CONNECTION_IS_CONNECTED(connection)) {
- protocol = purple_connection_get_protocol(connection);
- /* check if the protocol implements the chat interface */
- if(PURPLE_PROTOCOL_IMPLEMENTS(protocol, CHAT, info)) {
- should_disable_chat = FALSE;
- /* check if the protocol implement the room list interface */
- if(PURPLE_PROTOCOL_IMPLEMENTS(protocol, ROOMLIST, get_list)) {
- should_disable_room_list = FALSE;
- /* if we can't disable both, we can bail out of the loop */
- if(!should_disable_chat && !should_disable_room_list) {
- if(should_disable_chat) {
- pidgin_action_group_chat_actions_set_enable(PIDGIN_ACTION_GROUP(data),
- if(should_disable_room_list) {
- pidgin_action_group_room_list_actions_set_enable(PIDGIN_ACTION_GROUP(data),
/******************************************************************************
*****************************************************************************/
@@ -465,133 +245,6 @@
*****************************************************************************/
-pidgin_action_group_about(GSimpleAction *simple, GVariant *parameter,
- GtkWidget *about = pidgin_about_dialog_new();
- gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(window));
- gtk_widget_show_all(about);
-pidgin_action_group_add_buddy(GSimpleAction *simple, GVariant *parameter,
- purple_blist_request_add_buddy(NULL, NULL, NULL, NULL);
-pidgin_action_group_add_chat(GSimpleAction *simple, GVariant *parameter,
- purple_blist_request_add_chat(NULL, NULL, NULL, NULL);
-pidgin_action_group_add_group(GSimpleAction *simple, GVariant *parameter,
- purple_blist_request_add_group();
-pidgin_action_group_buddy_pounces(GSimpleAction *simple, GVariant *parameter,
- pidgin_pounces_manager_show();
-pidgin_action_group_custom_smiley(GSimpleAction *simple, GVariant *parameter,
- pidgin_smiley_manager_show();
-pidgin_action_group_debug(GSimpleAction *simple, GVariant *parameter,
- gboolean old = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/enabled");
- purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/debug/enabled", !old);
-pidgin_action_group_file_transfers(GSimpleAction *simple, GVariant *parameter,
- pidgin_xfer_dialog_show(NULL);
-pidgin_action_group_get_user_info(GSimpleAction *simple, GVariant *parameter,
-pidgin_action_group_join_chat(GSimpleAction *simple, GVariant *parameter,
- pidgin_blist_joinchat_show();
-pidgin_action_group_new_message(GSimpleAction *simple, GVariant *parameter,
-pidgin_action_group_online_help(GSimpleAction *simple, GVariant *parameter,
- purple_notify_uri(NULL, PURPLE_WEBSITE "help");
-pidgin_action_group_preferences(GSimpleAction *simple, GVariant *parameter,
-pidgin_action_group_privacy(GSimpleAction *simple, GVariant *parameter,
- pidgin_privacy_dialog_show();
-pidgin_action_group_quit(GSimpleAction *simple, GVariant *parameter,
-pidgin_action_group_room_list(GSimpleAction *simple, GVariant *parameter,
- pidgin_roomlist_dialog_show();
-pidgin_action_group_set_mood(GSimpleAction *simple, GVariant *parameter,
- pidgin_mood_dialog_show(NULL);
pidgin_action_group_show_buddy_icons(GSimpleAction *action, GVariant *value,
@@ -642,20 +295,6 @@
g_variant_get_string(value, NULL));
-pidgin_action_group_system_log(GSimpleAction *simple, GVariant *parameter,
-pidgin_action_group_view_user_log(GSimpleAction *simple, GVariant *parameter,
/******************************************************************************
*****************************************************************************/
@@ -664,60 +303,8 @@
pidgin_action_group_init(PidginActionGroup *group) {
- gpointer handle = NULL;
GActionEntry entries[] = {
- .name = PIDGIN_ACTION_ABOUT,
- .activate = pidgin_action_group_about,
- .name = PIDGIN_ACTION_ADD_BUDDY,
- .activate = pidgin_action_group_add_buddy,
- .name = PIDGIN_ACTION_ADD_CHAT,
- .activate = pidgin_action_group_add_chat,
- .name = PIDGIN_ACTION_ADD_GROUP,
- .activate = pidgin_action_group_add_group,
- .name = PIDGIN_ACTION_BUDDY_POUNCES,
- .activate = pidgin_action_group_buddy_pounces,
- .name = PIDGIN_ACTION_CUSTOM_SMILEY,
- .activate = pidgin_action_group_custom_smiley,
- .name = PIDGIN_ACTION_DEBUG,
- .activate = pidgin_action_group_debug,
- .name = PIDGIN_ACTION_FILE_TRANSFERS,
- .activate = pidgin_action_group_file_transfers,
- .name = PIDGIN_ACTION_GET_USER_INFO,
- .activate = pidgin_action_group_get_user_info,
- .name = PIDGIN_ACTION_JOIN_CHAT,
- .activate = pidgin_action_group_join_chat,
- .name = PIDGIN_ACTION_NEW_MESSAGE,
- .activate = pidgin_action_group_new_message,
- .name = PIDGIN_ACTION_ONLINE_HELP,
- .activate = pidgin_action_group_online_help,
- .name = PIDGIN_ACTION_PREFERENCES,
- .activate = pidgin_action_group_preferences,
- .name = PIDGIN_ACTION_PRIVACY,
- .activate = pidgin_action_group_privacy,
- .name = PIDGIN_ACTION_QUIT,
- .activate = pidgin_action_group_quit,
- .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,
.change_state = pidgin_action_group_show_buddy_icons,
@@ -742,12 +329,6 @@
.change_state = pidgin_action_group_sort_method,
- .name = PIDGIN_ACTION_SYSTEM_LOG,
- .activate = pidgin_action_group_system_log,
- .name = PIDGIN_ACTION_VIEW_USER_LOG,
- .activate = pidgin_action_group_view_user_log,
@@ -776,35 +357,6 @@
pidgin_action_group_setup_string(group, PIDGIN_ACTION_SORT_METHOD,
PIDGIN_PREFS_ROOT "/blist/sort_type",
pidgin_action_group_sort_method_callback);
- /* assume we are offline and disable all of the actions that require us to
- pidgin_action_group_online_actions_set_enable(group, FALSE);
- pidgin_action_group_chat_actions_set_enable(group, FALSE);
- pidgin_action_group_room_list_actions_set_enable(group, FALSE);
- /* connect to the online and offline signals in purple connections. This
- * is used to toggle states of actions that require being online.
- handle = purple_connections_get_handle();
- purple_signal_connect(handle, "online", group,
- PURPLE_CALLBACK(pidgin_action_group_online_cb),
- purple_signal_connect(handle, "offline", group,
- PURPLE_CALLBACK(pidgin_action_group_offline_cb),
- /* connect to account-signed-on and account-signed-off to toggle actions
- * that depend on specific interfaces in accounts.
- handle = purple_accounts_get_handle();
- purple_signal_connect(handle, "account-signed-on", group,
- PURPLE_CALLBACK(pidgin_action_group_signed_on_cb),
- purple_signal_connect(handle, "account-signed-off", group,
- PURPLE_CALLBACK(pidgin_action_group_signed_off_cb),
--- a/pidgin/pidginapplication.c Sat Nov 14 03:05:16 2020 -0600
+++ b/pidgin/pidginapplication.c Sat Nov 14 03:15:43 2020 -0600
@@ -35,8 +35,19 @@
+#include "gtkroomlist.h" +#include "gtksmiley-manager.h" +#include "pidginabout.h" +#include "pidginmooddialog.h" +#include "pidgin/pidginpluginsdialog.h" struct _PidginApplication {
@@ -67,6 +78,422 @@
G_DEFINE_TYPE(PidginApplication, pidgin_application, GTK_TYPE_APPLICATION)
/******************************************************************************
+ *****************************************************************************/ + * pidgin_application_online_actions: + * This list keeps track of which actions should only be enabled while online. +static const gchar *pidgin_application_online_actions[] = { + * pidgin_application_chat_actions: + * This list keeps track of which actions should only be enabled if a protocol + * supporting groups chats is connected. +static const gchar *pidgin_application_chat_actions[] = { + * pidgin_application_room_list_actions: + * This list keeps track of which actions should only be enabled if an online + * account supports room lists. +static const gchar *pidgin_application_room_list_actions[] = { + * pidgin_action_group_actions_set_enable: + * @group: The #PidginActionGroup instance. + * @actions: The action names. + * @n_actions: The number of @actions. + * @enabled: Whether or not to enable the actions. + * Sets the enabled property of the named actions to @enabled. +pidgin_application_actions_set_enabled(PidginApplication *application, + const gchar *const *actions, + for(i = 0; i < n_actions; i++) { + GAction *action = NULL; + const gchar *name = actions[i]; + action = g_action_map_lookup_action(G_ACTION_MAP(application), name); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), enabled); + g_warning("Failed to find action named %s", name); +pidgin_application_about(GSimpleAction *simple, GVariant *parameter, + GtkWidget *about = pidgin_about_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(window)); + gtk_widget_show_all(about); +pidgin_application_accounts(GSimpleAction *simple, GVariant *parameter, + pidgin_accounts_window_show(); +pidgin_application_add_buddy(GSimpleAction *simple, GVariant *parameter, + purple_blist_request_add_buddy(NULL, NULL, NULL, NULL); +pidgin_application_add_chat(GSimpleAction *simple, GVariant *parameter, + purple_blist_request_add_chat(NULL, NULL, NULL, NULL); +pidgin_application_add_group(GSimpleAction *simple, GVariant *parameter, + purple_blist_request_add_group(); +pidgin_application_buddy_pounces(GSimpleAction *simple, GVariant *parameter, + pidgin_pounces_manager_show(); +pidgin_application_custom_smiley(GSimpleAction *simple, GVariant *parameter, + pidgin_smiley_manager_show(); +pidgin_application_debug(GSimpleAction *simple, GVariant *parameter, + gboolean old = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/enabled"); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/debug/enabled", !old); +pidgin_application_file_transfers(GSimpleAction *simple, GVariant *parameter, + pidgin_xfer_dialog_show(NULL); +pidgin_application_get_user_info(GSimpleAction *simple, GVariant *parameter, +pidgin_application_join_chat(GSimpleAction *simple, GVariant *parameter, + pidgin_blist_joinchat_show(); +pidgin_application_new_message(GSimpleAction *simple, GVariant *parameter, +pidgin_application_online_help(GSimpleAction *simple, GVariant *parameter, + purple_notify_uri(NULL, PURPLE_WEBSITE "help"); +pidgin_application_plugins(GSimpleAction *simple, GVariant *parameter, + GtkWidget *dialog = pidgin_plugins_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(window)); + gtk_widget_show_all(dialog); +pidgin_application_preferences(GSimpleAction *simple, GVariant *parameter, +pidgin_application_privacy(GSimpleAction *simple, GVariant *parameter, + pidgin_privacy_dialog_show(); +pidgin_application_quit(GSimpleAction *simple, GVariant *parameter, +pidgin_application_room_list(GSimpleAction *simple, GVariant *parameter, + pidgin_roomlist_dialog_show(); +pidgin_application_set_mood(GSimpleAction *simple, GVariant *parameter, + pidgin_mood_dialog_show(NULL); +pidgin_application_system_log(GSimpleAction *simple, GVariant *parameter, +pidgin_application_view_user_log(GSimpleAction *simple, GVariant *parameter, +static GActionEntry app_entries[] = { + .activate = pidgin_application_about, + .activate = pidgin_application_add_buddy, + .activate = pidgin_application_add_chat, + .activate = pidgin_application_add_group, + .name = "buddy-pounces", + .activate = pidgin_application_buddy_pounces, + .name = "custom-smiley", + .activate = pidgin_application_custom_smiley, + .activate = pidgin_application_debug, + .name = "file-transfers", + .activate = pidgin_application_file_transfers, + .name = "get-user-info", + .activate = pidgin_application_get_user_info, + .activate = pidgin_application_join_chat, + .name = "manage-accounts", + .activate = pidgin_application_accounts, + .name = "manage-plugins", + .activate = pidgin_application_plugins, + .activate = pidgin_application_new_message, + .activate = pidgin_application_online_help, + .activate = pidgin_application_preferences, + .activate = pidgin_application_privacy, + .activate = pidgin_application_quit, + .activate = pidgin_application_room_list, + .activate = pidgin_application_set_mood, + .activate = pidgin_application_system_log, + .name = "view-user-log", + .activate = pidgin_application_view_user_log, +/****************************************************************************** + * Purple Signal Callbacks + *****************************************************************************/ +pidgin_application_online_cb(gpointer data) { + gint n_actions = G_N_ELEMENTS(pidgin_application_online_actions); + pidgin_application_actions_set_enabled(PIDGIN_APPLICATION(data), + pidgin_application_online_actions, +pidgin_application_offline_cb(gpointer data) { + gint n_actions = G_N_ELEMENTS(pidgin_application_online_actions); + pidgin_application_actions_set_enabled(PIDGIN_APPLICATION(data), + pidgin_application_online_actions, +pidgin_application_signed_on_cb(PurpleAccount *account, gpointer data) { + PidginApplication *application = PIDGIN_APPLICATION(data); + PurpleProtocol *protocol = NULL; + const gchar *protocol_id = NULL; + gboolean should_enable_chat = FALSE, should_enable_room_list = FALSE; + protocol_id = purple_account_get_protocol_id(account); + protocol = purple_protocols_find(protocol_id); + /* We assume that the current state is correct, so we don't bother changing + * state unless the newly connected account implements the chat interface, + * which would cause a state change. + should_enable_chat = PURPLE_PROTOCOL_IMPLEMENTS(protocol, CHAT, info); + if(should_enable_chat) { + n_actions = G_N_ELEMENTS(pidgin_application_chat_actions); + pidgin_application_actions_set_enabled(application, + pidgin_application_chat_actions, + /* likewise, for the room list, we only care about enabling in this + should_enable_room_list = PURPLE_PROTOCOL_IMPLEMENTS(protocol, ROOMLIST, + if(should_enable_room_list) { + n_actions = G_N_ELEMENTS(pidgin_application_room_list_actions); + pidgin_application_actions_set_enabled(application, + pidgin_application_room_list_actions, +pidgin_application_signed_off_cb(PurpleAccount *account, gpointer data) { + PidginApplication *application = PIDGIN_APPLICATION(data); + gboolean should_disable_chat = TRUE, should_disable_room_list = TRUE; + GList *connections = NULL, *l = NULL; + /* walk through all the connections, looking for online ones that implement + * the chat interface. We don't bother checking the account that this + * signal was emitted for, because it's already offline and will be + * filtered out by the online check. + connections = purple_connections_get_all(); + for(l = connections; l != NULL; l = l->next) { + PurpleConnection *connection = PURPLE_CONNECTION(l->data); + PurpleProtocol *protocol = NULL; + /* if the connection isn't online, we don't care about it */ + if(!PURPLE_CONNECTION_IS_CONNECTED(connection)) { + protocol = purple_connection_get_protocol(connection); + /* check if the protocol implements the chat interface */ + if(PURPLE_PROTOCOL_IMPLEMENTS(protocol, CHAT, info)) { + should_disable_chat = FALSE; + /* check if the protocol implements the room list interface */ + if(PURPLE_PROTOCOL_IMPLEMENTS(protocol, ROOMLIST, get_list)) { + should_disable_room_list = FALSE; + /* if we can't disable both, we can bail out of the loop */ + if(!should_disable_chat && !should_disable_room_list) { + if(should_disable_chat) { + n_actions = G_N_ELEMENTS(pidgin_application_chat_actions); + pidgin_application_actions_set_enabled(application, + pidgin_application_chat_actions, + if(should_disable_room_list) { + n_actions = G_N_ELEMENTS(pidgin_application_room_list_actions); + pidgin_application_actions_set_enabled(application, + pidgin_application_room_list_actions, +/****************************************************************************** * GApplication Implementation
*****************************************************************************/
@@ -75,6 +502,7 @@
GList *active_accounts = NULL;
gchar *search_path = NULL;
+ gpointer handle = NULL; G_APPLICATION_CLASS(pidgin_application_parent_class)->startup(application);
@@ -201,6 +629,29 @@
/* TODO: Use GtkApplicationWindow or add a window instead */
g_application_hold(application);
+ /* connect to the online and offline signals in purple connections. This + * is used to toggle states of actions that require being online. + handle = purple_connections_get_handle(); + purple_signal_connect(handle, "online", application, + PURPLE_CALLBACK(pidgin_application_online_cb), + purple_signal_connect(handle, "offline", application, + PURPLE_CALLBACK(pidgin_application_offline_cb), + /* connect to account-signed-on and account-signed-off to toggle actions + * that depend on specific interfaces in accounts. + handle = purple_accounts_get_handle(); + purple_signal_connect(handle, "account-signed-on", application, + PURPLE_CALLBACK(pidgin_application_signed_on_cb), + purple_signal_connect(handle, "account-signed-off", application, + PURPLE_CALLBACK(pidgin_application_signed_off_cb), @@ -256,10 +707,36 @@
pidgin_application_init(PidginApplication *application) {
GApplication *gapp = G_APPLICATION(application);
+ gboolean online = FALSE; g_application_add_main_option_entries(gapp, option_entries);
g_application_add_option_group(gapp, purple_get_option_group());
g_application_add_option_group(gapp, gplugin_get_option_group());
+ g_action_map_add_action_entries(G_ACTION_MAP(application), app_entries, + G_N_ELEMENTS(app_entries), application); + /* Set the default state for our actions to match our online state. */ + online = purple_connections_is_online(); + n_actions = G_N_ELEMENTS(pidgin_application_online_actions); + pidgin_application_actions_set_enabled(application, + pidgin_application_online_actions, + n_actions = G_N_ELEMENTS(pidgin_application_chat_actions); + pidgin_application_actions_set_enabled(application, + pidgin_application_chat_actions, + n_actions = G_N_ELEMENTS(pidgin_application_room_list_actions); + pidgin_application_actions_set_enabled(application, + pidgin_application_room_list_actions, --- a/pidgin/resources/BuddyList/menu.ui Sat Nov 14 03:05:16 2020 -0600
+++ b/pidgin/resources/BuddyList/menu.ui Sat Nov 14 03:15:43 2020 -0600
@@ -1,8 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.2 -->
+<!-- Generated with glade 3.22.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/>. <requires lib="gtk+" version="3.20"/>
<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="PidginBuddyListMenu" parent="GtkMenuBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -20,7 +42,7 @@
<object class="GtkMenuItem" id="new_message">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.new-message</property>
+ <property name="action_name">app.new-message</property> <property name="label" translatable="yes">New Instant _Message...</property>
<property name="use_underline">True</property>
<accelerator key="m" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -30,7 +52,7 @@
<object class="GtkMenuItem" id="join_chat">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.join-chat</property>
+ <property name="action_name">app.join-chat</property> <property name="label" translatable="yes">Join a _Chat...</property>
<property name="use_underline">True</property>
<accelerator key="c" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -40,7 +62,7 @@
<object class="GtkMenuItem" id="get_user_info">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.get-user-info</property>
+ <property name="action_name">app.get-user-info</property> <property name="label" translatable="yes">Get User _Info...</property>
<property name="use_underline">True</property>
<accelerator key="i" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -50,7 +72,7 @@
<object class="GtkMenuItem" id="view_user_log">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.view-user-log</property>
+ <property name="action_name">app.view-user-log</property> <property name="label" translatable="yes">View User _Log...</property>
<property name="use_underline">True</property>
<accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -139,7 +161,7 @@
<object class="GtkMenuItem" id="add_buddy">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.add-buddy</property>
+ <property name="action_name">app.add-buddy</property> <property name="label" translatable="yes">_Add Buddy...</property>
<property name="use_underline">True</property>
<accelerator key="b" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -149,7 +171,7 @@
<object class="GtkMenuItem" id="add_chat">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.add-chat</property>
+ <property name="action_name">app.add-chat</property> <property name="label" translatable="yes">Add C_hat...</property>
<property name="use_underline">True</property>
@@ -158,7 +180,7 @@
<object class="GtkMenuItem" id="add_group">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.add-group</property>
+ <property name="action_name">app.add-group</property> <property name="label" translatable="yes">Add _Group...</property>
<property name="use_underline">True</property>
@@ -173,7 +195,7 @@
<object class="GtkMenuItem" id="quit">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.quit</property>
+ <property name="action_name">app.quit</property> <property name="label" translatable="yes">_Quit</property>
<property name="use_underline">True</property>
<accelerator key="q" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -205,7 +227,7 @@
<object class="GtkMenuItem" id="buddy_pounces">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.buddy-pounces</property>
+ <property name="action_name">app.buddy-pounces</property> <property name="label" translatable="yes">Buddy _Pounces</property>
<property name="use_underline">True</property>
@@ -214,7 +236,7 @@
<object class="GtkMenuItem" id="custom_smileys">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.custom-smiley</property>
+ <property name="action_name">app.custom-smiley</property> <property name="label" translatable="yes">Custom Smile_ys</property>
<property name="use_underline">True</property>
<accelerator key="y" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -224,7 +246,7 @@
<object class="GtkMenuItem" id="preferences">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.preferences</property>
+ <property name="action_name">app.preferences</property> <property name="label" translatable="yes">Pr_eferences</property>
<property name="use_underline">True</property>
<accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -234,7 +256,7 @@
<object class="GtkMenuItem" id="privacy">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.privacy</property>
+ <property name="action_name">app.privacy</property> <property name="label" translatable="yes">Pr_ivacy</property>
<property name="use_underline">True</property>
@@ -243,7 +265,7 @@
<object class="GtkMenuItem" id="set_mood">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.set-mood</property>
+ <property name="action_name">app.set-mood</property> <property name="label" translatable="yes">Set _Mood</property>
<property name="use_underline">True</property>
<accelerator key="d" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -259,7 +281,7 @@
<object class="GtkMenuItem" id="file_transfers">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.file-transfers</property>
+ <property name="action_name">app.file-transfers</property> <property name="label" translatable="yes">_File Transfers</property>
<property name="use_underline">True</property>
<accelerator key="t" signal="activate" modifiers="GDK_CONTROL_MASK"/>
@@ -269,7 +291,7 @@
<object class="GtkMenuItem" id="room_list">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.room-list</property>
+ <property name="action_name">app.room-list</property> <property name="label" translatable="yes">R_oom List</property>
<property name="use_underline">True</property>
@@ -278,7 +300,7 @@
<object class="GtkMenuItem" id="system_log">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.system-log</property>
+ <property name="action_name">app.system-log</property> <property name="label" translatable="yes">System _Log</property>
<property name="use_underline">True</property>
@@ -309,7 +331,7 @@
<object class="GtkMenuItem" id="online_help">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.online-help</property>
+ <property name="action_name">app.online-help</property> <property name="label" translatable="yes">Online _Help</property>
<property name="use_underline">True</property>
<accelerator key="F1" signal="activate"/>
@@ -319,7 +341,7 @@
<object class="GtkMenuItem" id="debug">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.debug</property>
+ <property name="action_name">app.debug</property> <property name="label" translatable="yes">_Debug Window</property>
<property name="use_underline">True</property>
@@ -328,7 +350,7 @@
<object class="GtkMenuItem" id="about">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="action_name">blist.about</property>
+ <property name="action_name">app.about</property> <property name="label" translatable="yes">_About</property>
<property name="use_underline">True</property>