|
8 | 8 | * Site: https://pyqt.site , https://pyqt5.com |
9 | 9 | */ |
10 | 10 |
|
11 | | -package irony.pycharm.qsseditor |
| 11 | +@file:Suppress("ktlint:standard:no-wildcard-imports") |
12 | 12 |
|
| 13 | +package irony.pycharm.qsseditor |
13 | 14 | import com.intellij.openapi.diagnostic.logger |
14 | | -import org.java_websocket.client.WebSocketClient |
15 | | -import org.java_websocket.handshake.ServerHandshake |
16 | | -import java.net.URI |
| 15 | +import kotlinx.serialization.json.* |
| 16 | +import okhttp3.OkHttpClient |
| 17 | +import okhttp3.Request |
| 18 | +import okhttp3.WebSocket |
| 19 | +import okhttp3.WebSocketListener |
| 20 | +import java.util.concurrent.TimeUnit |
17 | 21 |
|
18 | 22 | private val Log = logger<QSSClient>() |
19 | 23 |
|
20 | | -class QSSClient(serverUri: URI?) : WebSocketClient(serverUri) { |
21 | | - override fun onOpen(handshakedata: ServerHandshake?) { |
| 24 | +interface MessageListener { |
| 25 | + fun onParams(array: JsonArray) |
| 26 | +} |
| 27 | + |
| 28 | +class KeywordsListener : MessageListener { |
| 29 | + override fun onParams(array: JsonArray) { |
| 30 | + Log.info("onParams: $array") |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +class QSSClient : WebSocketListener() { |
| 35 | + init { |
| 36 | + listener["addKeywords"] = KeywordsListener() |
| 37 | + } |
| 38 | + |
| 39 | + override fun onOpen( |
| 40 | + webSocket: okhttp3.WebSocket, |
| 41 | + response: okhttp3.Response, |
| 42 | + ) { |
22 | 43 | Log.debug("onOpen") |
23 | 44 | } |
24 | 45 |
|
25 | | - override fun onMessage(message: String?) { |
26 | | - Log.debug("onMessage: $message") |
| 46 | + override fun onMessage( |
| 47 | + webSocket: okhttp3.WebSocket, |
| 48 | + text: String, |
| 49 | + ) { |
| 50 | + Log.debug("onMessage: $text") |
| 51 | + if (text.isNotEmpty()) { |
| 52 | + val json = Json.parseToJsonElement(text).jsonObject |
| 53 | + if (json.getValue( |
| 54 | + "jsonrpc", |
| 55 | + ).jsonPrimitive.contentOrNull != "2.0" || json.getValue("method").jsonPrimitive.contentOrNull == null |
| 56 | + ) { |
| 57 | + Log.warn("onMessage: jsonrpc or method is null") |
| 58 | + return |
| 59 | + } |
| 60 | + |
| 61 | + // 处理对应消息 |
| 62 | + val method = json.getValue("method").jsonPrimitive.contentOrNull |
| 63 | + listener[method]?.onParams(json.getValue("params").jsonArray) |
| 64 | + } |
27 | 65 | } |
28 | 66 |
|
29 | | - override fun onClose( |
| 67 | + override fun onClosing( |
| 68 | + webSocket: okhttp3.WebSocket, |
30 | 69 | code: Int, |
31 | | - reason: String?, |
32 | | - remote: Boolean, |
| 70 | + reason: String, |
33 | 71 | ) { |
34 | | - Log.debug("onClose: code=$code, remote=$remote, reason=$reason") |
| 72 | + Log.debug("onClosing") |
| 73 | + if (done) { |
| 74 | + return |
| 75 | + } |
| 76 | + Thread.sleep(5000) |
| 77 | + reconnect(webSocket.request().url.host, webSocket.request().url.port) |
35 | 78 | } |
36 | 79 |
|
37 | | - override fun onError(e: Exception?) { |
38 | | - Log.error("onError", e) |
| 80 | + override fun onFailure( |
| 81 | + webSocket: okhttp3.WebSocket, |
| 82 | + t: Throwable, |
| 83 | + response: okhttp3.Response?, |
| 84 | + ) { |
| 85 | + Log.warn("onFailure, ${t.message}") |
| 86 | + if (done) { |
| 87 | + Log.info("client require shutdown") |
| 88 | + return |
| 89 | + } |
| 90 | + Thread.sleep(5000) |
| 91 | + reconnect(webSocket.request().url.host, webSocket.request().url.port) |
39 | 92 | } |
40 | 93 |
|
41 | 94 | companion object { |
42 | | - private var client: QSSClient? = null |
| 95 | + private var host: String = "" |
| 96 | + private var port: Int = 0 |
| 97 | + private var done: Boolean = false |
| 98 | + private var self: QSSClient? = null |
| 99 | + private var client: OkHttpClient? = null |
| 100 | + private var socket: WebSocket? = null |
| 101 | + private var listener: HashMap<String, MessageListener> = HashMap() |
43 | 102 |
|
44 | 103 | fun connect( |
45 | 104 | host: String, |
46 | 105 | port: Int, |
47 | 106 | ) { |
| 107 | + if (host == this.host && port == this.port) { |
| 108 | + if (socket != null || self != null) { |
| 109 | + return |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + this.host = host |
| 114 | + this.port = port |
| 115 | + |
48 | 116 | disconnect() |
| 117 | + |
| 118 | + if (self == null) { |
| 119 | + self = QSSClient() |
| 120 | + } |
49 | 121 | if (client == null) { |
| 122 | + client = OkHttpClient.Builder().pingInterval(5, TimeUnit.SECONDS).connectTimeout(30, TimeUnit.SECONDS).build() |
| 123 | + } |
| 124 | + |
| 125 | + if (socket == null) { |
50 | 126 | Log.debug("connect to node: ws://$host:$port") |
51 | | - client = QSSClient(URI("ws://$host:$port")) |
52 | | - client!!.connect() |
| 127 | + socket = client!!.newWebSocket(Request.Builder().url("ws://$host:$port").build(), self!!) |
53 | 128 | } |
54 | 129 | } |
55 | 130 |
|
56 | | - fun reconnect() { |
| 131 | + fun reconnect( |
| 132 | + host: String, |
| 133 | + port: Int, |
| 134 | + ) { |
57 | 135 | Log.debug("do reconnect") |
58 | | - client?.reconnect() |
| 136 | + socket = client!!.newWebSocket(Request.Builder().url("ws://$host:$port").build(), self!!) |
59 | 137 | } |
60 | 138 |
|
61 | | - fun disconnect() { |
| 139 | + private fun disconnect() { |
62 | 140 | Log.debug("do disconnect") |
63 | | - client?.close() |
64 | | - client = null |
| 141 | + socket?.cancel() |
| 142 | + socket?.close(1001, "client disconnect") |
| 143 | + socket = null |
| 144 | + } |
| 145 | + |
| 146 | + fun shutdown() { |
| 147 | + Log.info("do shutdown") |
| 148 | + done = true |
| 149 | + disconnect() |
| 150 | + } |
| 151 | + |
| 152 | + private fun buildMessage( |
| 153 | + method: String, |
| 154 | + message: List<String>, |
| 155 | + ): String { |
| 156 | + return buildJsonObject { |
| 157 | + put("jsonrpc", "2.0") |
| 158 | + put("method", method) |
| 159 | + putJsonArray("params") { |
| 160 | + for (s in message) { |
| 161 | + add(s) |
| 162 | + } |
| 163 | + } |
| 164 | + }.toString() |
| 165 | + } |
| 166 | + |
| 167 | + fun applyStyle(message: List<String>) { |
| 168 | + socket!!.send(buildMessage("setStyleSheet", message)) |
65 | 169 | } |
66 | 170 |
|
67 | | - fun send(message: String) { |
68 | | - client?.send(message) |
| 171 | + fun selectWidget(message: List<String>) { |
| 172 | + socket!!.send(buildMessage("selectWidget", message)) |
69 | 173 | } |
70 | 174 | } |
71 | 175 | } |
0 commit comments