19 |
19 |
20 class SingleApplicationServer(QLocalServer): |
20 class SingleApplicationServer(QLocalServer): |
21 """ |
21 """ |
22 Class implementing the single application server base class. |
22 Class implementing the single application server base class. |
23 """ |
23 """ |
|
24 |
24 def __init__(self, name): |
25 def __init__(self, name): |
25 """ |
26 """ |
26 Constructor |
27 Constructor |
27 |
28 |
28 @param name name this server is listening to (string) |
29 @param name name this server is listening to (string) |
29 """ |
30 """ |
30 super().__init__() |
31 super().__init__() |
31 |
32 |
32 res = self.listen(name) |
33 res = self.listen(name) |
33 if not res: |
34 if not res: |
34 # maybe it crashed last time |
35 # maybe it crashed last time |
35 self.removeServer(name) |
36 self.removeServer(name) |
36 self.listen(name) |
37 self.listen(name) |
37 |
38 |
38 self.newConnection.connect(self.__newConnection) |
39 self.newConnection.connect(self.__newConnection) |
39 |
40 |
40 self.qsock = None |
41 self.qsock = None |
41 |
42 |
42 def __newConnection(self): |
43 def __newConnection(self): |
59 """ |
60 """ |
60 Private method to receive the data from the client. |
61 Private method to receive the data from the client. |
61 """ |
62 """ |
62 while self.qsock and self.qsock.canReadLine(): |
63 while self.qsock and self.qsock.canReadLine(): |
63 line = bytes(self.qsock.readLine()).decode() |
64 line = bytes(self.qsock.readLine()).decode() |
64 |
65 |
65 ## print(line) ## debug # __IGNORE_WARNING_M891__ |
66 ##print(line) ## debug # __IGNORE_WARNING_M891__ |
66 |
67 |
67 try: |
68 try: |
68 commandDict = json.loads(line.strip()) |
69 commandDict = json.loads(line.strip()) |
69 except (TypeError, ValueError) as err: |
70 except (TypeError, ValueError) as err: |
70 EricMessageBox.critical( |
71 EricMessageBox.critical( |
71 None, |
72 None, |
72 self.tr("Single Application Protocol Error"), |
73 self.tr("Single Application Protocol Error"), |
73 self.tr("""<p>The response received from the single""" |
74 self.tr( |
74 """ application client could not be decoded.""" |
75 """<p>The response received from the single""" |
75 """ Please report this issue with the received""" |
76 """ application client could not be decoded.""" |
76 """ data to the eric bugs email address.</p>""" |
77 """ Please report this issue with the received""" |
77 """<p>Error: {0}</p>""" |
78 """ data to the eric bugs email address.</p>""" |
78 """<p>Data:<br/>{1}</p>""").format( |
79 """<p>Error: {0}</p>""" |
79 str(err), Utilities.html_encode(line.strip())), |
80 """<p>Data:<br/>{1}</p>""" |
80 EricMessageBox.Ok) |
81 ).format(str(err), Utilities.html_encode(line.strip())), |
|
82 EricMessageBox.Ok, |
|
83 ) |
81 return |
84 return |
82 |
85 |
83 command = commandDict["command"] |
86 command = commandDict["command"] |
84 arguments = commandDict["arguments"] |
87 arguments = commandDict["arguments"] |
85 |
88 |
86 self.handleCommand(command, arguments) |
89 self.handleCommand(command, arguments) |
87 |
90 |
88 def __disconnected(self): |
91 def __disconnected(self): |
89 """ |
92 """ |
90 Private method to handle the closure of the socket. |
93 Private method to handle the closure of the socket. |
91 """ |
94 """ |
92 self.qsock = None |
95 self.qsock = None |
93 |
96 |
94 def shutdown(self): |
97 def shutdown(self): |
95 """ |
98 """ |
96 Public method used to shut down the server. |
99 Public method used to shut down the server. |
97 """ |
100 """ |
98 if self.qsock is not None: |
101 if self.qsock is not None: |
99 self.qsock.readyRead.disconnect(self.__parseLine) |
102 self.qsock.readyRead.disconnect(self.__parseLine) |
100 self.qsock.disconnected.disconnect(self.__disconnected) |
103 self.qsock.disconnected.disconnect(self.__disconnected) |
101 |
104 |
102 self.qsock = None |
105 self.qsock = None |
103 |
106 |
104 self.close() |
107 self.close() |
105 |
108 |
106 def handleCommand(self, command, arguments): |
109 def handleCommand(self, command, arguments): |
107 """ |
110 """ |
108 Public slot to handle the command sent by the client. |
111 Public slot to handle the command sent by the client. |
109 |
112 |
110 <b>Note</b>: This method must be overridden by subclasses. |
113 <b>Note</b>: This method must be overridden by subclasses. |
111 |
114 |
112 @param command command sent by the client |
115 @param command command sent by the client |
113 @type str |
116 @type str |
114 @param arguments list of command arguments |
117 @param arguments list of command arguments |
115 @type list of str |
118 @type list of str |
116 @exception RuntimeError raised to indicate that this method must be |
119 @exception RuntimeError raised to indicate that this method must be |
121 |
124 |
122 class SingleApplicationClient: |
125 class SingleApplicationClient: |
123 """ |
126 """ |
124 Class implementing the single application client base class. |
127 Class implementing the single application client base class. |
125 """ |
128 """ |
|
129 |
126 def __init__(self, name): |
130 def __init__(self, name): |
127 """ |
131 """ |
128 Constructor |
132 Constructor |
129 |
133 |
130 @param name name of the local server to connect to (string) |
134 @param name name of the local server to connect to (string) |
131 """ |
135 """ |
132 self.name = name |
136 self.name = name |
133 self.connected = False |
137 self.connected = False |
134 |
138 |
135 def connect(self, timeout=10000): |
139 def connect(self, timeout=10000): |
136 """ |
140 """ |
137 Public method to connect the single application client to its server. |
141 Public method to connect the single application client to its server. |
138 |
142 |
139 @param timeout connection timeout value in milliseconds |
143 @param timeout connection timeout value in milliseconds |
140 @type int |
144 @type int |
141 @return value indicating success or an error number. Value is one of: |
145 @return value indicating success or an error number. Value is one of: |
142 <table> |
146 <table> |
143 <tr><td>0</td><td>No application is running</td></tr> |
147 <tr><td>0</td><td>No application is running</td></tr> |
153 err = self.sock.error() |
157 err = self.sock.error() |
154 if err == QLocalSocket.LocalSocketError.ServerNotFoundError: |
158 if err == QLocalSocket.LocalSocketError.ServerNotFoundError: |
155 return 0 |
159 return 0 |
156 else: |
160 else: |
157 return -err.value |
161 return -err.value |
158 |
162 |
159 def disconnect(self): |
163 def disconnect(self): |
160 """ |
164 """ |
161 Public method to disconnect from the Single Appliocation server. |
165 Public method to disconnect from the Single Appliocation server. |
162 """ |
166 """ |
163 self.sock.disconnectFromServer() |
167 self.sock.disconnectFromServer() |
164 self.connected = False |
168 self.connected = False |
165 |
169 |
166 def processArgs(self, args): |
170 def processArgs(self, args): |
167 """ |
171 """ |
168 Public method to process the command line args passed to the UI. |
172 Public method to process the command line args passed to the UI. |
169 |
173 |
170 <b>Note</b>: This method must be overridden by subclasses. |
174 <b>Note</b>: This method must be overridden by subclasses. |
171 |
175 |
172 @param args command line args (list of strings) |
176 @param args command line args (list of strings) |
173 @exception RuntimeError raised to indicate that this method must be |
177 @exception RuntimeError raised to indicate that this method must be |
174 implemented by a subclass |
178 implemented by a subclass |
175 """ |
179 """ |
176 raise RuntimeError("'processArgs' must be overridden") |
180 raise RuntimeError("'processArgs' must be overridden") |
177 |
181 |
178 def sendCommand(self, command, arguments): |
182 def sendCommand(self, command, arguments): |
179 """ |
183 """ |
180 Public method to send the command to the application server. |
184 Public method to send the command to the application server. |
181 |
185 |
182 @param command command to be sent to the server |
186 @param command command to be sent to the server |
183 @type str |
187 @type str |
184 @param arguments list of command arguments |
188 @param arguments list of command arguments |
185 @type list of str |
189 @type list of str |
186 """ |
190 """ |
187 if self.connected: |
191 if self.connected: |
188 commandDict = { |
192 commandDict = { |
189 "command": command, |
193 "command": command, |
190 "arguments": arguments, |
194 "arguments": arguments, |
191 } |
195 } |
192 self.sock.write(QByteArray( |
196 self.sock.write( |
193 "{0}\n".format(json.dumps(commandDict)).encode() |
197 QByteArray("{0}\n".format(json.dumps(commandDict)).encode()) |
194 )) |
198 ) |
195 self.sock.flush() |
199 self.sock.flush() |
196 |
200 |
197 def errstr(self): |
201 def errstr(self): |
198 """ |
202 """ |
199 Public method to return a meaningful error string for the last error. |
203 Public method to return a meaningful error string for the last error. |
200 |
204 |
201 @return error string for the last error (string) |
205 @return error string for the last error (string) |
202 """ |
206 """ |
203 return self.sock.errorString() |
207 return self.sock.errorString() |