diff -r 77189681b787 -r 51eefa621de4 Toolbox/SingleApplication.py --- a/Toolbox/SingleApplication.py Sat Dec 01 11:45:24 2018 +0100 +++ b/Toolbox/SingleApplication.py Thu Jan 10 14:22:59 2019 +0100 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2004 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# Copyright (c) 2004 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> # """ @@ -9,9 +9,15 @@ from __future__ import unicode_literals +import json + from PyQt5.QtCore import QByteArray from PyQt5.QtNetwork import QLocalServer, QLocalSocket +from E5Gui import E5MessageBox + +import Utilities + class SingleApplicationServer(QLocalServer): """ @@ -41,34 +47,46 @@ """ sock = self.nextPendingConnection() - # If we already have a connection, refuse this one. It will be closed + # If we already have a connection, refuse this one. It will be closed # automatically. if self.qsock is not None: return self.qsock = sock - self.qsock.readyRead.connect(self.__parseLine) + self.qsock.readyRead.connect(self.__receiveJson) self.qsock.disconnected.connect(self.__disconnected) - def __parseLine(self): + def __receiveJson(self): """ - Private method to handle data from the client. + Private method to receive the data from the client. """ while self.qsock and self.qsock.canReadLine(): line = bytes(self.qsock.readLine()).decode() ## print(line) ##debug - eoc = line.find('<') + 1 + try: + commandDict = json.loads(line.strip()) + except (TypeError, ValueError) as err: + E5MessageBox.critical( + None, + self.tr("Single Application Protocol Error"), + self.tr("""<p>The response received from the single""" + """ application client could not be decoded.""" + """ Please report this issue with the received""" + """ data to the eric bugs email address.</p>""" + """<p>Error: {0}</p>""" + """<p>Data:<br/>{1}</p>""").format( + str(err), Utilities.html_encode(line.strip())), + E5MessageBox.StandardButtons( + E5MessageBox.Ok)) + return - boc = line.find('>') - if boc >= 0 and eoc > boc: - # handle the command sent by the client. - cmd = line[boc:eoc] - params = line[eoc:-1] - - self.handleCommand(cmd, params) + command = commandDict["command"] + arguments = commandDict["arguments"] + + self.handleCommand(command, arguments) def __disconnected(self): """ @@ -88,14 +106,16 @@ self.close() - def handleCommand(self, cmd, params): + def handleCommand(self, command, arguments): """ Public slot to handle the command sent by the client. <b>Note</b>: This method must be overridden by subclasses. - @param cmd commandstring (string) - @param params parameterstring (string) + @param command command sent by the client + @type str + @param arguments list of command arguments + @type list of str @exception RuntimeError raised to indicate that this method must be implemented by a subclass """ @@ -115,10 +135,12 @@ self.name = name self.connected = False - def connect(self): + def connect(self, timeout=10000): """ Public method to connect the single application client to its server. + @param timeout connection timeout value in milliseconds + @type int @return value indicating success or an error number. Value is one of: <table> <tr><td>0</td><td>No application is running</td></tr> @@ -127,7 +149,7 @@ """ self.sock = QLocalSocket() self.sock.connectToServer(self.name) - if self.sock.waitForConnected(10000): + if self.sock.waitForConnected(timeout): self.connected = True return 1 else: @@ -156,14 +178,23 @@ """ raise RuntimeError("'processArgs' must be overridden") - def sendCommand(self, cmd): + def sendCommand(self, command, arguments): """ Public method to send the command to the application server. - @param cmd command to be sent (string) + @param command command to be sent to the server + @type str + @param arguments list of command arguments + @type list of str """ if self.connected: - self.sock.write(QByteArray(cmd.encode())) + commandDict = { + "command": command, + "arguments": arguments, + } + self.sock.write(QByteArray( + "{0}\n".format(json.dumps(commandDict)).encode() + )) self.sock.flush() def errstr(self):