Toolbox/SingleApplication.py

branch
maintenance
changeset 6646
51eefa621de4
parent 6645
ad476851d7e0
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):

eric ide

mercurial