pidgin/pidginaccountactionsmenu.c

changeset 41475
702bafe15ee3
parent 41474
ed1c0145c164
child 41476
1a53026013e4
equal deleted inserted replaced
41474:ed1c0145c164 41475:702bafe15ee3
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 }

mercurial