| 1 /* |
|
| 2 * Pidgin - Internet Messenger |
|
| 3 * Copyright (C) Pidgin Developers <devel@pidgin.im> |
|
| 4 * |
|
| 5 * Pidgin is the legal property of its developers, whose names are too numerous |
|
| 6 * to list here. Please refer to the COPYRIGHT file distributed with this |
|
| 7 * source distribution. |
|
| 8 * |
|
| 9 * This program is free software; you can redistribute it and/or modify |
|
| 10 * it under the terms of the GNU General Public License as published by |
|
| 11 * the Free Software Foundation; either version 2 of the License, or |
|
| 12 * (at your option) any later version. |
|
| 13 * |
|
| 14 * This program is distributed in the hope that it will be useful, |
|
| 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 17 * GNU General Public License for more details. |
|
| 18 * |
|
| 19 * You should have received a copy of the GNU General Public License |
|
| 20 * along with this program; if not, see <https://www.gnu.org/licenses/>. |
|
| 21 */ |
|
| 22 |
|
| 23 #include "pidginaccountactionsmenu.h" |
|
| 24 |
|
| 25 #include <purple.h> |
|
| 26 |
|
| 27 #include "gtkaccount.h" |
|
| 28 #include "pidgincore.h" |
|
| 29 #include "pidginmooddialog.h" |
|
| 30 |
|
| 31 struct _PidginAccountActionsMenu { |
|
| 32 GtkMenu parent; |
|
| 33 |
|
| 34 GtkWidget *separator; |
|
| 35 GtkWidget *set_mood; |
|
| 36 |
|
| 37 PurpleAccount *account; |
|
| 38 }; |
|
| 39 |
|
| 40 enum { |
|
| 41 PROP_ZERO, |
|
| 42 PROP_ACCOUNT, |
|
| 43 N_PROPERTIES |
|
| 44 }; |
|
| 45 static GParamSpec *properties[N_PROPERTIES] = { NULL, }; |
|
| 46 |
|
| 47 /****************************************************************************** |
|
| 48 * GSignal Handlers |
|
| 49 *****************************************************************************/ |
|
| 50 static void |
|
| 51 pidgin_account_actions_menu_edit_cb(GtkMenuItem *item, gpointer data) { |
|
| 52 PidginAccountActionsMenu *menu = PIDGIN_ACCOUNT_ACTIONS_MENU(data); |
|
| 53 |
|
| 54 pidgin_account_dialog_show(PIDGIN_MODIFY_ACCOUNT_DIALOG, menu->account); |
|
| 55 } |
|
| 56 |
|
| 57 static void |
|
| 58 pidgin_account_actions_menu_disable_cb(GtkMenuItem *item, gpointer data) { |
|
| 59 PidginAccountActionsMenu *menu = PIDGIN_ACCOUNT_ACTIONS_MENU(data); |
|
| 60 |
|
| 61 purple_account_set_enabled(menu->account, FALSE); |
|
| 62 } |
|
| 63 |
|
| 64 static void |
|
| 65 pidgin_account_actions_menu_set_mood_cb(GtkMenuItem *item, gpointer data) { |
|
| 66 PidginAccountActionsMenu *menu = PIDGIN_ACCOUNT_ACTIONS_MENU(data); |
|
| 67 |
|
| 68 pidgin_mood_dialog_show(menu->account); |
|
| 69 } |
|
| 70 |
|
| 71 static void |
|
| 72 pidgin_account_actions_menu_action(GtkMenuItem *item, gpointer data) { |
|
| 73 PurpleProtocolAction *action = (PurpleProtocolAction *)data; |
|
| 74 |
|
| 75 if(action && action->callback) { |
|
| 76 action->callback(action); |
|
| 77 } |
|
| 78 } |
|
| 79 |
|
| 80 /****************************************************************************** |
|
| 81 * Helpers |
|
| 82 *****************************************************************************/ |
|
| 83 static void |
|
| 84 pidgin_account_actions_menu_set_account(PidginAccountActionsMenu *menu, |
|
| 85 PurpleAccount *account) |
|
| 86 { |
|
| 87 PurpleConnection *connection = NULL; |
|
| 88 PurpleProtocol *protocol = NULL; |
|
| 89 GList *children = NULL; |
|
| 90 gboolean show_separator = FALSE; |
|
| 91 gint position = 0; |
|
| 92 |
|
| 93 if(g_set_object(&menu->account, account)) { |
|
| 94 if(!PURPLE_IS_ACCOUNT(menu->account)) { |
|
| 95 return; |
|
| 96 } |
|
| 97 } |
|
| 98 |
|
| 99 connection = purple_account_get_connection(account); |
|
| 100 if(connection == NULL) { |
|
| 101 return; |
|
| 102 } |
|
| 103 |
|
| 104 if(!PURPLE_CONNECTION_IS_CONNECTED(connection)) { |
|
| 105 return; |
|
| 106 } |
|
| 107 |
|
| 108 /* we're pretty sure we're going to insert some items into the menu, so we |
|
| 109 * need to figure out where to put them. GtkMenu stores its children in |
|
| 110 * order, so we just need to get the index of the set_mood item to find the |
|
| 111 * proper position. |
|
| 112 */ |
|
| 113 children = gtk_container_get_children(GTK_CONTAINER(menu)); |
|
| 114 position = g_list_index(children, menu->set_mood) + 1; |
|
| 115 g_list_free(children); |
|
| 116 |
|
| 117 protocol = purple_connection_get_protocol(connection); |
|
| 118 |
|
| 119 if(PURPLE_PROTOCOL_IMPLEMENTS(protocol, CLIENT, get_moods)) { |
|
| 120 gtk_widget_show(menu->set_mood); |
|
| 121 |
|
| 122 show_separator = TRUE; |
|
| 123 } |
|
| 124 |
|
| 125 if(PURPLE_IS_PROTOCOL_CLIENT(protocol)) { |
|
| 126 PurpleProtocolClient *client = PURPLE_PROTOCOL_CLIENT(protocol); |
|
| 127 GtkWidget *item = NULL; |
|
| 128 GList *actions = NULL; |
|
| 129 |
|
| 130 actions = purple_protocol_client_get_actions(client, connection); |
|
| 131 |
|
| 132 while(actions != NULL) { |
|
| 133 PurpleProtocolAction *action = (PurpleProtocolAction *)actions->data; |
|
| 134 |
|
| 135 if(action == NULL) { |
|
| 136 item = gtk_separator_menu_item_new(); |
|
| 137 gtk_menu_shell_insert(GTK_MENU_SHELL(menu), item, position++); |
|
| 138 gtk_widget_show(item); |
|
| 139 |
|
| 140 continue; |
|
| 141 } |
|
| 142 |
|
| 143 if(action->label == NULL) { |
|
| 144 purple_protocol_action_free(action); |
|
| 145 |
|
| 146 continue; |
|
| 147 } |
|
| 148 |
|
| 149 /* Make sure the action has its connection set. */ |
|
| 150 action->connection = connection; |
|
| 151 |
|
| 152 /* now add the action */ |
|
| 153 item = gtk_menu_item_new_with_label(action->label); |
|
| 154 g_signal_connect_data(G_OBJECT(item), "activate", |
|
| 155 G_CALLBACK(pidgin_account_actions_menu_action), |
|
| 156 action, |
|
| 157 (GClosureNotify)purple_protocol_action_free, |
|
| 158 0); |
|
| 159 gtk_menu_shell_insert(GTK_MENU_SHELL(menu), item, position++); |
|
| 160 gtk_widget_show(item); |
|
| 161 |
|
| 162 /* since we added an item, make sure items_added is true */ |
|
| 163 show_separator = TRUE; |
|
| 164 |
|
| 165 /* Iterate to the next item while deleting the one we just |
|
| 166 * processed. |
|
| 167 */ |
|
| 168 actions = g_list_delete_link(actions, actions); |
|
| 169 } |
|
| 170 } |
|
| 171 |
|
| 172 /* if we added any items, make our separator visible. */ |
|
| 173 if(show_separator) { |
|
| 174 gtk_widget_show(menu->separator); |
|
| 175 } |
|
| 176 } |
|
| 177 |
|
| 178 /****************************************************************************** |
|
| 179 * GObject Implementation |
|
| 180 *****************************************************************************/ |
|
| 181 G_DEFINE_TYPE(PidginAccountActionsMenu, pidgin_account_actions_menu, |
|
| 182 GTK_TYPE_MENU) |
|
| 183 |
|
| 184 static void |
|
| 185 pidgin_account_actions_menu_get_property(GObject *obj, guint param_id, |
|
| 186 GValue *value, GParamSpec *pspec) |
|
| 187 { |
|
| 188 PidginAccountActionsMenu *menu = PIDGIN_ACCOUNT_ACTIONS_MENU(obj); |
|
| 189 |
|
| 190 switch(param_id) { |
|
| 191 case PROP_ACCOUNT: |
|
| 192 g_value_set_object(value, |
|
| 193 pidgin_account_actions_menu_get_account(menu)); |
|
| 194 break; |
|
| 195 default: |
|
| 196 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); |
|
| 197 break; |
|
| 198 } |
|
| 199 } |
|
| 200 |
|
| 201 static void |
|
| 202 pidgin_account_actions_menu_set_property(GObject *obj, guint param_id, |
|
| 203 const GValue *value, |
|
| 204 GParamSpec *pspec) |
|
| 205 { |
|
| 206 PidginAccountActionsMenu *menu = PIDGIN_ACCOUNT_ACTIONS_MENU(obj); |
|
| 207 |
|
| 208 switch(param_id) { |
|
| 209 case PROP_ACCOUNT: |
|
| 210 pidgin_account_actions_menu_set_account(menu, |
|
| 211 g_value_get_object(value)); |
|
| 212 break; |
|
| 213 |
|
| 214 default: |
|
| 215 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); |
|
| 216 break; |
|
| 217 } |
|
| 218 } |
|
| 219 |
|
| 220 static void |
|
| 221 pidgin_account_actions_menu_finalize(GObject *obj) { |
|
| 222 PidginAccountActionsMenu *menu = PIDGIN_ACCOUNT_ACTIONS_MENU(obj); |
|
| 223 |
|
| 224 g_clear_object(&menu->account); |
|
| 225 |
|
| 226 G_OBJECT_CLASS(pidgin_account_actions_menu_parent_class)->finalize(obj); |
|
| 227 } |
|
| 228 |
|
| 229 static void |
|
| 230 pidgin_account_actions_menu_init(PidginAccountActionsMenu *menu) { |
|
| 231 /* initialize our template */ |
|
| 232 gtk_widget_init_template(GTK_WIDGET(menu)); |
|
| 233 }; |
|
| 234 |
|
| 235 static void |
|
| 236 pidgin_account_actions_menu_class_init(PidginAccountActionsMenuClass *klass) { |
|
| 237 GObjectClass *obj_class = G_OBJECT_CLASS(klass); |
|
| 238 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); |
|
| 239 |
|
| 240 gtk_widget_class_set_template_from_resource( |
|
| 241 widget_class, |
|
| 242 "/im/pidgin/Pidgin3/Accounts/actionsmenu.ui" |
|
| 243 ); |
|
| 244 |
|
| 245 obj_class->get_property = pidgin_account_actions_menu_get_property; |
|
| 246 obj_class->set_property = pidgin_account_actions_menu_set_property; |
|
| 247 obj_class->finalize = pidgin_account_actions_menu_finalize; |
|
| 248 |
|
| 249 /** |
|
| 250 * PidginAccountActionsMenu::account: |
|
| 251 * |
|
| 252 * The #PurpleAccount that this menu was created for. |
|
| 253 */ |
|
| 254 properties[PROP_ACCOUNT] = |
|
| 255 g_param_spec_object("account", "account", |
|
| 256 "The account this menu is for", |
|
| 257 PURPLE_TYPE_ACCOUNT, |
|
| 258 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | |
|
| 259 G_PARAM_STATIC_STRINGS); |
|
| 260 |
|
| 261 g_object_class_install_properties(obj_class, N_PROPERTIES, properties); |
|
| 262 |
|
| 263 gtk_widget_class_bind_template_child(widget_class, PidginAccountActionsMenu, |
|
| 264 separator); |
|
| 265 gtk_widget_class_bind_template_child(widget_class, PidginAccountActionsMenu, |
|
| 266 set_mood); |
|
| 267 |
|
| 268 gtk_widget_class_bind_template_callback(widget_class, |
|
| 269 pidgin_account_actions_menu_edit_cb); |
|
| 270 gtk_widget_class_bind_template_callback(widget_class, |
|
| 271 pidgin_account_actions_menu_disable_cb); |
|
| 272 gtk_widget_class_bind_template_callback(widget_class, |
|
| 273 pidgin_account_actions_menu_set_mood_cb); |
|
| 274 } |
|
| 275 |
|
| 276 /****************************************************************************** |
|
| 277 * Public API |
|
| 278 *****************************************************************************/ |
|
| 279 GtkWidget * |
|
| 280 pidgin_account_actions_menu_new(PurpleAccount *account) { |
|
| 281 GObject *obj = NULL; |
|
| 282 |
|
| 283 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); |
|
| 284 |
|
| 285 obj = g_object_new(PIDGIN_TYPE_ACCOUNT_ACTIONS_MENU, |
|
| 286 "account", account, |
|
| 287 NULL); |
|
| 288 |
|
| 289 return GTK_WIDGET(obj); |
|
| 290 } |
|
| 291 |
|
| 292 PurpleAccount * |
|
| 293 pidgin_account_actions_menu_get_account(PidginAccountActionsMenu *menu) { |
|
| 294 g_return_val_if_fail(PIDGIN_IS_ACCOUNT_ACTIONS_MENU(menu), NULL); |
|
| 295 |
|
| 296 return menu->account; |
|
| 297 } |
|