Mercurial > pidgin
changeset 14265:584cbd1628d0
[gaim-migrate @ 16947]
Added support for QQ faces. Thanks to csyfek@gmail.com for the images and protocol update.
committer: Tailor Script <tailor@pidgin.im>
line wrap: on
line diff
--- a/gtk/pixmaps/status/default/Makefile.am Mon Aug 21 06:06:54 2006 +0000 +++ b/gtk/pixmaps/status/default/Makefile.am Mon Aug 21 07:17:40 2006 +0000 @@ -42,6 +42,108 @@ yahoo.png \ zephyr.png +QQ_FACES = \ + qq_1.png \ + qq_2.png \ + qq_3.png \ + qq_4.png \ + qq_5.png \ + qq_6.png \ + qq_7.png \ + qq_8.png \ + qq_9.png \ + qq_10.png \ + qq_11.png \ + qq_12.png \ + qq_13.png \ + qq_14.png \ + qq_15.png \ + qq_16.png \ + qq_17.png \ + qq_18.png \ + qq_19.png \ + qq_20.png \ + qq_21.png \ + qq_22.png \ + qq_23.png \ + qq_24.png \ + qq_25.png \ + qq_26.png \ + qq_27.png \ + qq_28.png \ + qq_29.png \ + qq_30.png \ + qq_31.png \ + qq_32.png \ + qq_33.png \ + qq_34.png \ + qq_35.png \ + qq_36.png \ + qq_37.png \ + qq_38.png \ + qq_39.png \ + qq_40.png \ + qq_41.png \ + qq_42.png \ + qq_43.png \ + qq_44.png \ + qq_45.png \ + qq_46.png \ + qq_47.png \ + qq_48.png \ + qq_49.png \ + qq_50.png \ + qq_51.png \ + qq_52.png \ + qq_53.png \ + qq_54.png \ + qq_55.png \ + qq_56.png \ + qq_57.png \ + qq_58.png \ + qq_59.png \ + qq_60.png \ + qq_61.png \ + qq_62.png \ + qq_63.png \ + qq_64.png \ + qq_65.png \ + qq_66.png \ + qq_67.png \ + qq_68.png \ + qq_69.png \ + qq_70.png \ + qq_71.png \ + qq_72.png \ + qq_73.png \ + qq_74.png \ + qq_75.png \ + qq_76.png \ + qq_77.png \ + qq_78.png \ + qq_79.png \ + qq_80.png \ + qq_81.png \ + qq_82.png \ + qq_83.png \ + qq_84.png \ + qq_85.png \ + qq_86.png \ + qq_87.png \ + qq_88.png \ + qq_89.png \ + qq_90.png \ + qq_91.png \ + qq_92.png \ + qq_93.png \ + qq_94.png \ + qq_95.png \ + qq_96.png \ + qq_97.png \ + qq_98.png \ + qq_99.png \ + qq_100.png + gaimstatuspixdir = $(datadir)/pixmaps/gaim/status/default -gaimstatuspix_DATA = $(EXTRA_DIST) +gaimstatuspix_DATA = $(EXTRA_DIST) $(QQ_FACES)
--- a/libgaim/protocols/qq/buddy_info.c Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/buddy_info.c Mon Aug 21 07:17:40 2006 +0000 @@ -282,7 +282,7 @@ /************************ packets and UI management **************************/ /* send a packet to get detailed information of uid */ -void qq_send_packet_get_info(GaimConnection * gc, guint32 uid, gboolean show_window) +void qq_send_packet_get_info(GaimConnection *gc, guint32 uid, gboolean show_window) { qq_data *qd; gchar *uid_str; @@ -597,6 +597,14 @@ return; info = (contact_info *) segments; + if (qd->modifying_face && strtol(info->face, NULL, 10) != qd->my_icon) { + gchar *icon = g_strdup_printf("%i", qd->my_icon); + qd->modifying_face = FALSE; + memcpy(info->face, icon, 2); + qq_send_packet_modify_info(gc, info); + g_free(icon); + } + qq_refresh_buddy_and_myself(info, gc); query_list = qd->info_query;
--- a/libgaim/protocols/qq/buddy_list.c Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/buddy_list.c Mon Aug 21 07:17:40 2006 +0000 @@ -255,7 +255,7 @@ qq_buddy *q_bud; gint len, bytes, bytes_expected, i; guint16 position, unknown; - guint8 *data, *cursor, bar, pascal_len; + guint8 *data, *cursor, pascal_len; gchar *name; GaimBuddy *b; @@ -276,10 +276,8 @@ bytes = 0; /* 000-003: uid */ bytes += read_packet_dw(data, &cursor, len, &q_bud->uid); - /* 004-004: 0xff if buddy is self, 0x00 otherwise */ - bytes += read_packet_b(data, &cursor, len, &bar); - /* 005-005: icon index (1-255) */ - bytes += read_packet_b(data, &cursor, len, &q_bud->icon); + /* 004-005: icon index (1-255) */ + bytes += read_packet_w(data, &cursor, len, &q_bud->icon); /* 006-006: age */ bytes += read_packet_b(data, &cursor, len, &q_bud->age); /* 007-007: gender */
--- a/libgaim/protocols/qq/buddy_status.c Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/buddy_status.c Mon Aug 21 07:17:40 2006 +0000 @@ -120,20 +120,22 @@ return FALSE; } -/* the icon suffix is detemined by status - * although QQ server may return the right icon, I set it here myself */ -gchar get_suffix_from_status(guint8 status) +/* The QQ client seems to use a separate icon for each + * face/status combo, but we only use one and let Gaim + * handle the rest. We need to use this function to report + * the correct icon file back to the server. */ +gint get_icon_offset_from_self_status(guint8 status) { switch (status) { - case QQ_BUDDY_ONLINE_NORMAL: - return QQ_ICON_SUFFIX_NORMAL; - case QQ_BUDDY_ONLINE_AWAY: - return QQ_ICON_SUFFIX_AWAY; - case QQ_BUDDY_ONLINE_INVISIBLE: - case QQ_BUDDY_ONLINE_OFFLINE: - return QQ_ICON_SUFFIX_OFFLINE; + case QQ_SELF_STATUS_AVAILABLE: + return 0; + case QQ_SELF_STATUS_AWAY: + case QQ_SELF_STATUS_CUSTOM: + return 1; + case QQ_SELF_STATUS_INVISIBLE: + return 2; default: - return QQ_ICON_SUFFIX_DEFAULT; + return 2; } }
--- a/libgaim/protocols/qq/buddy_status.h Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/buddy_status.h Mon Aug 21 07:17:40 2006 +0000 @@ -59,7 +59,7 @@ gboolean is_online(guint8 status); gint qq_buddy_status_read(guint8 *data, guint8 **cursor, gint len, qq_buddy_status *s); -gchar get_suffix_from_status(guint8 status); +gint get_icon_offset_from_self_status(guint8 status); void qq_send_packet_change_status(GaimConnection *gc);
--- a/libgaim/protocols/qq/group_info.c Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/group_info.c Mon Aug 21 07:17:40 2006 +0000 @@ -283,7 +283,6 @@ { guint32 internal_group_id, member_uid; guint16 unknown; - guint8 bar; gint pascal_len, i; qq_group *group; qq_buddy *member; @@ -305,8 +304,7 @@ g_return_if_fail(member != NULL); i++; - read_packet_b(data, cursor, len, &bar); - read_packet_b(data, cursor, len, &(member->icon)); + read_packet_w(data, cursor, len, &(member->icon)); read_packet_b(data, cursor, len, &(member->age)); read_packet_b(data, cursor, len, &(member->gender)); pascal_len = convert_as_pascal_string(*cursor, &(member->nickname), QQ_CHARSET_DEFAULT);
--- a/libgaim/protocols/qq/im.c Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/im.c Mon Aug 21 07:17:40 2006 +0000 @@ -87,8 +87,7 @@ /* now comes the part for text only */ guint16 msg_seq; guint32 send_time; - guint8 unknown1; - guint8 sender_icon; + guint16 sender_icon; guint8 unknown2[3]; guint8 is_there_font_attr; guint8 unknown3[4]; @@ -268,8 +267,7 @@ /* push data into im_text */ read_packet_w(data, cursor, len, &(im_text->msg_seq)); read_packet_dw(data, cursor, len, &(im_text->send_time)); - read_packet_b(data, cursor, len, &(im_text->unknown1)); - read_packet_b(data, cursor, len, &(im_text->sender_icon)); + read_packet_w(data, cursor, len, &(im_text->sender_icon)); read_packet_data(data, cursor, len, (guint8 *) & (im_text->unknown2), 3); read_packet_b(data, cursor, len, &(im_text->is_there_font_attr)); /** @@ -515,10 +513,8 @@ bytes += create_packet_w(raw_data, &cursor, qd->send_seq); /* 038-041: send time */ bytes += create_packet_dw(raw_data, &cursor, (guint32) now); - /* 042-042: always 0x00 */ - bytes += create_packet_b(raw_data, &cursor, 0x00); - /* 043-043: sender icon */ - bytes += create_packet_b(raw_data, &cursor, qd->my_icon); + /* 042-043: sender icon */ + bytes += create_packet_w(raw_data, &cursor, qd->my_icon); /* 044-046: always 0x00 */ bytes += create_packet_w(raw_data, &cursor, 0x0000); bytes += create_packet_b(raw_data, &cursor, 0x00);
--- a/libgaim/protocols/qq/login_logout.c Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/login_logout.c Mon Aug 21 07:17:40 2006 +0000 @@ -229,6 +229,7 @@ qq_group_init(gc); /* Now goes on updating my icon/nickname, not showing info_window */ + qd->modifying_face = FALSE; qq_send_packet_get_info(gc, qd->uid, FALSE); /* change my status manually, even server may broadcast my online */ qd->status = (qd->login_mode == QQ_LOGIN_MODE_HIDDEN) ? QQ_SELF_STATUS_INVISIBLE : QQ_SELF_STATUS_AVAILABLE;
--- a/libgaim/protocols/qq/qq.c Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/qq.c Mon Aug 21 07:17:40 2006 +0000 @@ -147,27 +147,17 @@ /* returns the icon name for a buddy or protocol */ static const gchar *_qq_list_icon(GaimAccount *a, GaimBuddy *b) { - /* XXX temp commented out until we figure out what to do with - * status icons */ - /* gchar *filename; qq_buddy *q_bud; - gchar icon_suffix; - */ /* do not use g_return_val_if_fail, as it is not assertion */ if (b == NULL || b->proto_data == NULL) return "qq"; - /* q_bud = (qq_buddy *) b->proto_data; - - icon_suffix = get_suffix_from_status(q_bud->status); - filename = get_icon_name(q_bud->icon / 3 + 1, icon_suffix); + filename = get_icon_name(q_bud->icon / 3 + 1); return filename; - */ - return "qq"; } @@ -282,17 +272,20 @@ qq_buddy *q_bud = b->proto_data; const char *emblems[4] = { NULL, NULL, NULL, NULL }; - int i = 0; + int i = 1; if (q_bud == NULL) { emblems[0] = "offline"; } else { + /* TODO the wireless icon is a bit too big to look good with QQ faces */ + if (q_bud->status == QQ_BUDDY_ONLINE_AWAY || q_bud->status == QQ_SELF_STATUS_AWAY) + emblems[i++] = "away"; if (q_bud->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) emblems[i++] = "qq_member"; if (q_bud->comm_flag & QQ_COMM_FLAG_BIND_MOBILE) emblems[i++] = "wireless"; if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO) - emblems[i++] = "video"; + emblems[i%4] = "video"; } @@ -437,6 +430,85 @@ qq_prepare_modify_info(gc); } +static void _qq_change_face_cb(GaimConnection *gc, GaimRequestFields *fields) +{ + qq_data *qd; + GaimRequestField *field; + gint suffix; + + g_return_if_fail(gc != NULL && gc->proto_data != NULL); + qd = (qq_data *) gc->proto_data; + + field = gaim_request_fields_get_field(fields, "face_num"); + suffix = get_icon_offset_from_self_status(qd->status); + qd->my_icon = gaim_request_field_choice_get_value(field) * 3 + suffix; + qd->modifying_face = TRUE; + qq_send_packet_get_info(gc, qd->uid, FALSE); +} + +static void _qq_add_face_choice(GaimRequestFieldGroup *group, gint face_num) +{ + GaimRequestField *field; + struct stat img_stat; + FILE *file; + gchar *filename, *prefix, *img_data, *face; + gint size; + + face = g_strdup_printf("qq_%i.png", face_num); + prefix = br_extract_prefix(DATADIR); + filename = g_build_filename(prefix, "share","pixmaps", + "gaim","status","default", face, NULL); + g_free(face); + face = g_strdup_printf("%i", face_num); + stat(filename, &img_stat); + file = g_fopen(filename, "rb"); + if (file) { + img_data = g_malloc(img_stat.st_size); + size = fread(img_data, 1, img_stat.st_size, file); + + field = gaim_request_field_image_new(face, face, img_data, size); + gaim_request_field_group_add_field(group, field); + + g_free(img_data); + fclose(file); + } + g_free(face); + g_free(prefix); +} + +static void _qq_menu_change_face(GaimPluginAction *action) +{ + GaimConnection *gc = (GaimConnection *) action->context; + qq_data *qd = (qq_data *) gc->proto_data; + GaimRequestFields *fields; + GaimRequestFieldGroup *group; + GaimRequestField *field; + gchar *label; + gint i; + + fields = gaim_request_fields_new(); + group = gaim_request_field_group_new(_("Selection")); + gaim_request_fields_add_group(fields, group); + field = gaim_request_field_choice_new("face_num", + _("Select a number"), qd->my_icon / 3); + for(i = 1; i <= QQ_FACES; i++) { + label = g_strdup_printf("%i", i); + gaim_request_field_choice_add(field, label); + g_free(label); + } + gaim_request_field_group_add_field(group, field); + group = gaim_request_field_group_new(_("Faces")); + gaim_request_fields_add_group(fields, group); + for(i = 1; i <= QQ_FACES; i++) + _qq_add_face_choice(group, i); + + gaim_request_fields(gc, _("Change Your QQ Face"), + _("Change Face"), NULL, fields, + _("Update"), G_CALLBACK(_qq_change_face_cb), + _("Cancel"), NULL, + gc); +} + static void _qq_menu_change_password(GaimPluginAction *action) { gaim_notify_uri(NULL, "https://password.qq.com"); @@ -795,6 +867,9 @@ act = gaim_plugin_action_new(_("Modify My Information"), _qq_menu_modify_my_info); m = g_list_append(m, act); + act = gaim_plugin_action_new(_("Change My Face"), _qq_menu_change_face); + m = g_list_append(m, act); + act = gaim_plugin_action_new(_("Change Password"), _qq_menu_change_password); m = g_list_append(m, act);
--- a/libgaim/protocols/qq/qq.h Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/qq.h Mon Aug 21 07:17:40 2006 +0000 @@ -29,6 +29,7 @@ #include "proxy.h" #include "roomlist.h" +#define QQ_FACES 100 #define QQ_KEY_LENGTH 16 #define QQ_DEBUG 1 /* whether we are doing DEBUG */ @@ -37,7 +38,7 @@ struct _qq_buddy { guint32 uid; - guint8 icon; /* index: 01 - 85 */ + guint16 icon; /* index: 01 - 85 */ guint8 age; guint8 gender; gchar *nickname; @@ -83,7 +84,7 @@ /* get from keep_alive packet */ gchar *my_ip; /* my ip address detected by server */ guint16 my_port; /* my port detected by server */ - guint8 my_icon; /* my icon index */ + guint16 my_icon; /* my icon index */ guint32 all_online; /* the number of online QQ users */ time_t last_get_online; /* last time send get_friends_online packet */ @@ -103,7 +104,9 @@ GList *add_buddy_request; GQueue *before_login_packets; + /* TODO is there a better way of handling these? */ gboolean modifying_info; + gboolean modifying_face; }; void qq_function_not_implemented(GaimConnection *gc);
--- a/libgaim/protocols/qq/utils.c Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/utils.c Mon Aug 21 07:17:40 2006 +0000 @@ -159,9 +159,9 @@ /* return the QQ icon file name * the return needs to be freed */ -gchar *get_icon_name(gint set, gint suffix) +gchar *get_icon_name(gint set) { - return g_strdup_printf("qq_%d-%d", set, suffix); + return g_strdup_printf("qq_%d", set); } /* convert a QQ UID to a unique name of GAIM
--- a/libgaim/protocols/qq/utils.h Mon Aug 21 06:06:54 2006 +0000 +++ b/libgaim/protocols/qq/utils.h Mon Aug 21 07:17:40 2006 +0000 @@ -40,7 +40,7 @@ guint32 gaim_name_to_uid(const gchar *name); -gchar *get_icon_name(gint set, gint suffix); +gchar *get_icon_name(gint set); void try_dump_as_gbk(const guint8 *const data, gint len);