edu.tsinghua.lumaqq.ui.QQEventProcessor.java Source code

Java tutorial

Introduction

Here is the source code for edu.tsinghua.lumaqq.ui.QQEventProcessor.java

Source

/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*                    whg2001 <whg_2001@sohu.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.ui;

import static edu.tsinghua.lumaqq.resource.Messages.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;

import edu.tsinghua.lumaqq.models.Cluster;
import edu.tsinghua.lumaqq.models.ClusterType;
import edu.tsinghua.lumaqq.models.Group;
import edu.tsinghua.lumaqq.models.ModelRegistry;
import edu.tsinghua.lumaqq.models.ModelUtils;
import edu.tsinghua.lumaqq.models.Organization;
import edu.tsinghua.lumaqq.models.Status;
import edu.tsinghua.lumaqq.models.User;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.QQPort;
import edu.tsinghua.lumaqq.qq.beans.CardStub;
import edu.tsinghua.lumaqq.qq.beans.ContactInfo;
import edu.tsinghua.lumaqq.qq.beans.FriendOnlineEntry;
import edu.tsinghua.lumaqq.qq.beans.Member;
import edu.tsinghua.lumaqq.qq.beans.QQFriend;
import edu.tsinghua.lumaqq.qq.beans.QQLive;
import edu.tsinghua.lumaqq.qq.beans.QQOrganization;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.beans.SMSReply;
import edu.tsinghua.lumaqq.qq.beans.SimpleClusterInfo;
import edu.tsinghua.lumaqq.qq.events.IQQListener;
import edu.tsinghua.lumaqq.qq.events.QQEvent;
import edu.tsinghua.lumaqq.qq.packets.ErrorPacket;
import edu.tsinghua.lumaqq.qq.packets.in.AddFriendExReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ClusterCommandReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.FriendChangeStatusPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetOnlineOpReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetUserInfoReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.KeepAliveReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;
import edu.tsinghua.lumaqq.qq.packets.in.RequestKeyReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.SendSMSReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.SystemNotificationPacket;
import edu.tsinghua.lumaqq.qq.packets.out.DeleteFriendPacket;
import edu.tsinghua.lumaqq.qq.packets.out.RequestKeyPacket;
import edu.tsinghua.lumaqq.qq.packets.out.SendIMPacket;
import edu.tsinghua.lumaqq.ui.config.cluster.ClusterInfoWindow;
import edu.tsinghua.lumaqq.ui.config.user.UserInfoWindow;
import edu.tsinghua.lumaqq.ui.helper.CheckUpdateThread;
import edu.tsinghua.lumaqq.ui.helper.ShellRegistry;
import edu.tsinghua.lumaqq.ui.jobs.BackgroundJobExecutor;
import edu.tsinghua.lumaqq.ui.jobs.DownloadCustomHeadJob;
import edu.tsinghua.lumaqq.ui.jobs.DownloadFriendRemarkJob;
import edu.tsinghua.lumaqq.ui.jobs.DownloadGroupJob;
import edu.tsinghua.lumaqq.ui.jobs.DownloadSignatureJob;
import edu.tsinghua.lumaqq.ui.jobs.GetCustomHeadInfoJob;
import edu.tsinghua.lumaqq.ui.jobs.GetFriendLevelJob;
import edu.tsinghua.lumaqq.ui.jobs.GetFriendListJob;
import edu.tsinghua.lumaqq.ui.jobs.GetUserPropertyJob;
import edu.tsinghua.lumaqq.ui.jobs.IExecutor;
import edu.tsinghua.lumaqq.ui.jobs.IJob;

/**
 * QQ?
 * 
 * @author luma ?
 */
class QQEventProcessor implements IQQListener {
    // Log
    static Log log = LogFactory.getLog(QQEventProcessor.class);
    // ?
    private MainShell main;

    // 
    private Map<User, User> tempHash;

    // ???6
    // ???3
    // ????tcp???3
    // ??
    private int retryCount;

    /**
     * 
     */
    public QQEventProcessor(MainShell main) {
        this.main = main;
        tempHash = new HashMap<User, User>();
        retryCount = 0;
    }

    /**
     * ????
     */
    public void clear() {
        main.getCurrentOnlines().clear();
        tempHash.clear();
        main.getTipHelper().setFirstTime(true);
    }

    /* (non-Javadoc)
     * @see edu.tsinghua.lumaqq.qq.events.QQListener#qqEvent(edu.tsinghua.lumaqq.qq.events.QQEvent)
     */
    public void qqEvent(QQEvent e) {
        switch (e.type) {
        case QQEvent.QQ_GET_LOGIN_TOKEN_FAIL:
            processLoginTimeout();
            break;
        case QQEvent.QQ_LOGIN_SUCCESS:
            processLoginSuccess();
            break;
        case QQEvent.QQ_GET_FRIEND_ONLINE_SUCCESS:
            processGetFriendOnlineSuccess(e);
            break;
        case QQEvent.QQ_CHANGE_STATUS_SUCCESS:
            processChangeStatusSuccess();
            break;
        case QQEvent.QQ_CHANGE_STATUS_FAIL:
            processChangeStatusFail();
            break;
        case QQEvent.QQ_FRIEND_CHANGE_STATUS:
            processFriendChangeStatus(e);
            break;
        case QQEvent.QQ_RECEIVE_NORMAL_IM:
            processReceiveNormalIM(e);
            break;
        case QQEvent.QQ_UNKNOWN_TYPE_IM:
            processUnknownTypeIM(e);
            break;
        case QQEvent.QQ_REQUEST_SEND_FILE:
            processRequestSendFile(e);
            break;
        case QQEvent.QQ_KICKED_OUT_BY_SYSTEM:
            processKickedOutBySystem();
            break;
        case QQEvent.QQ_ADDED_BY_OTHERS:
        case QQEvent.QQ_ADDED_BY_OTHERS_EX:
        case QQEvent.QQ_REQUEST_ADD_ME:
        case QQEvent.QQ_REQUEST_ADD_ME_EX:
        case QQEvent.QQ_REQUEST_ADD_OTHER_APPROVED:
        case QQEvent.QQ_REQUEST_ADD_OTHER_REJECTED:
        case QQEvent.QQ_REQUEST_ADD_OTHER_APPROVED_AND_ADD:
            processReceiveSystemNotification(e);
            break;
        case QQEvent.QQ_LOGIN_FAIL:
            processLoginFail(e);
            break;
        case QQEvent.QQ_LOGIN_UNKNOWN_ERROR:
            processLoginUnknownError();
            break;
        case QQEvent.QQ_LOGIN_REDIRECT_NULL:
            processLoginRedirectNull();
            break;
        case QQEvent.QQ_ADD_FRIEND_SUCCESS:
        case QQEvent.QQ_ADD_FRIEND_ALREADY:
            processAddFriendSuccess(e);
            break;
        case QQEvent.QQ_DELETE_FRIEND_SUCCESS:
        case QQEvent.QQ_DELETE_FRIEND_FAIL:
            processDeleteFriendSuccess(e);
            break;
        /*case QQEvent.QQ_DELETE_FRIEND_FAIL:
        processDeleteFriendFail(e);
        break;*/
        case QQEvent.QQ_KEEP_ALIVE_SUCCESS:
            processKeepAliveSuccess(e);
            break;
        case QQEvent.QQ_CREATE_CLUSTER_SUCCESS:
            processClusterCreateSuccess(e);
            break;
        case QQEvent.QQ_CREATE_TEMP_CLUSTER_SUCCESS:
            processClusterCreateTempClusterSuccess(e);
            break;
        case QQEvent.QQ_GET_MEMBER_INFO_SUCCESS:
            processClusterGetMemberInfoSuccess(e);
            break;
        case QQEvent.QQ_GET_ONLINE_MEMBER_SUCCESS:
            processClusterGetOnlineMemberSuccess(e);
            break;
        case QQEvent.QQ_EXIT_CLUSTER_SUCCESS:
        case QQEvent.QQ_EXIT_TEMP_CLUSTER_SUCCESS:
        case QQEvent.QQ_DISMISS_CLUSTER_SUCCESS:
            processClusterExitClusterSuccess(e);
            break;
        case QQEvent.QQ_RECEIVE_SMS:
            processReceiveSMS(e);
            break;
        case QQEvent.QQ_RECEIVE_DISK_NOTIFICATION:
            processReceiveDiskNotification(e);
            break;
        case QQEvent.QQ_RECEIVE_CLUSTER_IM:
        case QQEvent.QQ_RECEIVE_TEMP_CLUSTER_IM:
        case QQEvent.QQ_RECEIVE_UNKNOWN_CLUSTER_IM:
            processReceiveClusterIM(e);
            break;
        case QQEvent.QQ_RECEIVE_TEMP_SESSION_IM:
            processReceiveTempSessionIM(e);
            break;
        case QQEvent.QQ_I_AM_ADDED_TO_CLUSTER:
            processIAmAddedToCluster(e);
            break;
        case QQEvent.QQ_ADMIN_ENTITLED:
            processAdminEntitled(e);
            break;
        case QQEvent.QQ_ADMIN_WITHDRAWED:
            processAdminWithdrawed(e);
            break;
        case QQEvent.QQ_SET_ROLE_SUCCESS:
            processSetRoleSuccess(e);
            break;
        case QQEvent.QQ_TRANSFER_ROLE_SUCCESS:
            processTransferRoleSuccess(e);
            break;
        case QQEvent.QQ_SET_ROLE_FAIL:
        case QQEvent.QQ_TRANSFER_ROLE_FAIL:
            processRoleOpFail(e);
            break;
        case QQEvent.QQ_I_AM_REMOVED_FROM_CLUSTER:
            processIAmRemovedFromCluster(e);
            break;
        case QQEvent.QQ_REQUEST_JOIN_CLUSTER:
            processRequestJoinCluster(e);
            break;
        case QQEvent.QQ_REQUEST_JOIN_CLUSTER_APPROVED:
            processRequestJoinClusterApproved(e);
            break;
        case QQEvent.QQ_REQUEST_JOIN_CLUSTER_REJECTED:
            processRequestJoinClusterRejected(e);
            break;
        case QQEvent.QQ_OPERATION_TIMEOUT:
            switch (e.operation) {
            case QQ.QQ_CMD_LOGIN:
            case QQ.QQ_CMD_REQUEST_LOGIN_TOKEN:
                processLoginTimeout();
                break;
            }
            break;
        case QQEvent.QQ_CONNECTION_LOST:
            processLoginTimeout();
            break;
        case QQEvent.QQ_PROXY_ERROR:
            processProxyError(e);
            break;
        case QQEvent.QQ_NETWORK_ERROR:
            processNetworkError(e);
            break;
        case QQEvent.QQ_RUNTIME_ERROR:
            processRuntimeError(e);
            break;
        case QQEvent.QQ_REQUEST_KEY_SUCCESS:
            processRequestKeySuccess(e);
            break;
        case QQEvent.QQ_REQUEST_KEY_FAIL:
            processRequestKeyFail(e);
            break;
        case QQEvent.QQ_GET_CLUSTER_INFO_SUCCESS:
            processClusterGetInfoSuccess(e);
            break;
        case QQEvent.QQ_GET_TEMP_CLUSTER_INFO_SUCCESS:
            processClusterGetTempClusterInfoSuccess(e);
            break;
        case QQEvent.QQ_GET_CLUSTER_INFO_FAIL:
        case QQEvent.QQ_GET_MEMBER_INFO_FAIL:
        case QQEvent.QQ_GET_ONLINE_MEMBER_FAIL:
        case QQEvent.QQ_GET_TEMP_CLUSTER_INFO_FAIL:
            processClusterCommandFail(e);
            break;
        case QQEvent.QQ_SEND_TEMP_CLUSTER_IM_FAIL:
        case QQEvent.QQ_SEND_CLUSTER_IM_EX_FAIL:
            processSendClusterIMFail(e);
            break;
        case QQEvent.QQ_SEND_IM_SUCCESS:
            processSendIMSucess(e);
            break;
        case QQEvent.QQ_SMS_SENT:
            processSMSSent(e);
            break;
        case QQEvent.QQ_GET_USER_INFO_SUCCESS:
            processGetUserInfoSuccess(e);
            break;
        case QQEvent.QQ_SUB_CLUSTER_OP_SUCCESS:
            processClusterSubClusterOpSuccess(e);
            break;
        case QQEvent.QQ_UPDATE_ORGANIZATION_SUCCESS:
            processClusterUpdateOrganizationSuccess(e);
            break;
        case QQEvent.QQ_GET_CARD_BATCH_SUCCESS:
            processClusterGetCardBatchSuccess(e);
            break;
        case QQEvent.QQ_FRIEND_SIGNATURE_CHANGED:
            processFriendSignatureChanged(e);
            break;
        case QQEvent.QQ_FRIEND_PROPERTY_CHANGED:
            processFriendPropertyChanged(e);
            break;
        case QQEvent.QQ_FRIEND_CUSTOM_HEAD_CHANGED:
            processFriendCustomHeadChanged(e);
            break;
        }
    }

    /**
     * ??
     * 
     * @param e
     */
    private void processRuntimeError(final QQEvent e) {
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.handleRuntimeError(e);
            }
        });
    }

    /**
     * ?
     * 
     * @param e
     */
    private void processReceiveDiskNotification(QQEvent e) {
        ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        final QQLive live = packet.qqlive;
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                DiskNotificationTipWindow win = new DiskNotificationTipWindow(main, live);
                win.open();
            }
        });
    }

    /**
     * ????
     * 
     * @param e
     */
    private void processFriendCustomHeadChanged(QQEvent e) {
        ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        main.getDiskJobQueue().addJob(new DownloadCustomHeadJob(packet.headChanges));
    }

    /**
     * ???
     * 
     * @param e
     */
    private void processFriendPropertyChanged(QQEvent e) {
        ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        if (!packet.propertyChange.hasCustomHead()) {
            final User u = ModelRegistry.getUser(packet.propertyChange.qq);
            if (u == null)
                return;
            u.hasCustomHead = false;
            if (u.qq == main.getMyModel().qq)
                main.getMyModel().hasCustomHead = false;
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.getBlindHelper().refreshGroup(u.group);
                }
            });
        }
    }

    /**
     * ???
     * 
     * @param e
     */
    private void processSMSSent(QQEvent e) {
        // ????
        SendSMSReplyPacket packet = (SendSMSReplyPacket) e.getSource();
        for (SMSReply reply : packet.replies) {
            if (reply.replyCode == QQ.QQ_REPLY_SMS_OK) {
                if (reply.isQQ) {
                    final User u = ModelRegistry.getUser(reply.qq);
                    if (u != null) {
                        main.getDisplay().syncExec(new Runnable() {
                            public void run() {
                                main.getBlindHelper().updateLatest(u);
                            }
                        });
                        return;
                    }
                }
            }
        }
    }

    /**
     * ?????
     * 
     * @param e
     */
    private void processSendIMSucess(QQEvent e) {
        // ??
        SendIMPacket packet = (SendIMPacket) e.getSource();
        final User f = ModelRegistry.getUser(packet.getReceiver());
        if (f == null)
            return;
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getBlindHelper().updateLatest(f);
            }
        });
    }

    /**
     * ???
     * 
     * @param e
     */
    private void processReceiveTempSessionIM(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getMessageHelper().putTempSessionIM(packet);
            }
        });
    }

    /**
     * ?
     * 
     * @param e
     */
    private void processReceiveSMS(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getMessageHelper().putSMS(packet);
            }
        });
    }

    /**
     * ?????
     * 
     * @param e
     */
    private void processFriendSignatureChanged(QQEvent e) {
        ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        final User u = ModelRegistry.getUser(packet.signatureOwner);
        if (u == null)
            return;

        u.signature = packet.signature;
        u.signatureModifiedTime = packet.modifiedTime;
        u.hasSignature = true;
        if (u.qq == main.getMyModel().qq)
            main.getMyModel().signature = u.signature;
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getBlindHelper().refreshGroup(u.group);
            }
        });
    }

    /**
     * ??
     * 
     * @param e
     */
    private void processTransferRoleSuccess(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        final Cluster c = ModelRegistry.getCluster(packet.clusterId);
        if (c == null)
            return;
        c.creator = packet.memberQQ;
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                boolean hasInfo = main.getShellRegistry().hasClusterInfoWindow(c);
                // ??
                if (hasInfo) {
                    ClusterInfoWindow cis = main.getShellRegistry().getClusterInfoWindow(c);
                    cis.setClusterModel(c);
                }
                // ???
                boolean hasIM = !main.getOptionHelper().isUseTabIMWindow()
                        && main.getShellRegistry().hasSendClusterIMWindow(c);
                if (hasIM)
                    main.getShellRegistry().getSendClusterIMWindow(c).refreshClusterInfo();
                // ?
                boolean hasTabIM = main.getOptionHelper().isUseTabIMWindow()
                        && main.getShellRegistry().isSendIMTabWindowOpened();
                if (hasTabIM) {
                    SendIMTabWindow sitw = main.getShellRegistry().getSendIMTabWindow();
                    sitw.refreshTab(c);
                }

                if (hasIM || hasTabIM || hasInfo) {
                    MessageDialog.openInformation(main.getShell(), message_box_common_info_title,
                            message_box_role_transferred);
                }
            }
        });
    }

    /**
     * ?
     * 
     * @param e
     */
    private void processRoleOpFail(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        final Cluster c = ModelRegistry.getCluster(packet.clusterId);
        if (c == null)
            return;
        boolean hasInfo = main.getShellRegistry().hasClusterInfoWindow(c);
        boolean hasIM = !main.getOptionHelper().isUseTabIMWindow()
                && main.getShellRegistry().hasSendClusterIMWindow(c);
        boolean hasTabIM = main.getOptionHelper().isUseTabIMWindow()
                && main.getShellRegistry().isSendIMTabWindowOpened();
        if (hasIM || hasTabIM || hasInfo) {
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    MessageDialog.openError(main.getShell(), message_box_common_fail_title, packet.errorMessage);
                }
            });
        }
    }

    /**
     * ??
     * 
     * @param e
     */
    private void processSetRoleSuccess(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        final Cluster c = ModelRegistry.getCluster(packet.clusterId);
        if ((packet.role & QQ.QQ_ROLE_ADMIN) != 0)
            c.addAdmin(packet.memberQQ);
        else
            c.removeAdmin(packet.memberQQ);

        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                // ???            
                if (refreshClusterRelatedWindow(c)) {
                    if ((packet.role & QQ.QQ_ROLE_ADMIN) != 0)
                        MessageDialog.openInformation(main.getShell(), message_box_common_info_title,
                                message_box_admin_set);
                    else
                        MessageDialog.openInformation(main.getShell(), message_box_common_info_title,
                                message_box_admin_unset);
                }
            }
        });
    }

    /**
     * ?
     * 
     * @param c
     *       Cluster
     * @return
     *       ??true
     */
    protected boolean refreshClusterRelatedWindow(Cluster c) {
        boolean hasInfo = main.getShellRegistry().hasClusterInfoWindow(c);
        // ??
        if (hasInfo) {
            ClusterInfoWindow cis = main.getShellRegistry().getClusterInfoWindow(c);
            cis.setClusterModel(c);
        }
        // ???
        boolean hasIM = !main.getOptionHelper().isUseTabIMWindow()
                && main.getShellRegistry().hasSendClusterIMWindow(c);
        if (hasIM)
            main.getShellRegistry().getSendClusterIMWindow(c).refreshClusterInfo();
        // ?
        boolean hasTabIM = main.getOptionHelper().isUseTabIMWindow()
                && main.getShellRegistry().isSendIMTabWindowOpened();
        if (hasTabIM) {
            SendIMTabWindow sitw = main.getShellRegistry().getSendIMTabWindow();
            sitw.refreshTab(c);
        }

        return hasIM || hasTabIM || hasInfo;
    }

    /**
      * ????? 
      * 
      * @param e
      */
    private void processClusterGetCardBatchSuccess(QQEvent e) {
        ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        final Cluster c = ModelRegistry.getCluster(packet.clusterId);
        if (c == null)
            return;
        if (c.cardUpdated)
            return;

        // ?????
        for (CardStub stub : packet.cardStubs) {
            User m = c.getMember(stub.qq);
            if (m == null)
                continue;
            m.cardName = stub.name;
            if (m.hasCardName())
                m.displayName = m.cardName;
        }

        // ??
        if (packet.nextStart != 0)
            main.getClient().getCardBatch(c.clusterId, packet.nextStart);
        else {
            c.cardUpdated = true;
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.getBlindHelper().refreshGroup(c.group);
                }
            });
        }
    }

    /**
      * ??
      * 
      * @param e
      */
    private void processClusterUpdateOrganizationSuccess(QQEvent e) {
        ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        Cluster c = ModelRegistry.getCluster(packet.clusterId);
        c.removeAllOrganizations();
        for (QQOrganization qqOrg : packet.organizations) {
            Organization org = new Organization();
            org.id = qqOrg.id;
            org.path = qqOrg.path;
            org.name = qqOrg.name;
            c.addOrganization(org);
        }
        main.getClient().getClusterInfo(c.clusterId);
    }

    /**
      * ????
      * 
      * @param e
      */
    private void processClusterSubClusterOpSuccess(QQEvent e) {
        ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        switch (packet.subClusterOpByte) {
        case QQ.QQ_CLUSTER_SUB_CMD_GET_DIALOG_LIST:
            final Cluster dialogContainer = ModelRegistry.getDialogContainer();
            if (dialogContainer != null) {
                dialogContainer.removeAllSubClusters();
                for (SimpleClusterInfo info : packet.subClusters) {
                    Cluster c = new Cluster();
                    c.clusterType = ClusterType.DIALOG;
                    c.clusterId = info.id;
                    c.name = info.name;
                    dialogContainer.addSubCluster(c);
                    ModelRegistry.addCluster(c);
                    main.getClient().getTempClusterInfo(c.clusterType.toQQConstant(), c.clusterId,
                            c.parentClusterId);
                }
                main.getDisplay().syncExec(new Runnable() {
                    public void run() {
                        main.getBlindHelper().refreshGroup(dialogContainer.group);
                    }
                });
            }
            break;
        case QQ.QQ_CLUSTER_SUB_CMD_GET_SUBJECT_LIST:
            final Cluster parent = ModelRegistry.getCluster(packet.clusterId);
            if (parent != null) {
                parent.removeAllSubClusters();
                for (SimpleClusterInfo info : packet.subClusters) {
                    Cluster c = new Cluster();
                    c.clusterType = ClusterType.SUBJECT;
                    c.clusterId = info.id;
                    c.name = info.name;
                    parent.addSubCluster(c);
                    ModelRegistry.addCluster(c);
                    main.getClient().getTempClusterInfo(c.clusterType.toQQConstant(), c.clusterId,
                            c.parentClusterId);
                }
                main.getDisplay().syncExec(new Runnable() {
                    public void run() {
                        main.getBlindHelper().refreshGroup(parent.group);
                    }
                });
            }
            break;
        }
    }

    /**
      * ??
      * 
      * @param e
      */
    private void processClusterCreateTempClusterSuccess(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                Cluster c = main.getBlindHelper().addTempCluster(packet.type, packet.clusterId,
                        packet.parentClusterId);
                if (c != null && main.getUIHelper().hasPromotingDiscuss(packet.getSequence())) {
                    main.getUIHelper().removePromotingDiscuss(packet.getSequence());
                    main.getShellLauncher().openClusterIMWindow(c);
                }
            }
        });
    }

    /**
     * ???0?
     */
    private void processLoginRedirectNull() {
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                // ???
                main.logout();
                main.checkLogin(true, false);
            }
        });
    }

    /**
     * ?
     * 
     * @param e
     */
    private void processNetworkError(final QQEvent e) {
        final ErrorPacket packet = (ErrorPacket) e.getSource();
        if (!packet.connectionId.equals(QQPort.MAIN.name))
            return;

        if (main.getClient().getUser().getStatus() != QQ.QQ_STATUS_OFFLINE) {
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.restartLogin(e);
                }
            });
        }
    }

    /**
    * ?
     * @param e
     */
    private void processRequestKeyFail(QQEvent e) {
        RequestKeyPacket packet = (RequestKeyPacket) e.getSource();
        main.getClient().requestKey(packet.getRequest());
    }

    /**
    * ??
    * 
     * @param e
     *       QQEvent
     */
    private void processRequestKeySuccess(QQEvent e) {
        RequestKeyReplyPacket packet = (RequestKeyReplyPacket) e.getSource();
        QQUser me = main.getClient().getUser();
        switch (packet.subCommand) {
        case QQ.QQ_SUB_CMD_REQUEST_FILE_AGENT_KEY:
            me.setFileAgentKey(packet.key);
            me.setFileAgentToken(packet.token);
            break;
        case QQ.QQ_SUB_CMD_REQUEST_UNKNOWN03_KEY:
            me.setUnknown03Key(packet.key);
            me.setUnknown03Token(packet.token);
            break;
        case QQ.QQ_SUB_CMD_REQUEST_UNKNOWN06_KEY:
            me.setUnknown06Key(packet.key);
            me.setUnknown06Token(packet.token);
            break;
        case QQ.QQ_SUB_CMD_REQUEST_UNKNOWN07_KEY:
            me.setUnknown07Key(packet.key);
            me.setUnknown07Token(packet.token);
            break;
        case QQ.QQ_SUB_CMD_REQUEST_UNKNOWN08_KEY:
            me.setUnknown08Key(packet.key);
            me.setUnknown08Token(packet.token);
            break;
        }
    }

    /**
    * ??
    * 
     * @param e
     *          QQEvent
     */
    private void processProxyError(QQEvent e) {
        final ErrorPacket packet = (ErrorPacket) e.getSource();
        if (!packet.connectionId.equals(QQPort.MAIN.name))
            return;

        if (main.getClient().getUser().getStatus() != QQ.QQ_STATUS_OFFLINE) {
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.stopWaitingPanelAnimation();
                    main.getClient().getUser().setStatus(QQ.QQ_STATUS_OFFLINE);
                    main.logout();
                    MessageDialog.openError(main.getShell(), message_box_proxy_error_title, packet.errorMessage);
                }
            });
        }
    }

    /**
    * ?IM???TCP?TCP???
    * 
     * @param e
     *       QQEvent
     */
    private void processUnknownTypeIM(QQEvent e) {
        ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        if (packet.header.type == QQ.QQ_RECV_IM_FRIEND || packet.header.type == QQ.QQ_RECV_IM_STRANGER) {
            if (packet.normalHeader.type == QQ.QQ_IM_TYPE_TCP_REQUEST)
                main.getClient().rejectSendFile(packet.normalHeader.sender, packet.normalHeader.sequence, false);
        }
    }

    /**
     * ??
     * 
     * @param e
     *       QQEvent
     */
    private void processRequestJoinClusterRejected(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getMessageHelper().putClusterNotification(packet);
            }
        });
    }

    /**
     * ???
     * 
     * @param e
     *          QQEvent
     */
    private void processRequestJoinClusterApproved(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        Cluster c = ModelRegistry.getCluster(packet.header.sender);
        if (c == null) {
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.getBlindHelper().addCluster(packet.header.sender, false);
                    main.getMessageHelper().putClusterNotification(packet);
                }
            });
        }
    }

    /**
     * ?
     * 
     * @param e
     *          QQEvent
     */
    private void processRequestJoinCluster(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        Cluster c = ModelRegistry.getCluster(packet.header.sender);
        if (c != null) {
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.getMessageHelper().putClusterNotification(packet);
                }
            });
        }
    }

    /**
     * ?
     * 
     * @param e
     *       QQEvent
     */
    private void processIAmRemovedFromCluster(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        Cluster c = ModelRegistry.getCluster(packet.header.sender);
        if (c != null) {
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    // senderQQ???
                    // sender
                    if (packet.sender == main.getMyModel().qq)
                        main.getBlindHelper().removeCluster(packet.header.sender);
                    // 
                    main.getMessageHelper().putClusterNotification(packet);
                }
            });
        }
    }

    /**
     * ??
     * 
     * @param e
     */
    private void processAdminEntitled(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        final Cluster c = ModelRegistry.getCluster(packet.header.sender);
        if (c != null) {
            // ?
            c.addAdmin(packet.memberQQ);

            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    // ?
                    if (packet.memberQQ == main.getMyModel().qq)
                        main.getMessageHelper().putClusterNotification(packet);
                    // ?
                    refreshClusterRelatedWindow(c);
                }
            });
        }
    }

    /**
     * ???
     * 
     * @param e
     */
    private void processAdminWithdrawed(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        final Cluster c = ModelRegistry.getCluster(packet.header.sender);
        if (c != null) {
            // ?
            c.removeAdmin(packet.memberQQ);

            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    // ??
                    if (packet.memberQQ == main.getMyModel().qq)
                        main.getMessageHelper().putClusterNotification(packet);
                    // ?
                    refreshClusterRelatedWindow(c);
                }
            });
        }
    }

    /**
     * ??
     * 
     * @param e
     *          QQEvent
     */
    private void processIAmAddedToCluster(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        Cluster c = ModelRegistry.getCluster(packet.header.sender);
        if (c == null) {
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.getBlindHelper().addCluster(packet.header.sender, false);
                    main.getMessageHelper().putClusterNotification(packet);
                }
            });
        }
    }

    /**
     * ???
     * 
     * @param e
     *       QQEvent
     */
    private void processReceiveClusterIM(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getMessageHelper().putClusterIM(packet);
            }
        });
    }

    /**
     * ??
     * 
     * @param e
     *       QQEvent
     */
    private void processClusterExitClusterSuccess(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getBlindHelper().removeCluster(packet.clusterId);
            }
        });
    }

    /**
     * ????
     * 
     * @param e
     *       QQEvent
     */
    private void processClusterGetMemberInfoSuccess(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                boolean showNick = main.getOptionHelper().isShowNick();
                Cluster c = ModelRegistry.getCluster(packet.clusterId);
                if (c != null) {
                    // ???model
                    for (QQFriend friend : packet.memberInfos) {
                        ContactInfo info = ModelUtils.createContact(friend);
                        User f = ModelRegistry.getUser(friend.qqNum);
                        if (f != null) {
                            f.nick = friend.nick;
                            f.headId = friend.head;
                            f.member = friend.isMember();
                            f.userFlag = friend.userFlag;
                            f.female = !friend.isGG();
                            f.info = info;
                            if (!f.hasCardName())
                                f.displayName = showNick ? f.nick
                                        : (f.hasRemarkName() ? f.getRemarkName() : f.nick);
                        }
                        f = c.getMember(friend.qqNum);
                        if (f != null) {
                            f.nick = friend.nick;
                            f.headId = friend.head;
                            f.member = friend.isMember();
                            f.info = info;
                            f.userFlag = friend.userFlag;
                            f.female = !friend.isGG();
                            if (!f.hasCardName())
                                f.displayName = showNick ? f.nick
                                        : (f.hasRemarkName() ? f.getRemarkName() : f.nick);
                        }
                    }
                    // ??
                    if (main.getShellRegistry().hasClusterInfoWindow(c)) {
                        ClusterInfoWindow cis = main.getShellRegistry().getClusterInfoWindow(c);
                        cis.setClusterModel(c);
                    }
                    // ???
                    if (main.getShellRegistry().hasSendClusterIMWindow(c))
                        main.getShellRegistry().getSendClusterIMWindow(c).refreshClusterInfo();
                    // ???????
                    Iterator<Integer> i = main.getShellRegistry().getSendClusterIMWindowModelIterator();
                    while (i.hasNext()) {
                        Cluster model = ModelRegistry.getCluster(i.next());
                        if (model == null)
                            continue;
                        if (model.parentClusterId == c.clusterId)
                            main.getShellRegistry().getSendClusterIMWindow(model).refreshClusterInfo();
                    }
                    // ?
                    main.getClient().getClusterOnlineMember(packet.clusterId);
                    // ?
                    main.getBlindHelper().refreshGroup(c.group);
                }
            }
        });
    }

    /**
     * ?
     */
    private void processKickedOutBySystem() {
        main.getDisplay().asyncExec(new Runnable() {
            public void run() {
                main.getClient().getUser().setStatus(QQ.QQ_STATUS_OFFLINE);
                main.logout();
                MessageDialog.openWarning(main.getShell(), message_box_common_warning_title,
                        message_box_login_twice);
            }
        });
    }

    /**
     * ??
     * 
     * @param e
     *          QQEvent
     */
    private void processClusterCreateSuccess(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getBlindHelper().addCluster(packet.clusterId, true);
            }
        });
    }

    /**
     * ???
     * 
     * @param e
     *       QQEvent
     */
    private void processRequestSendFile(QQEvent e) {
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        if (packet.fileArgs.transferType == QQ.QQ_TRANSFER_FILE) {
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.getMessageHelper().putSendFileRequestIM(packet);
                }
            });
        } else {
            log.debug("???");
        }
    }

    /**
     * ?
     */
    private void processLoginUnknownError() {
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getClient().getUser().setStatus(QQ.QQ_STATUS_OFFLINE);
                main.getUIHelper().stopStatusAnimation();
                main.getUIHelper().setTrayIconByStatus();
                main.logout();
                MessageDialog.openError(main.getShell(), message_box_login_fail_title,
                        message_box_login_unknown_error);
            }
        });
    }

    /**
     * ?
     * 
     * @param e
     *          QQEvent
     */
    private void processLoginTimeout() {
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                // ??
                retryCount++;
                if (retryCount > 6) {
                    main.getClient().getUser().setStatus(QQ.QQ_STATUS_OFFLINE);
                    main.getUIHelper().stopStatusAnimation();
                    main.getUIHelper().setTrayIconByStatus();
                    main.logout();
                    MessageDialog.openError(main.getShell(), message_box_login_fail_title,
                            message_box_login_timeout);
                } else {
                    // ??
                    // ???TCP
                    boolean forceTcp = retryCount % 2 == 0;
                    QQUser me = main.getClient().getUser();
                    byte status = me.getStatus();
                    me.setStatus(QQ.QQ_STATUS_OFFLINE);
                    main.logout();
                    me.setStatus(status);
                    main.checkLogin(true, forceTcp);
                }
            }
        });
    }

    /**
     * ?keep alive????
     * 
     * @param e
     *       QQEvent
     */
    private void processKeepAliveSuccess(QQEvent e) {
        // 
        main.setCurrentOnlineNumber(String.valueOf(((KeepAliveReplyPacket) e.getSource()).onlines));
    }

    /*
     * ?????
    // ??
    private void processDeleteFriendFail(QQEvent e) {
       // QQ?
       DeleteFriendPacket packet = (DeleteFriendPacket)e.getSource();
       final Integer key = new Integer(packet.getTo());
       // ??
       main.removeDeleteToMap(key);
       // ?
       main.getDisplay().syncExec(
     new Runnable() {
        public void run() {
           MessageBox box = new MessageBox(main.getShell(), SWT.ICON_ERROR | SWT.OK);
           box.setText(LumaQQ.getResourceString("message.box.common.fail.title"));
           box.setMessage(LumaQQ.getResourceString("error.delete.friend.fail", new Object[] { key.toString() }));
           box.open();
        }            
     }
       );
    }*/

    /**
     * ???
     * 
     * @param e
     */
    private void processAddFriendSuccess(QQEvent e) {
        final AddFriendExReplyPacket packet = (AddFriendExReplyPacket) e.getSource();
        main.getDisplay().asyncExec(new Runnable() {
            public void run() {
                main.getBlindHelper().addFriend(packet.friendQQ);
            }
        });
    }

    /**
     * ???
     * 
     * @param e
     *       QQEvent
     */
    private void processDeleteFriendSuccess(QQEvent e) {
        // QQ?
        final DeleteFriendPacket packet = (DeleteFriendPacket) e.getSource();

        // ??
        // ??LumaQQ??????
        //main.getClient().removeFriendFromList(packet.getTo());

        // model
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                // ?????????null
                Group g = main.removeDeleteToMap(packet.getTo());
                User f = ModelRegistry.getUser(packet.getTo());
                if (f != null && !f.group.isBlackList())
                    main.getBlindHelper().simpleMove(f, f.group, g);
            }
        });
    }

    /**
     * ??
     * @param e 
     */
    private void processLoginFail(final QQEvent e) {
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.restartLogin(e);
            }
        });
    }

    /**
     * ??
     * 
     * @param e
     *       QQEvent
     */
    private void processReceiveNormalIM(QQEvent e) {
        // ?
        final ReceiveIMPacket packet = (ReceiveIMPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getMessageHelper().putNormalIM(packet);
            }
        });
    }

    /**
     * ?
     * 
     * @param e
     *       QQEvent
     */
    private void processReceiveSystemNotification(QQEvent e) {
        final SystemNotificationPacket packet = (SystemNotificationPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getMessageHelper().putSystemNotificationAndUpdateAnimate(packet);
            }
        });
    }

    /**
     * ????
     * 
     * @param e   
     *          QQEvent
     */
    private void processFriendChangeStatus(QQEvent e) {
        final FriendChangeStatusPacket packet = (FriendChangeStatusPacket) e.getSource();
        final User f = ModelRegistry.getUser(packet.friendQQ);
        if (f != null) {
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    // ?????
                    if (packet.userFlag != 0)
                        f.userFlag = packet.userFlag;
                    if (f.status.toQQConstant() != packet.status) {
                        f.status = Status.valueOf(packet.status);
                        main.getBlindHelper().refreshGroup(f.group);

                        // ????
                        main.getBlindHelper().synchronizedLatestStatus(f, true);

                        // ???
                        if (f.isOnline() && main.getOptionHelper().isShowOnlineTip())
                            main.getTipHelper().getOnlineTipShell().addFriendModel(f);
                    }
                }
            });
        }
    }

    /**
     * ???
     */
    private void processChangeStatusFail() {
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                MessageDialog.openWarning(main.getShell(), message_box_common_fail_title, error_change_status_fail);
            }
        });
    }

    /**
     * ????
     */
    private void processChangeStatusSuccess() {
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                main.getUIHelper().stopStatusAnimation();
                main.getUIHelper().setTrayIconByStatus();
            }
        });
    }

    /**
     * ???????view
     * ?
     * 
     * @param e
     *       QQEvent
     */
    private void processGetFriendOnlineSuccess(QQEvent e) {
        // 
        GetOnlineOpReplyPacket packet = (GetOnlineOpReplyPacket) e.getSource();
        // ????
        for (FriendOnlineEntry entry : packet.onlineFriends) {
            // ??model
            final User f = ModelRegistry.getUser(entry.status.qqNum);
            if (f != null) {
                // ??
                tempHash.put(f, f);
                // ??view
                if (f.status.toQQConstant() != entry.status.status) {
                    f.ip = entry.status.ip;
                    f.port = entry.status.port;
                    f.userFlag = entry.userFlag;
                    f.status = Status.valueOf(entry.status.status);
                    main.getBlindHelper().synchronizedLatestStatus(f, false);
                    if (!main.getTipHelper().isFirstTime() && f.isOnline()
                            && main.getOptionHelper().isShowOnlineTip()) {
                        main.getDisplay().syncExec(new Runnable() {
                            public void run() {
                                main.getTipHelper().getOnlineTipShell().addFriendModel(f);
                            }
                        });
                    }
                }
            }
        }
        // ??????
        // ??online?position
        if (packet.finished) {
            for (final User f : main.getCurrentOnlines()) {
                if (!tempHash.containsKey(f)) {
                    f.status = Status.OFFLINE;
                    main.getBlindHelper().synchronizedLatestStatus(f, false);
                }
            }
            main.getCurrentOnlines().clear();
            main.getCurrentOnlines().addAll(tempHash.values());
            tempHash.clear();
            main.getTipHelper().setFirstTime(false);
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.getBlindHelper().refreshAll();
                }
            });

            // ????
            // ??????????
            // ?????
            Iterator<Integer> i = main.getShellRegistry().getSendClusterIMWindowModelIterator();
            while (i.hasNext()) {
                final Cluster model = ModelRegistry.getCluster(i.next());
                if (model == null)
                    continue;
                if (model.clusterType == ClusterType.NORMAL)
                    main.getClient().getClusterMemberInfo(model.clusterId, model.getMemberQQList());
                else if (model.parentClusterId == 0) {
                    main.getDisplay().asyncExec(new Runnable() {
                        public void run() {
                            main.getShellRegistry().getSendClusterIMWindow(model).refreshClusterInfo();
                        }
                    });
                }
            }
        } else
            main.getClient().getFriendOnline(packet.position);
    }

    /**
     * ??
     */
    private void processLoginSuccess() {
        if (main.getClient().getUser().isLoggedIn()) {
            main.getMessageQueue().setPostpone(true);
            retryCount = 0;

            final boolean autoDownloadGroup = main.getOptionHelper().isAutoDownloadGroup();
            final boolean autoDownloadFriendRemark = main.getOptionHelper().isAutoDownloadFriendRemark();
            final boolean userEmpty = ModelRegistry.getUserCount() == 0;
            IExecutor executor = new BackgroundJobExecutor(main);
            if (!autoDownloadGroup) {
                main.getMessageQueue().setPostpone(false);
                main.getMessageHelper().processPostponedIM();
                if (userEmpty) {
                    executor.addJob(new GetFriendListJob());
                    executor.addJob(new DownloadGroupJob());
                }
                executor.addJob(new GetUserPropertyJob());
                executor.addJob(new DownloadSignatureJob());
                executor.addJob(new GetFriendLevelJob());
                IJob job = new GetCustomHeadInfoJob();
                job.setSuccessLink(new DownloadCustomHeadJob());
                executor.addJob(job);
            }
            if (autoDownloadFriendRemark || autoDownloadGroup) {
                // ?
                if (userEmpty)
                    executor.addJob(new GetFriendListJob());
                if (userEmpty || autoDownloadGroup)
                    executor.addJob(new DownloadGroupJob());

                // ???
                executor.addJob(new GetUserPropertyJob());
                executor.addJob(new DownloadSignatureJob());
                executor.addJob(new GetFriendLevelJob());
                if (autoDownloadFriendRemark)
                    executor.addJob(new DownloadFriendRemarkJob());
                IJob job = new GetCustomHeadInfoJob();
                job.setSuccessLink(new DownloadCustomHeadJob());
                executor.addJob(job);

                // ?????
                main.getOptionHelper().setAutoDownloadGroup(false);
                main.getOptionHelper().setAutoDownloadFriendRemark(false);
            }

            // ?
            if (executor.getAllJobCount() > 0)
                executor.execute();

            // ?
            main.getClient().getFriendOnline();

            // ??
            main.getDisplay().syncExec(new Runnable() {
                public void run() {
                    main.getUIHelper().stopStatusAnimation();
                    main.getUIHelper().setTrayIconByStatus();
                    if (!autoDownloadFriendRemark && !autoDownloadGroup && !userEmpty) {
                        main.stopWaitingPanelAnimation();
                        main.switchPanel(MainShell.PANEL_MAIN);
                    }
                    if (main.getOptionHelper().isShowLastLoginTip())
                        main.getShellLauncher().openLastLoginTipWindow(main);
                }
            });

            // 
            if (main.getOptionHelper().isAutoCheckUpdate())
                new CheckUpdateThread(main).start();
        }
    }

    /**
     * @param e
     */
    private void processClusterGetTempClusterInfoSuccess(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                // ?
                Cluster c = ModelRegistry.getCluster(packet.clusterId);
                // ???
                if (c != null) {
                    c.creator = packet.info.creator;
                    c.authType = packet.info.authType;
                    c.category = packet.info.category;
                    c.oldCategory = packet.info.oldCategory;
                    c.description = packet.info.description;
                    c.notice = packet.info.notice;
                    c.versionId = packet.info.versionId;
                    c.externalId = packet.info.externalId;
                    c.clusterType = ClusterType.valueOfTemp(packet.type);
                    c.name = packet.info.name;

                    // ??
                    synchronizeMember(c, packet.members, true, c.parentClusterId);
                    // ??
                    if (main.getShellRegistry().hasClusterInfoWindow(c)) {
                        ClusterInfoWindow cis = main.getShellRegistry().getClusterInfoWindow(c);
                        cis.setClusterModel(c);
                    }
                    // ???
                    if (!main.getOptionHelper().isUseTabIMWindow()
                            && main.getShellRegistry().hasSendClusterIMWindow(c))
                        main.getShellRegistry().getSendClusterIMWindow(c).refreshClusterInfo();
                    // ?
                    if (main.getOptionHelper().isUseTabIMWindow()
                            && main.getShellRegistry().isSendIMTabWindowOpened()) {
                        SendIMTabWindow sitw = main.getShellRegistry().getSendIMTabWindow();
                        sitw.refreshTab(c);
                    }
                    // 
                    main.getBlindHelper().refreshGroup(main.getBlindHelper().getClusterGroup());
                }
            }
        });
    }

    /**
    * ????
    * 
     * @param e
     */
    private void processSendClusterIMFail(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                switch (packet.replyCode) {
                case QQ.QQ_REPLY_TEMP_CLUSTER_REMOVED:
                case QQ.QQ_REPLY_NOT_CLUSTER_MEMBER:
                case QQ.QQ_REPLY_NOT_TEMP_CLUSTER_MEMBER:
                    main.getBlindHelper().removeCluster(packet.clusterId);
                    break;
                }
            }
        });
    }

    /**
     * ?????
     * @param e
     */
    private void processClusterCommandFail(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                switch (packet.replyCode) {
                case QQ.QQ_REPLY_TEMP_CLUSTER_REMOVED:
                case QQ.QQ_REPLY_NOT_CLUSTER_MEMBER:
                case QQ.QQ_REPLY_NOT_TEMP_CLUSTER_MEMBER:
                    main.getBlindHelper().removeCluster(packet.clusterId);
                    break;
                }
            }
        });
    }

    /**
     * ???
     * 
     * @param e
     */
    private void processClusterGetOnlineMemberSuccess(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                Cluster c = ModelRegistry.getCluster(packet.clusterId);
                if (c == null)
                    return;

                // ???
                c.resetMemberStatus();
                for (Integer qq : packet.onlineMembers) {
                    User u = c.getMember(qq);
                    if (u != null)
                        u.status = Status.ONLINE;
                }

                // ???
                if (!main.getOptionHelper().isUseTabIMWindow() && main.getShellRegistry().hasSendClusterIMWindow(c))
                    main.getShellRegistry().getSendClusterIMWindow(c).refreshClusterInfo();
                // ?
                if (main.getOptionHelper().isUseTabIMWindow()
                        && main.getShellRegistry().isSendIMTabWindowOpened()) {
                    SendIMTabWindow sitw = main.getShellRegistry().getSendIMTabWindow();
                    sitw.refreshTab(c);
                }
                // ?
                main.getBlindHelper().refreshGroup(c.group);
            }
        });
    }

    /**
     * <pre>
     * ????????
     * ???20?
     * </pre>
     * 
     * @param e
     *       QQEvent
     */
    private void processClusterGetInfoSuccess(QQEvent e) {
        final ClusterCommandReplyPacket packet = (ClusterCommandReplyPacket) e.getSource();
        main.getDisplay().syncExec(new Runnable() {
            public void run() {
                // ?
                Cluster c = ModelRegistry.getCluster(packet.clusterId);
                // ???
                if (c != null) {
                    if (packet.externalId == 0) {
                        main.getBlindHelper().removeCluster(packet.clusterId);
                        return;
                    }

                    c.creator = packet.info.creator;
                    c.authType = packet.info.authType;
                    c.category = packet.info.category;
                    c.oldCategory = packet.info.oldCategory;
                    c.description = packet.info.description;
                    c.notice = packet.info.notice;
                    c.versionId = packet.info.versionId;
                    c.externalId = packet.externalId;
                    c.clusterType = ClusterType.NORMAL;
                    c.name = packet.info.name;
                    // ??
                    synchronizeMember(c, packet.members, false, 0);
                    // ??
                    if (main.getShellRegistry().hasClusterInfoWindow(c)) {
                        ClusterInfoWindow cis = main.getShellRegistry().getClusterInfoWindow(c);
                        cis.setClusterModel(c);
                    }
                    // ???
                    if (!main.getOptionHelper().isUseTabIMWindow()
                            && main.getShellRegistry().hasSendClusterIMWindow(c))
                        main.getShellRegistry().getSendClusterIMWindow(c).refreshClusterInfo();
                    // ?
                    if (main.getOptionHelper().isUseTabIMWindow()
                            && main.getShellRegistry().isSendIMTabWindowOpened()) {
                        SendIMTabWindow sitw = main.getShellRegistry().getSendIMTabWindow();
                        sitw.refreshTab(c);
                    }
                    // 
                    main.getBlindHelper().refreshGroup(c.group);
                    // ??
                    main.getBlindHelper().synchronizeLatest(c);
                    // ??               
                    main.getClient().getClusterMemberInfo(packet.clusterId, packet.members);
                }
            }
        });
    }

    /**
     * ???
     * 
     * @param e
     *       QQEvent
     */
    private void processGetUserInfoSuccess(QQEvent e) {
        Display display = main.getDisplay();
        User myModel = main.getMyModel();
        ShellRegistry shellRegistry = main.getShellRegistry();

        final ContactInfo info = ((GetUserInfoReplyPacket) e.getSource()).contactInfo;
        int qqNum = info.qq;
        if (qqNum == 0) {
            log.error("??QQ??");
            return;
        }
        // model
        User user = ModelRegistry.getUser(qqNum);
        if (user == null) {
            user = new User();
            user.qq = qqNum;
        }
        user.info = info;
        user.nick = info.nick;
        user.headId = info.head;
        // userFlag?GetUserInfo?16?
        // 16??16???
        // ????
        user.userFlag &= 0xFFFF0000;
        user.userFlag |= (info.userFlag & 0x0000FFFF);
        user.female = info.gender.equals(gender_mm);
        if (main.getOptionHelper().isShowNick())
            user.displayName = user.nick;
        else
            user.displayName = user.hasRemarkName() ? user.getRemarkName() : user.nick;
        // ???
        if (qqNum == myModel.qq) {
            myModel.info = info;
            myModel.headId = info.head;
            myModel.nick = info.nick;
            myModel.displayName = myModel.nick;
            myModel.userFlag = info.userFlag;
            myModel.female = info.gender.equals(gender_mm);
            main.getClient().getUser().setContactInfo(info);
        }

        final User finalUser = user;
        if (shellRegistry.hasUserInfoWindow(user)) {
            // ???????
            display.syncExec(new Runnable() {
                public void run() {
                    UserInfoWindow uis = main.getShellRegistry().getUserInfoWindow(finalUser);
                    if (uis != null)
                        uis.setFriendModel(finalUser);
                    SendIMWindow siw = main.getShellRegistry().getSendIMWindow(finalUser);
                    if (siw != null)
                        siw.refresh(finalUser);
                    if (main.getOptionHelper().isUseTabIMWindow()
                            && main.getShellRegistry().isSendIMTabWindowOpened()) {
                        SendIMTabWindow sitw = main.getShellRegistry().getSendIMTabWindow();
                        sitw.refreshTab(finalUser);
                    }
                }
            });
        }
        if (shellRegistry.hasTempSessionIMWindow(user)) {
            display.syncExec(new Runnable() {
                public void run() {
                    TempSessionIMWindow win = main.getShellRegistry().getTempSessionIMWindow(finalUser);
                    if (win != null)
                        win.refresh(finalUser);
                }
            });
        }

        // 
        if (finalUser.group != null) {
            display.syncExec(new Runnable() {
                public void run() {
                    main.getBlindHelper().refreshGroup(finalUser.group);
                    main.getBlindHelper().synchronizeLatest(finalUser);
                }
            });
        }
    }

    /**
     * ??
     */
    private void synchronizeMember(Cluster c, List<Member> newMembers, boolean tempCluster, int parentClusterId) {
        // ???
        c.clearAdmins();
        c.clearStockholders();
        List<User> existMembers = new ArrayList<User>();
        List<Member> newMembersBak = new ArrayList<Member>(newMembers);
        for (Iterator<Member> i = newMembersBak.iterator(); i.hasNext();) {
            Member member = i.next();
            User u = c.removeMember(member.qq);
            if (u != null) {
                u.organizationId = member.organization;
                existMembers.add(u);
                i.remove();
                if (member.isAdmin())
                    c.addAdmin(member.qq);
                else if (member.isStockholder())
                    c.addStockholder(member.qq);
            }
        }

        // Map???
        c.removeAllMembers();
        // ?????
        for (User member : existMembers)
            c.addMember(member);
        // ?
        Cluster parent = null;
        if (tempCluster && parentClusterId != 0) {
            parent = ModelRegistry.getCluster(parentClusterId);
            if (c.group == null)
                parent.addSubCluster(c);
        }
        for (Member member : newMembersBak) {
            // ?model??
            // ????
            int qq = member.qq;
            User f = null;
            if (qq == main.getMyModel().qq)
                f = main.getMyModel();
            else if (tempCluster) {
                if (parentClusterId == 0)
                    f = ModelRegistry.getUser(qq);
                else if (parent != null)
                    f = parent.getMember(qq);
            } else
                f = ModelRegistry.getUser(qq);

            // 
            if (f == null) {
                f = new User();
                f.qq = qq;
                f.nick = String.valueOf(qq);
                f.remark = main.getConfigHelper().getRemark(f.qq);
                f.displayName = main.getOptionHelper().isShowNick() ? f.nick
                        : ((f.remark == null) ? f.nick : f.remark.getName());
                f.organizationId = member.organization;
            } else {
                try {
                    f = (User) f.clone();
                    f.organizationId = member.organization;
                } catch (CloneNotSupportedException e) {
                    continue;
                }
            }
            c.addMember(f);
            if (member.isAdmin())
                c.addAdmin(member.qq);
            else if (member.isStockholder())
                c.addStockholder(member.qq);
        }
    }
}