📄 mainshell.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;
import static edu.tsinghua.lumaqq.resource.Messages.*;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;
import org.eclipse.swt.widgets.TreeItem;
import edu.tsinghua.lumaqq.IPSeeker;
import edu.tsinghua.lumaqq.LumaQQ;
import edu.tsinghua.lumaqq.MessageQueue;
import edu.tsinghua.lumaqq.QQShowManager;
import edu.tsinghua.lumaqq.Sounder;
import edu.tsinghua.lumaqq.disk.DiskContentProvider;
import edu.tsinghua.lumaqq.disk.DiskLabelProvider;
import edu.tsinghua.lumaqq.disk.DiskManager;
import edu.tsinghua.lumaqq.disk.DiskViewerSorter;
import edu.tsinghua.lumaqq.ecore.option.OpType;
import edu.tsinghua.lumaqq.events.IQQShowListener;
import edu.tsinghua.lumaqq.hotkey.IHotkeyListener;
import edu.tsinghua.lumaqq.models.Group;
import edu.tsinghua.lumaqq.models.ModelRegistry;
import edu.tsinghua.lumaqq.models.User;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.QQClient;
import edu.tsinghua.lumaqq.qq.Util;
import edu.tsinghua.lumaqq.qq.beans.Directory;
import edu.tsinghua.lumaqq.qq.beans.File;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.events.QQEvent;
import edu.tsinghua.lumaqq.qq.packets.ErrorPacket;
import edu.tsinghua.lumaqq.qq.packets.InPacket;
import edu.tsinghua.lumaqq.qq.packets.in.LoginReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;
import edu.tsinghua.lumaqq.qq.packets.in.SystemNotificationPacket;
import edu.tsinghua.lumaqq.record.RecordManager;
import edu.tsinghua.lumaqq.resource.Colors;
import edu.tsinghua.lumaqq.resource.Resources;
import edu.tsinghua.lumaqq.ui.config.user.UserInfoWindow;
import edu.tsinghua.lumaqq.ui.dialogs.CrashDialog;
import edu.tsinghua.lumaqq.ui.dialogs.DiskPasswordDialog;
import edu.tsinghua.lumaqq.ui.dialogs.LoginDialog;
import edu.tsinghua.lumaqq.ui.helper.BlindHelper;
import edu.tsinghua.lumaqq.ui.helper.ClusterCategoryTool;
import edu.tsinghua.lumaqq.ui.helper.ConfigHelper;
import edu.tsinghua.lumaqq.ui.helper.DateTool;
import edu.tsinghua.lumaqq.ui.helper.DragHelper;
import edu.tsinghua.lumaqq.ui.helper.ExportHelper;
import edu.tsinghua.lumaqq.ui.helper.FaceRegistry;
import edu.tsinghua.lumaqq.ui.helper.FileTool;
import edu.tsinghua.lumaqq.ui.helper.MenuHelper;
import edu.tsinghua.lumaqq.ui.helper.MessageHelper;
import edu.tsinghua.lumaqq.ui.helper.OptionHelper;
import edu.tsinghua.lumaqq.ui.helper.ShellLauncher;
import edu.tsinghua.lumaqq.ui.helper.ShellRegistry;
import edu.tsinghua.lumaqq.ui.helper.TimerHelper;
import edu.tsinghua.lumaqq.ui.helper.TipHelper;
import edu.tsinghua.lumaqq.ui.helper.UIHelper;
import edu.tsinghua.lumaqq.ui.helper.UITool;
import edu.tsinghua.lumaqq.ui.jobs.BackgroundJobExecutor;
import edu.tsinghua.lumaqq.ui.jobs.CancelDiskPasswordJob;
import edu.tsinghua.lumaqq.ui.jobs.CreateFileJob;
import edu.tsinghua.lumaqq.ui.jobs.DialogJobExecutor;
import edu.tsinghua.lumaqq.ui.jobs.DownloadFileJob;
import edu.tsinghua.lumaqq.ui.jobs.ICancelableJob;
import edu.tsinghua.lumaqq.ui.jobs.IExecutor;
import edu.tsinghua.lumaqq.ui.jobs.MoveJob;
import edu.tsinghua.lumaqq.ui.jobs.SetDiskPasswordJob;
import edu.tsinghua.lumaqq.ui.jobs.UploadGroupJob;
import edu.tsinghua.lumaqq.ui.listener.CenterBorderPaintListener;
import edu.tsinghua.lumaqq.widgets.mac.Ring;
import edu.tsinghua.lumaqq.widgets.qstyle.Blind;
import edu.tsinghua.lumaqq.widgets.qstyle.Slat;
import edu.tsinghua.lumaqq.widgets.rich.LineStyle;
import edu.tsinghua.lumaqq.widgets.rich2.Animator;
/**
* @author luma
*/
public class MainShell implements IQQShowListener {
private Shell shell;
private Display display;
private TrayItem item;
private Blind blind;
private Label btnSysMsg;
private Label btnSysMenu;
private Ring statusRing;
private QQClient client;
private Resources res;
// 群贴图接收器
private ClusterCustomFaceReceiver faceReceiver;
// QQ事件处理器
private QQEventProcessor processor;
// 声音播放精灵线程
private Sounder sounder;
// 网络硬盘任务线程
private IExecutor diskJobQueue;
// 发送消息的任务线程
private IExecutor imJobQueue;
// 用户自己的model
private User myModel;
// 当前在线人数的字符串表示
private String currentOnlineNumber;
// 当前消息字体和颜色,null为缺省
private Font font;
private LineStyle defaultStyle;
// 组背景颜色,如果为null,为缺省颜色
private Color groupColor;
// ip查找类引用
private IPSeeker seeker;
// 当前在线好友
private List<User> currentOnlines;
// 聊天记录管理器
private RecordManager rm;
// QQ秀管理器
private QQShowManager sm;
// 参数工具类实例
private OptionHelper optionHelper;
// 消息队列
private MessageQueue mq;
// 窗口位置备份
private Point shellLocation;
// 分组信息是否已经被修改
private boolean groupDirty;
// 删除请求哈希表,这个哈希表说明了如果某个用户删除成功就要把这个用户弄到哪个组去
private Map<Integer, Group> deleteToMap;
// 窗口注册表
private ShellRegistry shellRegistry;
// 窗口发射器
private ShellLauncher shellLauncher;
// 配置文件帮助类
private ConfigHelper configHelper;
// blind帮助类
private BlindHelper blindHelper;
// UI帮助类
private UIHelper uiHelper;
// 导出帮助类
private ExportHelper exportHelper;
// 消息处理帮助类
private MessageHelper messageHelper;
// 菜单帮助类
private MenuHelper menuHelper;
// 提示窗口帮助类
private TipHelper tipHelper;
// 定时器帮助类
private TimerHelper timerHelper;
private ClusterCategoryTool ccu;
private IHotkeyListener messageKeyListener;
private Listener falseMessageKeyListener;
private Label btnSMS;
// 面板数组
private Composite[] panels;
public static final int PANEL_MAIN = 0;
public static final int PANEL_WAITING = 1;
private Label waitingPanelHint;
private Animator waitingPanelAnimator;
private int currentPanel;
// true表示鼠标位于主面板bar之上
private boolean mouseOnBar;
// view
private Control[] views;
public static final int VIEW_FRIEND = 0;
public static final int VIEW_DISK = 1;
private Composite viewContainer;
// 网络硬盘相关
private DiskManager diskManager;
private TreeViewer diskViewer;
private CLabel lblDiskHint;
private Composite passwordPanel;
private Composite diskCenter;
private ToolItem tiUpload;
private ToolItem tiDownload;
private ToolItem tiRefresh;
private Composite diskTreePanel;
private ToolItem tiAbort;
private ToolItem tiAbortAll;
/**
* 初始化所有
*/
private void initialize() {
this.display = Display.getCurrent();
res = Resources.getInstance();
// 初始化组件
initLayout();
initVariables();
// 初始化菜单
menuHelper = new MenuHelper(this);
menuHelper.initMenu();
}
/**
* 初始化变量
*/
private void initVariables() {
mq = new MessageQueue();
seeker = IPSeeker.getInstance();
processor = new QQEventProcessor(this);
faceReceiver = new ClusterCustomFaceReceiver(this);
deleteToMap = new Hashtable<Integer, Group>();
shellRegistry = new ShellRegistry();
shellLauncher = new ShellLauncher(this);
uiHelper = new UIHelper(this);
exportHelper = new ExportHelper(this);
messageHelper = new MessageHelper(this);
blindHelper = new BlindHelper(this);
tipHelper = new TipHelper(this);
timerHelper = new TimerHelper();
currentOnlineNumber = search_current_online_unknown;
sounder = new Sounder();
diskJobQueue = new BackgroundJobExecutor(this);
diskJobQueue.setExitOnEmpty(false);
imJobQueue = new BackgroundJobExecutor(this);
imJobQueue.setExitOnEmpty(false);
currentOnlines = new ArrayList<User>();
mouseOnBar = false;
ccu = new ClusterCategoryTool();
ccu.init();
messageKeyListener = new IHotkeyListener() {
public void keyPressed() {
onMessageKey();
}
};
falseMessageKeyListener = new Listener() {
public void handleEvent(Event e) {
if(e.keyCode == 'z' && (e.stateMask & SWT.CTRL) != 0 && (e.stateMask & SWT.ALT) != 0) {
onMessageKey();
}
}
};
}
/**
* 切换面板
*
* @param panelId
*/
public void switchPanel(int panelId) {
BorderStyler styler = (BorderStyler)shell.getData(BorderStyler.STYLER);
StackLayout layout = (StackLayout)styler.getCenter().getLayout();
layout.topControl = panels[panelId];
currentPanel = panelId;
styler.getCenter().layout();
}
/**
* 切换视图
*
* @param viewId
*/
public void switchView(int viewId) {
StackLayout layout = (StackLayout)viewContainer.getLayout();
layout.topControl = views[viewId];
viewContainer.layout();
}
/**
* 检查分组是否修改过,根据系统设置判断是否上传
*/
public void checkGroupDirty() {
// 如果分组被修改了,检查系统设置
if(isGroupDirty() && client.getUser().isLoggedIn()) {
if(optionHelper.getAutoUploadGroup() == OpType.PROMPT_LITERAL) {
if(MessageDialog.openQuestion(shell,
message_box_common_question_title,
message_box_upload_group)) {
uploadGroup();
}
} else if(optionHelper.getAutoUploadGroup() == OpType.ALWAYS_LITERAL)
uploadGroup();
}
}
/**
* 上传分组
*/
private void uploadGroup() {
IExecutor executor = new DialogJobExecutor(this);
executor.addJob(new UploadGroupJob());
executor.execute();
}
public boolean isGroupDirty() {
return groupDirty;
}
/**
* @return
* 主Shell对象
*/
public Shell getShell() {
return shell;
}
/**
* @return
* 好友列表控件
*/
public Blind getBlind() {
return blind;
}
/**
* 关闭主shell
*/
public void close() {
if(shell != null && !shell.isDisposed())
shell.close();
}
public void setClient(QQClient client) {
this.client = client;
// 初始化系统设置
if(configHelper == null)
configHelper = new ConfigHelper(this);
if(optionHelper == null)
optionHelper = new OptionHelper();
configHelper.initSystemOptions();
// 初始化自己的model
configHelper.saveSelf();
configHelper.initSelf();
myModel = configHelper.getMyself();
// 初始化窗口,只初始化一次
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -