13870
|
1 /**
|
|
2 * The QQ2003C protocol plugin
|
|
3 *
|
|
4 * for gaim
|
|
5 *
|
|
6 * Copyright (C) 2004 Puzzlebird
|
|
7 *
|
|
8 * This program is free software; you can redistribute it and/or modify
|
|
9 * it under the terms of the GNU General Public License as published by
|
|
10 * the Free Software Foundation; either version 2 of the License, or
|
|
11 * (at your option) any later version.
|
|
12 *
|
|
13 * This program is distributed in the hope that it will be useful,
|
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16 * GNU General Public License for more details.
|
|
17 *
|
|
18 * You should have received a copy of the GNU General Public License
|
|
19 * along with this program; if not, write to the Free Software
|
|
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
21 */
|
|
22
|
|
23 // START OF FILE
|
|
24 /*****************************************************************************/
|
|
25 #include "debug.h" // gaim_debug
|
|
26 #include "blist.h" // GAIM_BLIST_NODE_IS_BUDDY
|
|
27 #include "notify.h" // gaim_notify_warning
|
|
28
|
|
29 #include "utils.h" // gaim_name_to_uid
|
|
30 #include "group_admindlg.h"
|
|
31 #include "group_find.h" // qq_group_find_by_internal_group_id
|
|
32 #include "group_join.h" // auth_type
|
|
33 #include "group_opt.h" // QQ_GROUP_TYPE_PERMANENT
|
|
34
|
|
35 enum {
|
|
36 COLUMN_SELECTED = 0,
|
|
37 COLUMN_UID,
|
|
38 COLUMN_NICKNAME,
|
|
39 NUM_COLUMNS
|
|
40 };
|
|
41
|
|
42 enum {
|
|
43 PAGE_INFO = 0,
|
|
44 PAGE_MEMBER,
|
|
45 };
|
|
46
|
|
47 typedef struct _qun_info_window {
|
|
48 guint32 internal_group_id;
|
|
49 GaimConnection *gc;
|
|
50 GtkWidget *window;
|
|
51 GtkWidget *notebook;
|
|
52 GtkWidget *lbl_external_group_id;
|
|
53 GtkWidget *lbl_admin_uid;
|
|
54 GtkWidget *ent_group_name;
|
|
55 GtkWidget *cmb_group_category;
|
|
56 GtkWidget *txt_group_desc;
|
|
57 GtkWidget *txt_group_notice;
|
|
58 GtkWidget *rad_auth[3];
|
|
59 GtkWidget *btn_mod;
|
|
60 GtkWidget *btn_close;
|
|
61 GtkWidget *tre_members;
|
|
62 } qun_info_window;
|
|
63
|
|
64 const gchar *qq_group_category[] = {
|
|
65 "同学", "朋友", "同事", "其他",
|
|
66 }; // qq_group_category
|
|
67
|
|
68 const gchar *qq_group_auth_type_desc[] = {
|
|
69 "无须认证", "需要认证", "不可添加",
|
|
70 }; // qq_group_auth_type_desc
|
|
71
|
|
72 /*****************************************************************************/
|
|
73 static void _qq_group_info_window_deleteevent(GtkWidget * widget, GdkEvent * event, gpointer data) {
|
|
74 gtk_widget_destroy(widget); // this will call _window_destroy
|
|
75 } // _window_deleteevent
|
|
76
|
|
77 /*****************************************************************************/
|
|
78 static void _qq_group_info_window_close(GtkWidget * widget, gpointer data)
|
|
79 {
|
|
80 // this will call _info_window_destroy if it is info-window
|
|
81 gtk_widget_destroy(GTK_WIDGET(data));
|
|
82 } // _window_close
|
|
83
|
|
84 /*****************************************************************************/
|
|
85 static void _qq_group_info_window_destroy(GtkWidget * widget, gpointer data)
|
|
86 {
|
|
87 GaimConnection *gc;
|
|
88 GList *list;
|
|
89 qq_data *qd;
|
|
90 qun_info_window *info_window;
|
|
91
|
|
92 gc = (GaimConnection *) data;
|
|
93 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
|
|
94 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Group info is destoryed\n");
|
|
95
|
|
96 qd = (qq_data *) gc->proto_data;
|
|
97 list = qd->qun_info_window;
|
|
98
|
|
99 while (list) {
|
|
100 info_window = (qun_info_window *) (list->data);
|
|
101 if (info_window->window != widget)
|
|
102 list = list->next;
|
|
103 else {
|
|
104 qd->qun_info_window = g_list_remove(qd->qun_info_window, info_window);
|
|
105 g_free(info_window);
|
|
106 break;
|
|
107 } // if info_window
|
|
108 } // while
|
|
109 } // _window_destroy
|
|
110
|
|
111 /*****************************************************************************/
|
|
112 void qq_qun_info_window_free(qq_data * qd)
|
|
113 {
|
|
114 gint i;
|
|
115 qun_info_window *info_window;
|
|
116
|
|
117 i = 0;
|
|
118 while (qd->qun_info_window) {
|
|
119 info_window = (qun_info_window *) qd->qun_info_window->data;
|
|
120 qd->qun_info_window = g_list_remove(qd->qun_info_window, info_window);
|
|
121 if (info_window->window)
|
|
122 gtk_widget_destroy(info_window->window);
|
|
123 g_free(info_window);
|
|
124 i++;
|
|
125 } // while
|
|
126
|
|
127 gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d Qun info windows are freed\n", i);
|
|
128 } // qq_qun_info_window_free
|
|
129
|
|
130 /*****************************************************************************/
|
|
131 static void _qq_group_info_window_modify(GtkWidget * widget, gpointer data)
|
|
132 {
|
|
133 GaimConnection *gc;
|
|
134 qun_info_window *info_window;
|
|
135
|
|
136 g_return_if_fail(data != NULL);
|
|
137 info_window = (qun_info_window *) data;
|
|
138
|
|
139 gc = info_window->gc;
|
|
140 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
|
|
141
|
|
142 //henry: This function contains some codes only supported by gtk-2.4 or later
|
|
143 //#if !GTK_CHECK_VERSION(2,4,0)
|
|
144 // gaim_notify_info(gc, _("QQ Qun Operation"),
|
|
145 // _("This version of GTK-2 does not support this function"), NULL);
|
|
146 // return;
|
|
147 //#else
|
|
148 gint page, group_category, i = 0;
|
|
149 qq_group *group;
|
|
150 qq_data *qd;
|
|
151 GtkTextIter start, end;
|
|
152 GtkTreeModel *model;
|
|
153 GtkTreeIter iter;
|
|
154 GValue value = { 0, };
|
|
155 guint32 *new_members;
|
|
156 guint32 uid;
|
|
157 gboolean selected;
|
|
158
|
|
159 qd = (qq_data *) gc->proto_data;
|
|
160
|
|
161 // we assume the modification can succeed
|
|
162 // maybe it needs some tweak here
|
|
163 group = qq_group_find_by_internal_group_id(gc, info_window->internal_group_id);
|
|
164 g_return_if_fail(group != NULL);
|
|
165
|
|
166 new_members = g_newa(guint32, QQ_QUN_MEMBER_MAX);
|
|
167
|
|
168 page = gtk_notebook_get_current_page(GTK_NOTEBOOK(info_window->notebook));
|
|
169 switch (page) {
|
|
170 case PAGE_INFO:
|
|
171 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Gonna change Qun detailed information\n");
|
|
172 // get the group_category
|
|
173 #if GTK_CHECK_VERSION(2,4,0)
|
|
174 group_category = gtk_combo_box_get_active(GTK_COMBO_BOX(info_window->cmb_group_category));
|
|
175 #else
|
|
176 group_category = gtk_option_menu_get_history(GTK_OPTION_MENU(info_window->cmb_group_category));
|
|
177 #endif
|
|
178
|
|
179 if (group_category >= 0)
|
|
180 group->group_category = group_category;
|
|
181 else {
|
|
182 g_free(group);
|
|
183 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Invalid group_category: %d\n", group_category);
|
|
184 return;
|
|
185 } // if group_category
|
|
186 // get auth_type
|
|
187 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->rad_auth[0])))
|
|
188 group->auth_type = QQ_GROUP_AUTH_TYPE_NO_AUTH;
|
|
189 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->rad_auth[1])))
|
|
190 group->auth_type = QQ_GROUP_AUTH_TYPE_NEED_AUTH;
|
|
191 else
|
|
192 group->auth_type = QQ_GROUP_AUTH_TYPE_NO_ADD;
|
|
193 // MUST use g_strdup, otherwise core dump after info_window is closed
|
|
194 group->group_name_utf8 = g_strdup(gtk_entry_get_text(GTK_ENTRY(info_window->ent_group_name)));
|
|
195 gtk_text_buffer_get_bounds(gtk_text_view_get_buffer
|
|
196 (GTK_TEXT_VIEW(info_window->txt_group_desc)), &start, &end);
|
|
197 group->group_desc_utf8 =
|
|
198 g_strdup(gtk_text_buffer_get_text
|
|
199 (gtk_text_view_get_buffer
|
|
200 (GTK_TEXT_VIEW(info_window->txt_group_desc)), &start, &end, FALSE));
|
|
201 gtk_text_buffer_get_bounds(gtk_text_view_get_buffer
|
|
202 (GTK_TEXT_VIEW(info_window->txt_group_notice)), &start, &end);
|
|
203 group->notice_utf8 =
|
|
204 g_strdup(gtk_text_buffer_get_text
|
|
205 (gtk_text_view_get_buffer
|
|
206 (GTK_TEXT_VIEW(info_window->txt_group_notice)), &start, &end, FALSE));
|
|
207 // finally we can modify it with new information
|
|
208 qq_group_modify_info(gc, group);
|
|
209 break;
|
|
210 case PAGE_MEMBER:
|
|
211 if (info_window->tre_members == NULL) {
|
|
212 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Member list is not ready, cannot modify!\n");
|
|
213 } else {
|
|
214 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Gonna change Qun member list\n");
|
|
215 model = gtk_tree_view_get_model(GTK_TREE_VIEW(info_window->tre_members));
|
|
216 if (gtk_tree_model_get_iter_first(model, &iter)) {
|
|
217 gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value);
|
|
218 uid = g_value_get_uint(&value);
|
|
219 g_value_unset(&value);
|
|
220 gtk_tree_model_get_value(model, &iter, COLUMN_SELECTED, &value);
|
|
221 selected = g_value_get_boolean(&value);
|
|
222 g_value_unset(&value);
|
|
223 if (!selected)
|
|
224 new_members[i++] = uid;
|
|
225 while (gtk_tree_model_iter_next(model, &iter)) {
|
|
226 gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value);
|
|
227 uid = g_value_get_uint(&value);
|
|
228 g_value_unset(&value);
|
|
229 gtk_tree_model_get_value(model, &iter, COLUMN_SELECTED, &value);
|
|
230 selected = g_value_get_boolean(&value);
|
|
231 g_value_unset(&value);
|
|
232 if (!selected)
|
|
233 new_members[i++] = uid;
|
|
234 } // while
|
|
235 new_members[i] = 0xffffffff; // this labels the end
|
|
236 } else
|
|
237 new_members[0] = 0xffffffff;
|
|
238 qq_group_modify_members(gc, group, new_members);
|
|
239 } // if info_window->tre_members
|
|
240 break;
|
|
241 default:
|
|
242 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Invalid page number: %d\n", page);
|
|
243 } // switch
|
|
244
|
|
245 _qq_group_info_window_close(NULL, info_window->window);
|
|
246
|
|
247 //#endif /* GTK_CHECK_VERSION */
|
|
248 } // _qq_group_info_window_modify
|
|
249
|
|
250 /*****************************************************************************/
|
|
251 static void _qq_group_member_list_deleted_toggled(GtkCellRendererToggle * cell, gchar * path_str, gpointer data) {
|
|
252 qun_info_window *info_window;
|
|
253 GaimConnection *gc;
|
|
254 qq_group *group;
|
|
255
|
|
256 info_window = (qun_info_window *) data;
|
|
257 g_return_if_fail(info_window != NULL);
|
|
258
|
|
259 gc = info_window->gc;
|
|
260 g_return_if_fail(gc != NULL);
|
|
261
|
|
262 group = qq_group_find_by_internal_group_id(gc, info_window->internal_group_id);
|
|
263 g_return_if_fail(group != NULL);
|
|
264
|
|
265 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(info_window->tre_members));
|
|
266 GtkTreeIter iter;
|
|
267 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
|
|
268 gboolean selected;
|
|
269 guint32 uid;
|
|
270
|
|
271 gtk_tree_model_get_iter(model, &iter, path);
|
|
272 gtk_tree_model_get(model, &iter, COLUMN_SELECTED, &selected, -1);
|
|
273 gtk_tree_model_get(model, &iter, COLUMN_UID, &uid, -1);
|
|
274
|
|
275 if (uid != group->creator_uid) { // do not allow delete admin
|
|
276 selected ^= 1;
|
|
277 gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_SELECTED, selected, -1);
|
|
278 gtk_tree_path_free(path);
|
|
279 } else
|
|
280 gaim_notify_error(gc, NULL, _("Qun creator cannot be removed"), NULL);
|
|
281 } // _qq_group_member_list_deleted_toggled
|
|
282
|
|
283 /*****************************************************************************/
|
|
284 static void _qq_group_member_list_drag_data_rcv_cb
|
|
285 (GtkWidget * widget, GdkDragContext * dc, guint x, guint y,
|
|
286 GtkSelectionData * sd, guint info, guint t, gpointer data) {
|
|
287
|
|
288 GaimConnection *gc;
|
|
289 GaimAccount *account;
|
|
290 GaimBlistNode *n = NULL;
|
|
291 GaimContact *c = NULL;
|
|
292 GaimBuddy *b = NULL;
|
|
293 GtkWidget *treeview;
|
|
294 GtkTreeModel *model;
|
|
295 GtkListStore *store;
|
|
296 GtkTreeIter iter;
|
|
297 GValue value = { 0, };
|
|
298 guint32 uid, input_uid;
|
|
299
|
|
300 treeview = widget;
|
|
301 gc = (GaimConnection *) data;
|
|
302 g_return_if_fail(gc != NULL);
|
|
303 account = gaim_connection_get_account(gc);
|
|
304
|
|
305 if (sd->target != gdk_atom_intern("GAIM_BLIST_NODE", FALSE) || sd->data == NULL) {
|
|
306 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Invalid drag data received, discard...\n");
|
|
307 return;
|
|
308 } // if (sd->target
|
|
309
|
|
310 memcpy(&n, sd->data, sizeof(n));
|
|
311
|
|
312 // we expect GAIM_BLIST_CONTACT_NODE and GAIM_BLIST_BUDDY_NODE
|
|
313 if (GAIM_BLIST_NODE_IS_CONTACT(n)) {
|
|
314 c = (GaimContact *) n;
|
|
315 b = c->priority; // we get the first buddy only
|
|
316 } else if (GAIM_BLIST_NODE_IS_BUDDY(n))
|
|
317 b = (GaimBuddy *) n;
|
|
318
|
|
319 if (b == NULL) {
|
|
320 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "No valid GaimBuddy is passed from DnD\n");
|
|
321 return;
|
|
322 } // if b == NULL
|
|
323
|
|
324 gaim_debug(GAIM_DEBUG_INFO, "QQ", "We get a GaimBuddy: %s\n", b->name);
|
|
325 input_uid = gaim_name_to_uid(b->name);
|
|
326 g_return_if_fail(input_uid > 0);
|
|
327
|
|
328 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
|
|
329 // we need to check if the user id in the member list is unique
|
|
330 // possibly a tree transverse is necessary to achieve this
|
|
331 if (gtk_tree_model_get_iter_first(model, &iter)) {
|
|
332 gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value);
|
|
333 uid = g_value_get_uint(&value);
|
|
334 g_value_unset(&value);
|
|
335 while (uid != input_uid && gtk_tree_model_iter_next(model, &iter)) {
|
|
336 gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value);
|
|
337 uid = g_value_get_uint(&value);
|
|
338 g_value_unset(&value);
|
|
339 } // while
|
|
340 } else
|
|
341 uid = 0; // if gtk_tree_model_get_iter_first
|
|
342
|
|
343 if (uid == input_uid) {
|
|
344 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Qun already has this buddy %s\n", b->name);
|
|
345 return;
|
|
346 } else { // we add it to list
|
|
347 store = GTK_LIST_STORE(model);
|
|
348 gtk_list_store_append(store, &iter);
|
|
349 gtk_list_store_set(store, &iter,
|
|
350 COLUMN_SELECTED, FALSE, COLUMN_UID, input_uid, COLUMN_NICKNAME, b->alias, -1);
|
|
351 // re-sort the list
|
|
352 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), COLUMN_UID, GTK_SORT_ASCENDING);
|
|
353 } // if uid
|
|
354
|
|
355 } // _qq_group_member_list_drag_data_rcv_cb
|
|
356
|
|
357 /*****************************************************************************/
|
|
358 static GtkWidget *_create_page_info(GaimConnection * gc, qq_group * group, gboolean do_manage, qun_info_window * info_window) {
|
|
359 GtkWidget *vbox, *hbox;
|
|
360 GtkWidget *frame_info, *frame_auth;
|
|
361 GtkWidget *tbl_info;
|
|
362 GtkWidget *label, *entry, *combo, *text, *scrolled_window;
|
|
363 gint i;
|
|
364
|
|
365 g_return_val_if_fail(gc != NULL && group != NULL, NULL);
|
|
366
|
|
367 vbox = gtk_vbox_new(FALSE, 5);
|
|
368
|
|
369 frame_info = gtk_frame_new(NULL);
|
|
370 gtk_box_pack_start(GTK_BOX(vbox), frame_info, TRUE, TRUE, 0);
|
|
371
|
|
372 tbl_info = gtk_table_new(6, 4, FALSE);
|
|
373 gtk_table_set_row_spacings(GTK_TABLE(tbl_info), 4);
|
|
374 gtk_table_set_col_spacing(GTK_TABLE(tbl_info), 1, 10);
|
|
375 gtk_container_add(GTK_CONTAINER(frame_info), tbl_info);
|
|
376
|
|
377 label = gtk_label_new(_("Group ID: "));
|
|
378 gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
|
|
379 label = gtk_label_new(g_strdup_printf("%d", group->external_group_id));
|
|
380 gtk_table_attach(GTK_TABLE(tbl_info), label, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
|
|
381 info_window->lbl_external_group_id = label;
|
|
382
|
|
383 label = gtk_label_new(_("Group Name"));
|
|
384 gtk_table_attach(GTK_TABLE(tbl_info), label, 2, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
|
|
385 entry = gtk_entry_new();
|
|
386 gtk_widget_set_size_request(entry, 100, -1);
|
|
387 if (group->group_name_utf8 != NULL)
|
|
388 gtk_entry_set_text(GTK_ENTRY(entry), group->group_name_utf8);
|
|
389 gtk_table_attach(GTK_TABLE(tbl_info), entry, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
|
|
390 info_window->ent_group_name = entry;
|
|
391
|
|
392 label = gtk_label_new(_("Admin: "));
|
|
393 gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
|
|
394 label = gtk_label_new(g_strdup_printf("%d", group->creator_uid));
|
|
395 gtk_table_attach(GTK_TABLE(tbl_info), label, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
|
|
396 info_window->lbl_admin_uid = label;
|
|
397
|
|
398 label = gtk_label_new(_("Category"));
|
|
399 gtk_table_attach(GTK_TABLE(tbl_info), label, 2, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
|
|
400
|
|
401 //henry: these codes are supported only in GTK-2.4 or later
|
|
402 #if GTK_CHECK_VERSION(2, 4, 0)
|
|
403 combo = gtk_combo_box_new_text();
|
|
404 for (i = 0; i < 4; i++)
|
|
405 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), qq_group_category[i]);
|
|
406 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), group->group_category);
|
|
407 #else
|
|
408 GtkWidget *menu;
|
|
409 GtkWidget *item;
|
|
410
|
|
411 combo = gtk_option_menu_new();
|
|
412 menu = gtk_menu_new();
|
|
413 for (i = 0; i < 4; i++) {
|
|
414 item = gtk_menu_item_new_with_label(qq_group_category[i]);
|
|
415 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
|
|
416 gtk_widget_show(item);
|
|
417 }
|
|
418 gtk_option_menu_set_menu(GTK_OPTION_MENU(combo), menu);
|
|
419 gtk_option_menu_set_history(GTK_OPTION_MENU(combo), group->group_category);
|
|
420 #endif /* GTK_CHECK_VERSION */
|
|
421
|
|
422 gtk_table_attach(GTK_TABLE(tbl_info), combo, 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
|
|
423 info_window->cmb_group_category = combo;
|
|
424
|
|
425 label = gtk_label_new(_("Description"));
|
|
426 gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
|
|
427 text = gtk_text_view_new();
|
|
428 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
|
|
429 gtk_widget_set_size_request(text, -1, 50);
|
|
430 if (group->group_desc_utf8 != NULL)
|
|
431 gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), group->group_desc_utf8, -1);
|
|
432 info_window->txt_group_desc = text;
|
|
433
|
|
434 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
|
|
435 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
436 gtk_container_add(GTK_CONTAINER(scrolled_window), text);
|
|
437 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN);
|
|
438 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 2);
|
|
439 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 2);
|
|
440 gtk_table_attach(GTK_TABLE(tbl_info), scrolled_window, 0, 4, 3, 4, GTK_FILL, GTK_FILL, 0, 0);
|
|
441
|
|
442 label = gtk_label_new(_("Group Notice"));
|
|
443 gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0);
|
|
444 text = gtk_text_view_new();
|
|
445 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
|
|
446 gtk_widget_set_size_request(text, -1, 50);
|
|
447 if (group->notice_utf8 != NULL)
|
|
448 gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), group->notice_utf8, -1);
|
|
449 info_window->txt_group_notice = text;
|
|
450
|
|
451 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
|
|
452 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
453 gtk_container_add(GTK_CONTAINER(scrolled_window), text);
|
|
454 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN);
|
|
455 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 2);
|
|
456 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 2);
|
|
457 gtk_table_attach(GTK_TABLE(tbl_info), scrolled_window, 0, 4, 5, 6, GTK_FILL, GTK_FILL, 0, 0);
|
|
458
|
|
459 frame_auth = gtk_frame_new(_("Authentication"));
|
|
460 hbox = gtk_hbox_new(FALSE, 5);
|
|
461 gtk_container_add(GTK_CONTAINER(frame_auth), hbox);
|
|
462 info_window->rad_auth[0] = gtk_radio_button_new_with_label(NULL, qq_group_auth_type_desc[0]);
|
|
463 info_window->rad_auth[1] =
|
|
464 gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON
|
|
465 (info_window->rad_auth[0]), qq_group_auth_type_desc[1]);
|
|
466 info_window->rad_auth[2] =
|
|
467 gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON
|
|
468 (info_window->rad_auth[0]), qq_group_auth_type_desc[2]);
|
|
469 for (i = 0; i < 3; i++)
|
|
470 gtk_box_pack_start(GTK_BOX(hbox), info_window->rad_auth[i], FALSE, FALSE, 0);
|
|
471 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(info_window->rad_auth[group->auth_type - 1]), TRUE);
|
|
472 gtk_box_pack_start(GTK_BOX(vbox), frame_auth, FALSE, FALSE, 0);
|
|
473
|
|
474 if (!do_manage) {
|
|
475 gtk_widget_set_sensitive(frame_info, FALSE);
|
|
476 gtk_widget_set_sensitive(frame_auth, FALSE);
|
|
477 } // if ! do_manage
|
|
478
|
|
479 return vbox;
|
|
480 } // _create_info_page
|
|
481
|
|
482 /*****************************************************************************/
|
|
483 static GtkWidget *_create_page_members
|
|
484 (GaimConnection * gc, qq_group * group, gboolean do_manage, qun_info_window * info_window) {
|
|
485 GtkWidget *vbox, *sw, *treeview;
|
|
486 GtkTreeModel *model;
|
|
487 GtkListStore *store;
|
|
488 GtkTreeIter iter;
|
|
489 GtkCellRenderer *renderer;
|
|
490 GtkTreeViewColumn *column;
|
|
491 GList *list;
|
|
492 qq_buddy *q_bud;
|
|
493 GtkTargetEntry gte = { "GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, 0 };
|
|
494
|
|
495 g_return_val_if_fail(gc != NULL && group != NULL, NULL);
|
|
496
|
|
497 vbox = gtk_vbox_new(FALSE, 0);
|
|
498
|
|
499 if (group->members == NULL) { // if NULL, not ready
|
|
500 sw = gtk_label_new(_
|
|
501 ("OpenQ is collecting member information.\nPlease close this window and open again"));
|
|
502 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
|
|
503 return vbox;
|
|
504 } // if group->members
|
|
505
|
|
506 sw = gtk_scrolled_window_new(NULL, NULL);
|
|
507 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
|
|
508 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
509 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
|
|
510
|
|
511 store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_UINT, G_TYPE_STRING);
|
|
512
|
|
513 list = group->members;
|
|
514 while (list != NULL) {
|
|
515 q_bud = (qq_buddy *) list->data;
|
|
516 gtk_list_store_append(store, &iter);
|
|
517 gtk_list_store_set(store, &iter,
|
|
518 COLUMN_SELECTED, FALSE,
|
|
519 COLUMN_UID, q_bud->uid, COLUMN_NICKNAME, q_bud->nickname, -1);
|
|
520 list = list->next;
|
|
521 } // for
|
|
522
|
|
523 model = GTK_TREE_MODEL(store);
|
|
524 treeview = gtk_tree_view_new_with_model(model);
|
|
525 info_window->tre_members = treeview;
|
|
526
|
|
527 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
|
|
528 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), COLUMN_UID);
|
|
529 g_object_unref(model);
|
|
530
|
|
531 // set up drag & drop ONLY for managable Qun
|
|
532 if (do_manage) {
|
|
533 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(treeview), >e, 1, GDK_ACTION_COPY);
|
|
534 g_signal_connect(G_OBJECT(treeview), "drag-data-received",
|
|
535 G_CALLBACK(_qq_group_member_list_drag_data_rcv_cb), gc);
|
|
536 } // if do manage
|
|
537
|
|
538 gtk_container_add(GTK_CONTAINER(sw), treeview);
|
|
539
|
|
540 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
|
|
541 renderer = gtk_cell_renderer_toggle_new();
|
|
542
|
|
543 // it seems this signal has to be handled
|
|
544 // otherwise, the checkbox in the column does not reponse to user action
|
|
545 if (do_manage)
|
|
546 g_signal_connect(renderer, "toggled", G_CALLBACK(_qq_group_member_list_deleted_toggled), info_window);
|
|
547
|
|
548 column = gtk_tree_view_column_new_with_attributes(_("Del"), renderer, "active", COLUMN_SELECTED, NULL);
|
|
549
|
|
550 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column), GTK_TREE_VIEW_COLUMN_FIXED);
|
|
551 gtk_tree_view_column_set_fixed_width(GTK_TREE_VIEW_COLUMN(column), 30);
|
|
552 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
|
|
553
|
|
554 renderer = gtk_cell_renderer_text_new();
|
|
555 column = gtk_tree_view_column_new_with_attributes(_("UID"), renderer, "text", COLUMN_UID, NULL);
|
|
556 gtk_tree_view_column_set_sort_column_id(column, COLUMN_UID);
|
|
557 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
|
|
558 // default sort by UID
|
|
559 gtk_tree_view_column_set_sort_order(column, GTK_SORT_ASCENDING);
|
|
560 gtk_tree_view_column_set_sort_indicator(column, TRUE);
|
|
561
|
|
562 renderer = gtk_cell_renderer_text_new();
|
|
563 column = gtk_tree_view_column_new_with_attributes(_("Nickname"), renderer, "text", COLUMN_NICKNAME, NULL);
|
|
564 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
|
|
565
|
|
566 return vbox;
|
|
567 } // _create_page_members
|
|
568
|
|
569 /*****************************************************************************/
|
|
570 void qq_group_detail_window_show(GaimConnection * gc, qq_group * group)
|
|
571 {
|
|
572 GtkWidget *vbox, *notebook;
|
|
573 GtkWidget *label, *bbox;
|
|
574 GList *list;
|
|
575 qq_data *qd;
|
|
576 qun_info_window *info_window = NULL;
|
|
577 gboolean do_manage, do_show, do_exist;
|
|
578
|
|
579 g_return_if_fail(gc != NULL && gc->proto_data != NULL && group != NULL);
|
|
580 qd = (qq_data *) gc->proto_data;
|
|
581
|
|
582 do_manage = group->my_status == QQ_GROUP_MEMBER_STATUS_IS_ADMIN;
|
|
583 do_show = do_manage || (group->my_status == QQ_GROUP_MEMBER_STATUS_IS_MEMBER);
|
|
584
|
|
585 if (!do_show) {
|
|
586 gaim_notify_error(gc, _("QQ Qun Operation"),
|
|
587 _("You can not view Qun details"),
|
|
588 _("Only Qun admin or Qun member can view details"));
|
|
589 return;
|
|
590 } // if ! do_show
|
|
591
|
|
592 list = qd->qun_info_window;
|
|
593 do_exist = FALSE;
|
|
594 while (list != NULL) {
|
|
595 info_window = (qun_info_window *) list->data;
|
|
596 if (info_window->internal_group_id == group->internal_group_id) {
|
|
597 break;
|
|
598 do_exist = TRUE;
|
|
599 } else
|
|
600 list = list->next;
|
|
601 } // while list
|
|
602
|
|
603 if (!do_exist) {
|
|
604 info_window = g_new0(qun_info_window, 1);
|
|
605 info_window->gc = gc;
|
|
606 info_window->internal_group_id = group->internal_group_id;
|
|
607 g_list_append(qd->qun_info_window, info_window);
|
|
608
|
|
609 info_window->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
610 g_signal_connect(GTK_WINDOW(info_window->window),
|
|
611 "delete_event", G_CALLBACK(_qq_group_info_window_deleteevent), NULL);
|
|
612 g_signal_connect(G_OBJECT(info_window->window), "destroy",
|
|
613 G_CALLBACK(_qq_group_info_window_destroy), gc);
|
|
614
|
|
615 gtk_window_set_title(GTK_WINDOW(info_window->window), _("Manage Qun"));
|
|
616 gtk_window_set_resizable(GTK_WINDOW(info_window->window), FALSE);
|
|
617 gtk_container_set_border_width(GTK_CONTAINER(info_window->window), 5);
|
|
618
|
|
619 vbox = gtk_vbox_new(FALSE, 0);
|
|
620 gtk_container_add(GTK_CONTAINER(info_window->window), vbox);
|
|
621
|
|
622 notebook = gtk_notebook_new();
|
|
623 info_window->notebook = notebook;
|
|
624 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
|
|
625 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
|
|
626
|
|
627 label = gtk_label_new(_("Qun Information"));
|
|
628 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
|
|
629 _create_page_info(gc, group, do_manage, info_window), label);
|
|
630 label = gtk_label_new(_("Members"));
|
|
631 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
|
|
632 _create_page_members(gc, group, do_manage, info_window), label);
|
|
633
|
|
634 bbox = gtk_hbutton_box_new();
|
|
635 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_SPREAD);
|
|
636 gtk_box_set_spacing(GTK_BOX(bbox), 10);
|
|
637
|
|
638 info_window->btn_mod = gtk_button_new_with_label(_("Modify"));
|
|
639 gtk_container_add(GTK_CONTAINER(bbox), info_window->btn_mod);
|
|
640 g_signal_connect(G_OBJECT(info_window->btn_mod), "clicked",
|
|
641 G_CALLBACK(_qq_group_info_window_modify), info_window);
|
|
642
|
|
643 info_window->btn_close = gtk_button_new_with_label(_("Close"));
|
|
644 gtk_container_add(GTK_CONTAINER(bbox), info_window->btn_close);
|
|
645 g_signal_connect(G_OBJECT(info_window->btn_close),
|
|
646 "clicked", G_CALLBACK(_qq_group_info_window_close), info_window->window);
|
|
647
|
|
648 if (!do_manage)
|
|
649 gtk_widget_set_sensitive(info_window->btn_mod, FALSE);
|
|
650 gtk_box_pack_start(GTK_BOX(vbox), bbox, TRUE, TRUE, 5);
|
|
651 gtk_widget_show_all(info_window->window);
|
|
652
|
|
653 } else // we already have this
|
|
654 gtk_widget_grab_focus(info_window->window);
|
|
655
|
|
656 } // qq_group_manage_window_show
|
|
657
|
|
658 /*****************************************************************************/
|
|
659 // END OF FILE
|