pidgin/pidginaccountchooser.c

changeset 40534
8dad2981fb86
parent 40496
6941fece679b
child 41030
ec8b76f3bf0a
equal deleted inserted replaced
40533:b1921b17b683 40534:8dad2981fb86
1 /* pidgin 1 /*
2 * Pidgin - Internet Messenger
3 * Copyright (C) Pidgin Developers <devel@pidgin.im>
2 * 4 *
3 * Pidgin is the legal property of its developers, whose names are too numerous 5 * Pidgin is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this 6 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution. 7 * source distribution.
6 * 8 *
18 * along with this program; if not, write to the Free Software 20 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
20 */ 22 */
21 #include <gtk/gtk.h> 23 #include <gtk/gtk.h>
22 24
23 #include "gtkutils.h"
24 #include "pidginaccountchooser.h" 25 #include "pidginaccountchooser.h"
25 26
26 /****************************************************************************** 27 #include "pidginaccountstore.h"
27 * Enums
28 *****************************************************************************/
29 28
30 enum 29 struct _PidginAccountChooser {
31 { 30 GtkComboBox parent;
32 AOP_ICON_COLUMN, 31
33 AOP_NAME_COLUMN, 32 PurpleFilterAccountFunc filter_func;
34 AOP_DATA_COLUMN,
35 AOP_COLUMN_COUNT
36 }; 33 };
37 34
38 enum 35 enum
39 { 36 {
40 PROP_0, 37 PROP_0,
41 PROP_ACCOUNT, 38 PROP_ACCOUNT,
42 PROP_SHOW_ALL,
43 PROP_LAST 39 PROP_LAST
44 }; 40 };
45 41
46 /****************************************************************************** 42 static GParamSpec *properties[PROP_LAST] = {NULL};
47 * Structs
48 *****************************************************************************/
49
50 struct _PidginAccountChooser {
51 GtkComboBox parent;
52
53 GtkListStore *model;
54
55 PurpleFilterAccountFunc filter_func;
56 gboolean show_all;
57 };
58 43
59 /****************************************************************************** 44 /******************************************************************************
60 * Code 45 * Callbacks
61 *****************************************************************************/ 46 *****************************************************************************/
62 static GParamSpec *properties[PROP_LAST] = {NULL};
63
64 G_DEFINE_TYPE(PidginAccountChooser, pidgin_account_chooser, GTK_TYPE_COMBO_BOX)
65
66 static gpointer
67 account_chooser_get_selected(PidginAccountChooser *chooser)
68 {
69 gpointer data = NULL;
70 GtkTreeIter iter;
71
72 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(chooser), &iter)) {
73 gtk_tree_model_get(
74 gtk_combo_box_get_model(GTK_COMBO_BOX(chooser)), &iter,
75 AOP_DATA_COLUMN, &data, -1);
76 }
77
78 return data;
79 }
80
81 static void 47 static void
82 account_chooser_select_by_data(GtkWidget *chooser, gpointer data) 48 pidgin_account_chooser_changed_cb(GtkComboBox *widget, gpointer user_data) {
83 {
84 GtkTreeModel *model;
85 GtkTreeIter iter;
86 gpointer iter_data;
87 model = gtk_combo_box_get_model(GTK_COMBO_BOX(chooser));
88 if (gtk_tree_model_get_iter_first(model, &iter)) {
89 do {
90 gtk_tree_model_get(model, &iter, AOP_DATA_COLUMN,
91 &iter_data, -1);
92 if (iter_data == data) {
93 gtk_combo_box_set_active_iter(
94 GTK_COMBO_BOX(chooser), &iter);
95 return;
96 }
97 } while (gtk_tree_model_iter_next(model, &iter));
98 }
99 }
100
101 static void
102 set_account_menu(PidginAccountChooser *chooser, PurpleAccount *default_account)
103 {
104 PurpleAccount *account;
105 GdkPixbuf *pixbuf = NULL;
106 GList *list;
107 GList *p;
108 GtkTreeIter iter;
109 gint default_item = 0;
110 gint i;
111 gchar buf[256];
112
113 if (chooser->show_all) {
114 list = purple_accounts_get_all();
115 } else {
116 list = purple_connections_get_all();
117 }
118
119 gtk_list_store_clear(chooser->model);
120 for (p = list, i = 0; p != NULL; p = p->next, i++) {
121 if (chooser->show_all) {
122 account = (PurpleAccount *)p->data;
123 } else {
124 PurpleConnection *gc = (PurpleConnection *)p->data;
125
126 account = purple_connection_get_account(gc);
127 }
128
129 if (chooser->filter_func && !chooser->filter_func(account)) {
130 i--;
131 continue;
132 }
133
134 pixbuf = pidgin_create_protocol_icon(
135 account, PIDGIN_PROTOCOL_ICON_SMALL);
136
137 if (pixbuf) {
138 if (purple_account_is_disconnected(account) &&
139 chooser->show_all && purple_connections_get_all()) {
140 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf,
141 0.0, FALSE);
142 }
143 }
144
145 if (purple_account_get_private_alias(account)) {
146 g_snprintf(buf, sizeof(buf), "%s (%s) (%s)",
147 purple_account_get_username(account),
148 purple_account_get_private_alias(account),
149 purple_account_get_protocol_name(account));
150 } else {
151 g_snprintf(buf, sizeof(buf), "%s (%s)",
152 purple_account_get_username(account),
153 purple_account_get_protocol_name(account));
154 }
155
156 gtk_list_store_append(chooser->model, &iter);
157 gtk_list_store_set(chooser->model, &iter, AOP_ICON_COLUMN,
158 pixbuf, AOP_NAME_COLUMN, buf,
159 AOP_DATA_COLUMN, account, -1);
160
161 if (pixbuf) {
162 g_object_unref(pixbuf);
163 }
164
165 if (default_account && account == default_account) {
166 default_item = i;
167 }
168 }
169
170 gtk_combo_box_set_active(GTK_COMBO_BOX(chooser), default_item);
171 }
172
173 static void
174 regenerate_account_menu(PidginAccountChooser *chooser)
175 {
176 PurpleAccount *account;
177
178 account = (PurpleAccount *)account_chooser_get_selected(chooser);
179
180 set_account_menu(chooser, account);
181 }
182
183 static void
184 account_menu_sign_on_off_cb(PurpleConnection *gc, PidginAccountChooser *chooser)
185 {
186 regenerate_account_menu(chooser);
187 }
188
189 static void
190 account_menu_added_removed_cb(PurpleAccount *account,
191 PidginAccountChooser *chooser)
192 {
193 regenerate_account_menu(chooser);
194 }
195
196 static gboolean
197 account_menu_destroyed_cb(GtkWidget *chooser, GdkEvent *event, void *user_data)
198 {
199 purple_signals_disconnect_by_handle(chooser);
200
201 return FALSE;
202 }
203
204 static void
205 pidgin_account_chooser_changed_cb(GtkComboBox *widget, gpointer user_data)
206 {
207 g_object_notify_by_pspec(G_OBJECT(widget), properties[PROP_ACCOUNT]); 49 g_object_notify_by_pspec(G_OBJECT(widget), properties[PROP_ACCOUNT]);
208 } 50 }
209 51
210 /****************************************************************************** 52 /******************************************************************************
211 * GObject implementation 53 * GObject implementation
212 *****************************************************************************/ 54 *****************************************************************************/
55 G_DEFINE_TYPE(PidginAccountChooser, pidgin_account_chooser, GTK_TYPE_COMBO_BOX)
56
213 static void 57 static void
214 pidgin_account_chooser_get_property(GObject *object, guint prop_id, 58 pidgin_account_chooser_get_property(GObject *object, guint prop_id,
215 GValue *value, GParamSpec *pspec) 59 GValue *value, GParamSpec *pspec)
216 { 60 {
217 PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(object); 61 PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(object);
218 62
219 switch (prop_id) { 63 switch (prop_id) {
220 case PROP_ACCOUNT: 64 case PROP_ACCOUNT:
221 g_value_set_object(value, account_chooser_get_selected(chooser)); 65 g_value_set_object(value, pidgin_account_chooser_get_selected(chooser));
222 break;
223 case PROP_SHOW_ALL:
224 g_value_set_boolean(value, chooser->show_all);
225 break; 66 break;
226 default: 67 default:
227 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 68 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
228 break; 69 break;
229 } 70 }
235 { 76 {
236 PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(object); 77 PidginAccountChooser *chooser = PIDGIN_ACCOUNT_CHOOSER(object);
237 78
238 switch (prop_id) { 79 switch (prop_id) {
239 case PROP_ACCOUNT: 80 case PROP_ACCOUNT:
240 account_chooser_select_by_data(GTK_WIDGET(chooser), 81 pidgin_account_chooser_set_selected(chooser,
241 g_value_get_object(value)); 82 g_value_get_object(value));
242 break;
243 case PROP_SHOW_ALL:
244 chooser->show_all = g_value_get_boolean(value);
245 break; 83 break;
246 default: 84 default:
247 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 85 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
248 break; 86 break;
249 } 87 }
261 99
262 properties[PROP_ACCOUNT] = g_param_spec_object( 100 properties[PROP_ACCOUNT] = g_param_spec_object(
263 "account", "Account", "The account that is currently selected.", 101 "account", "Account", "The account that is currently selected.",
264 PURPLE_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); 102 PURPLE_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
265 103
266 properties[PROP_SHOW_ALL] = g_param_spec_boolean(
267 "show-all", "Show all",
268 "Whether to show all accounts, or just online ones.", FALSE,
269 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
270 G_PARAM_STATIC_STRINGS);
271
272 g_object_class_install_properties(obj_class, PROP_LAST, properties); 104 g_object_class_install_properties(obj_class, PROP_LAST, properties);
273 105
274 /* Widget template */ 106 /* Widget template */
275
276 gtk_widget_class_set_template_from_resource( 107 gtk_widget_class_set_template_from_resource(
277 widget_class, "/im/pidgin/Pidgin/Accounts/chooser.ui"); 108 widget_class, "/im/pidgin/Pidgin/Accounts/chooser.ui");
278
279 gtk_widget_class_bind_template_child(widget_class, PidginAccountChooser,
280 model);
281
282 gtk_widget_class_bind_template_callback(widget_class,
283 account_menu_destroyed_cb);
284 } 109 }
285 110
286 static void 111 static void
287 pidgin_account_chooser_init(PidginAccountChooser *chooser) 112 pidgin_account_chooser_init(PidginAccountChooser *chooser) {
288 {
289 gtk_widget_init_template(GTK_WIDGET(chooser)); 113 gtk_widget_init_template(GTK_WIDGET(chooser));
290 114
291 set_account_menu(chooser, NULL); 115 /* this callback emits the notify for the account property */
292
293 g_signal_connect(chooser, "changed", 116 g_signal_connect(chooser, "changed",
294 G_CALLBACK(pidgin_account_chooser_changed_cb), NULL); 117 G_CALLBACK(pidgin_account_chooser_changed_cb), NULL);
295
296 /* Register the purple sign on/off event callbacks. */
297 purple_signal_connect(
298 purple_connections_get_handle(), "signed-on", chooser,
299 PURPLE_CALLBACK(account_menu_sign_on_off_cb), chooser);
300 purple_signal_connect(
301 purple_connections_get_handle(), "signed-off", chooser,
302 PURPLE_CALLBACK(account_menu_sign_on_off_cb), chooser);
303 purple_signal_connect(
304 purple_accounts_get_handle(), "account-added", chooser,
305 PURPLE_CALLBACK(account_menu_added_removed_cb), chooser);
306 purple_signal_connect(
307 purple_accounts_get_handle(), "account-removed", chooser,
308 PURPLE_CALLBACK(account_menu_added_removed_cb), chooser);
309 } 118 }
310 119
311 /****************************************************************************** 120 /******************************************************************************
312 * Public API 121 * Public API
313 *****************************************************************************/ 122 *****************************************************************************/
314 GtkWidget * 123 GtkWidget *
315 pidgin_account_chooser_new(PurpleAccount *default_account, gboolean show_all) 124 pidgin_account_chooser_new(void) {
316 {
317 PidginAccountChooser *chooser = NULL; 125 PidginAccountChooser *chooser = NULL;
318 126
319 chooser = g_object_new(PIDGIN_TYPE_ACCOUNT_CHOOSER, "account", 127 chooser = g_object_new(PIDGIN_TYPE_ACCOUNT_CHOOSER, NULL);
320 default_account, "show-all", show_all, NULL);
321 128
322 return GTK_WIDGET(chooser); 129 return GTK_WIDGET(chooser);
323 } 130 }
324 131
325 void 132 void
327 PurpleFilterAccountFunc filter_func) 134 PurpleFilterAccountFunc filter_func)
328 { 135 {
329 g_return_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser)); 136 g_return_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser));
330 137
331 chooser->filter_func = filter_func; 138 chooser->filter_func = filter_func;
332 regenerate_account_menu(chooser);
333 } 139 }
334 140
335 PurpleAccount * 141 PurpleAccount *
336 pidgin_account_chooser_get_selected(GtkWidget *chooser) 142 pidgin_account_chooser_get_selected(PidginAccountChooser *chooser) {
337 { 143 GtkTreeIter iter;
144 gpointer account = NULL;
145
338 g_return_val_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser), NULL); 146 g_return_val_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser), NULL);
339 147
340 return (PurpleAccount *)account_chooser_get_selected( 148 if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(chooser), &iter)) {
341 PIDGIN_ACCOUNT_CHOOSER(chooser)); 149 GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(chooser));
150 gtk_tree_model_get(model, &iter,
151 PIDGIN_ACCOUNT_STORE_COLUMN_ACCOUNT, &account, -1);
152 }
153
154 return account;
342 } 155 }
343 156
344 void 157 void
345 pidgin_account_chooser_set_selected(GtkWidget *chooser, PurpleAccount *account) 158 pidgin_account_chooser_set_selected(PidginAccountChooser *chooser,
159 PurpleAccount *account)
346 { 160 {
161 GtkTreeModel *model = NULL;
162 GtkTreeIter iter;
163 PurpleAccount *acc = NULL;
164
347 g_return_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser)); 165 g_return_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser));
348 166
349 account_chooser_select_by_data(chooser, account); 167 model = gtk_combo_box_get_model(GTK_COMBO_BOX(chooser));
168 g_return_if_fail(GTK_IS_TREE_MODEL(model));
350 169
351 /* NOTE: Property notification occurs in 'changed' signal callback. */ 170 if(gtk_tree_model_get_iter_first(model, &iter)) {
171 do {
172 gtk_tree_model_get(model, &iter,
173 PIDGIN_ACCOUNT_STORE_COLUMN_ACCOUNT, &acc, -1);
174 if(acc == account) {
175 /* NOTE: Property notification occurs in 'changed' signal
176 * callback.
177 */
178 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(chooser), &iter);
179
180 g_object_unref(G_OBJECT(acc));
181
182 return;
183 }
184 g_object_unref(G_OBJECT(acc));
185 } while(gtk_tree_model_iter_next(model, &iter));
186 }
352 } 187 }
353 188
354 gboolean
355 pidgin_account_chooser_get_show_all(GtkWidget *chooser)
356 {
357 g_return_val_if_fail(PIDGIN_IS_ACCOUNT_CHOOSER(chooser), FALSE);
358
359 return PIDGIN_ACCOUNT_CHOOSER(chooser)->show_all;
360 }

mercurial