├── .gitignore ├── README.md ├── cn.ieclipse.smartqq.feature ├── .project ├── build.properties ├── epl-v10.html ├── feature.properties ├── feature.xml └── license.html ├── cn.ieclipse.smartqq ├── .classpath ├── .project ├── META-INF │ └── MANIFEST.MF ├── build.properties ├── icons │ ├── QQ.png │ ├── broadcast.png │ ├── clear_co.png │ ├── editor_area.png │ ├── eye-slash.png │ ├── face.png │ ├── image.png │ ├── lock_co.png │ ├── project.png │ ├── qrcode.png │ ├── review.png │ ├── type.png │ └── wechat.png ├── libs │ ├── core-0.0.1.jar │ ├── dom4j-1.6.1.jar │ ├── gson-2.8.0.jar │ ├── happy-dns-java-0.1.4.jar │ ├── okhttp-3.8.1.jar │ ├── okio-1.13.0.jar │ ├── qiniu-java-sdk-7.2.7.jar │ ├── smartqq-0.0.1.jar │ └── wechat-0.0.1.jar ├── plugin.xml ├── src │ ├── cn │ │ └── ieclipse │ │ │ ├── smartim │ │ │ ├── IMClientFactory.java │ │ │ ├── IMHistoryManager.java │ │ │ ├── IMPlugin.java │ │ │ ├── IMReceiveCallback.java │ │ │ ├── IMRobotCallback.java │ │ │ ├── IMSendCallback.java │ │ │ ├── actions │ │ │ │ ├── BroadcastAction.java │ │ │ │ ├── ClearHistoryAction.java │ │ │ │ ├── DisconnectAction.java │ │ │ │ ├── IMChatAction.java │ │ │ │ ├── IMPanelAction.java │ │ │ │ ├── LoginAction.java │ │ │ │ ├── MockConsoleAction.java │ │ │ │ ├── ScrollLockAction.java │ │ │ │ ├── SendFileAction.java │ │ │ │ ├── SendImageAction.java │ │ │ │ ├── SendProjectFileAction.java │ │ │ │ ├── SettingsAction.java │ │ │ │ └── ToggleContactsAction.java │ │ │ ├── common │ │ │ │ ├── IDEUtils.java │ │ │ │ ├── IMUtils.java │ │ │ │ ├── LetterImageFactory.java │ │ │ │ ├── Notifications.java │ │ │ │ ├── PreventESCTraverseListener.java │ │ │ │ ├── RestUtils.java │ │ │ │ └── TranslateAnimation.java │ │ │ ├── console │ │ │ │ ├── ClosableTabHost.java │ │ │ │ ├── HistoryOperation.java │ │ │ │ ├── IMChatConsole.java │ │ │ │ ├── JSBridge.java │ │ │ │ ├── MockChatConsole.java │ │ │ │ ├── Splitter.java │ │ │ │ ├── TabComposite.java │ │ │ │ └── history.html │ │ │ ├── decorators │ │ │ │ ├── IMChatDecoration.java │ │ │ │ ├── IMChatDecorator.java │ │ │ │ └── IMCompositeImageDescriptor.java │ │ │ ├── dialogs │ │ │ │ ├── HotKeyInputDialog.java │ │ │ │ ├── LoginDialog.java │ │ │ │ ├── OpenFileDialog.java │ │ │ │ ├── PasteFileDialog.java │ │ │ │ └── ReviewDialog.java │ │ │ ├── handlers │ │ │ │ └── ReviewHandler.java │ │ │ ├── preferences │ │ │ │ ├── CompositeFieldEditor.java │ │ │ │ ├── HotKeyFieldEditor.java │ │ │ │ ├── HotKeyPreferencePage.java │ │ │ │ ├── Messages.java │ │ │ │ ├── PreferenceInitializer.java │ │ │ │ ├── QiniuPerferencePage.java │ │ │ │ ├── RobotPreferencePage.java │ │ │ │ ├── SettingsPerferencePage.java │ │ │ │ ├── SmartQQPreferencePage.java │ │ │ │ ├── messages.properties │ │ │ │ └── messages_zh.properties │ │ │ └── views │ │ │ │ ├── IMContactContentProvider.java │ │ │ │ ├── IMContactDoubleClicker.java │ │ │ │ ├── IMContactLabelProvider.java │ │ │ │ └── IMContactView.java │ │ │ ├── smartqq │ │ │ ├── QQBroadcastAction.java │ │ │ ├── QQBroadcastDialog.java │ │ │ ├── QQChatConsole.java │ │ │ ├── QQContactView.java │ │ │ ├── QQContentProvider.java │ │ │ ├── QQLabelProvider.java │ │ │ ├── QQMidificationCallback.java │ │ │ ├── QQReceiveCallback.java │ │ │ ├── QQRobotCallback.java │ │ │ ├── QQUtils.java │ │ │ └── test │ │ │ │ ├── HotKeyTest.java │ │ │ │ ├── LetterImageTest.java │ │ │ │ └── Login.java │ │ │ └── wechat │ │ │ ├── WXBroadcastAction.java │ │ │ ├── WXBroadcastDialog.java │ │ │ ├── WXChatConsole.java │ │ │ ├── WXChatConsoleMock.java │ │ │ ├── WXContactContentProvider.java │ │ │ ├── WXContactLabelProvider.java │ │ │ ├── WXContactView.java │ │ │ ├── WXMessageInterceptor.java │ │ │ ├── WXModificationCallback.java │ │ │ ├── WXReceiveCallback.java │ │ │ ├── WXRobotCallback.java │ │ │ └── WXUtils.java │ ├── icons │ │ └── SmartIcons.java │ └── org │ │ └── eclipse │ │ └── wb │ │ └── swt │ │ ├── FieldLayoutPreferencePage.java │ │ ├── ResourceManager.java │ │ └── SWTResourceManager.java └── test │ └── cn │ └── ieclipse │ └── smartim │ └── console │ ├── ReviewLinkTest.java │ └── SenderLinkTest.java ├── main.png └── screenshot.gif /.gitignore: -------------------------------------------------------------------------------- 1 | .settings 2 | bin/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![GitHub release](https://img.shields.io/github/release/jamling/SmartQQ4Eclipse.svg?maxAge=3600)](https://github.com/Jamling/SmartQQ4Eclipse) 2 | [![Eclipse Marketplace](https://img.shields.io/eclipse-marketplace/v/SmartQQ.svg)](https://marketplace.eclipse.org/content/smartqq) 3 | [![Eclipse Marketplace](https://img.shields.io/eclipse-marketplace/dt/SmartQQ.svg)](https://marketplace.eclipse.org/content/smartqq) 4 | 5 | ## SmartIM4Eclipse (原SmartQQ4Eclipse) 6 | 7 | ![screenshot](https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/master/screenshot.gif) 8 | 9 | Eclipse上的SmartIM插件,防Boss利器,让你可以在eclipse中使用QQ/微信进行聊天 10 | 11 | Intellij IDEA上的插件请移步这里: https://github.com/Jamling/SmartIM4IntelliJ, 支持所有的Intellij IDE哦,包含Android Studio, WebStrom等 12 | 13 | ## 功能 14 | 15 | - [x] 收发文本消息 16 | - [x] 收发图片 17 | - [x] 收发文件 18 | - [x] 发送工程中的文件 19 | - [x] Code Review 发送代码位置及评语 20 | - [x] 超链接点击 21 | - [x] 热键设定 22 | - [x] 一键关闭 23 | - [x] 支持图灵机器人接入 24 | 25 | **SmartQQ官方协议不支持收发图片和文件,扩展的文件收发由[第三方实现](http://api.ieclipse.cn/smartqq)** 26 | 27 | |Feature |Swing | Eclipse | IntelliJ | 28 | | ---------------- |:---------:|:----------:|:-----------:| 29 | | 文本消息 | Y | Y | Y | 30 | | 聊天记录 | Y | Y | Y | 31 | | 消息提醒 | O | Y | O | 32 | | 接收表情 | O | Y | X | 33 | | 图灵机器人       | Y       |         Y | Y | 34 | | 发送文件       | Y       |         Y | Y | 35 | | 消息群发       | Y       |         Y | Y | 36 | | 代码评审       | X       |         Y | Y | 37 | 38 | ## 安装 39 | 40 | 从3.0开始,本插件依赖于[Eclipse Explorer]插件,如果安装时提示缺失[Eclipse Explorer]插件,如下示例错误 41 | ``` 42 | Cannot complete the install because one or more required items could not be found. 43 | Software being installed: SmartQQ Feature 3.1.0.201803020925 (cn.ieclipse.smartqq.feature.feature.group 3.1.0.201803020925) 44 | Missing requirement: SmartQQ Feature 3.1.0.201803020925 (cn.ieclipse.smartqq.feature.feature.group 3.1.0.201803020925) 45 | requires 'cn.ieclipse.pde.explorer 4.1.0' but it could not be found 46 | ``` 47 | 请先安装[Eclipse Explorer]插件或手动添加http://dl.ieclipse.cn/updates 更新站点后再安装SmartQQ 48 | 49 | ### Eclipse Marketplace 50 | 51 | 1. 点击Eclipse->Help->Eclipse Marketplace...打开eclipse插件市场 52 | 2. 输入SmartIM搜索 53 | 3. 点击Install安装 54 | 55 | **推荐使用Eclipse Martplace安装** 56 | 57 | ### Install New Software 58 | 59 | 1. 点击Eclipse->Help->Install New Software...搜索插件 60 | 2. 在Work with后面的输入框中输入http://dl.ieclipse.cn/updates/ 并回车 61 | 3. 选中SmartIM,并取消勾选"Contact all update site during install to find required software" 62 | 4. 点击底部Next按钮继续安装 63 | 64 | ## 使用 65 | 66 | 1. 点击Windows->Show view->Others,找到SmartIM下的SmartQQ或Wechat双击打开SmartQQ或Wechat视图 67 | 2. 点击视图工具栏或菜单栏中的同步图标进行登录 68 | 3. 使用手机QQ/手机微信扫描二维码(SmartQQ视图使用手机QQ,Wechat视图使用手机微信扫一扫) 69 | 4. 验证成功后,等待拉取最近消息,好友及群组列表 70 | 5. 双击SmartIM视图中的好友或群,打开聊天窗口 71 | 6. 输入聊天内容,并按快捷键(默认为Enter)发送聊天信息 72 | 73 | ### 微信 74 | 1. 如果微信无法生成二维码图片,提示javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name,请给eclipse加上`-Djsse.enableSNIExtension=false`参数,可以在eclipse.ini中加,也可以在eclipse快捷方式目标位置中添加 75 | 76 | ## 进阶使用 77 | 1. 文件发送 78 | - 点击聊天Console菜单(就是那个倒三角)选择 Send File 或 Send Project File 选择文件后发送 79 | - 对要发送的文件复制,然后粘贴到聊天窗口,再点击发送超链接,确认发送文件 80 | 2. 消息群发 81 | - 在SmartIM视图中,点击Broadcast工具图标(就是那个发射塔的图标),输入内容并选择要发送的好友,群及讨论群,再点击确定 82 | 3. 代码评审(未来接入Gerrit) 83 | - 在编辑器中右键菜单中点击`Code Review`,输入对代码的评审注释,选择发送的对象,点击确定发送 84 | - 对方接收到代码评审消息,点击代码位置,直接跳转到本地相同的代码位置,然后修改吧。 85 | 86 | ## 快捷键 87 | 88 | 注:在eclipse中,CR表示Enter键 89 | 90 | - 发送,默认CR (Enter键),发送消息 91 | - 隐藏聊天,默认Alt + M,隐藏Contact视图 92 | - 关闭聊天,默认Alt + C,关闭当前聊天窗口 93 | 94 | 注:快捷键有可能与eclipse中的热键冲突,请点击?打开首选项重新设置 95 | 96 | ## 感谢 97 | 98 | - SmartQQ Java API: https://github.com/ScienJus/smartqq 99 | - Wechat Java API: https://github.com/biezhi/wechat-bot-api 100 | - SmartIM library: https://github.com/Jamling/SmartIM 101 | 102 | ## 问题提交 103 | 104 | 提交问题前,请参考[常见问题](https://github.com/Jamling/SmartIM/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) 105 | 106 | 任何问题包括建议均可以在[Issue](https://github.com/Jamling/SmartIM4Eclipse/issues)中提交 107 | 108 | 如果为Issue,建议带上eclipse版本及本插件版本信息(可以在Preference->SmartIM中查看并复制版本信息) 109 | 110 | ## 开发 111 | 112 | 如果您对本项目感兴趣,请fork本项目,源代码下载完成之后,会有编译错误,需要将依赖的smartim-core等三个工程从build path中移除,并将libs下的core-x.x.x.jar, smartqq-x.x.x.jar, wechat.x.x.x.jar添加到build path. 113 | 114 | [Eclipse Explorer]: https://github.com/Jamling/eclipse-explorer 115 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq.feature/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | cn.ieclipse.smartqq.feature 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.pde.FeatureBuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.pde.FeatureNature 16 | 17 | 18 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq.feature/build.properties: -------------------------------------------------------------------------------- 1 | bin.includes = feature.xml,\ 2 | license.html,\ 3 | feature.properties,\ 4 | epl-v10.html,\ 5 | build.properties 6 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq.feature/feature.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | %description 11 | 12 | 13 | 14 | %copyright 15 | 16 | 17 | 18 | %license 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq.feature/license.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq.feature/license.html -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | cn.ieclipse.smartqq 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.pde.ManifestBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.pde.SchemaBuilder 20 | 21 | 22 | 23 | 24 | 25 | org.eclipse.pde.PluginNature 26 | org.eclipse.jdt.core.javanature 27 | 28 | 29 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: SmartIM 4 | Bundle-SymbolicName: cn.ieclipse.smartqq;singleton:=true 5 | Bundle-Version: 3.4.0.qualifier 6 | Bundle-Activator: cn.ieclipse.smartim.IMPlugin 7 | Bundle-Vendor: ieclipse.cn 8 | Require-Bundle: org.eclipse.ui, 9 | org.eclipse.core.runtime, 10 | org.eclipse.ui.console, 11 | org.eclipse.jface.text, 12 | org.eclipse.core.resources, 13 | org.eclipse.ui.ide, 14 | org.eclipse.ui.workbench.texteditor, 15 | org.eclipse.core.net, 16 | org.slf4j.api, 17 | ch.qos.logback.classic, 18 | ch.qos.logback.core, 19 | org.eclipse.ui.browser, 20 | cn.ieclipse.pde.explorer;bundle-version="4.1.0", 21 | org.eclipse.ui.workbench, 22 | org.junit;resolution:=optional 23 | Bundle-RequiredExecutionEnvironment: JavaSE-1.7 24 | Bundle-ActivationPolicy: lazy 25 | Bundle-ClassPath: ., 26 | libs/gson-2.8.0.jar, 27 | libs/okhttp-3.8.1.jar, 28 | libs/okio-1.13.0.jar, 29 | libs/happy-dns-java-0.1.4.jar, 30 | libs/qiniu-java-sdk-7.2.7.jar, 31 | libs/core-0.0.1.jar, 32 | libs/smartqq-0.0.1.jar, 33 | libs/wechat-0.0.1.jar, 34 | libs/dom4j-1.6.1.jar 35 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/,\ 2 | test/ 3 | output.. = bin/ 4 | bin.includes = plugin.xml,\ 5 | META-INF/,\ 6 | .,\ 7 | icons/,\ 8 | libs/ 9 | jars.compile.order = .,\ 10 | libs/ 11 | javacDefaultEncoding.. = UTF-8 12 | additional.bundles = org.junit 13 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/QQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/QQ.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/broadcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/broadcast.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/clear_co.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/clear_co.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/editor_area.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/editor_area.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/eye-slash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/eye-slash.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/face.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/image.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/lock_co.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/lock_co.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/project.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/qrcode.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/review.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/type.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/icons/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/icons/wechat.png -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/libs/core-0.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/libs/core-0.0.1.jar -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/libs/dom4j-1.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/libs/dom4j-1.6.1.jar -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/libs/gson-2.8.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/libs/gson-2.8.0.jar -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/libs/happy-dns-java-0.1.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/libs/happy-dns-java-0.1.4.jar -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/libs/okhttp-3.8.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/libs/okhttp-3.8.1.jar -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/libs/okio-1.13.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/libs/okio-1.13.0.jar -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/libs/qiniu-java-sdk-7.2.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/libs/qiniu-java-sdk-7.2.7.jar -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/libs/smartqq-0.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/libs/smartqq-0.0.1.jar -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/libs/wechat-0.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/cn.ieclipse.smartqq/libs/wechat-0.0.1.jar -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 10 | 11 | 18 | 19 | 26 | 27 | 28 | 30 | 32 | 33 | 34 | 36 | 40 | 41 | 46 | 47 | 52 | 53 | 58 | 59 | 64 | 65 | 66 | 68 | 71 | 76 | 77 | 78 | 79 | 81 | 84 | 85 | 86 | 88 | 91 | 92 | 93 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/IMClientFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim; 17 | 18 | import java.io.File; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import com.scienjus.smartqq.client.SmartQQClient; 23 | 24 | import io.github.biezhi.wechat.api.WechatClient; 25 | 26 | /** 27 | * 类/接口描述 28 | * 29 | * @author Jamling 30 | * @date 2017年10月14日 31 | * 32 | */ 33 | public class IMClientFactory { 34 | public static final String TYPE_QQ = "QQ"; 35 | public static final String TYPE_WECHAT = "Wechat"; 36 | private Map clients = null; 37 | 38 | private static IMClientFactory instance = new IMClientFactory(); 39 | 40 | private void checkClients() { 41 | if (clients == null) { 42 | clients = new HashMap<>(); 43 | } 44 | } 45 | 46 | private SmartClient create(String type) { 47 | if (TYPE_QQ.equalsIgnoreCase(type)) { 48 | return new SmartQQClient(); 49 | } 50 | else if (TYPE_WECHAT.equalsIgnoreCase(type)) { 51 | return new WechatClient(); 52 | } 53 | throw new UnsupportedOperationException("No client type " + type); 54 | } 55 | 56 | public SmartClient getClient(String type) { 57 | checkClients(); 58 | SmartClient client = clients.get(type); 59 | if (client == null || client.isClose()) { 60 | client = create(type); 61 | File dir = IMPlugin.getDefault().getStateDir().getAbsoluteFile(); 62 | client.setWorkDir(new File(dir, type)); 63 | clients.put(type, client); 64 | } 65 | return client; 66 | } 67 | 68 | public SmartQQClient getQQClient() { 69 | return (SmartQQClient) getClient(TYPE_QQ); 70 | } 71 | 72 | public WechatClient getWechatClient() { 73 | return (WechatClient) getClient(TYPE_WECHAT); 74 | } 75 | 76 | public static IMClientFactory getInstance() { 77 | return instance; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/IMHistoryManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim; 17 | 18 | import java.io.File; 19 | import java.util.HashMap; 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | import cn.ieclipse.util.FileStorage; 24 | import cn.ieclipse.smartim.preferences.SettingsPerferencePage; 25 | 26 | /** 27 | * 类/接口描述 28 | * 29 | * @author Jamling 30 | * @date 2017年10月23日 31 | * 32 | */ 33 | public class IMHistoryManager { 34 | private Map stores = new HashMap<>(); 35 | private static final int max = 30; 36 | private static final int size = 500; 37 | private long ts = System.currentTimeMillis(); 38 | 39 | private static IMHistoryManager instance = new IMHistoryManager(); 40 | public static final String HISTORY_NAME = "history"; 41 | 42 | public static IMHistoryManager getInstance() { 43 | return instance; 44 | } 45 | 46 | private FileStorage get(File dir, String uin) { 47 | FileStorage fs = stores.get(uin); 48 | if (fs == null) { 49 | File f = new File(dir, uin); 50 | fs = new FileStorage(size, f.getAbsolutePath()); 51 | boolean persistent = IMPlugin.getDefault().getPreferenceStore() 52 | .getBoolean(SettingsPerferencePage.LOG_HISTORY); 53 | fs.setPersistent(persistent); 54 | stores.put(uin, fs); 55 | } 56 | return fs; 57 | } 58 | 59 | public List load(File dir, String uin) { 60 | FileStorage fs = get(dir, uin); 61 | return fs.getLast(max); 62 | } 63 | 64 | public boolean save(File dir, String uin, String rawMsg) { 65 | FileStorage fs = get(dir, uin); 66 | boolean ret = fs.append(rawMsg); 67 | ret = ret && fs.isPersistent(); 68 | if (System.currentTimeMillis() - ts > 1000 * 120) { 69 | flush(); 70 | ts = System.currentTimeMillis(); 71 | } 72 | return ret; 73 | } 74 | 75 | public boolean clear(File dir, String uin) { 76 | FileStorage fs = get(dir, uin); 77 | fs.release(); 78 | return true; 79 | } 80 | 81 | public void flush() { 82 | if (!stores.isEmpty()) { 83 | for (FileStorage fs : stores.values()) { 84 | if (fs.isPersistent()) { 85 | fs.flush(); 86 | } 87 | } 88 | stores.clear(); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/IMPlugin.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim; 2 | 3 | import java.io.File; 4 | 5 | import org.eclipse.core.net.proxy.IProxyService; 6 | import org.eclipse.core.runtime.IStatus; 7 | import org.eclipse.core.runtime.Status; 8 | import org.eclipse.jface.resource.ImageDescriptor; 9 | import org.eclipse.swt.graphics.Color; 10 | import org.eclipse.swt.widgets.Display; 11 | import org.eclipse.ui.PlatformUI; 12 | import org.eclipse.ui.plugin.AbstractUIPlugin; 13 | import org.eclipse.wb.swt.SWTResourceManager; 14 | import org.osgi.framework.BundleContext; 15 | import org.osgi.framework.ServiceReference; 16 | 17 | import com.scienjus.smartqq.QNUploader; 18 | 19 | import cn.ieclipse.smartim.preferences.SettingsPerferencePage; 20 | 21 | /** 22 | * The activator class controls the plug-in life cycle 23 | */ 24 | public class IMPlugin extends AbstractUIPlugin { 25 | 26 | // The plug-in ID 27 | public static final String PLUGIN_ID = "cn.ieclipse.smartqq"; //$NON-NLS-1$ 28 | 29 | // The shared instance 30 | private static IMPlugin plugin; 31 | 32 | /** 33 | * The constructor 34 | */ 35 | public IMPlugin() { 36 | } 37 | 38 | public void start(BundleContext context) throws Exception { 39 | super.start(context); 40 | plugin = this; 41 | } 42 | 43 | public void stop(BundleContext context) throws Exception { 44 | plugin = null; 45 | super.stop(context); 46 | } 47 | 48 | /** 49 | * Returns the shared instance 50 | * 51 | * @return the shared instance 52 | */ 53 | public static IMPlugin getDefault() { 54 | if (plugin == null) { 55 | plugin = new IMPlugin(); 56 | } 57 | return plugin; 58 | } 59 | 60 | /** 61 | * Returns an image descriptor for the image file at the given plug-in 62 | * relative path 63 | * 64 | * @param path 65 | * the path 66 | * @return the image descriptor 67 | */ 68 | public static ImageDescriptor getImageDescriptor(String path) { 69 | return imageDescriptorFromPlugin(PLUGIN_ID, path); 70 | } 71 | 72 | public static ImageDescriptor getSharedImage(String name) { 73 | return PlatformUI.getWorkbench().getSharedImages() 74 | .getImageDescriptor(name); 75 | } 76 | 77 | public static Color getSystemColor(int colorId) { 78 | return SWTResourceManager.getColor(colorId); 79 | } 80 | 81 | // --------> 82 | private QNUploader uploader; 83 | 84 | public IProxyService proxyService; 85 | 86 | public IProxyService getProxyService() { 87 | if (proxyService == null) { 88 | ServiceReference ref = getBundle().getBundleContext() 89 | .getServiceReference(IProxyService.class); 90 | proxyService = getBundle().getBundleContext().getService(ref); 91 | } 92 | 93 | return proxyService; 94 | } 95 | 96 | public QNUploader getUploader() { 97 | if (uploader == null) { 98 | uploader = new QNUploader(); 99 | } 100 | return uploader; 101 | } 102 | 103 | public File getStateDir() { 104 | return getStateLocation().makeAbsolute().toFile(); 105 | } 106 | 107 | public void log(String msg, Throwable e) { 108 | if (e == null) { 109 | IStatus info = new Status(IStatus.INFO, IMPlugin.PLUGIN_ID, msg); 110 | getLog().log(info); 111 | } 112 | else { 113 | IStatus info = new Status(IStatus.ERROR, IMPlugin.PLUGIN_ID, msg, 114 | e); 115 | getLog().log(info); 116 | } 117 | } 118 | 119 | public void log(String msg) { 120 | log(msg, null); 121 | } 122 | 123 | public void warn(String msg) { 124 | IStatus info = new Status(IStatus.WARNING, IMPlugin.PLUGIN_ID, msg); 125 | getLog().log(info); 126 | } 127 | 128 | public static void runOnUI(Runnable runnable) { 129 | Display display = Display.getDefault(); 130 | if (display != null) { 131 | display.asyncExec(runnable); 132 | } 133 | } 134 | 135 | public boolean enable = true; 136 | 137 | public static void setEnable(boolean enable) { 138 | getDefault().enable = enable; 139 | } 140 | 141 | public static void setNotify(boolean enable) { 142 | getDefault().getPreferenceStore() 143 | .setValue(SettingsPerferencePage.NOTIFY_ENABLE, enable); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/IMReceiveCallback.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim; 2 | 3 | import cn.ieclipse.smartim.callback.ReceiveCallback; 4 | import cn.ieclipse.smartim.common.Notifications; 5 | import cn.ieclipse.smartim.console.IMChatConsole; 6 | import cn.ieclipse.smartim.model.impl.AbstractContact; 7 | import cn.ieclipse.smartim.model.impl.AbstractFrom; 8 | import cn.ieclipse.smartim.model.impl.AbstractMessage; 9 | import cn.ieclipse.smartim.preferences.SettingsPerferencePage; 10 | import cn.ieclipse.smartim.views.IMContactView; 11 | import cn.ieclipse.util.EncodeUtils; 12 | 13 | public abstract class IMReceiveCallback implements ReceiveCallback { 14 | protected IMChatConsole lastConsole; 15 | protected IMContactView fContactView; 16 | 17 | public IMReceiveCallback(IMContactView fContactView) { 18 | this.fContactView = fContactView; 19 | } 20 | 21 | protected abstract String getNotifyContent(AbstractMessage message, 22 | AbstractFrom from); 23 | 24 | protected abstract String getMsgContent(AbstractMessage message, 25 | AbstractFrom from); 26 | 27 | protected void handle(boolean unknown, boolean notify, 28 | AbstractMessage message, AbstractFrom from, 29 | AbstractContact contact) { 30 | SmartClient client = fContactView.getClient(); 31 | String msg = getMsgContent(message, from); 32 | if (!unknown) { 33 | String hf = EncodeUtils.getMd5(from.getContact().getName()); 34 | IMHistoryManager.getInstance().save(client.getWorkDir(IMHistoryManager.HISTORY_NAME), hf, msg); 35 | } 36 | 37 | if (notify) { 38 | boolean hide = unknown 39 | && !IMPlugin.getDefault().getPreferenceStore() 40 | .getBoolean(SettingsPerferencePage.NOTIFY_UNKNOWN); 41 | try { 42 | hide = hide || from.getMember().getUin() 43 | .equals(fContactView.getClient().getAccount().getUin()); 44 | } catch (Exception e) { 45 | IMPlugin.getDefault().log("", e); 46 | } 47 | if (hide || fContactView.isCurrent(contact)) { 48 | // don't notify 49 | } 50 | else { 51 | CharSequence content = getNotifyContent(message, from); 52 | Notifications.notify(fContactView, contact, 53 | contact.getName(), content); 54 | } 55 | } 56 | 57 | IMChatConsole console = fContactView 58 | .findConsoleById(contact.getUin(), false); 59 | if (console != null) { 60 | lastConsole = console; 61 | console.write(msg); 62 | fContactView.highlight(console); 63 | } 64 | if (!fContactView.isCurrent(console)) { 65 | if (contact != null) { 66 | contact.increaceUnRead(); 67 | } 68 | } 69 | 70 | if (contact != null) { 71 | contact.setLastMessage(message); 72 | } 73 | 74 | fContactView.notifyUpdateContacts(0, false); 75 | } 76 | 77 | @Override 78 | public void onReceiveError(Throwable e) { 79 | if (e == null) { 80 | return; 81 | } 82 | if (lastConsole != null) { 83 | lastConsole.error(e); 84 | } 85 | else { 86 | IMPlugin.getDefault().log(fContactView.getTitle() + "接收异常", e); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/IMSendCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim; 17 | 18 | import cn.ieclipse.smartim.callback.SendCallback; 19 | import cn.ieclipse.smartim.common.IMUtils; 20 | import cn.ieclipse.smartim.common.Notifications; 21 | import cn.ieclipse.smartim.console.IMChatConsole; 22 | import cn.ieclipse.smartim.exception.HttpException; 23 | import cn.ieclipse.smartim.exception.LogicException; 24 | import cn.ieclipse.smartim.views.IMContactView; 25 | 26 | /** 27 | * 类/接口描述 28 | * 29 | * @author Jamling 30 | * @date 2017年10月16日 31 | * 32 | */ 33 | public class IMSendCallback implements SendCallback { 34 | protected IMContactView fContactView; 35 | 36 | public IMSendCallback(IMContactView contactView) { 37 | this.fContactView = contactView; 38 | } 39 | 40 | @Override 41 | public void onSendResult(int type, String targetId, CharSequence msg, 42 | boolean success, Throwable t) { 43 | if (success) { 44 | onSuccess(type, targetId, msg); 45 | } 46 | else { 47 | onFailure(type, targetId, msg, t); 48 | } 49 | } 50 | 51 | protected void onSuccess(int type, String targetId, CharSequence msg) { 52 | fContactView.notifyUpdateContacts(0, true); 53 | } 54 | 55 | protected void onFailure(int type, String targetId, CharSequence msg, 56 | Throwable t) { 57 | String s = IMUtils.isEmpty(msg) ? "" 58 | : (msg.length() > 20 ? msg.toString().substring(0, 20) + "..." 59 | : msg.toString()); 60 | String code = ""; 61 | if (t != null) { 62 | if (t instanceof LogicException) { 63 | code = String.format("api code=%d", 64 | ((LogicException) t).getCode()); 65 | } 66 | else if (t instanceof HttpException) { 67 | code = String.format("http code=%d", 68 | ((HttpException) t).getCode()); 69 | } 70 | } 71 | IMChatConsole console = fContactView.findConsoleById(targetId, 72 | true); 73 | if (console != null) { 74 | console.error(String.format("%s 发送失败!%s", msg, code)); 75 | } 76 | else { 77 | IMPlugin.getDefault() 78 | .log(String.format("发送到%s的信息(%s)", targetId, msg), t); 79 | Notifications.notify("发送失败", String.format("%s 发送失败!%s", s, code)); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/BroadcastAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import org.eclipse.jface.dialogs.MessageDialog; 19 | import org.eclipse.swt.widgets.Shell; 20 | 21 | import cn.ieclipse.smartim.views.IMContactView; 22 | import icons.SmartIcons; 23 | 24 | /** 25 | * 类/接口描述 26 | * 27 | * @author Jamling 28 | * @date 2017年8月22日 29 | * 30 | */ 31 | public class BroadcastAction extends IMPanelAction { 32 | public BroadcastAction(IMContactView contactView) { 33 | super(contactView); 34 | setText("&BroadCast"); 35 | setToolTipText("Broadcast message to SmartQQ group/discuss/friends"); 36 | setImageDescriptor(SmartIcons.broadcast); 37 | } 38 | 39 | @Override 40 | public void run() { 41 | if (fContactView != null) { 42 | Shell shell = fContactView.getSite().getShell(); 43 | if (fContactView.getClient().isLogin()) { 44 | openDialog(shell); 45 | } 46 | else { 47 | MessageDialog.openError(shell, null, "已断开连接,请重新登录成功后再试"); 48 | } 49 | } 50 | } 51 | 52 | protected void openDialog(Shell shell) { 53 | 54 | } 55 | 56 | public static String groupMacro = "{group}"; 57 | public static String memberMacro = "{member}"; 58 | } 59 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/ClearHistoryAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import cn.ieclipse.smartim.console.IMChatConsole; 19 | import icons.SmartIcons; 20 | 21 | /** 22 | * 清除聊天记录 23 | * 24 | * @author Jamling 25 | * @date 2018年2月8日 26 | * 27 | */ 28 | public class ClearHistoryAction extends IMChatAction { 29 | 30 | public ClearHistoryAction(IMChatConsole console) { 31 | super(console); 32 | setText("Clear"); 33 | setToolTipText("Clear history"); 34 | setImageDescriptor(SmartIcons.clear); 35 | } 36 | 37 | @Override 38 | public void run() { 39 | if (fConsole != null) { 40 | fConsole.clearHistories(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/DisconnectAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2015 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import cn.ieclipse.smartim.views.IMContactView; 19 | import icons.SmartIcons; 20 | 21 | /** 22 | * 类/接口描述 23 | * 24 | * @author Jamling 25 | * @date 2017年6月20日 26 | * 27 | */ 28 | public class DisconnectAction extends IMPanelAction { 29 | 30 | public DisconnectAction(IMContactView contactView) { 31 | super(contactView); 32 | setText("Close"); 33 | setToolTipText("Disconnect from server"); 34 | setImageDescriptor(SmartIcons.signout); 35 | } 36 | 37 | @Override 38 | public void run() { 39 | if (fContactView != null) { 40 | fContactView.close(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/IMChatAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import org.eclipse.jface.action.Action; 19 | 20 | import cn.ieclipse.smartim.console.IMChatConsole; 21 | 22 | /** 23 | * 类/接口描述 24 | * 25 | * @author Jamling 26 | * @date 2018年2月24日 27 | * 28 | */ 29 | public class IMChatAction extends Action { 30 | protected IMChatConsole fConsole; 31 | 32 | public IMChatAction(IMChatConsole console) { 33 | this.fConsole = console; 34 | } 35 | 36 | public IMChatAction(IMChatConsole console, String name, int style) { 37 | super(name, style); 38 | this.fConsole = console; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/IMPanelAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import org.eclipse.jface.action.Action; 19 | 20 | import cn.ieclipse.smartim.views.IMContactView; 21 | 22 | /** 23 | * 类/接口描述 24 | * 25 | * @author Jamling 26 | * @date 2018年2月24日 27 | * 28 | */ 29 | public class IMPanelAction extends Action { 30 | protected IMContactView fContactView; 31 | 32 | public IMPanelAction(IMContactView contactView) { 33 | this.fContactView = contactView; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/LoginAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2015 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import org.eclipse.jface.dialogs.MessageDialog; 19 | import org.eclipse.swt.widgets.Shell; 20 | 21 | import cn.ieclipse.smartim.dialogs.LoginDialog; 22 | import cn.ieclipse.smartim.views.IMContactView; 23 | import icons.SmartIcons; 24 | 25 | /** 26 | * 类/接口描述 27 | * 28 | * @author Jamling 29 | * @date 2017年6月20日 30 | * 31 | */ 32 | public class LoginAction extends IMPanelAction { 33 | 34 | public LoginAction(IMContactView view) { 35 | super(view); 36 | setText("Login"); 37 | setToolTipText("Click to show qrcode"); 38 | setImageDescriptor(SmartIcons.signin); 39 | } 40 | 41 | @Override 42 | public void run() { 43 | if (fContactView != null) { 44 | Shell shell = fContactView.getSite().getShell(); 45 | boolean ok = true; 46 | if (fContactView.getClient().isLogin()) { 47 | ok = MessageDialog.openConfirm(shell, null, 48 | "您已处于登录状态,确定要重新登录吗?"); 49 | } 50 | if (ok) { 51 | // fContactView.close(); 52 | LoginDialog dialog = new LoginDialog(shell); 53 | dialog.setClient(fContactView.getClient()); 54 | dialog.open(); 55 | } 56 | fContactView.initContacts(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/MockConsoleAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2015 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import com.scienjus.smartqq.model.Friend; 19 | 20 | import cn.ieclipse.smartim.common.IMUtils; 21 | import cn.ieclipse.smartim.console.MockChatConsole; 22 | import cn.ieclipse.smartim.views.IMContactView; 23 | import cn.ieclipse.wechat.WXChatConsole; 24 | import cn.ieclipse.wechat.WXChatConsoleMock; 25 | import cn.ieclipse.wechat.WXContactView; 26 | import icons.SmartIcons; 27 | 28 | /** 29 | * 类/接口描述 30 | * 31 | * @author Jamling 32 | * @date 2017年6月20日 33 | * 34 | */ 35 | public class MockConsoleAction extends IMPanelAction { 36 | 37 | public MockConsoleAction(IMContactView contactView) { 38 | super(contactView); 39 | setText("Mock"); 40 | setToolTipText("Mock chat"); 41 | setImageDescriptor(SmartIcons.test); 42 | } 43 | 44 | @Override 45 | public void run() { 46 | Friend f = new Friend(); 47 | f.setUserId(System.currentTimeMillis()); 48 | f.setMarkname("Test" + System.currentTimeMillis()); 49 | MockChatConsole console = null; 50 | if (fContactView instanceof WXContactView) { 51 | console = new WXChatConsoleMock(f, fContactView); 52 | } else { 53 | console =new MockChatConsole(f, fContactView); 54 | } 55 | console.initMockMsg(); 56 | fContactView.getTabbedChat().setSelection(console); 57 | fContactView.randBling(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/ScrollLockAction.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.actions; 2 | 3 | import org.eclipse.jface.action.Action; 4 | 5 | import cn.ieclipse.smartim.console.IMChatConsole; 6 | import icons.SmartIcons; 7 | 8 | public class ScrollLockAction extends IMChatAction { 9 | 10 | public ScrollLockAction(IMChatConsole console) { 11 | super(console, "Scroll Lock", Action.AS_CHECK_BOX); 12 | this.setToolTipText("Scroll Lock"); 13 | setImageDescriptor(SmartIcons.lock); 14 | } 15 | 16 | @Override 17 | public void run() { 18 | fConsole.setScrollLock(isChecked()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/SendFileAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import org.eclipse.swt.SWT; 19 | import org.eclipse.swt.widgets.FileDialog; 20 | 21 | import cn.ieclipse.smartim.console.IMChatConsole; 22 | import icons.SmartIcons; 23 | 24 | /** 25 | * 类/接口描述 26 | * 27 | * @author Jamling 28 | * @date 2017年8月14日 29 | * 30 | */ 31 | public class SendFileAction extends IMChatAction { 32 | protected String[] filterNames; 33 | protected String[] filterExtensions; 34 | protected String dialogTitle; 35 | 36 | public SendFileAction(IMChatConsole console) { 37 | super(console); 38 | setText("Send File"); 39 | setToolTipText("Send file or paste file to chat console"); 40 | setImageDescriptor(SmartIcons.file); 41 | } 42 | 43 | @Override 44 | public void run() { 45 | if (fConsole != null) { 46 | if (!fConsole.enableUpload()) { 47 | fConsole.error("文件正在发送中,请不要频繁操作"); 48 | } 49 | FileDialog dialog = new FileDialog(fConsole.getControl().getShell(), 50 | SWT.OPEN); 51 | if (filterExtensions != null) { 52 | dialog.setFilterExtensions(filterExtensions); 53 | } 54 | if (filterNames != null) { 55 | dialog.setFilterNames(filterNames); 56 | } 57 | if (dialogTitle != null) { 58 | dialog.setText(dialogTitle); 59 | } 60 | String file = dialog.open(); 61 | if (file != null) { 62 | fConsole.sendFile(file); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/SendImageAction.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.actions; 2 | 3 | import cn.ieclipse.smartim.console.IMChatConsole; 4 | import icons.SmartIcons; 5 | 6 | public class SendImageAction extends SendFileAction { 7 | 8 | public SendImageAction(IMChatConsole console) { 9 | super(console); 10 | setText("图片"); 11 | this.setToolTipText("发送图片"); 12 | setImageDescriptor(SmartIcons.image); 13 | filterNames = new String[] { "Image Files", "All Files (*)" }; 14 | filterExtensions = new String[] { "*.gif;*.png;*.jpg;*.jpeg;*.bmp", 15 | "*" }; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/SendProjectFileAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import org.eclipse.core.resources.IFile; 19 | import org.eclipse.core.resources.IResource; 20 | import org.eclipse.core.resources.ResourcesPlugin; 21 | import org.eclipse.jface.window.Window; 22 | import org.eclipse.swt.widgets.Shell; 23 | import org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog; 24 | 25 | import cn.ieclipse.smartim.console.IMChatConsole; 26 | import icons.SmartIcons; 27 | 28 | /** 29 | * 类/接口描述 30 | * 31 | * @author Jamling 32 | * @date 2017年8月22日 33 | * 34 | */ 35 | public class SendProjectFileAction extends SendFileAction { 36 | 37 | public SendProjectFileAction(IMChatConsole console) { 38 | super(console); 39 | setText("Send Project File"); 40 | setToolTipText( 41 | "Send your project(workspace) file to " + fConsole.getName()); 42 | setImageDescriptor(SmartIcons.projectFile); 43 | } 44 | 45 | @Override 46 | public void run() { 47 | if (fConsole != null) { 48 | ProjectFileDialog dialog = new ProjectFileDialog(new Shell(), 49 | fConsole.getName()); 50 | if (Window.OK == dialog.open()) { 51 | Object obj = dialog.getFirstResult(); 52 | if (obj instanceof IFile) { 53 | String file = ((IFile) obj).getLocation().toOSString(); 54 | if (file != null) { 55 | fConsole.sendFile(file); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | 62 | private static class ProjectFileDialog 63 | extends FilteredResourcesSelectionDialog { 64 | public ProjectFileDialog(Shell shell, String name) { 65 | super(shell, false, ResourcesPlugin.getWorkspace().getRoot(), 66 | IResource.FILE); 67 | setTitle("Select project file to send to " + name); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/SettingsAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2015 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import org.eclipse.swt.widgets.Shell; 19 | import org.eclipse.ui.PlatformUI; 20 | import org.eclipse.ui.dialogs.PreferencesUtil; 21 | 22 | import cn.ieclipse.smartim.preferences.HotKeyPreferencePage; 23 | import cn.ieclipse.smartim.preferences.QiniuPerferencePage; 24 | import cn.ieclipse.smartim.preferences.RobotPreferencePage; 25 | import cn.ieclipse.smartim.preferences.SettingsPerferencePage; 26 | import cn.ieclipse.smartim.preferences.SmartQQPreferencePage; 27 | import cn.ieclipse.smartim.views.IMContactView; 28 | import icons.SmartIcons; 29 | 30 | /** 31 | * 类/接口描述 32 | * 33 | * @author Jamling 34 | * @date 2017年6月20日 35 | * 36 | */ 37 | public class SettingsAction extends IMPanelAction { 38 | public SettingsAction(IMContactView contactView) { 39 | super(contactView); 40 | setText("Settings"); 41 | setToolTipText("Settings & Helps"); 42 | setImageDescriptor(SmartIcons.settings); 43 | } 44 | 45 | @Override 46 | public void run() { 47 | open(null); 48 | } 49 | 50 | public static void open(String pageID) { 51 | Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() 52 | .getShell(); 53 | String pageId = pageID == null ? SmartQQPreferencePage.class.getName() : pageID; 54 | String[] ids = { pageId, 55 | SmartQQPreferencePage.class.getName(), 56 | HotKeyPreferencePage.class.getName(), 57 | RobotPreferencePage.class.getName(), 58 | QiniuPerferencePage.class.getName(), 59 | SettingsPerferencePage.class.getName()}; 60 | PreferencesUtil.createPreferenceDialogOn(shell, pageId, ids, null) 61 | .open(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/actions/ToggleContactsAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.actions; 17 | 18 | import cn.ieclipse.smartim.views.IMContactView; 19 | import icons.SmartIcons; 20 | 21 | /** 22 | * 类/接口描述 23 | * 24 | * @author Jamling 25 | * @date 2018年2月11日 26 | * 27 | */ 28 | public class ToggleContactsAction extends IMPanelAction { 29 | 30 | public ToggleContactsAction(IMContactView contactView) { 31 | super(contactView); 32 | setText("&Toggle Contacts"); 33 | setToolTipText("Toggle contacts"); 34 | setImageDescriptor(SmartIcons.hide); 35 | } 36 | 37 | @Override 38 | public void run() { 39 | if (fContactView != null) { 40 | fContactView.toggleContacts(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/common/IDEUtils.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.common; 2 | 3 | import java.net.MalformedURLException; 4 | import java.net.URL; 5 | 6 | import org.eclipse.core.resources.IFile; 7 | import org.eclipse.core.resources.IProject; 8 | import org.eclipse.core.resources.ResourcesPlugin; 9 | import org.eclipse.core.runtime.IPath; 10 | import org.eclipse.core.runtime.Path; 11 | import org.eclipse.core.runtime.preferences.IEclipsePreferences; 12 | import org.eclipse.core.runtime.preferences.InstanceScope; 13 | import org.eclipse.jface.dialogs.MessageDialog; 14 | import org.eclipse.jface.text.BadLocationException; 15 | import org.eclipse.jface.text.IDocument; 16 | import org.eclipse.jface.text.IRegion; 17 | import org.eclipse.swt.graphics.Color; 18 | import org.eclipse.swt.widgets.Shell; 19 | import org.eclipse.ui.IEditorPart; 20 | import org.eclipse.ui.IViewPart; 21 | import org.eclipse.ui.IWorkbenchPage; 22 | import org.eclipse.ui.PartInitException; 23 | import org.eclipse.ui.PlatformUI; 24 | import org.eclipse.ui.browser.IWorkbenchBrowserSupport; 25 | import org.eclipse.ui.ide.IDE; 26 | import org.eclipse.ui.texteditor.IDocumentProvider; 27 | import org.eclipse.ui.texteditor.ITextEditor; 28 | import org.eclipse.wb.swt.SWTResourceManager; 29 | 30 | import cn.ieclipse.smartim.IMPlugin; 31 | 32 | public class IDEUtils { 33 | public static void open(String file, int lineNumber) { 34 | try { 35 | IPath path = new Path(file); 36 | String prj = path.segment(0); 37 | IProject project = ResourcesPlugin.getWorkspace().getRoot() 38 | .getProject(prj); 39 | 40 | IFile f = project.getFile(path.removeFirstSegments(1)); 41 | IEditorPart editorPart = IDE.openEditor(PlatformUI.getWorkbench() 42 | .getActiveWorkbenchWindow().getActivePage(), f); 43 | if (editorPart instanceof ITextEditor && lineNumber >= 0) { 44 | ITextEditor textEditor = (ITextEditor) editorPart; 45 | IDocumentProvider provider = textEditor.getDocumentProvider(); 46 | provider.connect(editorPart.getEditorInput()); 47 | IDocument document = provider 48 | .getDocument(editorPart.getEditorInput()); 49 | try { 50 | IRegion line = document.getLineInformation(lineNumber); 51 | textEditor.selectAndReveal(line.getOffset(), 52 | line.getLength()); 53 | } catch (BadLocationException e) { 54 | e.printStackTrace(); 55 | } 56 | provider.disconnect(editorPart.getEditorInput()); 57 | } 58 | } catch (Exception e) { 59 | String msg = String.format("unable to open %s", file); 60 | IMPlugin.getDefault().log(msg, e); 61 | Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() 62 | .getShell(); 63 | MessageDialog.openWarning(shell, null, 64 | msg + "\n exception: " + e.toString()); 65 | } 66 | } 67 | 68 | public static void toggleViewPart(String viewId, boolean show) { 69 | IWorkbenchPage page = PlatformUI.getWorkbench() 70 | .getActiveWorkbenchWindow().getActivePage(); 71 | if (show) { 72 | try { 73 | page.showView(viewId); 74 | } catch (PartInitException e) { 75 | IMPlugin.getDefault().log("无法打开" + viewId, e); 76 | } catch (Exception e) { 77 | e.printStackTrace(); 78 | } 79 | return; 80 | } 81 | IViewPart view = page.findView(viewId); 82 | if (view != null) { 83 | page.hideView(view); 84 | } 85 | } 86 | 87 | public static boolean openInternalBrowser(String url, boolean external) { 88 | boolean ret = false; 89 | IWorkbenchBrowserSupport support = PlatformUI.getWorkbench() 90 | .getBrowserSupport(); 91 | boolean ext = external || !support.isInternalWebBrowserAvailable(); 92 | try { 93 | if (!ext) { 94 | int style = IWorkbenchBrowserSupport.LOCATION_BAR 95 | | IWorkbenchBrowserSupport.NAVIGATION_BAR 96 | | IWorkbenchBrowserSupport.AS_EDITOR; 97 | support.createBrowser(style, IMPlugin.PLUGIN_ID, null, null) 98 | .openURL(new URL(url)); 99 | ret = true; 100 | } 101 | else { 102 | support.getExternalBrowser().openURL(new URL(url)); 103 | ret = true; 104 | } 105 | } catch (PartInitException e) { 106 | e.printStackTrace(); 107 | } catch (MalformedURLException e) { 108 | e.printStackTrace(); 109 | } 110 | return ret; 111 | } 112 | 113 | public static Color getColor(int r, int g, int b) { 114 | return SWTResourceManager.getColor(r, g, b); 115 | } 116 | 117 | public static Color getPrefColor(String pluginId, String key) { 118 | IEclipsePreferences pref = InstanceScope.INSTANCE.getNode(pluginId); 119 | String c = pref.get(key, null); 120 | if (c != null) { 121 | String[] cs = c.split(","); 122 | if (cs.length == 3) { 123 | return getColor(Integer.parseInt(cs[0]), 124 | Integer.parseInt(cs[1]), Integer.parseInt(cs[2])); 125 | } 126 | } 127 | return null; 128 | } 129 | 130 | public static Color getEditorBack() { 131 | Color bg = getPrefColor("org.eclipse.ui.editors", 132 | "AbstractTextEditor.Color.Background"); 133 | return bg; 134 | } 135 | 136 | public static Color getEditorFore() { 137 | Color bg = getPrefColor("org.eclipse.ui.editors", 138 | "AbstractTextEditor.Color.Foreground"); 139 | return bg; 140 | } 141 | 142 | public static String getHtmlColor(Color c) { 143 | String rgb = ""; 144 | if (c != null) { 145 | rgb = "#" + dec2hex(c.getRed()) + dec2hex(c.getGreen()) 146 | + dec2hex(c.getBlue()); 147 | } 148 | return rgb; 149 | } 150 | 151 | private static String dec2hex(int d) { 152 | int i = d & 0xff; 153 | String s = Integer.toHexString(i); 154 | if (s.length() < 2) { 155 | s = "0" + s; 156 | } 157 | return s; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/common/PreventESCTraverseListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.common; 17 | 18 | import org.eclipse.swt.SWT; 19 | import org.eclipse.swt.events.TraverseEvent; 20 | import org.eclipse.swt.events.TraverseListener; 21 | 22 | /** 23 | * 类/接口描述 24 | * 25 | * @author Jamling 26 | * @date 2017年10月26日 27 | * 28 | */ 29 | public class PreventESCTraverseListener implements TraverseListener { 30 | 31 | @Override 32 | public void keyTraversed(TraverseEvent e) { 33 | if (e.detail == SWT.TRAVERSE_ESCAPE) { 34 | e.doit = false; 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/common/RestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2018 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.common; 17 | 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | 21 | import javax.swing.JOptionPane; 22 | import javax.swing.SwingUtilities; 23 | import javax.swing.text.html.StyleSheet; 24 | 25 | import org.eclipse.core.runtime.Platform; 26 | 27 | import com.google.gson.Gson; 28 | 29 | import cn.ieclipse.smartim.IMPlugin; 30 | import okhttp3.Call; 31 | import okhttp3.OkHttpClient; 32 | import okhttp3.Request; 33 | import okhttp3.Response; 34 | 35 | /** 36 | * 类/接口描述 37 | * 38 | * @author Jamling 39 | * @date 2019年1月16日 40 | * 41 | */ 42 | public class RestUtils { 43 | public final static String welcome_format = "http://api.ieclipse.cn/smartqq/index/welcome?p=%s&im=%s&v=%s"; 44 | public final static String update_url = "http://api.ieclipse.cn/smartqq/index/notice?p=eclipse"; 45 | public final static String about_url = "http://api.ieclipse.cn/smartqq/index/about"; 46 | 47 | 48 | public static String getWelcome(String im) { 49 | try { 50 | okhttp3.Request.Builder builder = new okhttp3.Request.Builder() 51 | .url(String.format(welcome_format, "eclipse", im, 52 | Platform.getBundle(IMPlugin.PLUGIN_ID).getVersion().toString())) 53 | .get(); 54 | Request request = builder.build(); 55 | Call call = new OkHttpClient().newCall(request); 56 | Response response = call.execute(); 57 | String json = response.body().string(); 58 | if (response.code() == 200) { 59 | return json; 60 | } 61 | } catch (Exception e) { 62 | } 63 | return null; 64 | } 65 | 66 | public static void checkUpdate() { 67 | new Thread() { 68 | public void run() { 69 | try { 70 | okhttp3.Request.Builder builder = (new okhttp3.Request.Builder()) 71 | .url(RestUtils.update_url).get(); 72 | Request request = builder.build(); 73 | Call call = new OkHttpClient().newCall(request); 74 | Response response = call.execute(); 75 | String json = response.body().string(); 76 | if (response.code() == 200) { 77 | final UpdateInfo info = new Gson().fromJson(json, 78 | UpdateInfo.class); 79 | 80 | } 81 | } catch (Exception ex) { 82 | } 83 | }; 84 | }.start(); 85 | } 86 | 87 | public static class UpdateInfo { 88 | public String latest; 89 | public String desc; 90 | public String link; 91 | } 92 | 93 | public static void loadStyleAsync(final StyleSheet styleSheet) { 94 | // new Thread() { 95 | // @Override 96 | // public void run() { 97 | // loadStyleSync(styleSheet); 98 | // } 99 | // }.start(); 100 | } 101 | 102 | public static void loadStyleSync(final StyleSheet styleSheet) { 103 | try { 104 | styleSheet.importStyleSheet( 105 | new URL("http://dl.ieclipse.cn/r/smartim.css")); 106 | } catch (MalformedURLException e1) { 107 | e1.printStackTrace(); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/common/TranslateAnimation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.common; 17 | 18 | import org.eclipse.swt.widgets.Shell; 19 | 20 | /** 21 | * 类/接口描述 22 | * 23 | * @author Jamling 24 | * @date 2017年10月24日 25 | * 26 | */ 27 | public class TranslateAnimation { 28 | Shell target; 29 | long duration; 30 | 31 | int startX; 32 | int endX; 33 | int startY; 34 | int endY; 35 | float stepX; 36 | float stepY; 37 | 38 | long interval = 50; 39 | 40 | public TranslateAnimation(int startX, int endX, int startY, int endY) { 41 | super(); 42 | this.startX = startX; 43 | this.endX = endX; 44 | this.startY = startY; 45 | this.endY = endY; 46 | } 47 | 48 | public TranslateAnimation setTarget(Shell target) { 49 | this.target = target; 50 | return this; 51 | } 52 | 53 | public TranslateAnimation setDuration(long duration) { 54 | this.duration = duration; 55 | return this; 56 | } 57 | 58 | public void start() { 59 | if (duration <= 0 || target == null) { 60 | return; 61 | } 62 | stepX = ((endX - startX) * 1.0f / duration); 63 | stepY = ((endY - startY) * 1.0f / duration); 64 | 65 | new Thread() { 66 | public void run() { 67 | long start = interval; 68 | while (start <= duration) { 69 | float x = startX + start * stepX; 70 | float y = startY + start * stepY; 71 | move(x, y); 72 | start += interval; 73 | try { 74 | Thread.sleep(interval); 75 | } catch (InterruptedException e) { 76 | // 77 | } 78 | } 79 | move(endX, endY); 80 | }; 81 | }.start(); 82 | } 83 | 84 | private void move(final float x, final float y) { 85 | if (target != null && !target.isDisposed()) { 86 | target.getDisplay().asyncExec(new Runnable() { 87 | @Override 88 | public void run() { 89 | if (target != null && !target.isDisposed()) { 90 | target.setLocation((int) x, (int) y); 91 | } 92 | } 93 | }); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/console/ClosableTabHost.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.console; 2 | 3 | import org.eclipse.swt.SWT; 4 | import org.eclipse.swt.custom.CTabFolder; 5 | import org.eclipse.swt.custom.CTabItem; 6 | import org.eclipse.swt.events.SelectionAdapter; 7 | import org.eclipse.swt.events.SelectionEvent; 8 | import org.eclipse.swt.graphics.Image; 9 | import org.eclipse.swt.graphics.Rectangle; 10 | import org.eclipse.swt.widgets.Composite; 11 | 12 | import cn.ieclipse.smartim.IMPlugin; 13 | import cn.ieclipse.smartim.views.IMContactView; 14 | 15 | public class ClosableTabHost extends CTabFolder { 16 | IMContactView imPanel; 17 | IMChatConsole currentItem; 18 | 19 | /** 20 | * Create the composite. 21 | * 22 | * @param parent 23 | * @param style 24 | */ 25 | public ClosableTabHost(Composite parent) { 26 | super(parent, SWT.CLOSE | SWT.FLAT); 27 | setUnselectedImageVisible(true); 28 | setUnselectedCloseVisible(false); 29 | // setSimple(false); 30 | // setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); 31 | addSelectionListener(new SelectionAdapter() { 32 | @Override 33 | public void widgetSelected(SelectionEvent e) { 34 | if (e.item instanceof IMChatConsole) { 35 | IMChatConsole item = (IMChatConsole) e.item; 36 | item.setImage(item.IMG_NORMAL); 37 | item.clearUnread(); 38 | currentItem = item; 39 | } 40 | } 41 | }); 42 | } 43 | 44 | @Override 45 | protected void checkSubclass() { 46 | // Disable the check that prevents subclassing of SWT components 47 | } 48 | 49 | @Override 50 | public void setSelection(int index) { 51 | super.setSelection(index); 52 | if (index >= 0 && index < getItemCount()) { 53 | if (getItem(index) instanceof IMChatConsole) { 54 | currentItem = (IMChatConsole) getItem(index); 55 | } 56 | } 57 | } 58 | 59 | public IMChatConsole getCurrentItem() { 60 | return currentItem; 61 | } 62 | 63 | public void bling(int index, String name) { 64 | int size = getItemCount(); 65 | if (index >= 0 && index < size) { 66 | final CTabItem item = getItem(index); 67 | new Thread(new BlingThread(name, item)).start(); 68 | } 69 | } 70 | 71 | public static class BlingThread implements Runnable { 72 | int count = 4; 73 | long interval = 300; 74 | String name; 75 | CTabItem item; 76 | Rectangle bounds; 77 | 78 | Runnable cmd = new Runnable() { 79 | @Override 80 | public void run() { 81 | if (item != null && !item.isDisposed() 82 | && item instanceof IMChatConsole) { 83 | // String text = item.getText(); 84 | // item.setText("".equals(text) ? name : ""); 85 | Image img = item.getImage(); 86 | Image bling = ((IMChatConsole) item).IMG_SELECTED; 87 | item.setImage(img == bling ? img : bling); 88 | } 89 | } 90 | }; 91 | 92 | public BlingThread(String name, CTabItem item) { 93 | this.item = item; 94 | this.name = name; 95 | bounds = item.getBounds(); 96 | } 97 | 98 | @Override 99 | public void run() { 100 | while (count > 0) { 101 | try { 102 | IMPlugin.runOnUI(cmd); 103 | Thread.sleep(interval); 104 | count--; 105 | } catch (InterruptedException e) { 106 | return; 107 | } 108 | } 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/console/JSBridge.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.console; 2 | 3 | import org.eclipse.swt.browser.Browser; 4 | import org.eclipse.swt.browser.BrowserFunction; 5 | 6 | public class JSBridge extends BrowserFunction { 7 | 8 | public JSBridge(Browser browser, String name) { 9 | super(browser, name); 10 | } 11 | 12 | @Override 13 | public Object function(Object[] arguments) { 14 | Object obj = super.function(arguments); 15 | if (callback != null) { 16 | return callback.onFunction(arguments); 17 | } 18 | return obj; 19 | } 20 | 21 | private Callback callback; 22 | 23 | public void setCallback(Callback callback) { 24 | this.callback = callback; 25 | } 26 | 27 | public interface Callback { 28 | Object onFunction(Object[] args); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/console/MockChatConsole.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.console; 2 | 3 | import java.util.List; 4 | 5 | import org.eclipse.swt.SWT; 6 | 7 | import cn.ieclipse.smartim.IMHistoryManager; 8 | import cn.ieclipse.smartim.SmartClient; 9 | import cn.ieclipse.smartim.common.IMUtils; 10 | import cn.ieclipse.smartim.common.LetterImageFactory; 11 | import cn.ieclipse.smartim.model.IContact; 12 | import cn.ieclipse.smartim.views.IMContactView; 13 | 14 | /** 15 | * Created by Jamling on 2018/1/3. 16 | */ 17 | public class MockChatConsole extends IMChatConsole { 18 | public MockChatConsole(IContact target, IMContactView imPanel) { 19 | super(target, imPanel); 20 | IMG_NORMAL = LetterImageFactory.create('F', SWT.COLOR_BLACK); 21 | IMG_SELECTED = LetterImageFactory.create('F', SWT.COLOR_RED); 22 | setImage(IMG_NORMAL); 23 | } 24 | 25 | @Override 26 | public void loadHistory(String raw) { 27 | if (IMUtils.isMySendMsg(raw)) { 28 | write(raw); 29 | return; 30 | } 31 | } 32 | 33 | @Override 34 | public void post(String msg) { 35 | 36 | } 37 | 38 | @Override 39 | public SmartClient getClient() { 40 | return null; 41 | } 42 | 43 | @Override 44 | public void loadHistories() { 45 | List ms = IMHistoryManager.getInstance().load(getHistoryDir(), 46 | getHistoryFile()); 47 | int size = ms.size(); 48 | for (int i=0; i < size; i++) { 49 | String raw = ms.get(i); 50 | if (!IMUtils.isEmpty(raw)) { 51 | try { 52 | loadHistory(raw); 53 | } catch (Exception e) { 54 | error("历史消息记录:" + raw); 55 | } 56 | } 57 | } 58 | } 59 | 60 | @Override 61 | public void send(String input) { 62 | String name = "我"; 63 | String msg = formatInput(name, input); 64 | System.out.println(msg); 65 | if (!hideMyInput()) { 66 | insertDocument(msg); 67 | IMHistoryManager.getInstance().save(getHistoryDir(), 68 | getHistoryFile(), msg); 69 | } 70 | } 71 | 72 | @Override 73 | public void sendWithoutPost(String msg, boolean raw) { 74 | if (!hideMyInput()) { 75 | String name = "Me"; 76 | insertDocument(raw ? msg : formatInput(name, msg)); 77 | IMHistoryManager.getInstance().save(getHistoryDir(), getHistoryFile(), msg); 78 | } 79 | } 80 | 81 | public void initMockMsg() { 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/console/Splitter.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.console; 2 | import org.eclipse.swt.SWT; 3 | import org.eclipse.swt.graphics.Rectangle; 4 | import org.eclipse.swt.layout.FormAttachment; 5 | import org.eclipse.swt.layout.FormData; 6 | import org.eclipse.swt.layout.FormLayout; 7 | import org.eclipse.swt.widgets.Composite; 8 | import org.eclipse.swt.widgets.Control; 9 | import org.eclipse.swt.widgets.Event; 10 | import org.eclipse.swt.widgets.Listener; 11 | import org.eclipse.swt.widgets.Sash; 12 | 13 | public class Splitter extends Composite { 14 | 15 | public Splitter(Composite parent, Control ctrlA, Control ctrlB, 16 | int splitDirection) { 17 | super(parent, SWT.NONE); 18 | 19 | setLocation(0, 0); 20 | setSize(parent.getSize()); 21 | setVisible(true); 22 | boolean result = ctrlA.setParent(this); 23 | assert result; 24 | result = ctrlB.setParent(this); 25 | assert result; 26 | 27 | final Sash sash = new Sash(this, splitDirection); 28 | final FormLayout form = new FormLayout(); 29 | setLayout(form); 30 | 31 | FormData ctrlAFormData = new FormData(); 32 | ctrlAFormData.left = new FormAttachment(0, 0); 33 | ctrlAFormData.top = new FormAttachment(0, 0); 34 | 35 | if (splitDirection == SWT.VERTICAL) { 36 | ctrlAFormData.right = new FormAttachment(sash, 0); 37 | ctrlAFormData.bottom = new FormAttachment(100, 0); 38 | } 39 | else if (splitDirection == SWT.HORIZONTAL) { 40 | ctrlAFormData.right = new FormAttachment(100, 0); 41 | ctrlAFormData.bottom = new FormAttachment(sash, 0); 42 | } 43 | 44 | ctrlA.setLayoutData(ctrlAFormData); 45 | 46 | final int limit = 20; 47 | final FormData sashData = new FormData(); 48 | 49 | if (splitDirection == SWT.VERTICAL) { 50 | // sashData.width = 10; 51 | final int percent = 30; 52 | sashData.left = new FormAttachment(percent, 0); 53 | sashData.top = new FormAttachment(0, 0); 54 | sashData.bottom = new FormAttachment(100, 0); 55 | sash.setLayoutData(sashData); 56 | 57 | sash.addListener(SWT.Selection, new Listener() { 58 | public void handleEvent(Event e) { 59 | Rectangle sashRect = sash.getBounds(); 60 | Rectangle shellRect = sash.getParent().getClientArea(); 61 | int right = shellRect.width - sashRect.width - limit; 62 | e.x = Math.max(Math.min(e.x, right), limit); 63 | if (e.x != sashRect.x) { 64 | sashData.left = new FormAttachment(0, e.x); 65 | sash.getParent().layout(); 66 | } 67 | } 68 | }); 69 | } 70 | else if (splitDirection == SWT.HORIZONTAL) { 71 | // sashData.width = 10; 72 | final int percent = 70; 73 | sashData.left = new FormAttachment(0, 0); 74 | sashData.top = new FormAttachment(percent, 0); 75 | sashData.right = new FormAttachment(100, 0); 76 | sash.setLayoutData(sashData); 77 | 78 | sash.addListener(SWT.Selection, new Listener() { 79 | public void handleEvent(Event e) { 80 | Rectangle sashRect = sash.getBounds(); 81 | Rectangle shellRect = sash.getParent().getClientArea(); 82 | // Rectangle shellRect = getClientArea(); 83 | int right = shellRect.height - sashRect.height - limit; 84 | e.y = Math.max(Math.min(e.y, right), limit); 85 | if (e.y != sashRect.y) { 86 | sashData.top = new FormAttachment(0, e.y); 87 | sash.getParent().layout(); 88 | } 89 | } 90 | }); 91 | } 92 | 93 | FormData ctrlBFormData = new FormData(); 94 | ctrlBFormData.right = new FormAttachment(100, 0); 95 | ctrlBFormData.bottom = new FormAttachment(100, 0); 96 | if (splitDirection == SWT.VERTICAL) { 97 | ctrlBFormData.left = new FormAttachment(sash, 0); 98 | ctrlBFormData.top = new FormAttachment(0, 0); 99 | } 100 | else if (splitDirection == SWT.HORIZONTAL) { 101 | ctrlBFormData.left = new FormAttachment(0, 0); 102 | ctrlBFormData.top = new FormAttachment(sash, 0); 103 | } 104 | ctrlB.setLayoutData(ctrlBFormData); 105 | 106 | layout(); 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/console/history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SmartIM 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 55 | 56 | 57 |
58 | 61 |
62 | 66 | 67 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/decorators/IMChatDecoration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.decorators; 17 | 18 | import org.eclipse.jface.resource.ImageDescriptor; 19 | import org.eclipse.jface.viewers.IDecoration; 20 | import org.eclipse.jface.viewers.IDecorationContext; 21 | import org.eclipse.swt.graphics.Color; 22 | import org.eclipse.swt.graphics.Font; 23 | 24 | /** 25 | * 类/接口描述 26 | * 27 | * @author Jamling 28 | * @date 2017年10月26日 29 | * 30 | */ 31 | public class IMChatDecoration implements IDecoration { 32 | 33 | @Override 34 | public void addPrefix(String prefix) { 35 | // TODO Auto-generated method stub 36 | 37 | } 38 | 39 | @Override 40 | public void addSuffix(String suffix) { 41 | // TODO Auto-generated method stub 42 | 43 | } 44 | 45 | @Override 46 | public void addOverlay(ImageDescriptor overlay) { 47 | // TODO Auto-generated method stub 48 | 49 | } 50 | 51 | @Override 52 | public void addOverlay(ImageDescriptor overlay, int quadrant) { 53 | // TODO Auto-generated method stub 54 | 55 | } 56 | 57 | @Override 58 | public void setForegroundColor(Color color) { 59 | // TODO Auto-generated method stub 60 | 61 | } 62 | 63 | @Override 64 | public void setBackgroundColor(Color color) { 65 | // TODO Auto-generated method stub 66 | 67 | } 68 | 69 | @Override 70 | public void setFont(Font font) { 71 | // TODO Auto-generated method stub 72 | 73 | } 74 | 75 | @Override 76 | public IDecorationContext getDecorationContext() { 77 | // TODO Auto-generated method stub 78 | return null; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/decorators/IMChatDecorator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.decorators; 17 | 18 | import org.eclipse.jface.resource.ImageDescriptor; 19 | import org.eclipse.jface.viewers.IDecoration; 20 | import org.eclipse.jface.viewers.ILabelDecorator; 21 | import org.eclipse.jface.viewers.ILabelProviderListener; 22 | import org.eclipse.swt.SWT; 23 | import org.eclipse.swt.graphics.Image; 24 | 25 | import cn.ieclipse.smartim.common.LetterImageFactory; 26 | import cn.ieclipse.smartim.model.impl.AbstractContact; 27 | 28 | /** 29 | * 类/接口描述 30 | * 31 | * @author Jamling 32 | * @date 2017年10月26日 33 | * 34 | */ 35 | public class IMChatDecorator implements ILabelDecorator { 36 | 37 | @Override 38 | public void addListener(ILabelProviderListener listener) { 39 | // TODO Auto-generated method stub 40 | 41 | } 42 | 43 | @Override 44 | public void dispose() { 45 | // TODO Auto-generated method stub 46 | 47 | } 48 | 49 | @Override 50 | public boolean isLabelProperty(Object element, String property) { 51 | // TODO Auto-generated method stub 52 | return false; 53 | } 54 | 55 | @Override 56 | public void removeListener(ILabelProviderListener listener) { 57 | // TODO Auto-generated method stub 58 | 59 | } 60 | 61 | @Override 62 | public Image decorateImage(Image image, Object element) { 63 | if (image != null && element instanceof AbstractContact) { 64 | AbstractContact c = (AbstractContact) element; 65 | int ch = Math.min(c.getUnread(), 9) + (int) '0'; 66 | ImageDescriptor id = LetterImageFactory.createDescriptor((char) ch, 67 | SWT.COLOR_RED); 68 | return new IMCompositeImageDescriptor(image, id, 69 | IDecoration.TOP_LEFT).createImage(); 70 | } 71 | return null; 72 | } 73 | 74 | @Override 75 | public String decorateText(String text, Object element) { 76 | if (element instanceof AbstractContact) { 77 | AbstractContact c = (AbstractContact) element; 78 | CharSequence s = c.getLastMessage().getText(); 79 | return text + "[" + s + "]"; 80 | } 81 | return null; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/decorators/IMCompositeImageDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.decorators; 17 | 18 | import org.eclipse.jface.resource.ImageDescriptor; 19 | import org.eclipse.jface.viewers.DecorationOverlayIcon; 20 | import org.eclipse.swt.graphics.Image; 21 | 22 | /** 23 | * 类/接口描述 24 | * 25 | * @author Jamling 26 | * @date 2017年10月26日 27 | * 28 | */ 29 | public class IMCompositeImageDescriptor extends DecorationOverlayIcon { 30 | 31 | public IMCompositeImageDescriptor(Image baseImage, 32 | ImageDescriptor overlayImage, int quadrant) { 33 | super(baseImage, overlayImage, quadrant); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/dialogs/HotKeyInputDialog.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.dialogs; 2 | 3 | import org.eclipse.jface.dialogs.IInputValidator; 4 | import org.eclipse.jface.dialogs.InputDialog; 5 | import org.eclipse.swt.events.KeyEvent; 6 | import org.eclipse.swt.events.KeyListener; 7 | import org.eclipse.swt.widgets.Button; 8 | import org.eclipse.swt.widgets.Composite; 9 | import org.eclipse.swt.widgets.Control; 10 | import org.eclipse.swt.widgets.Shell; 11 | 12 | import cn.ieclipse.smartim.common.PreventESCTraverseListener; 13 | import cn.ieclipse.smartim.preferences.HotKeyFieldEditor; 14 | 15 | public class HotKeyInputDialog extends InputDialog { 16 | 17 | public HotKeyInputDialog(Shell parentShell, String dialogTitle, 18 | String dialogMessage, String initialValue, 19 | IInputValidator validator) { 20 | super(parentShell, dialogTitle, dialogMessage, initialValue, validator); 21 | } 22 | 23 | public HotKeyInputDialog(Shell parentShell, HotKeyFieldEditor editor) { 24 | this(parentShell, "Input key", 25 | "Set hot key for '" + editor.getLabelText() + "'", 26 | editor.getTextControl(null).getText(), null); 27 | getShell().addTraverseListener(new PreventESCTraverseListener()); 28 | } 29 | 30 | @Override 31 | protected Control createDialogArea(Composite parent) { 32 | Control control = super.createDialogArea(parent); 33 | getText().addKeyListener(new KeyListener() { 34 | 35 | @Override 36 | public void keyReleased(KeyEvent e) { 37 | 38 | } 39 | 40 | @Override 41 | public void keyPressed(KeyEvent e) { 42 | e.doit = false; 43 | getText().setText(HotKeyFieldEditor.keyEvent2String(e)); 44 | } 45 | }); 46 | return control; 47 | } 48 | 49 | @Override 50 | protected Button createButton(Composite parent, int id, String label, 51 | boolean defaultButton) { 52 | return super.createButton(parent, id, label, false); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/dialogs/LoginDialog.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.dialogs; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.FileNotFoundException; 5 | 6 | import org.eclipse.jface.dialogs.Dialog; 7 | import org.eclipse.jface.dialogs.IDialogConstants; 8 | import org.eclipse.jface.dialogs.MessageDialog; 9 | import org.eclipse.swt.SWT; 10 | import org.eclipse.swt.graphics.Image; 11 | import org.eclipse.swt.graphics.Point; 12 | import org.eclipse.swt.graphics.Rectangle; 13 | import org.eclipse.swt.layout.GridData; 14 | import org.eclipse.swt.layout.GridLayout; 15 | import org.eclipse.swt.widgets.Composite; 16 | import org.eclipse.swt.widgets.Control; 17 | import org.eclipse.swt.widgets.Display; 18 | import org.eclipse.swt.widgets.Label; 19 | import org.eclipse.swt.widgets.Shell; 20 | import org.eclipse.swt.widgets.Text; 21 | import org.eclipse.wb.swt.SWTResourceManager; 22 | 23 | import cn.ieclipse.smartim.IMPlugin; 24 | import cn.ieclipse.smartim.SmartClient; 25 | import cn.ieclipse.smartim.callback.LoginCallback; 26 | 27 | public class LoginDialog extends Dialog { 28 | private SmartClient client; 29 | private Text text; 30 | private Label qrcode; 31 | 32 | /** 33 | * Create the dialog. 34 | * 35 | * @param parentShell 36 | */ 37 | public LoginDialog(Shell parentShell) { 38 | super(parentShell); 39 | } 40 | 41 | /** 42 | * Create contents of the dialog. 43 | * 44 | * @param parent 45 | */ 46 | @Override 47 | protected Control createDialogArea(Composite parent) { 48 | Composite container = (Composite) super.createDialogArea(parent); 49 | container.setLayout(new GridLayout(1, false)); 50 | 51 | qrcode = new Label(container, SWT.NONE); 52 | qrcode.setAlignment(SWT.CENTER); 53 | qrcode.setImage(SWTResourceManager.getImage(LoginDialog.class, 54 | "/icons/full/progress/waiting.gif")); 55 | qrcode.setLayoutData( 56 | new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 1)); 57 | 58 | text = new Text(container, SWT.READ_ONLY | SWT.WRAP | SWT.MULTI); 59 | text.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED)); 60 | text.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true, 1, 1)); 61 | new Thread() { 62 | public void run() { 63 | doLogin(); 64 | } 65 | }.start(); 66 | 67 | return container; 68 | } 69 | 70 | /** 71 | * Create contents of the button bar. 72 | * 73 | * @param parent 74 | */ 75 | @Override 76 | protected void createButtonsForButtonBar(Composite parent) { 77 | createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, 78 | true); 79 | createButton(parent, IDialogConstants.CANCEL_ID, 80 | IDialogConstants.CANCEL_LABEL, false); 81 | } 82 | 83 | /** 84 | * Return the initial size of the dialog. 85 | */ 86 | @Override 87 | protected Point getInitialSize() { 88 | return new Point(450, 300); 89 | } 90 | 91 | public void setClient(SmartClient client) { 92 | this.client = client; 93 | } 94 | 95 | protected void doLogin() { 96 | if (client == null) { 97 | return; 98 | } 99 | LoginCallback callback = new LoginCallback() { 100 | @Override 101 | public void onQrcode(final String path) { 102 | Display.getDefault().asyncExec(new Runnable() { 103 | 104 | @Override 105 | public void run() { 106 | if (qrcode == null || qrcode.isDisposed()) { 107 | return; 108 | } 109 | Image image; 110 | try { 111 | image = new Image(Display.getDefault(), 112 | new FileInputStream(path)); 113 | Point p = qrcode.getParent().getSize(); 114 | Rectangle p2 = image.getBounds(); 115 | int x = (p.x - p2.width) >> 1; 116 | int y = (p.y - p2.height) >> 1; 117 | 118 | if (x < 0 || y < 0) { 119 | qrcode.setBounds(new Rectangle(0, 0, p2.width, 120 | p2.height)); 121 | } 122 | else { 123 | Rectangle p3 = new Rectangle(x, y, p2.width, 124 | p2.height); 125 | qrcode.setBounds(p3); 126 | } 127 | qrcode.setImage(image); 128 | 129 | getShell().pack(); 130 | } catch (FileNotFoundException e) { 131 | if (text == null || text.isDisposed()) { 132 | return; 133 | } 134 | text.setText("二维码图片不存在,请确认" + path + "目录可读写"); 135 | } 136 | } 137 | }); 138 | } 139 | 140 | @Override 141 | public void onLogin(final boolean ok, final Exception e) { 142 | Display.getDefault().asyncExec(new Runnable() { 143 | 144 | @Override 145 | public void run() { 146 | if (ok) { 147 | close(); 148 | } 149 | else { 150 | if (text == null || text.isDisposed()) { 151 | return; 152 | } 153 | text.setText( 154 | e == null ? "" 155 | : e.getMessage() == null 156 | ? e.toString() 157 | : e.getMessage()); 158 | MessageDialog.openWarning(text.getShell(), "登录失败", 159 | e.toString() + "\n请在Error Log中查看详情"); 160 | IMPlugin.getDefault().log("登录失败", e); 161 | } 162 | } 163 | }); 164 | } 165 | }; 166 | client.setLoginCallback(callback); 167 | client.login(); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/dialogs/OpenFileDialog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.dialogs; 17 | 18 | import java.io.File; 19 | 20 | import org.eclipse.jface.dialogs.IDialogConstants; 21 | import org.eclipse.jface.dialogs.MessageDialog; 22 | import org.eclipse.swt.SWT; 23 | import org.eclipse.swt.events.SelectionAdapter; 24 | import org.eclipse.swt.events.SelectionListener; 25 | import org.eclipse.swt.layout.FillLayout; 26 | import org.eclipse.swt.layout.GridData; 27 | import org.eclipse.swt.widgets.Button; 28 | import org.eclipse.swt.widgets.Composite; 29 | import org.eclipse.swt.widgets.Control; 30 | import org.eclipse.swt.widgets.Display; 31 | import org.eclipse.swt.widgets.Shell; 32 | 33 | import cn.ieclipse.pde.explorer.ExplorerPlugin; 34 | import cn.ieclipse.smartim.common.IDEUtils; 35 | 36 | /** 37 | * 类/接口描述 38 | * 39 | * @author Jamling 40 | * @date 2018年2月8日 41 | * 42 | */ 43 | public class OpenFileDialog extends MessageDialog { 44 | int selection = 0; 45 | 46 | public OpenFileDialog(Shell parent, String title, String message) { 47 | super(parent, title, null, message, CONFIRM, new String[] { 48 | IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL }, 0); 49 | } 50 | 51 | @Override 52 | protected Control createCustomArea(Composite parent) { 53 | Composite composite = new Composite(parent, SWT.NONE); 54 | FillLayout fl_composite = new FillLayout(SWT.VERTICAL); 55 | fl_composite.spacing = 10; 56 | fl_composite.marginHeight = 10; 57 | composite.setLayout(fl_composite); 58 | composite.setLayoutData( 59 | new GridData(SWT.FILL, SWT.TOP, true, true, 1, 1)); 60 | 61 | rb1 = new Button(composite, SWT.RADIO); 62 | rb1.setSelection(true); 63 | rb1.setText("Eclipse Explorer 在操作系统的浏览器中打开,可以对文件自由操作"); 64 | rb1.addSelectionListener(listener); 65 | 66 | rb2 = new Button(composite, SWT.RADIO); 67 | rb2.setText("Eclipse 内置浏览器,适用于可查看的文件,比如文本,图像"); 68 | rb2.addSelectionListener(listener); 69 | 70 | rb3 = new Button(composite, SWT.RADIO); 71 | rb3.setText("操作系统默认浏览器,适用范围同上"); 72 | rb3.addSelectionListener(listener); 73 | 74 | return composite; 75 | } 76 | 77 | private SelectionListener listener = new SelectionAdapter() { 78 | public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { 79 | if (e.widget == rb1) { 80 | selection = 0; 81 | } 82 | else if (e.widget == rb2) { 83 | selection = 1; 84 | } 85 | else if (e.widget == rb3) { 86 | selection = 2; 87 | } 88 | }; 89 | }; 90 | private Button rb1; 91 | private Button rb2; 92 | private Button rb3; 93 | 94 | public static boolean open(Shell shell, String url) { 95 | String title = "请选择打开方式"; 96 | String message = "SmartQQ检测到您试图打开一个本地文件,请选择以下打开方式"; 97 | OpenFileDialog dialog = new OpenFileDialog( 98 | shell == null ? new Shell() : shell, title, message); 99 | if (dialog.open() == OK) { 100 | if (dialog.selection == 0) { 101 | String file = url.substring("file://".length()); 102 | if (ExplorerPlugin.getOS() == ExplorerPlugin.OS_WINDOWS) { 103 | if (file.startsWith("/")) { 104 | file = file.substring(1); 105 | // file = file.replace("/", "\\"); 106 | } 107 | } 108 | File f = new File(file); 109 | ExplorerPlugin.explorer(f.getParent(), f.getAbsolutePath()); 110 | return true; 111 | } 112 | else if (dialog.selection == 1) { 113 | return IDEUtils.openInternalBrowser(url, false); 114 | } 115 | else if (dialog.selection == 2) { 116 | return IDEUtils.openInternalBrowser(url, true); 117 | } 118 | } 119 | return false; 120 | } 121 | 122 | public static void main(String[] args) { 123 | new OpenFileDialog(new Shell(), "title", "message").open(); 124 | Display display = Display.getDefault(); 125 | while (!display.isDisposed()) { 126 | if (!display.readAndDispatch()) { 127 | display.sleep(); 128 | } 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/dialogs/PasteFileDialog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.dialogs; 17 | 18 | import java.io.File; 19 | 20 | import org.eclipse.jface.dialogs.IDialogConstants; 21 | import org.eclipse.jface.dialogs.MessageDialog; 22 | import org.eclipse.swt.SWT; 23 | import org.eclipse.swt.events.SelectionAdapter; 24 | import org.eclipse.swt.events.SelectionListener; 25 | import org.eclipse.swt.layout.FillLayout; 26 | import org.eclipse.swt.layout.GridData; 27 | import org.eclipse.swt.widgets.Button; 28 | import org.eclipse.swt.widgets.Composite; 29 | import org.eclipse.swt.widgets.Control; 30 | import org.eclipse.swt.widgets.Display; 31 | import org.eclipse.swt.widgets.Shell; 32 | 33 | import cn.ieclipse.pde.explorer.ExplorerPlugin; 34 | import cn.ieclipse.smartim.common.IDEUtils; 35 | 36 | /** 37 | * 类/接口描述 38 | * 39 | * @author Jamling 40 | * @date 2018年2月8日 41 | * 42 | */ 43 | public class PasteFileDialog extends MessageDialog { 44 | int selection = 0; 45 | 46 | public PasteFileDialog(Shell parent, String title, String message) { 47 | super(parent, title, null, message, CONFIRM, new String[] { 48 | IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL }, 0); 49 | } 50 | 51 | @Override 52 | protected Control createCustomArea(Composite parent) { 53 | Composite composite = new Composite(parent, SWT.NONE); 54 | FillLayout fl_composite = new FillLayout(SWT.VERTICAL); 55 | fl_composite.spacing = 10; 56 | fl_composite.marginHeight = 10; 57 | composite.setLayout(fl_composite); 58 | composite.setLayoutData( 59 | new GridData(SWT.FILL, SWT.TOP, true, true, 1, 1)); 60 | 61 | rb1 = new Button(composite, SWT.RADIO); 62 | rb1.setSelection(true); 63 | rb1.setText("发送文件,文件上传成功后将发送给对方"); 64 | rb1.addSelectionListener(listener); 65 | 66 | rb2 = new Button(composite, SWT.RADIO); 67 | rb2.setText("代码评审,发送代码位置,并输入评语"); 68 | rb2.addSelectionListener(listener); 69 | 70 | return composite; 71 | } 72 | 73 | private SelectionListener listener = new SelectionAdapter() { 74 | public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { 75 | if (e.widget == rb1) { 76 | selection = 0; 77 | } 78 | else if (e.widget == rb2) { 79 | selection = 1; 80 | } 81 | }; 82 | }; 83 | private Button rb1; 84 | private Button rb2; 85 | 86 | public static int open(Shell shell, String url) { 87 | String title = "请选择操作"; 88 | String message = String.format("SmartQQ检测到您粘贴了一个工作区中的文件(%s),请选择以下操作", 89 | url); 90 | PasteFileDialog dialog = new PasteFileDialog( 91 | shell == null ? new Shell() : shell, title, message); 92 | if (dialog.open() == OK) { 93 | return dialog.selection; 94 | } 95 | return -1; 96 | } 97 | 98 | public static void main(String[] args) { 99 | new PasteFileDialog(new Shell(), "title", "message").open(); 100 | Display display = Display.getDefault(); 101 | while (!display.isDisposed()) { 102 | if (!display.readAndDispatch()) { 103 | display.sleep(); 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/handlers/ReviewHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.handlers; 17 | 18 | import org.eclipse.core.commands.AbstractHandler; 19 | import org.eclipse.core.commands.ExecutionEvent; 20 | import org.eclipse.core.commands.ExecutionException; 21 | import org.eclipse.core.resources.IFile; 22 | import org.eclipse.jface.text.TextSelection; 23 | import org.eclipse.jface.viewers.ISelection; 24 | import org.eclipse.ui.IEditorPart; 25 | import org.eclipse.ui.IFileEditorInput; 26 | import org.eclipse.ui.PlatformUI; 27 | 28 | import cn.ieclipse.smartim.dialogs.ReviewDialog; 29 | 30 | /** 31 | * 类/接口描述 32 | * 33 | * @author Jamling 34 | * @date 2017年8月21日 35 | * 36 | */ 37 | public class ReviewHandler extends AbstractHandler { 38 | 39 | @Override 40 | public Object execute(ExecutionEvent event) throws ExecutionException { 41 | IEditorPart editor = PlatformUI.getWorkbench() 42 | .getActiveWorkbenchWindow().getActivePage().getActiveEditor(); 43 | if (editor.getEditorInput() instanceof IFileEditorInput) { 44 | IFileEditorInput input = (IFileEditorInput) editor.getEditorInput(); 45 | IFile file = input.getFile(); 46 | ISelection sel = editor.getEditorSite().getSelectionProvider() 47 | .getSelection(); 48 | if (sel instanceof TextSelection) { 49 | TextSelection ts = (TextSelection) sel; 50 | ReviewDialog dialog = new ReviewDialog(editor.getSite().getShell()); 51 | dialog.setData(file, ts); 52 | dialog.open(); 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/CompositeFieldEditor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2015 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.preferences; 17 | 18 | import org.eclipse.jface.preference.FieldEditor; 19 | import org.eclipse.swt.SWT; 20 | import org.eclipse.swt.events.DisposeEvent; 21 | import org.eclipse.swt.events.DisposeListener; 22 | import org.eclipse.swt.layout.GridData; 23 | import org.eclipse.swt.widgets.Composite; 24 | 25 | /** 26 | * 类/接口描述 27 | * 28 | * @author Jamling 29 | * @date 2017年6月21日 30 | * 31 | */ 32 | public class CompositeFieldEditor extends FieldEditor { 33 | private Composite fComposite; 34 | 35 | public CompositeFieldEditor(String labelText, Composite parent) { 36 | super(CompositeFieldEditor.class.getName(), labelText, parent); 37 | } 38 | 39 | @Override 40 | protected void adjustForNumColumns(int numColumns) { 41 | GridData gd = (GridData) fComposite.getLayoutData(); 42 | gd.horizontalSpan = numColumns - 1; 43 | // We only grab excess space if we have to 44 | // If another field editor has more columns then 45 | // we assume it is setting the width. 46 | gd.grabExcessHorizontalSpace = gd.horizontalSpan == 1; 47 | } 48 | 49 | @Override 50 | protected void doFillIntoGrid(Composite parent, int numColumns) { 51 | getLabelControl(parent); 52 | 53 | fComposite = getCompositeControl(parent); 54 | GridData gd = new GridData(); 55 | gd.horizontalSpan = numColumns - 1; 56 | gd.horizontalAlignment = GridData.FILL; 57 | gd.grabExcessHorizontalSpace = true; 58 | 59 | fComposite.setLayoutData(gd); 60 | } 61 | 62 | @Override 63 | protected void doLoad() { 64 | // TODO Auto-generated method stub 65 | 66 | } 67 | 68 | @Override 69 | protected void doLoadDefault() { 70 | // TODO Auto-generated method stub 71 | 72 | } 73 | 74 | @Override 75 | protected void doStore() { 76 | // TODO Auto-generated method stub 77 | 78 | } 79 | 80 | @Override 81 | public int getNumberOfControls() { 82 | // TODO Auto-generated method stub 83 | return 0; 84 | } 85 | 86 | public Composite getCompositeControl(Composite parent) { 87 | if (fComposite == null) { 88 | fComposite = new Composite(parent, SWT.NONE); 89 | 90 | fComposite.addDisposeListener(new DisposeListener() { 91 | @Override 92 | public void widgetDisposed(DisposeEvent event) { 93 | fComposite = null; 94 | } 95 | }); 96 | } 97 | else { 98 | checkParent(fComposite, parent); 99 | } 100 | return fComposite; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/HotKeyPreferencePage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.preferences; 17 | 18 | import org.eclipse.jface.preference.FieldEditorPreferencePage; 19 | import org.eclipse.ui.IWorkbench; 20 | import org.eclipse.ui.IWorkbenchPreferencePage; 21 | 22 | import cn.ieclipse.smartim.IMPlugin; 23 | 24 | public class HotKeyPreferencePage extends FieldEditorPreferencePage 25 | implements IWorkbenchPreferencePage { 26 | 27 | public static final String KEY_SEND = IMPlugin.PLUGIN_ID + ".key.send"; //$NON-NLS-1$ 28 | public static final String KEY_INPUT = IMPlugin.PLUGIN_ID + ".key.input"; //$NON-NLS-1$ 29 | public static final String KEY_NEXT = IMPlugin.PLUGIN_ID + ".key.next"; //$NON-NLS-1$ 30 | public static final String KEY_PREV = IMPlugin.PLUGIN_ID + ".key.prev"; //$NON-NLS-1$ 31 | public static final String KEY_INPUT_ESC = IMPlugin.PLUGIN_ID 32 | + ".key.input.esc"; //$NON-NLS-1$ 33 | public static final String KEY_HIDE = IMPlugin.PLUGIN_ID + ".key.hide"; //$NON-NLS-1$ 34 | public static final String KEY_HIDE_CLOSE = IMPlugin.PLUGIN_ID 35 | + ".key.hide_close"; //$NON-NLS-1$ 36 | 37 | public HotKeyPreferencePage() { 38 | super(GRID); 39 | setPreferenceStore(IMPlugin.getDefault().getPreferenceStore()); 40 | setDescription(Messages.HotKeyPreferencePage_desc); 41 | } 42 | 43 | /** 44 | * Creates the field editors. Field editors are abstractions of the common 45 | * GUI blocks needed to manipulate various types of preferences. Each field 46 | * editor knows how to save and restore itself. 47 | */ 48 | public void createFieldEditors() { 49 | HotKeyFieldEditor send = new HotKeyFieldEditor(KEY_SEND, 50 | Messages.HotKeyPreferencePage_send, getFieldEditorParent()); 51 | addField(send); 52 | 53 | // addField(new HotKeyFieldEditor(KEY_INPUT, 54 | // Messages.HotKeyPreferencePage_input, getFieldEditorParent())); 55 | // addField(new HotKeyFieldEditor(KEY_INPUT_ESC, 56 | // Messages.HotKeyPreferencePage_hide_input, 57 | // getFieldEditorParent())); 58 | // addField(new HotKeyFieldEditor(KEY_NEXT, 59 | // Messages.HotKeyPreferencePage_next_chat, 60 | // getFieldEditorParent())); 61 | // addField(new HotKeyFieldEditor(KEY_PREV, 62 | // Messages.HotKeyPreferencePage_prev_chat, 63 | // getFieldEditorParent())); 64 | addField(new HotKeyFieldEditor(KEY_HIDE, 65 | Messages.HotKeyPreferencePage_hide_chat, 66 | getFieldEditorParent())); 67 | addField(new HotKeyFieldEditor(KEY_HIDE_CLOSE, 68 | Messages.HotKeyPreferencePage_close_chat, 69 | getFieldEditorParent())); 70 | } 71 | 72 | @Override 73 | public void init(IWorkbench workbench) { 74 | } 75 | } -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/Messages.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.preferences; 2 | 3 | import org.eclipse.osgi.util.NLS; 4 | 5 | public class Messages extends NLS { 6 | private static final String BUNDLE_NAME = "cn.ieclipse.smartim.preferences.messages"; //$NON-NLS-1$ 7 | public static String HotKeyPreferencePage_close_chat; 8 | public static String HotKeyPreferencePage_desc; 9 | public static String HotKeyPreferencePage_hide_chat; 10 | public static String HotKeyPreferencePage_hide_input; 11 | public static String HotKeyPreferencePage_input; 12 | public static String HotKeyPreferencePage_next_chat; 13 | public static String HotKeyPreferencePage_prev_chat; 14 | public static String HotKeyPreferencePage_send; 15 | public static String PreferenceInitializer_robot_group_welcome; 16 | public static String PreferenceInitializer_robot_name; 17 | public static String RobotPreferencePage_desc; 18 | public static String RobotPreferencePage_enable; 19 | public static String RobotPreferencePage_member_welcome; 20 | public static String RobotPreferencePage_name; 21 | public static String RobotPreferencePage_reply_friend; 22 | public static String RobotPreferencePage_reply_member; 23 | public static String RobotPreferencePage_robot_empty; 24 | public static String RobotPreferencePage_turing_key; 25 | public static String SettingsPerferencePage_desc; 26 | public static String SettingsPerferencePage_hide_my_input; 27 | public static String SettingsPerferencePage_log_history; 28 | public static String SettingsPerferencePage_notify_dismiss; 29 | public static String SettingsPerferencePage_notify_enable; 30 | public static String SettingsPerferencePage_notify_friend; 31 | public static String SettingsPerferencePage_notify_group; 32 | public static String SettingsPerferencePage_notify_unknown; 33 | public static String SettingsPerferencePage_notify_unread; 34 | public static String SmartQQPreferencePage_desc; 35 | public static String SmartQQPreferencePage_github; 36 | 37 | static { 38 | // initialize resource bundle 39 | NLS.initializeMessages(BUNDLE_NAME, Messages.class); 40 | } 41 | 42 | private Messages() { 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/PreferenceInitializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.preferences; 17 | 18 | import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; 19 | import org.eclipse.jface.preference.IPreferenceStore; 20 | 21 | import cn.ieclipse.smartim.IMPlugin; 22 | 23 | /** 24 | * Class used to initialize default preference values. 25 | */ 26 | public class PreferenceInitializer extends AbstractPreferenceInitializer { 27 | 28 | /* 29 | * (non-Javadoc) 30 | * 31 | * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer# 32 | * initializeDefaultPreferences() 33 | */ 34 | public void initializeDefaultPreferences() { 35 | IPreferenceStore store = IMPlugin.getDefault().getPreferenceStore(); 36 | 37 | store.setDefault(HotKeyPreferencePage.KEY_SEND, "CR"); //$NON-NLS-1$ 38 | store.setDefault(HotKeyPreferencePage.KEY_INPUT, "CR"); //$NON-NLS-1$ 39 | store.setDefault(HotKeyPreferencePage.KEY_INPUT_ESC, "ESC"); //$NON-NLS-1$ 40 | store.setDefault(HotKeyPreferencePage.KEY_NEXT, "ARROW_RIGHT"); //$NON-NLS-1$ 41 | store.setDefault(HotKeyPreferencePage.KEY_PREV, "ARROW_LEFT"); //$NON-NLS-1$ 42 | store.setDefault(HotKeyPreferencePage.KEY_HIDE, "Alt + H"); //$NON-NLS-1$ 43 | store.setDefault(HotKeyPreferencePage.KEY_HIDE_CLOSE, "Alt + TabComposite"); //$NON-NLS-1$ 44 | 45 | store.setDefault(RobotPreferencePage.ROBOT_ENABLE, false); 46 | store.setDefault(RobotPreferencePage.ROBOT_NAME, 47 | Messages.PreferenceInitializer_robot_name); 48 | store.setDefault(RobotPreferencePage.TURING_API, 49 | "http://www.tuling123.com/openapi/api"); //$NON-NLS-1$ 50 | store.setDefault(RobotPreferencePage.TURING_KEY, ""); //$NON-NLS-1$ 51 | store.setDefault(RobotPreferencePage.GROUP_WELCOME, 52 | Messages.PreferenceInitializer_robot_group_welcome); 53 | store.setDefault(RobotPreferencePage.GROUP_REPLY_ANY, false); 54 | store.setDefault(RobotPreferencePage.FRIEND_REPLY_ANY, false); 55 | store.setDefault(RobotPreferencePage.ROBOT_EMPTY, ""); 56 | 57 | store.setDefault(QiniuPerferencePage.ENABLE, false); 58 | store.setDefault(QiniuPerferencePage.TS, false); 59 | store.setDefault(QiniuPerferencePage.AK, ""); 60 | store.setDefault(QiniuPerferencePage.SK, ""); 61 | store.setDefault(QiniuPerferencePage.ZONE, "autoZone"); 62 | store.setDefault(QiniuPerferencePage.BUCKET, ""); 63 | store.setDefault(QiniuPerferencePage.DOMAIN, ""); 64 | 65 | store.setDefault(SettingsPerferencePage.NOTIFY_ENABLE, true); 66 | store.setDefault(SettingsPerferencePage.NOTIFY_GROUP, false); 67 | store.setDefault(SettingsPerferencePage.NOTIFY_FRIEND, true); 68 | store.setDefault(SettingsPerferencePage.NOTIFY_DISMISS, 5); 69 | store.setDefault(SettingsPerferencePage.NOTIFY_UNREAD, true); 70 | store.setDefault(SettingsPerferencePage.NOTIFY_UNKNOWN, false); 71 | store.setDefault(SettingsPerferencePage.HIDE_MY_INPUT, true); 72 | store.setDefault(SettingsPerferencePage.LOG_HISTORY, true); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/QiniuPerferencePage.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.preferences; 2 | 3 | import org.eclipse.jface.preference.BooleanFieldEditor; 4 | import org.eclipse.jface.preference.ComboFieldEditor; 5 | import org.eclipse.jface.preference.FieldEditorPreferencePage; 6 | import org.eclipse.jface.preference.StringFieldEditor; 7 | import org.eclipse.ui.IWorkbench; 8 | import org.eclipse.ui.IWorkbenchPreferencePage; 9 | 10 | import cn.ieclipse.smartim.IMPlugin; 11 | 12 | public class QiniuPerferencePage extends FieldEditorPreferencePage 13 | implements IWorkbenchPreferencePage { 14 | 15 | public static final String AK = IMPlugin.PLUGIN_ID + ".qn.accessKey"; 16 | public static final String SK = IMPlugin.PLUGIN_ID + ".qn.setretKey"; 17 | public static final String BUCKET = IMPlugin.PLUGIN_ID + ".qn.bucket"; 18 | public static final String ZONE = IMPlugin.PLUGIN_ID + ".qn.zone"; 19 | public static final String DOMAIN = IMPlugin.PLUGIN_ID + ".qn.domain"; 20 | public static final String TS = IMPlugin.PLUGIN_ID + ".qn.ts"; 21 | public static final String ENABLE = IMPlugin.PLUGIN_ID + ".qn.enable"; 22 | 23 | public static final String[][] ZONE_VALUE = { { "自动", "autoZone" }, 24 | { "华东", "huadong" }, { "华北", "huabei" }, { "华南", "huanan" }, 25 | { "北美", "beimei" } }; 26 | 27 | /** 28 | * Create the preference page. 29 | */ 30 | public QiniuPerferencePage() { 31 | super(GRID); 32 | setPreferenceStore(IMPlugin.getDefault().getPreferenceStore()); 33 | setDescription("SmartQQ文件传输详情请参考http://api.ieclipse.cn/smartqq\r\n如果您未设置七牛云储存,发送的文件将上传到本人私有储存空间(temp.ieclipse.cn,文件大小有限制而且非永久保存),建议您注册七牛云来实现文件传输\r\n注:如果使用您自己的七牛云,带*的accessKey和secretKey必填,否则不生效哦"); 34 | } 35 | 36 | /** 37 | * Create contents of the preference page. 38 | */ 39 | @Override 40 | protected void createFieldEditors() { 41 | // Create the field editors 42 | addField(new BooleanFieldEditor(ENABLE, "启用七牛云", 43 | getFieldEditorParent())); 44 | ComboFieldEditor zone = new ComboFieldEditor(ZONE, "机房", ZONE_VALUE, 45 | getFieldEditorParent()); 46 | addField(zone); 47 | addField(new StringFieldEditor(AK, "AccessKey *", 48 | getFieldEditorParent())); 49 | addField(new StringFieldEditor(SK, "SecretKey *", 50 | getFieldEditorParent())); 51 | addField(new StringFieldEditor(BUCKET, "存储空间", getFieldEditorParent())); 52 | addField(new StringFieldEditor(DOMAIN, "空间域名", getFieldEditorParent())); 53 | addField(new BooleanFieldEditor(TS, "给上传的文件添加时间戳(下载时强制更新缓存)", 54 | getFieldEditorParent())); 55 | } 56 | 57 | /** 58 | * Initialize the preference page. 59 | */ 60 | public void init(IWorkbench workbench) { 61 | // Initialize the preference page 62 | 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/RobotPreferencePage.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.preferences; 2 | 3 | import org.eclipse.jface.preference.BooleanFieldEditor; 4 | import org.eclipse.jface.preference.FieldEditorPreferencePage; 5 | import org.eclipse.jface.preference.StringFieldEditor; 6 | import org.eclipse.ui.IWorkbench; 7 | import org.eclipse.ui.IWorkbenchPreferencePage; 8 | 9 | import cn.ieclipse.smartim.IMPlugin; 10 | 11 | public class RobotPreferencePage extends FieldEditorPreferencePage 12 | implements IWorkbenchPreferencePage { 13 | 14 | public static final String ROBOT_ENABLE = IMPlugin.PLUGIN_ID 15 | + ".robot.enable"; //$NON-NLS-1$ 16 | 17 | public static final String ROBOT_NAME = IMPlugin.PLUGIN_ID + ".robot.name"; //$NON-NLS-1$ 18 | public static final String ROBOT_DEPLAY = IMPlugin.PLUGIN_ID 19 | + ".robot.deplay"; //$NON-NLS-1$ 20 | public static final String TURING_KEY = IMPlugin.PLUGIN_ID + ".turing.key"; //$NON-NLS-1$ 21 | public static final String TURING_API = IMPlugin.PLUGIN_ID + ".turing.api"; //$NON-NLS-1$ 22 | 23 | public static final String GROUP_WELCOME = IMPlugin.PLUGIN_ID 24 | + ".group.welcome"; //$NON-NLS-1$ 25 | 26 | public static final String GROUP_REPLY_ANY = IMPlugin.PLUGIN_ID 27 | + ".group.reply.any"; //$NON-NLS-1$ 28 | 29 | public static final String FRIEND_REPLY_ANY = IMPlugin.PLUGIN_ID 30 | + ".friend.reply.any"; //$NON-NLS-1$ 31 | 32 | public static final String ROBOT_EMPTY = IMPlugin.PLUGIN_ID 33 | + ".robot.empty"; //$NON-NLS-1$ 34 | 35 | public RobotPreferencePage() { 36 | super(GRID); 37 | setPreferenceStore(IMPlugin.getDefault().getPreferenceStore()); 38 | setDescription( 39 | Messages.RobotPreferencePage_desc); 40 | } 41 | 42 | @Override 43 | protected void createFieldEditors() { 44 | addField(new BooleanFieldEditor(ROBOT_ENABLE, Messages.RobotPreferencePage_enable, 45 | getFieldEditorParent())); 46 | addField(new StringFieldEditor(ROBOT_NAME, Messages.RobotPreferencePage_name, 47 | getFieldEditorParent())); 48 | addField(new StringFieldEditor(TURING_KEY, Messages.RobotPreferencePage_turing_key, 49 | getFieldEditorParent())); 50 | addField(new StringFieldEditor(GROUP_WELCOME, Messages.RobotPreferencePage_member_welcome, 51 | getFieldEditorParent())); 52 | addField(new BooleanFieldEditor(GROUP_REPLY_ANY, 53 | Messages.RobotPreferencePage_reply_member, 54 | getFieldEditorParent())); 55 | addField(new BooleanFieldEditor(FRIEND_REPLY_ANY, Messages.RobotPreferencePage_reply_friend, 56 | getFieldEditorParent())); 57 | addField(new StringFieldEditor(ROBOT_EMPTY, Messages.RobotPreferencePage_robot_empty, 58 | getFieldEditorParent())); 59 | } 60 | 61 | @Override 62 | public void init(IWorkbench workbench) { 63 | // TODO Auto-generated method stub 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/SettingsPerferencePage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.preferences; 17 | 18 | import org.eclipse.jface.preference.BooleanFieldEditor; 19 | import org.eclipse.jface.preference.FieldEditorPreferencePage; 20 | import org.eclipse.jface.preference.IntegerFieldEditor; 21 | import org.eclipse.ui.IWorkbench; 22 | import org.eclipse.ui.IWorkbenchPreferencePage; 23 | 24 | import cn.ieclipse.smartim.IMPlugin; 25 | 26 | /** 27 | * 类/接口描述 28 | * 29 | * @author Jamling 30 | * @date 2017年10月25日 31 | * 32 | */ 33 | public class SettingsPerferencePage extends FieldEditorPreferencePage 34 | implements IWorkbenchPreferencePage { 35 | 36 | public static final String NOTIFY_ENABLE = IMPlugin.PLUGIN_ID 37 | + ".notify.enable"; //$NON-NLS-1$ 38 | 39 | public static final String NOTIFY_DISMISS = IMPlugin.PLUGIN_ID 40 | + ".notify.dismiss"; //$NON-NLS-1$ 41 | 42 | public static final String NOTIFY_GROUP = IMPlugin.PLUGIN_ID 43 | + ".notify.group"; //$NON-NLS-1$ 44 | 45 | public static final String NOTIFY_FRIEND = IMPlugin.PLUGIN_ID 46 | + ".notify.friend"; //$NON-NLS-1$ 47 | 48 | public static final String NOTIFY_UNKNOWN = IMPlugin.PLUGIN_ID 49 | + ".notify.unknown"; //$NON-NLS-1$ 50 | 51 | public static final String NOTIFY_UNREAD = IMPlugin.PLUGIN_ID 52 | + ".notify.unread"; //$NON-NLS-1$ 53 | 54 | public static final String HIDE_MY_INPUT = IMPlugin.PLUGIN_ID 55 | + ".hide.myinput"; //$NON-NLS-1$ 56 | 57 | public static final String LOG_HISTORY = IMPlugin.PLUGIN_ID 58 | + ".log.history"; //$NON-NLS-1$ 59 | 60 | public SettingsPerferencePage() { 61 | super(FLAT); 62 | setPreferenceStore(IMPlugin.getDefault().getPreferenceStore()); 63 | setDescription(Messages.SettingsPerferencePage_desc); 64 | } 65 | 66 | @Override 67 | protected void createFieldEditors() { 68 | addField(new BooleanFieldEditor(NOTIFY_ENABLE, 69 | Messages.SettingsPerferencePage_notify_enable, 70 | getFieldEditorParent())); 71 | addField(new BooleanFieldEditor(NOTIFY_GROUP, 72 | Messages.SettingsPerferencePage_notify_group, 73 | getFieldEditorParent())); 74 | addField(new BooleanFieldEditor(NOTIFY_FRIEND, 75 | Messages.SettingsPerferencePage_notify_friend, 76 | getFieldEditorParent())); 77 | addField(new BooleanFieldEditor(NOTIFY_UNKNOWN, 78 | Messages.SettingsPerferencePage_notify_unknown, 79 | getFieldEditorParent())); 80 | addField(new IntegerFieldEditor(NOTIFY_DISMISS, 81 | Messages.SettingsPerferencePage_notify_dismiss, 82 | getFieldEditorParent())); 83 | addField(new BooleanFieldEditor(NOTIFY_UNREAD, 84 | Messages.SettingsPerferencePage_notify_unread, 85 | getFieldEditorParent())); 86 | addField(new BooleanFieldEditor(HIDE_MY_INPUT, 87 | Messages.SettingsPerferencePage_hide_my_input, 88 | getFieldEditorParent())); 89 | addField(new BooleanFieldEditor(LOG_HISTORY, 90 | Messages.SettingsPerferencePage_log_history, 91 | getFieldEditorParent())); 92 | } 93 | 94 | @Override 95 | public void init(IWorkbench workbench) { 96 | // TODO Auto-generated method stub 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/SmartQQPreferencePage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2015 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartim.preferences; 17 | 18 | import java.net.URL; 19 | 20 | import org.eclipse.core.runtime.Platform; 21 | import org.eclipse.jface.preference.PreferencePage; 22 | import org.eclipse.swt.SWT; 23 | import org.eclipse.swt.events.SelectionAdapter; 24 | import org.eclipse.swt.events.SelectionEvent; 25 | import org.eclipse.swt.layout.GridLayout; 26 | import org.eclipse.swt.widgets.Composite; 27 | import org.eclipse.swt.widgets.Control; 28 | import org.eclipse.swt.widgets.Label; 29 | import org.eclipse.swt.widgets.Link; 30 | import org.eclipse.swt.widgets.Text; 31 | import org.eclipse.ui.IWorkbench; 32 | import org.eclipse.ui.IWorkbenchPreferencePage; 33 | import org.eclipse.ui.PartInitException; 34 | import org.eclipse.ui.PlatformUI; 35 | import org.eclipse.ui.browser.IWebBrowser; 36 | import org.eclipse.ui.browser.IWorkbenchBrowserSupport; 37 | import org.osgi.framework.Bundle; 38 | 39 | import cn.ieclipse.smartim.IMPlugin; 40 | 41 | /** 42 | * 类/接口描述 43 | * 44 | * @author Jamling 45 | * @date 2017年6月22日 46 | * 47 | */ 48 | public class SmartQQPreferencePage extends PreferencePage 49 | implements IWorkbenchPreferencePage { 50 | 51 | public SmartQQPreferencePage() { 52 | setPreferenceStore(IMPlugin.getDefault().getPreferenceStore()); 53 | setDescription(Messages.SmartQQPreferencePage_desc); 54 | } 55 | 56 | @Override 57 | public void init(IWorkbench workbench) { 58 | // TODO Auto-generated method stub 59 | 60 | } 61 | 62 | @Override 63 | protected Control createContents(Composite parent) { 64 | Composite comp = new Composite(parent, SWT.NONE); 65 | comp.setLayout(new GridLayout(1, false)); 66 | Label lbl = new Label(comp, SWT.BOLD); 67 | lbl.setText("Installation"); //$NON-NLS-1$ 68 | 69 | Text text = new Text(comp, SWT.WRAP | SWT.READ_ONLY); 70 | text.setText(getBundlesInfo()); 71 | 72 | Link l = new Link(comp, SWT.ITALIC); 73 | l.setText(Messages.SmartQQPreferencePage_github); 74 | l.addSelectionListener(new SelectionAdapter() { 75 | @Override 76 | public void widgetSelected(SelectionEvent e) { 77 | String url = e.text; 78 | if (url.indexOf("://") < 0) { //$NON-NLS-1$ 79 | url = "http://" + url; //$NON-NLS-1$ 80 | } 81 | openBrowser(url); 82 | } 83 | 84 | private void openBrowser(String url) { 85 | IWorkbenchBrowserSupport support = PlatformUI.getWorkbench() 86 | .getBrowserSupport(); 87 | IWebBrowser browser; 88 | try { 89 | browser = support.getExternalBrowser(); 90 | browser.openURL(new URL(url)); 91 | } catch (PartInitException e) { 92 | // TODO Auto-generated catch block 93 | e.printStackTrace(); 94 | } catch (Exception e) { 95 | // TODO: handle exception 96 | } 97 | } 98 | }); 99 | return comp; 100 | } 101 | 102 | private static String getBundlesInfo() { 103 | StringBuilder sb = new StringBuilder(); 104 | Bundle bundle = Platform.getProduct().getDefiningBundle(); 105 | sb.append("Platform:\n\u25cf "); //$NON-NLS-1$ 106 | sb.append(getBundleInfo(bundle)); 107 | bundle = Platform.getBundle(IMPlugin.PLUGIN_ID); 108 | sb.append("\nHost plugin:\n\u25cf "); //$NON-NLS-1$ 109 | sb.append(getBundleInfo(bundle)); 110 | return sb.toString(); 111 | } 112 | 113 | private static String getBundleInfo(Bundle bundle) { 114 | String name = bundle.getHeaders().get("Bundle-Name"); //$NON-NLS-1$ 115 | String ver = bundle.getVersion().toString(); 116 | // UNINSTALLED,INSTALLED, RESOLVED, STARTING, STOPPING, ACTIVE. 117 | String stStr = "unknown"; //$NON-NLS-1$ 118 | int st = bundle.getState(); 119 | if (st == Bundle.UNINSTALLED) { 120 | stStr = "uninstalled"; //$NON-NLS-1$ 121 | } 122 | else if (st == Bundle.INSTALLED) { 123 | stStr = "installed"; //$NON-NLS-1$ 124 | } 125 | else if (st == Bundle.RESOLVED) { 126 | stStr = "resolved"; //$NON-NLS-1$ 127 | } 128 | else if (st == Bundle.STARTING) { 129 | stStr = "starting"; //$NON-NLS-1$ 130 | } 131 | else if (st == Bundle.STOPPING) { 132 | stStr = "stopping"; //$NON-NLS-1$ 133 | } 134 | else if (st == Bundle.ACTIVE) { 135 | stStr = "active"; //$NON-NLS-1$ 136 | } 137 | return String.format("%s(%s):%s", name, ver, stStr); //$NON-NLS-1$ 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/messages.properties: -------------------------------------------------------------------------------- 1 | HotKeyPreferencePage_close_chat=Close chat 2 | HotKeyPreferencePage_desc=Hot key settings, the default mey conflict with Eclipse, please change it. 3 | HotKeyPreferencePage_hide_chat=Hide chat & contacts 4 | HotKeyPreferencePage_hide_input=Hide input 5 | HotKeyPreferencePage_input=Active input 6 | HotKeyPreferencePage_next_chat=Next chat 7 | HotKeyPreferencePage_prev_chat=Previous chat 8 | HotKeyPreferencePage_send=Send message 9 | PreferenceInitializer_robot_group_welcome=Welcom {user} {memo} 10 | PreferenceInitializer_robot_name=[Robot] 11 | RobotPreferencePage_desc=Robot settings, the robot can help you to answer your friend or group member 12 | RobotPreferencePage_enable=Enable the robot 13 | RobotPreferencePage_member_welcome=New member welcome 14 | RobotPreferencePage_name=Robot name 15 | RobotPreferencePage_reply_friend=Reply any friend 16 | RobotPreferencePage_reply_member=Reply any group or discuss member (enable when chat session is open) 17 | RobotPreferencePage_robot_empty=Auto reply for empty 18 | RobotPreferencePage_turing_key=Turing Key 19 | SettingsPerferencePage_desc=Settgins 20 | SettingsPerferencePage_hide_my_input=Hide my input message in group/discuss chat 21 | SettingsPerferencePage_log_history=Save chat log to disk 22 | SettingsPerferencePage_notify_dismiss=Hide notification after (Seconds) 23 | SettingsPerferencePage_notify_enable=Enable message notification 24 | SettingsPerferencePage_notify_friend=Notify when friend message received 25 | SettingsPerferencePage_notify_group=Notify when group message received 26 | SettingsPerferencePage_notify_unknown=Notify when message received from unkown user in group/discuss 27 | SettingsPerferencePage_notify_unread=Update chat list e.g. unread number when message received 28 | SmartQQPreferencePage_desc=SmartIM(SmartQQ) is an anti-boss plugin for developers, it's a simple implements of SmartQQ/Wechat, allow you to chat to your QQ, Wechat friends. 29 | SmartQQPreferencePage_github=Any question and suggestion please visit https\://github.com/Jamling/SmartQQ4Eclipse 30 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/preferences/messages_zh.properties: -------------------------------------------------------------------------------- 1 | HotKeyPreferencePage_close_chat=\u5173\u95ed\u804a\u5929 2 | HotKeyPreferencePage_desc=\u70ed\u952e\u8bbe\u7f6e\u5982\u4e0eEclipse\u51b2\u7a81\uff0c\u8bf7\u81ea\u884c\u4fee\u6539 3 | HotKeyPreferencePage_hide_chat=\u9690\u85cf\u804a\u5929\u9762\u677f 4 | HotKeyPreferencePage_hide_input=\u53d6\u6d88\u8f93\u5165 5 | HotKeyPreferencePage_input=\u6fc0\u6d3b\u8f93\u5165 6 | HotKeyPreferencePage_next_chat=\u5207\u6362\u4e0b\u4e00\u4e2a\u804a\u5929 7 | HotKeyPreferencePage_prev_chat=\u5207\u6362\u4e0a\u4e00\u4e2a\u804a\u5929 8 | HotKeyPreferencePage_send=\u53d1\u9001\u6d88\u606f 9 | PreferenceInitializer_robot_group_welcome=\u6b22\u8fce{user} {memo} 10 | PreferenceInitializer_robot_name=[\u6211\u7684\u5c0f\u79d8] 11 | RobotPreferencePage_desc=\u673a\u5668\u4eba\u8bbe\u7f6e\uff0c\u8ba9\u673a\u5668\u4eba\u4e0e\u60a8\u7684\u597d\u53cb\u6216\u7fa4\u53cb\u4e92\u52a8\uff0c\u652f\u6301@\u56de\u590d\uff0c\u6b22\u8fce\u65b0\u6210\u5458\u52a0\u5165\u7b49\u529f\u80fd 12 | RobotPreferencePage_enable=\u5f00\u542f\u673a\u5668\u4eba 13 | RobotPreferencePage_member_welcome=\u7fa4\u65b0\u6210\u5458\u6b22\u8fce\u8bcd 14 | RobotPreferencePage_name=\u673a\u5668\u4eba\u540d\u5b57 15 | RobotPreferencePage_reply_friend=\u56de\u590d\u597d\u53cb\u4fe1\u606f 16 | RobotPreferencePage_reply_member=\u56de\u590d\u7fa4\u53cb\u4fe1\u606f\uff08\u5f53\u804a\u5929\u4f1a\u8bdd\u6253\u5f00\u65f6\u6709\u6548\uff09 17 | RobotPreferencePage_robot_empty=\u804a\u5929\u81ea\u52a8\u56de\u590d 18 | RobotPreferencePage_turing_key=\u56fe\u7075\u673a\u5668\u4ebaApiKey 19 | SettingsPerferencePage_desc=\u8bbe\u7f6e 20 | SettingsPerferencePage_hide_my_input=\u5728\u7fa4\u804a\u4e2d\u9690\u85cf\u81ea\u5df1\u8f93\u5165\u7684\u5185\u5bb9 21 | SettingsPerferencePage_log_history=\u4fdd\u5b58\u804a\u5929\u8bb0\u5f55 22 | SettingsPerferencePage_notify_dismiss=\u901a\u77e5\u7a97\u53e3\u663e\u793a\u65f6\u95f4\uff08\u5355\u4f4d\uff1a\u79d2\uff09 23 | SettingsPerferencePage_notify_enable=\u5f00\u542f\u6d88\u606f\u901a\u77e5 24 | SettingsPerferencePage_notify_friend=\u63a5\u6536\u597d\u53cb\u6d88\u606f\u65f6\u901a\u77e5 25 | SettingsPerferencePage_notify_group=\u63a5\u6536\u7fa4\u7ec4\u6d88\u606f\u65f6\u901a\u77e5 26 | SettingsPerferencePage_notify_unknown=\u63a5\u6536\u672a\u8bc6\u522b\u7528\u6237\uff08\u5982SmartQQ\u7528\u6237\uff09\u6d88\u606f\u65f6\u901a\u77e5 27 | SettingsPerferencePage_notify_unread=\u5b9e\u65f6\u66f4\u65b0\u804a\u5929\u5217\u8868\uff08\u663e\u793a\u6d88\u606f\u672a\u8bfb\u6570\u7b49\uff09 28 | SmartQQPreferencePage_desc=SmartIM(SmartQQ)\u662f\u4e00\u6b3e\u9632boss\u7684\u5229\u5668\uff0c\u5b83\u53ef\u4ee5\u8ba9\u60a8\u5728eclipse\u4e2d\u4e0e\u60a8\u7684\u670b\u53cb\u804a\u5929\uff0c\u76ee\u524d\u652f\u6301SmartQQ\u548c\u5fae\u4fe1 29 | SmartQQPreferencePage_github=\u5982\u6709\u95ee\u9898\u6216\u5efa\u8bae\uff0c\u8bf7\u8bbf\u95eehttps\://github.com/Jamling/SmartQQ4Eclipse 30 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/views/IMContactContentProvider.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.views; 2 | 3 | import org.eclipse.jface.viewers.IStructuredContentProvider; 4 | import org.eclipse.jface.viewers.ITreeContentProvider; 5 | 6 | public abstract class IMContactContentProvider 7 | implements IStructuredContentProvider, ITreeContentProvider { 8 | protected boolean check = false; 9 | protected IMContactView fView; 10 | 11 | public IMContactContentProvider(IMContactView view, boolean check) { 12 | this.fView = view; 13 | this.check = check; 14 | } 15 | 16 | public IMContactContentProvider(IMContactView view) { 17 | this.fView = view; 18 | } 19 | 20 | public IMContactContentProvider(boolean check) { 21 | this.check = check; 22 | } 23 | } -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/views/IMContactDoubleClicker.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.views; 2 | 3 | import org.eclipse.jface.viewers.DoubleClickEvent; 4 | import org.eclipse.jface.viewers.IDoubleClickListener; 5 | import org.eclipse.jface.viewers.IStructuredSelection; 6 | 7 | import cn.ieclipse.smartim.model.IContact; 8 | 9 | public class IMContactDoubleClicker implements IDoubleClickListener { 10 | 11 | protected IMContactView fView; 12 | 13 | public IMContactDoubleClicker(IMContactView view) { 14 | this.fView = view; 15 | } 16 | 17 | @Override 18 | public void doubleClick(DoubleClickEvent event) { 19 | if (fView.getClient() == null || !fView.getClient().isLogin()) { 20 | return; 21 | } 22 | IStructuredSelection isel = (IStructuredSelection) event.getSelection(); 23 | Object obj = isel.getFirstElement(); 24 | if (obj != null) { 25 | // if (obj instanceof AbstractContact) { 26 | // ((AbstractContact) obj).clearUnRead(); 27 | // } 28 | // fView.doUpdateContacts(0); 29 | click(obj); 30 | } 31 | } 32 | 33 | public void click(Object obj) { 34 | if (obj instanceof IContact) { 35 | fView.openConsole((IContact) obj); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartim/views/IMContactLabelProvider.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.views; 2 | 3 | import org.eclipse.jface.viewers.LabelProvider; 4 | import org.eclipse.swt.SWT; 5 | import org.eclipse.swt.graphics.Image; 6 | import org.eclipse.ui.ISharedImages; 7 | import org.eclipse.ui.PlatformUI; 8 | 9 | import cn.ieclipse.smartim.common.LetterImageFactory; 10 | import cn.ieclipse.smartim.model.IContact; 11 | import cn.ieclipse.smartim.model.VirtualCategory; 12 | import cn.ieclipse.smartim.model.impl.AbstractContact; 13 | 14 | public abstract class IMContactLabelProvider extends LabelProvider { 15 | 16 | protected IMContactView fView; 17 | 18 | public IMContactLabelProvider(IMContactView view) { 19 | this.fView = view; 20 | } 21 | 22 | public String getText(Object obj) { 23 | if (obj instanceof IContact) { 24 | return ((IContact) obj).getName(); 25 | } 26 | else if (obj instanceof VirtualCategory) { 27 | return ((VirtualCategory) obj).name; 28 | } 29 | return null; 30 | } 31 | 32 | public abstract Image getContactImage(Object target); 33 | 34 | public Image getImage(Object obj) { 35 | if (obj instanceof AbstractContact) { 36 | AbstractContact c = (AbstractContact) obj; 37 | if (c.getUnread() > 0) { 38 | // int ch = Math.min(c.getUnread(), 9) + (int) '0'; 39 | int ch = c.getUnread() + (int) '0'; 40 | if (c.getUnread() > 9) { 41 | ch = '?'; 42 | } 43 | return LetterImageFactory.create((char) ch, SWT.COLOR_RED); 44 | } 45 | } 46 | 47 | Image img = getContactImage(obj); 48 | if (img != null) { 49 | return img; 50 | } 51 | 52 | String imageKey = ISharedImages.IMG_OBJ_ELEMENT; 53 | if (obj instanceof VirtualCategory) 54 | imageKey = ISharedImages.IMG_OBJ_FOLDER; 55 | return PlatformUI.getWorkbench().getSharedImages().getImage(imageKey); 56 | } 57 | } -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/QQBroadcastAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartqq; 17 | 18 | import org.eclipse.swt.widgets.Shell; 19 | 20 | import cn.ieclipse.smartim.actions.BroadcastAction; 21 | import cn.ieclipse.smartim.views.IMContactView; 22 | 23 | /** 24 | * 类/接口描述 25 | * 26 | * @author Jamling 27 | * @date 2017年10月19日 28 | * 29 | */ 30 | public class QQBroadcastAction extends BroadcastAction { 31 | private QQContactView contactView; 32 | 33 | public QQBroadcastAction(IMContactView contactView) { 34 | super(contactView); 35 | this.contactView = (QQContactView) contactView; 36 | setText("QQ消息群发"); 37 | } 38 | 39 | @Override 40 | protected void openDialog(Shell shell) { 41 | QQBroadcastDialog dialog = new QQBroadcastDialog(shell, contactView); 42 | dialog.open(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/QQChatConsole.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartqq; 2 | 3 | import java.io.File; 4 | 5 | import org.eclipse.jface.preference.IPreferenceStore; 6 | import org.eclipse.swt.SWT; 7 | 8 | import com.google.gson.JsonObject; 9 | import com.google.gson.JsonParser; 10 | import com.scienjus.smartqq.QNUploader; 11 | import com.scienjus.smartqq.client.SmartQQClient; 12 | import com.scienjus.smartqq.handler.msg.DiscussMessageHandler; 13 | import com.scienjus.smartqq.handler.msg.FriendMessageHandler; 14 | import com.scienjus.smartqq.handler.msg.GroupMessageHandler; 15 | import com.scienjus.smartqq.model.Discuss; 16 | import com.scienjus.smartqq.model.DiscussInfo; 17 | import com.scienjus.smartqq.model.Friend; 18 | import com.scienjus.smartqq.model.Group; 19 | import com.scienjus.smartqq.model.GroupInfo; 20 | import com.scienjus.smartqq.model.QQMessage; 21 | import com.scienjus.smartqq.model.UserInfo; 22 | 23 | import cn.ieclipse.smartim.IMClientFactory; 24 | import cn.ieclipse.smartim.IMPlugin; 25 | import cn.ieclipse.smartim.common.IMUtils; 26 | import cn.ieclipse.smartim.common.LetterImageFactory; 27 | import cn.ieclipse.smartim.console.IMChatConsole; 28 | import cn.ieclipse.smartim.model.IContact; 29 | import cn.ieclipse.smartim.model.impl.AbstractFrom; 30 | import cn.ieclipse.smartim.preferences.QiniuPerferencePage; 31 | import cn.ieclipse.smartim.preferences.SettingsPerferencePage; 32 | import cn.ieclipse.smartim.views.IMContactView; 33 | 34 | public class QQChatConsole extends IMChatConsole { 35 | 36 | public QQChatConsole(IContact target, IMContactView imPanel) { 37 | super(target, imPanel); 38 | char ch = QQUtils.getContactChar(target); 39 | IMG_NORMAL = LetterImageFactory.create(ch, SWT.COLOR_BLACK); 40 | IMG_SELECTED = LetterImageFactory.create(ch, SWT.COLOR_RED); 41 | setImage(IMG_NORMAL); 42 | } 43 | 44 | @Override 45 | public SmartQQClient getClient() { 46 | return (SmartQQClient) IMClientFactory.getInstance().getQQClient(); 47 | } 48 | 49 | @Override 50 | public void loadHistory(String raw) { 51 | if (IMUtils.isMySendMsg(raw)) { 52 | write(raw); 53 | return; 54 | } 55 | JsonObject obj = new JsonParser().parse(raw).getAsJsonObject(); 56 | QQMessage m = null; 57 | if (obj.has("group_code")) { 58 | m = (QQMessage) new GroupMessageHandler().handle(obj); 59 | } 60 | else if (obj.has("did")) { 61 | m = (QQMessage) new DiscussMessageHandler().handle(obj); 62 | } 63 | else { 64 | m = (QQMessage) new FriendMessageHandler().handle(obj); 65 | } 66 | 67 | AbstractFrom from = getClient().parseFrom(m); 68 | String name = from == null ? "未知用户" : from.getName(); 69 | String msg = IMUtils.formatHtmlMsg(m.getTime(), name, m.getContent()); 70 | write(msg); 71 | } 72 | 73 | public void post(final String msg) { 74 | SmartQQClient client = getClient(); 75 | if (this.contact != null) { 76 | QQMessage m = client.createMessage(msg, contact); 77 | client.sendMessage(m, this.contact); 78 | } 79 | } 80 | 81 | private boolean isGroupChat() { 82 | return (contact instanceof Group) || (contact instanceof GroupInfo) 83 | || (contact instanceof Discuss) 84 | || (contact instanceof DiscussInfo); 85 | } 86 | 87 | @Override 88 | public boolean hideMyInput() { 89 | if (contact instanceof Friend) { 90 | return false; 91 | } 92 | boolean hide = IMPlugin.getDefault().getPreferenceStore() 93 | .getBoolean(SettingsPerferencePage.HIDE_MY_INPUT); 94 | return hide; 95 | } 96 | 97 | public void sendFileInternal(final String file) throws Exception { 98 | final File f = new File(file); 99 | if (f.length() > (1 << 18)) { 100 | write(String.format("%s 上传中,请稍候……", f.getName())); 101 | } 102 | QNUploader uploader = IMPlugin.getDefault().getUploader(); 103 | IPreferenceStore store = IMPlugin.getDefault().getPreferenceStore(); 104 | String ak = store.getString(QiniuPerferencePage.AK); 105 | String sk = store.getString(QiniuPerferencePage.SK); 106 | String bucket = store.getString(QiniuPerferencePage.BUCKET); 107 | String domain = store.getString(QiniuPerferencePage.DOMAIN); 108 | String qq = ((UserInfo) getClient().getAccount()).getAccount(); 109 | boolean enable = store.getBoolean(QiniuPerferencePage.ENABLE); 110 | boolean ts = store.getBoolean(QiniuPerferencePage.TS); 111 | if (!enable) { 112 | ak = ""; 113 | sk = ""; 114 | } 115 | QNUploader.UploadInfo info = uploader.upload(qq, f, ak, sk, bucket, null); 116 | String url = info.getUrl(domain, ts); 117 | 118 | String msg = String.format("来自SmartQQ的文件: %s (大小%s), 点击链接%s 查看", 119 | IMUtils.getName(file), IMUtils.formatFileSize(info.fsize), url); 120 | send(msg); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/QQContactView.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartqq; 2 | 3 | import org.eclipse.jface.viewers.TreeViewer; 4 | import org.eclipse.swt.widgets.Composite; 5 | 6 | import com.scienjus.smartqq.client.SmartQQClient; 7 | 8 | import cn.ieclipse.smartim.IMClientFactory; 9 | import cn.ieclipse.smartim.IMPlugin; 10 | import cn.ieclipse.smartim.IMSendCallback; 11 | import cn.ieclipse.smartim.model.IContact; 12 | import cn.ieclipse.smartim.views.IMContactDoubleClicker; 13 | import cn.ieclipse.smartim.views.IMContactView; 14 | 15 | public class QQContactView extends IMContactView { 16 | 17 | /** 18 | * The ID of the view as specified by the extension. 19 | */ 20 | public static final String ID = "cn.ieclipse.smartqq.views.QQContactView"; 21 | 22 | private TreeViewer ftvFriend; 23 | private TreeViewer ftvRecent; 24 | private TreeViewer ftvGroup; 25 | private TreeViewer ftvDiscuss; 26 | 27 | /** 28 | * The constructor. 29 | */ 30 | public QQContactView() { 31 | viewId = ID; 32 | contentProvider = new QQContentProvider(this, false); 33 | labelProvider = new QQLabelProvider(this); 34 | doubleClicker = new IMContactDoubleClicker(this); 35 | 36 | receiveCallback = new QQReceiveCallback(this); 37 | robotCallback = new QQRobotCallback(this); 38 | sendCallback = new IMSendCallback(this); 39 | loadWelcome("qq"); 40 | } 41 | 42 | /** 43 | * This is a callback that will allow us to create the viewer and initialize 44 | * it. 45 | */ 46 | public void createPartControl(Composite parent) { 47 | super.createPartControl(parent); 48 | ftvRecent = createTab("Recents", tabFolder); 49 | ftvFriend = createTab("Friends", tabFolder); 50 | ftvGroup = createTab("Groups", tabFolder); 51 | ftvDiscuss = createTab("Discuss", tabFolder); 52 | tabFolder.setSelection(0); 53 | 54 | initTrees(ftvRecent, ftvFriend, ftvGroup, ftvDiscuss); 55 | } 56 | 57 | protected void doLoadContacts() { 58 | client = getClient(); 59 | if (client.isLogin()) { 60 | try { 61 | client.init(); 62 | notifyLoadContacts(true); 63 | client.setReceiveCallback(receiveCallback); 64 | client.addReceiveCallback(robotCallback); 65 | client.setSendCallback(sendCallback); 66 | client.setModificationCallbacdk( 67 | new QQMidificationCallback(this)); 68 | client.start(); 69 | } catch (Exception e) { 70 | IMPlugin.getDefault().log("SmartQQ初始化失败", e); 71 | } 72 | } 73 | else { 74 | notifyLoadContacts(false); 75 | } 76 | } 77 | 78 | @Override 79 | protected void onLoadContacts(boolean success) { 80 | if (success) { 81 | ftvFriend.setInput("friend"); 82 | ftvGroup.setInput("group"); 83 | ftvDiscuss.setInput("discuss"); 84 | ftvRecent.setInput("recent"); 85 | } 86 | else { 87 | ftvFriend.setInput(null); 88 | ftvGroup.setInput(null); 89 | ftvDiscuss.setInput(null); 90 | ftvRecent.setInput(null); 91 | } 92 | } 93 | 94 | @Override 95 | protected void makeActions() { 96 | super.makeActions(); 97 | broadcast = new QQBroadcastAction(this); 98 | } 99 | 100 | @Override 101 | public SmartQQClient getClient() { 102 | return (SmartQQClient) IMClientFactory.getInstance().getQQClient(); 103 | } 104 | 105 | @Override 106 | protected void doUpdateContacts(int index) { 107 | super.doUpdateContacts(index); 108 | if (index == 0) { 109 | boolean focus = ftvRecent.getTree().isFocusControl(); 110 | if (focus || !updateContactsOnlyFocus) { 111 | ftvRecent.refresh(true); 112 | } 113 | } 114 | } 115 | 116 | @Override 117 | public IMContactView createContactsUI() { 118 | // TODO Auto-generated method stub 119 | return null; 120 | } 121 | 122 | @Override 123 | public cn.ieclipse.smartim.console.IMChatConsole createConsoleUI( 124 | IContact contact) { 125 | return new QQChatConsole(contact, this); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/QQContentProvider.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartqq; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import org.eclipse.jface.viewers.Viewer; 7 | 8 | import com.scienjus.smartqq.client.SmartQQClient; 9 | import com.scienjus.smartqq.model.Category; 10 | import com.scienjus.smartqq.model.Discuss; 11 | import com.scienjus.smartqq.model.Group; 12 | import com.scienjus.smartqq.model.QQContact; 13 | import com.scienjus.smartqq.model.Recent; 14 | 15 | import cn.ieclipse.smartim.model.VirtualCategory; 16 | import cn.ieclipse.smartim.views.IMContactContentProvider; 17 | import cn.ieclipse.smartim.views.IMContactView; 18 | 19 | public class QQContentProvider extends IMContactContentProvider { 20 | 21 | public QQContentProvider(IMContactView view, boolean check) { 22 | super(view, check); 23 | } 24 | 25 | @Override 26 | public void dispose() { 27 | // TODO Auto-generated method stub 28 | 29 | } 30 | 31 | @Override 32 | public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 33 | } 34 | 35 | @Override 36 | public Object[] getChildren(Object parentElement) { 37 | if (parentElement instanceof Category) { 38 | return ((Category) parentElement).getFriends().toArray(); 39 | } 40 | else if (parentElement instanceof VirtualCategory) { 41 | return ((VirtualCategory) parentElement).getChildren(); 42 | } 43 | return null; 44 | } 45 | 46 | @Override 47 | public Object getParent(Object element) { 48 | // TODO Auto-generated method stub 49 | return null; 50 | } 51 | 52 | @Override 53 | public boolean hasChildren(Object element) { 54 | if (element instanceof Category) { 55 | return true; 56 | } 57 | else if (element instanceof VirtualCategory) { 58 | return ((VirtualCategory) element).hasChildren(); 59 | } 60 | return false; 61 | } 62 | 63 | @Override 64 | public Object[] getElements(Object inputElement) { 65 | SmartQQClient client = (SmartQQClient) fView.getClient(); 66 | if ("recent".equals(inputElement)) { 67 | // List recents = client.getRecentList(); 68 | // return recents == null ? null : recents.toArray(); 69 | return getRecentTargets(client).toArray(); 70 | } 71 | else if ("group".equals(inputElement)) { 72 | List groups = client.getGroupList(); 73 | if (check) { 74 | return new Object[] { new VirtualCategory<>("Group", groups) }; 75 | } 76 | return groups == null ? null : groups.toArray(); 77 | } 78 | else if ("discuss".equals(inputElement)) { 79 | List groups = client.getDiscussList(); 80 | if (check) { 81 | return new Object[] { 82 | new VirtualCategory<>("Discuss", groups) }; 83 | } 84 | return groups == null ? null : groups.toArray(); 85 | } 86 | else if ("friend".equals(inputElement)) { 87 | List categories = client.getFriendListWithCategory(); 88 | return categories == null ? null : categories.toArray(); 89 | } 90 | else { 91 | return null; 92 | } 93 | } 94 | 95 | public List getRecentTargets(SmartQQClient client) { 96 | List recents = client.getRecentList(); 97 | List list = client.getRecents2(); 98 | synchronized (this) { 99 | Collections.sort(list); 100 | } 101 | return list; 102 | } 103 | } -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/QQLabelProvider.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartqq; 2 | 3 | import org.eclipse.swt.SWT; 4 | import org.eclipse.swt.graphics.Image; 5 | import org.eclipse.ui.ISharedImages; 6 | 7 | import com.scienjus.smartqq.client.SmartQQClient; 8 | import com.scienjus.smartqq.model.Category; 9 | import com.scienjus.smartqq.model.Recent; 10 | 11 | import cn.ieclipse.smartim.IMPlugin; 12 | import cn.ieclipse.smartim.common.LetterImageFactory; 13 | import cn.ieclipse.smartim.model.IContact; 14 | import cn.ieclipse.smartim.model.VirtualCategory; 15 | import cn.ieclipse.smartim.views.IMContactLabelProvider; 16 | import cn.ieclipse.smartim.views.IMContactView; 17 | 18 | public class QQLabelProvider extends IMContactLabelProvider { 19 | 20 | public QQLabelProvider(IMContactView view) { 21 | super(view); 22 | } 23 | 24 | public String getText(Object obj) { 25 | SmartQQClient client = (SmartQQClient) fView.getClient(); 26 | if (obj instanceof Category) { 27 | return ((Category) obj).getName(); 28 | } 29 | else if (obj instanceof VirtualCategory) { 30 | return ((VirtualCategory) obj).name; 31 | } 32 | else if (obj instanceof Recent) { 33 | Recent r = (Recent) obj; 34 | Object target = client.getRecentTarget(r); 35 | if (target != null) { 36 | return super.getText(target); 37 | } 38 | else { 39 | return null; 40 | } 41 | } 42 | return super.getText(obj); 43 | } 44 | 45 | @Override 46 | public Image getContactImage(Object obj) { 47 | if (obj instanceof Recent) { 48 | int type = ((Recent) obj).getType(); 49 | if (type == 0) { 50 | return LetterImageFactory.create('F', SWT.COLOR_DARK_GREEN); 51 | } 52 | else if (type == 1) { 53 | return LetterImageFactory.create('G', SWT.COLOR_DARK_BLUE); 54 | } 55 | else if (type == 2) { 56 | return LetterImageFactory.create('D', SWT.COLOR_DARK_CYAN); 57 | } 58 | } 59 | else if (obj instanceof Category) { 60 | return IMPlugin.getSharedImage(ISharedImages.IMG_OBJ_FOLDER) 61 | .createImage(); 62 | } 63 | if (obj instanceof IContact) { 64 | IContact target = (IContact) obj; 65 | char ch = QQUtils.getContactChar(target); 66 | if (ch == 'F') { 67 | return LetterImageFactory.create(ch, SWT.COLOR_DARK_GREEN); 68 | } 69 | else if (ch == 'G') { 70 | return LetterImageFactory.create(ch, SWT.COLOR_DARK_BLUE); 71 | } 72 | else if (ch == 'D') { 73 | return LetterImageFactory.create(ch, SWT.COLOR_DARK_CYAN); 74 | } 75 | } 76 | return null; 77 | } 78 | } -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/QQMidificationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartqq; 17 | 18 | import com.scienjus.smartqq.model.QQContact; 19 | import com.scienjus.smartqq.model.Recent; 20 | 21 | import cn.ieclipse.smartim.callback.ModificationCallback; 22 | import cn.ieclipse.smartim.model.IContact; 23 | 24 | /** 25 | * 类/接口描述 26 | * 27 | * @author Jamling 28 | * @date 2017年10月26日 29 | * 30 | */ 31 | public class QQMidificationCallback implements ModificationCallback { 32 | QQContactView fContactView; 33 | 34 | public QQMidificationCallback(QQContactView view) { 35 | this.fContactView = view; 36 | } 37 | 38 | @Override 39 | public void onContactChanged(IContact contact) { 40 | if (contact instanceof Recent || contact instanceof QQContact) { 41 | fContactView.notifyUpdateContacts(0, true); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/QQReceiveCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartqq; 17 | 18 | import com.scienjus.smartqq.model.DiscussFrom; 19 | import com.scienjus.smartqq.model.FriendFrom; 20 | import com.scienjus.smartqq.model.GroupFrom; 21 | import com.scienjus.smartqq.model.QQMessage; 22 | 23 | import cn.ieclipse.smartim.IMPlugin; 24 | import cn.ieclipse.smartim.IMReceiveCallback; 25 | import cn.ieclipse.smartim.common.IMUtils; 26 | import cn.ieclipse.smartim.model.IContact; 27 | import cn.ieclipse.smartim.model.impl.AbstractContact; 28 | import cn.ieclipse.smartim.model.impl.AbstractFrom; 29 | import cn.ieclipse.smartim.model.impl.AbstractMessage; 30 | import cn.ieclipse.smartim.preferences.SettingsPerferencePage; 31 | 32 | /** 33 | * 类/接口描述 34 | * 35 | * @author Jamling 36 | * @date 2017年10月16日 37 | * 38 | */ 39 | public class QQReceiveCallback extends IMReceiveCallback { 40 | private QQContactView fContactView; 41 | 42 | public QQReceiveCallback(QQContactView fContactView) { 43 | super(fContactView); 44 | this.fContactView = fContactView; 45 | } 46 | 47 | @Override 48 | public void onReceiveMessage(AbstractMessage message, AbstractFrom from) { 49 | if (from != null && from.getContact() != null) { 50 | boolean unknown = false; 51 | boolean notify = IMPlugin.getDefault().getPreferenceStore() 52 | .getBoolean(SettingsPerferencePage.NOTIFY_FRIEND); 53 | String uin = from.getContact().getUin(); 54 | IContact qqContact = null; 55 | if (from instanceof GroupFrom) { 56 | GroupFrom gf = (GroupFrom) from; 57 | unknown = (gf.getGroupUser() == null 58 | || gf.getGroupUser().isUnknown()); 59 | uin = gf.getGroup().getUin(); 60 | notify = IMPlugin.getDefault().getPreferenceStore() 61 | .getBoolean(SettingsPerferencePage.NOTIFY_GROUP); 62 | qqContact = fContactView.getClient() 63 | .getGroup(gf.getGroup().getId()); 64 | } 65 | else if (from instanceof DiscussFrom) { 66 | DiscussFrom gf = (DiscussFrom) from; 67 | unknown = (gf.getDiscussUser() == null 68 | || gf.getDiscussUser().isUnknown()); 69 | uin = gf.getDiscuss().getUin(); 70 | notify = IMPlugin.getDefault().getPreferenceStore() 71 | .getBoolean(SettingsPerferencePage.NOTIFY_GROUP); 72 | qqContact = fContactView.getClient() 73 | .getDiscuss(gf.getDiscuss().getId()); 74 | } 75 | else { 76 | qqContact = from.getContact(); 77 | } 78 | handle(unknown, notify, message, from, (AbstractContact) qqContact); 79 | } 80 | } 81 | 82 | @Override 83 | protected String getMsgContent(AbstractMessage message, AbstractFrom from) { 84 | String name = from.getName(); 85 | String msg = null; 86 | if (message instanceof QQMessage) { 87 | QQMessage m = (QQMessage) message; 88 | msg = IMUtils.formatHtmlMsg(m.getTime(), name, m.getContent()); 89 | msg = QQUtils.decodeEmoji(msg); 90 | } 91 | return msg; 92 | } 93 | 94 | @Override 95 | protected String getNotifyContent(AbstractMessage message, 96 | AbstractFrom from) { 97 | CharSequence content = (from instanceof FriendFrom) ? message.getText() 98 | : from.getName() + ":" + message.getText(); 99 | return content.toString(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/QQUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.smartqq; 17 | 18 | import com.scienjus.smartqq.model.Discuss; 19 | import com.scienjus.smartqq.model.DiscussInfo; 20 | import com.scienjus.smartqq.model.Group; 21 | import com.scienjus.smartqq.model.GroupInfo; 22 | 23 | import cn.ieclipse.smartim.common.IMUtils; 24 | import cn.ieclipse.smartim.model.IContact; 25 | 26 | /** 27 | * 类/接口描述 28 | * 29 | * @author Jamling 30 | * @date 2018年2月12日 31 | * 32 | */ 33 | public class QQUtils { 34 | public static char getContactChar(IContact target) { 35 | char ch = 'F'; 36 | if (target instanceof Group || target instanceof GroupInfo) { 37 | ch = 'G'; 38 | } 39 | else if (target instanceof Discuss || target instanceof DiscussInfo) { 40 | ch = 'D'; 41 | } 42 | return ch; 43 | } 44 | 45 | public static String decodeEmoji(String src) { 46 | return src; 47 | // String regex = "\\[\"face\",([1-9][0-9])\\]"; 48 | // if (src != null) { 49 | // String n = src.replaceAll(regex, 50 | // ""); 51 | // return n; 52 | // } 53 | // else { 54 | // return ""; 55 | // } 56 | } 57 | 58 | public static void main(String[] args) { 59 | String src = IMUtils.formatHtmlMsg(true, true, 60 | System.currentTimeMillis(), "Me", 61 | "1毛9[\"face\",0] [\"face\",71] 哈哈"); 62 | System.out.println(src); 63 | System.out.println(decodeEmoji(src)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/test/HotKeyTest.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartqq.test; 2 | 3 | import org.eclipse.swt.SWT; 4 | import org.eclipse.swt.events.KeyEvent; 5 | import org.eclipse.swt.events.KeyListener; 6 | import org.eclipse.swt.widgets.Display; 7 | import org.eclipse.swt.widgets.Shell; 8 | import org.eclipse.swt.widgets.Text; 9 | 10 | import cn.ieclipse.smartim.preferences.HotKeyFieldEditor; 11 | 12 | public class HotKeyTest extends Shell { 13 | private Text text; 14 | private Text text_1; 15 | 16 | /** 17 | * Launch the application. 18 | * 19 | * @param args 20 | */ 21 | public static void main(String args[]) { 22 | try { 23 | Display display = Display.getDefault(); 24 | HotKeyTest shell = new HotKeyTest(display); 25 | shell.open(); 26 | shell.layout(); 27 | while (!shell.isDisposed()) { 28 | if (!display.readAndDispatch()) { 29 | display.sleep(); 30 | } 31 | } 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | } 35 | } 36 | 37 | /** 38 | * Create the shell. 39 | * 40 | * @param display 41 | */ 42 | public HotKeyTest(Display display) { 43 | super(display, SWT.SHELL_TRIM); 44 | 45 | text = new Text(this, SWT.BORDER); 46 | text.setBounds(10, 10, 188, 23); 47 | text.addKeyListener(new KeyListener() { 48 | 49 | @Override 50 | public void keyReleased(KeyEvent e) { 51 | 52 | } 53 | 54 | @Override 55 | public void keyPressed(KeyEvent e) { 56 | e.doit = false; 57 | text.setText(HotKeyFieldEditor.keyEvent2String(e)); 58 | } 59 | }); 60 | 61 | text_1 = new Text(this, SWT.BORDER); 62 | text_1.setBounds(10, 39, 188, 23); 63 | 64 | text_1.addKeyListener(new KeyListener() { 65 | 66 | @Override 67 | public void keyReleased(KeyEvent e) { 68 | // TODO Auto-generated method stub 69 | 70 | } 71 | 72 | @Override 73 | public void keyPressed(KeyEvent e) { 74 | if (text.getText() 75 | .equals(HotKeyFieldEditor.keyEvent2String(e))) { 76 | e.doit = false; 77 | text_1.setText(""); 78 | } 79 | } 80 | }); 81 | 82 | createContents(); 83 | } 84 | 85 | /** 86 | * Create contents of the shell. 87 | */ 88 | protected void createContents() { 89 | setText("SWT Application"); 90 | setSize(450, 300); 91 | 92 | } 93 | 94 | @Override 95 | protected void checkSubclass() { 96 | // Disable the check that prevents subclassing of SWT components 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/test/LetterImageTest.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartqq.test; 2 | 3 | import org.eclipse.swt.SWT; 4 | import org.eclipse.swt.layout.GridLayout; 5 | import org.eclipse.swt.widgets.Display; 6 | import org.eclipse.swt.widgets.Label; 7 | import org.eclipse.swt.widgets.Shell; 8 | 9 | import cn.ieclipse.smartim.common.LetterImageFactory; 10 | 11 | public class LetterImageTest extends Shell { 12 | 13 | /** 14 | * Launch the application. 15 | * 16 | * @param args 17 | */ 18 | public static void main(String args[]) { 19 | try { 20 | Display display = Display.getDefault(); 21 | LetterImageTest shell = new LetterImageTest(display); 22 | shell.open(); 23 | shell.layout(); 24 | while (!shell.isDisposed()) { 25 | if (!display.readAndDispatch()) { 26 | display.sleep(); 27 | } 28 | } 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | /** 35 | * Create the shell. 36 | * 37 | * @param display 38 | */ 39 | public LetterImageTest(Display display) { 40 | super(display, SWT.SHELL_TRIM); 41 | setLayout(new GridLayout(20, true)); 42 | int start = 0x0; 43 | for (int i = start; i < start + 256; i++) { 44 | Label lblNewLabel = new Label(this, SWT.NONE); 45 | lblNewLabel.setImage( 46 | LetterImageFactory.create((char) i, SWT.COLOR_RED)); 47 | } 48 | createContents(); 49 | } 50 | 51 | /** 52 | * Create contents of the shell. 53 | */ 54 | protected void createContents() { 55 | setText("SWT Application"); 56 | setSize(450, 300); 57 | } 58 | 59 | @Override 60 | protected void checkSubclass() { 61 | // Disable the check that prevents subclassing of SWT components 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/smartqq/test/Login.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package cn.ieclipse.smartqq.test; 5 | 6 | import org.eclipse.swt.widgets.Display; 7 | import org.eclipse.swt.widgets.Shell; 8 | 9 | import cn.ieclipse.smartim.dialogs.LoginDialog; 10 | 11 | /** 12 | * @author Jamling 13 | * 14 | */ 15 | public class Login { 16 | 17 | /** 18 | * @param args 19 | */ 20 | public static void main(String[] args) { 21 | LoginDialog dialog = new LoginDialog(new Shell()); 22 | dialog.open(); 23 | Display display = Display.getDefault(); 24 | while (!display.isDisposed()) { 25 | if (!display.readAndDispatch()) { 26 | display.sleep(); 27 | } 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/wechat/WXBroadcastAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.wechat; 17 | 18 | import org.eclipse.swt.widgets.Shell; 19 | 20 | import cn.ieclipse.smartim.actions.BroadcastAction; 21 | import cn.ieclipse.smartim.views.IMContactView; 22 | 23 | /** 24 | * 类/接口描述 25 | * 26 | * @author Jamling 27 | * @date 2017年10月19日 28 | * 29 | */ 30 | public class WXBroadcastAction extends BroadcastAction { 31 | private WXContactView contactView; 32 | 33 | public WXBroadcastAction(IMContactView contactView) { 34 | super(contactView); 35 | this.contactView = (WXContactView) contactView; 36 | setText("群发微信消息"); 37 | } 38 | 39 | @Override 40 | protected void openDialog(Shell shell) { 41 | WXBroadcastDialog dialog = new WXBroadcastDialog(shell, contactView); 42 | dialog.open(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/wechat/WXChatConsoleMock.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.wechat; 2 | 3 | import cn.ieclipse.smartim.console.MockChatConsole; 4 | import cn.ieclipse.smartim.model.IContact; 5 | import cn.ieclipse.smartim.views.IMContactView; 6 | 7 | public class WXChatConsoleMock extends MockChatConsole { 8 | 9 | public WXChatConsoleMock(IContact target, IMContactView imPanel) { 10 | super(target, imPanel); 11 | } 12 | 13 | @Override 14 | public String getHistoryFile() { 15 | return "wechat.txt"; 16 | } 17 | 18 | @Override 19 | protected String formatInput(String name, String input) { 20 | return WXUtils.formatHtmlOutgoing(name, input, true); 21 | } 22 | 23 | @Override 24 | public void initMockMsg() { 25 | send("中国万岁Abc"); 26 | send("中国万岁Abc"); 27 | send("百度www.baidu.com"); 28 | send("百度www.baidu.com欢迎你"); 29 | send("内事不决问百度外事不决问谷哥"); 30 | String s = " List groups = new ArrayList<>();\n" 31 | + " List starts = new ArrayList<>();\n" 32 | + " List ends = new ArrayList<>();\n" + " while (m.find()) {\n" 33 | + " starts.add(m.start());\n" + " ends.add(m.end());\n" 34 | + " groups.add(m.group());\n" + " }"; 35 | send(s); 36 | s = "图片https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top_86d58ae1.png你造么"; 37 | send(s); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/wechat/WXContactContentProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.wechat; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collections; 20 | import java.util.List; 21 | import java.util.TreeMap; 22 | 23 | import org.eclipse.jface.viewers.Viewer; 24 | 25 | import cn.ieclipse.smartim.common.IMUtils; 26 | import cn.ieclipse.smartim.model.VirtualCategory; 27 | import cn.ieclipse.smartim.views.IMContactContentProvider; 28 | import cn.ieclipse.smartim.views.IMContactView; 29 | import io.github.biezhi.wechat.api.WechatClient; 30 | import io.github.biezhi.wechat.model.Contact; 31 | 32 | /** 33 | * 类/接口描述 34 | * 35 | * @author Jamling 36 | * @date 2017年10月14日 37 | * 38 | */ 39 | public class WXContactContentProvider extends IMContactContentProvider { 40 | 41 | public WXContactContentProvider(IMContactView view, boolean check) { 42 | super(view, check); 43 | } 44 | 45 | @Override 46 | public Object[] getElements(Object inputElement) { 47 | WechatClient client = (WechatClient) fView.getClient(); 48 | if ("recent".equals(inputElement)) { 49 | List list = client.getRecentList(); 50 | if (list == null) { 51 | return null; 52 | } 53 | synchronized (this) { 54 | Collections.sort(list); 55 | } 56 | return list.toArray(); 57 | } 58 | else if ("group".equals(inputElement)) { 59 | List groups = client.getGroupList(); 60 | if (check) { 61 | return new Object[] { new VirtualCategory<>("Group", groups) }; 62 | } 63 | return groups == null ? null : groups.toArray(); 64 | } 65 | else if ("friend".equals(inputElement)) { 66 | List list = client.getMemberList(); 67 | if (check) { 68 | return getContactGroup(list).toArray(); 69 | } 70 | List> cates = new ArrayList<>(); 71 | cates.add(new VirtualCategory<>("groups", client.getGroupList())); 72 | cates.addAll(getContactGroup(list)); 73 | 74 | return cates.toArray(); 75 | } 76 | else if ("public".equals(inputElement)) { 77 | List list = client.getPublicUsersList(); 78 | return list == null ? null : list.toArray(); 79 | } 80 | return null; 81 | } 82 | 83 | @Override 84 | public void dispose() { 85 | // TODO Auto-generated method stub 86 | 87 | } 88 | 89 | @Override 90 | public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 91 | // TODO Auto-generated method stub 92 | 93 | } 94 | 95 | @Override 96 | public Object[] getChildren(Object parentElement) { 97 | if (parentElement instanceof Contact) { 98 | Contact contact = (Contact) parentElement; 99 | return contact.MemberList.toArray(); 100 | } 101 | else if (parentElement instanceof VirtualCategory) { 102 | return ((VirtualCategory) parentElement).getChildren(); 103 | } 104 | return null; 105 | } 106 | 107 | @Override 108 | public Object getParent(Object element) { 109 | // TODO Auto-generated method stub 110 | return null; 111 | } 112 | 113 | @Override 114 | public boolean hasChildren(Object element) { 115 | if (element instanceof Contact) { 116 | Contact contact = (Contact) element; 117 | // return !IMUtils.isEmpty(contact.MemberList); 118 | return false; 119 | } 120 | else if (element instanceof VirtualCategory) { 121 | return ((VirtualCategory) element).hasChildren(); 122 | } 123 | return false; 124 | } 125 | 126 | public List> getContactGroup(List list) { 127 | List> cates = new ArrayList<>(); 128 | if (!IMUtils.isEmpty(list)) { 129 | List unA = new ArrayList<>(); 130 | TreeMap> maps = new TreeMap<>(); 131 | for (Contact c : list) { 132 | String py = c.getPYInitial(); 133 | char A = IMUtils.isEmpty(py) ? '#' : py.charAt(0); 134 | if (A >= 'A' && A <= 'Z' || A >= 'a' && A <= 'z') { 135 | String a = String.valueOf(A).toUpperCase(); 136 | List values = maps.get(a); 137 | if (values == null) { 138 | values = new ArrayList<>(); 139 | maps.put(a, values); 140 | } 141 | values.add(c); 142 | } 143 | else { 144 | unA.add(c); 145 | } 146 | } 147 | for (String n : maps.keySet()) { 148 | cates.add(new VirtualCategory<>(n, maps.get(n))); 149 | } 150 | if (!IMUtils.isEmpty(unA)) { 151 | cates.add(new VirtualCategory<>("#", unA)); 152 | } 153 | } 154 | return cates; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/wechat/WXContactLabelProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.wechat; 17 | 18 | import org.eclipse.swt.SWT; 19 | import org.eclipse.swt.graphics.Image; 20 | 21 | import cn.ieclipse.smartim.common.LetterImageFactory; 22 | import cn.ieclipse.smartim.views.IMContactLabelProvider; 23 | import cn.ieclipse.smartim.views.IMContactView; 24 | import io.github.biezhi.wechat.model.Contact; 25 | 26 | /** 27 | * 类/接口描述 28 | * 29 | * @author Jamling 30 | * @date 2017年10月16日 31 | * 32 | */ 33 | public class WXContactLabelProvider extends IMContactLabelProvider { 34 | 35 | public WXContactLabelProvider(IMContactView view) { 36 | super(view); 37 | } 38 | 39 | @Override 40 | public Image getContactImage(Object obj) { 41 | if (obj instanceof Contact) { 42 | Contact c = (Contact) obj; 43 | char ch = WXUtils.getContactChar(c); 44 | if (ch > 0) { 45 | if (ch == 'F') { 46 | return LetterImageFactory.create(ch, SWT.COLOR_DARK_GREEN); 47 | } 48 | else if (ch == 'G') { 49 | return LetterImageFactory.create(ch, SWT.COLOR_DARK_BLUE); 50 | } 51 | else if (ch == 'P') { 52 | return LetterImageFactory.create(ch, SWT.COLOR_DARK_CYAN); 53 | } 54 | else if (ch == 'S') { 55 | return LetterImageFactory.create(ch, SWT.COLOR_DARK_RED); 56 | } 57 | } 58 | } 59 | return null; 60 | } 61 | 62 | public String getText(Object obj) { 63 | if (obj instanceof Contact) { 64 | return WXUtils.getPureName(((Contact) obj).getName()); 65 | } 66 | return super.getText(obj); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/wechat/WXContactView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.wechat; 17 | 18 | import org.eclipse.jface.viewers.TreeViewer; 19 | import org.eclipse.swt.widgets.Composite; 20 | 21 | import cn.ieclipse.smartim.IMClientFactory; 22 | import cn.ieclipse.smartim.IMPlugin; 23 | import cn.ieclipse.smartim.IMSendCallback; 24 | import cn.ieclipse.smartim.console.IMChatConsole; 25 | import cn.ieclipse.smartim.handler.MessageInterceptor; 26 | import cn.ieclipse.smartim.model.IContact; 27 | import cn.ieclipse.smartim.views.IMContactDoubleClicker; 28 | import cn.ieclipse.smartim.views.IMContactView; 29 | import io.github.biezhi.wechat.api.WechatClient; 30 | 31 | /** 32 | * 微信联系人视图 33 | * 34 | * @author Jamling 35 | * @date 2017年10月14日 36 | * 37 | */ 38 | public class WXContactView extends IMContactView { 39 | 40 | /** 41 | * The ID of the view as specified by the extension. 42 | */ 43 | public static final String ID = "cn.ieclipse.wechat.views.WXContactView"; 44 | 45 | private TreeViewer ftvFriend; 46 | private TreeViewer ftvGroup; 47 | private TreeViewer ftvPublic; 48 | private WXModificationCallback modificationCallback; 49 | private MessageInterceptor interceptor; 50 | 51 | public WXContactView() { 52 | viewId = ID; 53 | labelProvider = new WXContactLabelProvider(this); 54 | contentProvider = new WXContactContentProvider(this, false); 55 | doubleClicker = new IMContactDoubleClicker(this); 56 | 57 | receiveCallback = new WXReceiveCallback(this); 58 | robotCallback = new WXRobotCallback(this); 59 | sendCallback = new IMSendCallback(this); 60 | modificationCallback = new WXModificationCallback(this); 61 | interceptor = new WXMessageInterceptor(); 62 | loadWelcome("wechat"); 63 | } 64 | 65 | @Override 66 | public void createPartControl(Composite parent) { 67 | super.createPartControl(parent); 68 | ftvFriend = createTab("Chats", tabFolder); 69 | ftvGroup = createTab("Contacts", tabFolder); 70 | ftvPublic = createTab("Publics", tabFolder); 71 | tabFolder.setSelection(0); 72 | initTrees(ftvFriend, ftvGroup, ftvPublic); 73 | } 74 | 75 | @Override 76 | public void doLoadContacts() { 77 | WechatClient client = (WechatClient) getClient(); 78 | if (client.isLogin()) { 79 | try { 80 | client.init(); 81 | notifyLoadContacts(true); 82 | client.setReceiveCallback(receiveCallback); 83 | client.setSendCallback(sendCallback); 84 | client.addReceiveCallback(robotCallback); 85 | client.setModificationCallbacdk(modificationCallback); 86 | client.addMessageInterceptor(interceptor); 87 | client.start(); 88 | } catch (Exception e) { 89 | IMPlugin.getDefault().log("微信初始化失败", e); 90 | } 91 | } 92 | else { 93 | notifyLoadContacts(false); 94 | } 95 | } 96 | 97 | @Override 98 | protected void onLoadContacts(boolean success) { 99 | if (success) { 100 | ftvFriend.setInput("recent"); 101 | ftvGroup.setInput("friend"); 102 | ftvPublic.setInput("public"); 103 | } 104 | else { 105 | ftvFriend.setInput(null); 106 | ftvGroup.setInput(null); 107 | ftvPublic.setInput(null); 108 | } 109 | } 110 | 111 | @Override 112 | protected void doUpdateContacts(int index) { 113 | super.doUpdateContacts(index); 114 | if (index == 0) { 115 | boolean focus = ftvFriend.getTree().isFocusControl(); 116 | if (focus || !updateContactsOnlyFocus) { 117 | ftvFriend.refresh(true); 118 | } 119 | } 120 | } 121 | 122 | @Override 123 | protected void makeActions() { 124 | super.makeActions(); 125 | broadcast = new WXBroadcastAction(this); 126 | } 127 | 128 | @Override 129 | public WechatClient getClient() { 130 | return (WechatClient) IMClientFactory.getInstance().getWechatClient(); 131 | } 132 | 133 | @Override 134 | public IMContactView createContactsUI() { 135 | // TODO Auto-generated method stub 136 | return null; 137 | } 138 | 139 | @Override 140 | public IMChatConsole createConsoleUI(IContact contact) { 141 | WXChatConsole console = new WXChatConsole(contact, this); 142 | return console; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/wechat/WXMessageInterceptor.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.wechat; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | import cn.ieclipse.smartim.common.IMUtils; 7 | import cn.ieclipse.smartim.handler.MessageInterceptor; 8 | import cn.ieclipse.smartim.model.IMessage; 9 | import io.github.biezhi.wechat.model.WechatMessage; 10 | 11 | public class WXMessageInterceptor implements MessageInterceptor { 12 | Pattern code = Pattern.compile(IMUtils.CODE_REGEX); 13 | 14 | @Override 15 | public boolean handle(IMessage message) { 16 | if (message instanceof WechatMessage) { 17 | WechatMessage msg = (WechatMessage) message; 18 | if (msg.MsgType == WechatMessage.MSGTYPE_TEXT) { 19 | Matcher m = code.matcher(msg.getText()); 20 | if (m.find()) { 21 | String linkText = m.group().substring(6).trim(); 22 | int s = m.start() + 6; 23 | int e = s + linkText.length(); 24 | StringBuilder sb = new StringBuilder(msg.getText()); 25 | sb.delete(s, e); 26 | String url = String.format("%s", 27 | linkText, linkText); 28 | sb.insert(s, url); 29 | msg.text = sb.toString(); 30 | } 31 | } 32 | } 33 | return false; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/wechat/WXModificationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.wechat; 17 | 18 | import cn.ieclipse.smartim.callback.ModificationCallback; 19 | import cn.ieclipse.smartim.model.IContact; 20 | import io.github.biezhi.wechat.model.Contact; 21 | 22 | /** 23 | * 类/接口描述 24 | * 25 | * @author Jamling 26 | * @date 2017年10月27日 27 | * 28 | */ 29 | public class WXModificationCallback implements ModificationCallback { 30 | private WXContactView fContactView; 31 | 32 | public WXModificationCallback(WXContactView fContactView) { 33 | this.fContactView = fContactView; 34 | } 35 | 36 | @Override 37 | public void onContactChanged(IContact contact) { 38 | if (contact instanceof Contact || contact == null) { 39 | fContactView.notifyUpdateContacts(0, true); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/wechat/WXReceiveCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.wechat; 17 | 18 | import cn.ieclipse.smartim.IMPlugin; 19 | import cn.ieclipse.smartim.IMReceiveCallback; 20 | import cn.ieclipse.smartim.common.IMUtils; 21 | import cn.ieclipse.smartim.model.impl.AbstractFrom; 22 | import cn.ieclipse.smartim.model.impl.AbstractMessage; 23 | import cn.ieclipse.smartim.preferences.SettingsPerferencePage; 24 | import io.github.biezhi.wechat.model.Contact; 25 | import io.github.biezhi.wechat.model.GroupFrom; 26 | import io.github.biezhi.wechat.model.UserFrom; 27 | import io.github.biezhi.wechat.model.WechatMessage; 28 | 29 | /** 30 | * 类/接口描述 31 | * 32 | * @author Jamling 33 | * @date 2017年10月14日 34 | * 35 | */ 36 | public class WXReceiveCallback extends IMReceiveCallback { 37 | 38 | public WXReceiveCallback(WXContactView fContactView) { 39 | super(fContactView); 40 | } 41 | 42 | @Override 43 | public void onReceiveMessage(AbstractMessage message, AbstractFrom from) { 44 | if (from != null && from.getContact() != null) { 45 | boolean unknown = false; 46 | boolean notify = IMPlugin.getDefault().getPreferenceStore() 47 | .getBoolean(SettingsPerferencePage.NOTIFY_FRIEND); 48 | String uin = from.getContact().getUin(); 49 | Contact contact = (Contact) from.getContact(); 50 | if (from instanceof GroupFrom) { 51 | GroupFrom gf = (GroupFrom) from; 52 | unknown = gf.getMember() == null || gf.getMember().isUnknown(); 53 | notify = IMPlugin.getDefault().getPreferenceStore() 54 | .getBoolean(SettingsPerferencePage.NOTIFY_GROUP); 55 | } 56 | else { 57 | unknown = from.getMember() == null; 58 | } 59 | handle(unknown, notify, message, from, contact); 60 | } 61 | } 62 | 63 | @Override 64 | protected String getNotifyContent(AbstractMessage message, 65 | AbstractFrom from) { 66 | CharSequence content = (from instanceof UserFrom) ? message.getText() 67 | : from.isOut() ? from.getTarget().getName() 68 | : from.getName() + ":" + message.getText(); 69 | return content.toString(); 70 | } 71 | 72 | @Override 73 | protected String getMsgContent(AbstractMessage message, AbstractFrom from) { 74 | if (message instanceof WechatMessage) { 75 | return WXUtils.formatHtmlIncoming((WechatMessage) message, from); 76 | } 77 | return message.getClass().getName(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/cn/ieclipse/wechat/WXUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.ieclipse.wechat; 17 | 18 | import java.text.SimpleDateFormat; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.regex.Matcher; 22 | import java.util.regex.Pattern; 23 | 24 | import cn.ieclipse.smartim.common.IMUtils; 25 | import cn.ieclipse.smartim.model.IContact; 26 | import cn.ieclipse.smartim.model.impl.AbstractFrom; 27 | import cn.ieclipse.util.StringUtils; 28 | import io.github.biezhi.wechat.model.Contact; 29 | import io.github.biezhi.wechat.model.UserFrom; 30 | import io.github.biezhi.wechat.model.WechatMessage; 31 | 32 | /** 33 | * 类/接口描述 34 | * 35 | * @author Jamling 36 | * @date 2018年2月8日 37 | * 38 | */ 39 | public class WXUtils { 40 | public static char getContactChar(IContact contact) { 41 | if (contact instanceof Contact) { 42 | Contact c = (Contact) contact; 43 | char ch = 'F'; 44 | if (c.isPublic()) { 45 | ch = 'P'; 46 | } 47 | else if (c.isGroup()) { 48 | ch = 'G'; 49 | } 50 | else if (c.is3rdApp() || c.isSpecial()) { 51 | ch = 'S'; 52 | } 53 | return ch; 54 | } 55 | return 0; 56 | } 57 | 58 | public static String decodeEmoji(String src) { 59 | String regex = StringUtils.encodeXml(""); 60 | Pattern p = Pattern.compile(regex, Pattern.MULTILINE); 61 | Matcher m = p.matcher(src); 62 | 63 | List groups = new ArrayList<>(); 64 | List starts = new ArrayList<>(); 65 | List ends = new ArrayList<>(); 66 | while (m.find()) { 67 | starts.add(m.start()); 68 | ends.add(m.end()); 69 | groups.add(m.group()); 70 | } 71 | if (!starts.isEmpty()) { 72 | StringBuilder sb = new StringBuilder(src); 73 | int offset = 0; 74 | for (int i = 0; i < starts.size(); i++) { 75 | int s = starts.get(i); 76 | int e = ends.get(i); 77 | String g = groups.get(i); 78 | 79 | int pos = offset + s; 80 | sb.delete(pos, offset + e); 81 | String ng = g; 82 | ng = StringUtils.decodeXml(g); 83 | sb.insert(pos, ng); 84 | offset += ng.length() - g.length(); 85 | } 86 | return sb.toString(); 87 | } 88 | return src; 89 | } 90 | 91 | public static String getPureName(String name) { 92 | String regex = ""; 93 | return name.replaceAll(regex, "").trim(); 94 | } 95 | 96 | // ------------>消息格式化 97 | // 1. 输入消息,即将发出去的消息 98 | // 1.1 发送的消息=输入的消息 99 | // 1.2 显示的消息= html转义->处理超链接->处理换行和空格 100 | // 2. 接收的消息 101 | // 2.1 处理超链接 102 | // ------------> 103 | 104 | static String formatHtmlMsg(boolean my, long time, String name, 105 | String msg) { 106 | String t = new SimpleDateFormat("HH:mm:ss").format(time); 107 | String clz = my ? "sender my" : "sender"; 108 | return String.format(IMUtils.DIV_ROW_FORMAT, clz, t, name, name, msg); 109 | } 110 | 111 | /** 112 | * 格式化发出去的消息,对于输入的消息 显示的消息= html转义->处理超链接->处理换行和空格 113 | * 114 | * @param name 115 | * 发送者 116 | * @param msg 117 | * 原始输入内容 118 | * @param encode 119 | * 是否进行转义 120 | * @return 格式化的消息内容 121 | */ 122 | public static String formatHtmlOutgoing(String name, String msg, 123 | boolean encode) { 124 | String content = msg; 125 | if (encode) { 126 | content = StringUtils.encodeXml(msg); 127 | content = content.replaceAll(" ", " "); 128 | content = IMUtils.autoLink(content); 129 | content = content.replaceAll("\r?\n", "
"); 130 | } 131 | return WXUtils.formatHtmlMsg(true, System.currentTimeMillis(), name, 132 | content); 133 | } 134 | 135 | /** 136 | * 格式化收到的消息 137 | * 138 | * @param m 139 | * 微信消息 140 | * @param from 141 | * 发送者 142 | * @return 格式化的html消息 143 | */ 144 | public static String formatHtmlIncoming(WechatMessage m, 145 | AbstractFrom from) { 146 | String name = from.isOut() ? from.getTarget().getName() 147 | : from.getName(); 148 | name = WXUtils.getPureName(name); 149 | String msg = null; 150 | String text = m.getText() == null ? "" : m.getText().toString(); 151 | boolean my = from.isOut() ? true : false; 152 | if (m.MsgType != WechatMessage.MSGTYPE_TEXT) { 153 | if (m.MsgType == WechatMessage.MSGTYPE_APP 154 | && m.AppMsgType == WechatMessage.APPMSGTYPE_ATTACH) { 155 | if (m.AppMsgInfo != null) { 156 | 157 | } 158 | } 159 | } 160 | else { 161 | if (from instanceof UserFrom) { 162 | Contact c = (Contact) from.getContact(); 163 | } 164 | } 165 | msg = WXUtils.formatHtmlMsg(my, m.getTime(), name, text); 166 | msg = WXUtils.decodeEmoji(msg); 167 | return msg; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/src/icons/SmartIcons.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 ieclipse.cn. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package icons; 17 | 18 | import org.eclipse.jface.resource.ImageDescriptor; 19 | import org.eclipse.ui.ISharedImages; 20 | import org.eclipse.ui.ide.IDE; 21 | 22 | import cn.ieclipse.smartim.IMPlugin; 23 | 24 | /** 25 | * 类/接口描述 26 | * 27 | * @author Jamling 28 | * @date 2017年11月2日 29 | * 30 | */ 31 | public class SmartIcons { 32 | public static abstract class IconLoader { 33 | public static ImageDescriptor getIcon(String path) { 34 | return IMPlugin.getImageDescriptor(path); 35 | } 36 | public static ImageDescriptor getShare(String name) { 37 | return IMPlugin.getSharedImage(name); 38 | } 39 | } 40 | 41 | public static ImageDescriptor qq = IconLoader.getIcon("/icons/QQ.png"); 42 | public static ImageDescriptor wechat = IconLoader.getIcon("/icons/wechat.png"); 43 | 44 | public static ImageDescriptor signin = IconLoader.getIcon("/icons/qrcode.png"); 45 | public static ImageDescriptor signout = IconLoader.getShare(ISharedImages.IMG_ELCL_STOP); 46 | public static ImageDescriptor test = IconLoader.getShare(ISharedImages.IMG_DEC_FIELD_WARNING); 47 | public static ImageDescriptor close = IconLoader.getIcon("/icons/close.png"); 48 | public static ImageDescriptor show = IconLoader.getIcon("/icons/eye.png"); 49 | public static ImageDescriptor hide = IconLoader.getIcon("/icons/eye-slash.png"); 50 | public static ImageDescriptor broadcast = IconLoader.getIcon("/icons/broadcast.png"); 51 | public static ImageDescriptor settings = IconLoader.getShare(ISharedImages.IMG_LCL_LINKTO_HELP); 52 | 53 | public static ImageDescriptor group = IconLoader.getIcon("/icons/user-circle.png"); 54 | public static ImageDescriptor friend = IconLoader.getIcon("/icons/user.png"); 55 | public static ImageDescriptor discuss = IconLoader.getIcon("/icons/user-o.png"); 56 | 57 | public static ImageDescriptor file = IconLoader.getShare(ISharedImages.IMG_OBJ_FILE); 58 | public static ImageDescriptor image = IconLoader.getIcon("/icons/image.png"); 59 | public static ImageDescriptor projectFile = IconLoader.getShare(IDE.SharedImages.IMG_OBJ_PROJECT); 60 | public static ImageDescriptor face = IconLoader.getIcon("/icons/face.png"); 61 | public static ImageDescriptor lock = IconLoader.getIcon("/icons/lock_co.png"); 62 | public static ImageDescriptor clear = IconLoader.getIcon("/icons/clear_co.png"); 63 | 64 | public static ImageDescriptor paste = IconLoader.getShare(ISharedImages.IMG_TOOL_PASTE); 65 | public static ImageDescriptor copy = IconLoader.getShare(ISharedImages.IMG_TOOL_COPY); 66 | 67 | public static void main(String[] args) { 68 | System.out.println(group); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/test/cn/ieclipse/smartim/console/ReviewLinkTest.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.console; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | import org.junit.After; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | 14 | public class ReviewLinkTest { 15 | 16 | String regex = "Code: [\\S ]+:[\\d]+ ?"; 17 | 18 | @Before 19 | public void setUp() throws Exception { 20 | } 21 | 22 | @After 23 | public void tearDown() throws Exception { 24 | } 25 | 26 | @Test 27 | public void testGetLinkText() { 28 | 29 | String input = "16:17:28 Send1: Code: /var/path/file:33"; 30 | input += "\n" + "16:17:38 Send 2: Code: \\TabComposite:\\\\path\\file:do.java:33 "; 31 | input += "\n" + "16:17:46 发送者: Code: /var/path path2/src.:33 "; 32 | Pattern p = Pattern.compile(regex, Pattern.MULTILINE); 33 | Matcher m = p.matcher(input); 34 | List list = new ArrayList<>(); 35 | while (m.find()) { 36 | list.add(m.group()); 37 | } 38 | System.out.println(list); 39 | assertEquals("Code: /var/path/file:33", getLinkText(list.get(0))); 40 | assertEquals("Code: \\TabComposite:\\\\path\\file:do.java:33 ", getLinkText(list.get(1))); 41 | assertEquals("Code: /var/path path2/src.:33 ", getLinkText(list.get(2))); 42 | } 43 | 44 | private Object getLinkText(String string) { 45 | return string; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /cn.ieclipse.smartqq/test/cn/ieclipse/smartim/console/SenderLinkTest.java: -------------------------------------------------------------------------------- 1 | package cn.ieclipse.smartim.console; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | import org.junit.After; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | 14 | public class SenderLinkTest { 15 | public String regex = "^\\d{2}:\\d{2}:\\d{2} [^:]+: "; 16 | 17 | @Before 18 | public void setUp() throws Exception { 19 | } 20 | 21 | @After 22 | public void tearDown() throws Exception { 23 | } 24 | 25 | @Test 26 | public void testGetLinkText() { 27 | String input = "16:17:28 Send1: SmartQQ支持发送文件吗?"; 28 | input += "\n" + "16:17:38 Send 2: 支持的"; 29 | input += "\n" + "16:17:46 发送者: 你是什么版本?"; 30 | Pattern p = Pattern.compile(regex, Pattern.MULTILINE); 31 | Matcher m = p.matcher(input); 32 | List list = new ArrayList<>(); 33 | while (m.find()) { 34 | list.add(m.group()); 35 | } 36 | assertEquals("Send1", getLinkText(list.get(0))); 37 | assertEquals("Send 2", getLinkText(list.get(1))); 38 | assertEquals("发送者", getLinkText(list.get(2))); 39 | } 40 | 41 | private String getLinkText(String line) { 42 | int linkStart = 9; 43 | int linkEnd = line.indexOf(':', linkStart); 44 | return line.substring(linkStart, linkEnd); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/main.png -------------------------------------------------------------------------------- /screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jamling/SmartIM4Eclipse/48d97932fa70807be7f79c4a0cecc3f786b6475e/screenshot.gif --------------------------------------------------------------------------------