⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 downloadgroupjob.java

📁 java写的qq代码实现qq的部分功能
💻 JAVA
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.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.jobs;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;

import edu.tsinghua.lumaqq.IconHolder;
import edu.tsinghua.lumaqq.LumaQQ;
import edu.tsinghua.lumaqq.models.ClusterModel;
import edu.tsinghua.lumaqq.models.FriendModel;
import edu.tsinghua.lumaqq.models.GroupModel;
import edu.tsinghua.lumaqq.models.IQQNode;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.beans.ClusterInfo;
import edu.tsinghua.lumaqq.qq.beans.DownloadFriendEntry;
import edu.tsinghua.lumaqq.qq.events.IQQListener;
import edu.tsinghua.lumaqq.qq.events.QQEvent;
import edu.tsinghua.lumaqq.qq.packets.in.DownloadGroupFriendReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GroupDataOpReplyPacket;
import edu.tsinghua.lumaqq.ui.MainShell;
import edu.tsinghua.lumaqq.utils.OptionUtil;
import edu.tsinghua.swt.models.DefaultShutterModel;
import edu.tsinghua.swt.models.INode;

/**
 * 下载好友分组的任务
 * 
 * @author luma
 */
public class DownloadGroupJob extends AbstractJob implements IQQListener {
    private IconHolder icons;
    private IProgressMonitor monitor;
    
	// 组名list和组内好友的hash,用在下载分组信息的时候,因为下载分组信息是
	// 分两部分进行的,一部分得到组名称一部分得到组的好友,光完成一部分还不
	// 行,所以需要暂时保存一下结果
	private List groupNames;
	private List friends;
	
	// 分组好友是否已经下载完毕
	private boolean downloadGroupFriendFinished;
	
	private boolean finished;

    /* (non-Javadoc)
     * @see edu.tsinghua.lumaqq.ui.jobs.IJob#prepare(edu.tsinghua.lumaqq.ui.MainShell)
     */
    public void prepare(MainShell main) {
        super.prepare(main);
        icons = IconHolder.getInstance();
		downloadGroupFriendFinished = false;
		finished = false;
        main.getClient().addQQListener(this);
    }

    /* (non-Javadoc)
     * @see edu.tsinghua.lumaqq.ui.jobs.IJob#clear()
     */
    public void clear() {
        main.getClient().removeQQListener(this);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
     */
    public void run(IProgressMonitor monitor) throws InvocationTargetException,
            InterruptedException {
        this.monitor = monitor;   
        monitor.beginTask("", 100);        
		monitor.subTask(LumaQQ.getString("job.download.group.1"));
		
		main.getClient().downloadGroup();
		main.getClient().downloadFriend(0);
		
		monitor.worked(10);
		
		synchronized(this) {
		    while(!finished) {
                try {
                    this.wait(2000);
                } catch (InterruptedException e) {                    
                }	        
		    }
		}
    }

    /* (non-Javadoc)
     * @see edu.tsinghua.lumaqq.qq.events.IQQListener#qqEvent(edu.tsinghua.lumaqq.qq.events.QQEvent)
     */
    public void qqEvent(QQEvent e) {
        switch(e.type) {
			case QQEvent.QQ_DOWNLOAD_GROUP_NAME_SUCCESS:
				processDownloadGroupNameSuccess(e);
				break;
			case QQEvent.QQ_DOWNLOAD_GROUP_FRIEND_SUCCESS:
				processDownloadGroupFriendSuccess(e);
				break;
			case QQEvent.QQ_DOWNLOAD_GROUP_FRIEND_FAIL:
				processDownloadGroupFriendFail(e);
				break;
			case QQEvent.QQ_OPERATION_TIMEOUT:
			    switch(e.operation) {
			        case QQ.QQ_CMD_DOWNLOAD_GROUP_FRIEND:        
			        case QQ.QQ_CMD_GROUP_DATA_OP:
			            processDownloadGroupFriendFail(e);
			        	break;
			    }
				break;
        }
    }

	/**
	 * 处理下载分组好友列表失败事件
	 * 
	 * @param e
	 * 		QQEvent
	 */
	private void processDownloadGroupFriendFail(QQEvent e) {
		groupNames = null;
		friends = null;
		errorMessage = LumaQQ.getString("job.download.group.error");
		wake();
	}

	/**
	 * 处理下载分组好友列表成功事件
	 * 
	 * @param e
	 * 			QQEvent
	 */
	private void processDownloadGroupFriendSuccess(QQEvent e) {		
	    if(friends == null)
		    friends = new ArrayList();
	        
		DownloadGroupFriendReplyPacket packet = (DownloadGroupFriendReplyPacket)e.getSource();		
	    friends.addAll(packet.friends);
		if(packet.beginFrom == 0) {
			downloadGroupFriendFinished = true;
			if(groupNames != null)
				resetModel();
		} else {
			downloadGroupFriendFinished = false;
			main.getClient().downloadFriend(packet.beginFrom);
			monitor.worked(10);
		}
	}

	/**
	 * 处理下载分组名称成功事件
	 * 
	 * @param e
	 * 		QQEvent
	 */
	private void processDownloadGroupNameSuccess(QQEvent e) {
		GroupDataOpReplyPacket packet = (GroupDataOpReplyPacket)e.getSource();
		groupNames = packet.groupNames;
		if(downloadGroupFriendFinished && friends != null)
			resetModel();
	}
	
	/**
	 * 重新设置shutter的model
	 */
	private void resetModel() {		
	    monitor.subTask(LumaQQ.getString("job.download.group.2"));
	    
		downloadGroupFriendFinished = false;
		main.setFriendListFinished(false);
		
		final DefaultShutterModel model = new DefaultShutterModel();
		// 用来保存需要得到信息的好友或者群
		List needInfos = new ArrayList();
		// 加入我的好友组model
		GroupModel gModel = new GroupModel(LumaQQ.getString("group.default.friend"));
		model.addTab(gModel);
		// 加入下载到的组
		Iterator iter = groupNames.iterator();
		while(iter.hasNext()) {
			gModel = new GroupModel((String)iter.next());
			model.addTab(gModel);
		}
		// 添加群组
		gModel = new GroupModel(LumaQQ.getString("group.default.cluster"));
		gModel.addProperty(IQQNode.CLUSTER, "true");
		gModel.addProperty(IQQNode.UPLOAD, "false");
		model.addTab(gModel);
		int clusterIndex = 0;
		int[] cluster = main.getMVCHelper().listClusterGroup();
		if(cluster != null && cluster.length > 0) {
			// 得到群的索引,当前显然是最后一个tab
			clusterIndex = model.getTabCount() - 1;
			// 得到旧model中的群个数
			int size = main.getModel().getItemCount(cluster[0]);
			// 逐个添加这些ClusterModel
			for(int i = 0; i < size; i++) {
				ClusterModel c = (ClusterModel)main.getModel().getItem(cluster[0], i);
				model.addItem(clusterIndex, c);
			}
		}
		// 添加陌生人组
		gModel = new GroupModel(LumaQQ.getString("group.default.stranger"));
		gModel.addProperty(IQQNode.FRIENDLY, "false");
		gModel.addProperty(IQQNode.UPLOAD, "false");
		model.addTab(gModel);
		// 添加陌生人组中的人
		int[] stranger = main.getMVCHelper().listStrangerGroup();
		if(stranger != null && stranger.length > 0) {
			int sIndex = model.getTabCount() - 1;
			int size = main.getModel().getItemCount(stranger[0]);
			for(int i = 0; i < size; i++)
				model.addItem(sIndex, main.getModel().getItem(stranger[0], i));			
		}
		// 添加黑名单组
		gModel = new GroupModel(LumaQQ.getString("group.default.blacklist"));
		gModel.addProperty(IQQNode.FRIENDLY, "false");
		gModel.addProperty(IQQNode.BLACKLIST, "true");
		gModel.addProperty(IQQNode.UPLOAD, "false");
		model.addTab(gModel);
		// 设置黑名单的可见状态
		GroupModel bModel = null;
		final int[] blacklist = main.getMVCHelper().listBlacklistGroup();
		if(blacklist != null && blacklist.length > 0) {
			bModel = (GroupModel)main.getModel().getTab(blacklist[0]);
			gModel.addProperty(IQQNode.VISIBLE, bModel.getProperty(IQQNode.VISIBLE));
			// 添加黑名单中的人
			int bIndex = model.getTabCount() - 1;
			int size = main.getModel().getItemCount(blacklist[0]);
			for(int i = 0; i < size; i++)
				model.addItem(bIndex, main.getModel().getItem(blacklist[0], i));
		}
		final boolean blacklistVisible = (bModel != null && "false".equals(bModel.getProperty(IQQNode.VISIBLE))) ? false : true;
		// 添加最近联系人组
		if(OptionUtil.getInstance().isEnableLatest()) {
			gModel = new GroupModel(LumaQQ.getString("group.default.latest"));
			gModel.addProperty(IQQNode.FRIENDLY, "false");
			gModel.addProperty(IQQNode.UPLOAD, "false");
			model.addTab(gModel);
			
			final int[] latest = main.getMVCHelper().listLatestGroup();
			int lIndex = model.getTabCount() - 1;
			if(latest != null && latest.length > 0) {
				GroupModel oldGroup = (GroupModel)main.getModel().getTab(latest[0]);
				int size = main.getModel().getItemCount(latest[0]);
				for(int i = 0; i < size; i++)
					model.addItem(lIndex, main.getModel().getItem(latest[0], i));
			}
		}
		
		monitor.worked(20);
		
		// 得到组总数
		int tabCount = groupNames.size() + 1;
		// 添加分组中的好友
		int size = friends.size();
		for(int i = 0; i < size; i++) {
			// 得到下载项
			DownloadFriendEntry dfe = (DownloadFriendEntry)friends.get(i);
			if(dfe.isCluster()) {			    
				ClusterModel c = main.getMVCHelper().getClusterModel(dfe.qqNum);
				// 如果等于null,则添加。不等于null不做什么,因为前面已经添加过了
				if(c == null) {
					needInfos.add(dfe);
					c = new ClusterModel(dfe.qqNum);
					ClusterInfo info = new ClusterInfo();
					info.clusterId = dfe.qqNum;
					c.addProperty(IQQNode.INFO, info);
					c.addProperty(INode.IMAGE, icons.getClusterHead(1));
					c.addProperty(IQQNode.HEAD, new Integer(1));
					model.addItem(clusterIndex, c);
				}					
			} else {
			    // 如果group不正确,置0
			    if(dfe.group >= tabCount)
			        dfe.group = 0;
				// 搜索目前的model,得到这个好友的model,如果没有找到这个好友,创建一个新model
				//     并把这个model保存到一个list中,因为需要得到这些好友的info。另外,还要
				//     把有消息的好友保存起来,因为在设置新model完成后,要恢复图标的跳动和闪烁
				FriendModel old = main.getMVCHelper().getFriendModel(dfe.qqNum);
				if(old != null) {
					FriendModel f = old.cloneProperties();
					f.addProperty(IQQNode.STATUS, IQQNode.VALUE_OFFLINE);
					model.addItem(dfe.group, f);
				} else {
					needInfos.add(dfe);
					FriendModel f = new FriendModel(String.valueOf(dfe.qqNum), icons.getHead(0));
					f.addProperty(IQQNode.QQ_NUMBER, new Integer(dfe.qqNum));
					f.addProperty(IQQNode.STATUS, IQQNode.VALUE_OFFLINE);
					f.addProperty(IQQNode.HEAD, new Integer(0));
					f.addProperty(IQQNode.MEMBER, "false");
					model.addItem(dfe.group, f);
				}				
			}
		}
		// 新model已经完全构造好了,现在把旧model替换成新model
		main.getDisplay().syncExec(new Runnable() {
			public void run() {
				main.setModel(model);		
				main.getMVCHelper().setModel(model);
				// 判断黑名单当前是否是隐藏的,如果是,隐藏黑名单
				if(!blacklistVisible) {
					main.getShutter().hideTab(blacklist[0], true);
				}
			}				
		});
		
		monitor.worked(20);
		
		// 对于那些没有在旧model中出现的好友或者群,请求得到他们的info
		iter = needInfos.iterator();
		while(iter.hasNext()) {
			DownloadFriendEntry dfe = (DownloadFriendEntry)iter.next();
			if(dfe.isCluster() && dfe.qqNum != 0)
				main.getClient().getClusterInfo(dfe.qqNum);
			else
				main.getClient().getUserInfo(dfe.qqNum);
		}

		// 恢复图标的跳动和闪烁,然后关闭提示框
		main.getDisplay().syncExec(new Runnable() {
			public void run() {
			    main.getUIHelper().resetAllImageEffect();
			}				
		});
		
		main.setFriendListFinished(true);
		friends = null;
		groupNames = null;
		main.getDisplay().syncExec(new Runnable() {
			public void run() {
				// 得到在线好友, 设置firstTime为true是为了防止不必要的上线提示
				main.getTipHelper().setFirstTime(true);
				main.getClient().getFriendOnline();		
				// 处理延迟消息
			    main.getMessageHelper().processPostponedIM();
			}						
		});
		
		monitor.done();
		wake();
	}
	
	/**
	 * 唤醒任务线程,使其返回
	 */
	private void wake() {
		synchronized(this) {
		    finished = true;
		    this.notify();
		}
	}

    /* (non-Javadoc)
     * @see edu.tsinghua.lumaqq.ui.jobs.IJob#isSuccess()
     */
    public boolean isSuccess() {
        return errorMessage != null;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -