QtSingleApplication for PySide or PyQt
Question: Is there a Python version of the C++ class
[`QtSingleApplication`](http://doc.qt.digia.com/solutions/4/qtsingleapplication/qtsingleapplication.html)
from [Qt Solutions](http://qt.digia.com/Product/Qt-Add-Ons/Qt-Solutions-
Archive/)?

[`QtSingleApplication`](http://doc.qt.digia.com/solutions/4/qtsingleapplication/qtsingleapplication.html)
is used to make sure that there can never be more than one instance of an
application running at the same time.


Answer: Here is my own implementation. It has been tested with Python 2.7 and PySide
1.1.

It has essentially the same interface as the [C++ version of
`QtSingleApplication`](http://doc.qt.digia.com/solutions/4/qtsingleapplication/qtsingleapplication.html).
The main difference is that you must supply an application unique id to the
constructor. (The C++ version by default uses the path to the executable as a
unique id; that would not work here because the executable will most likely be
`python.exe`.)

    
    
    from PySide.QtCore import *
    from PySide.QtGui import *
    from PySide.QtNetwork import *
    
    class QtSingleApplication(QApplication):
    
        messageReceived = Signal(unicode)
    
        def __init__(self, id, *argv):
    
            super(QtSingleApplication, self).__init__(*argv)
            self._id = id
            self._activationWindow = None
            self._activateOnMessage = False
    
            # Is there another instance running?
            self._outSocket = QLocalSocket()
            self._outSocket.connectToServer(self._id)
            self._isRunning = self._outSocket.waitForConnected()
    
            if self._isRunning:
                # Yes, there is.
                self._outStream = QTextStream(self._outSocket)
                self._outStream.setCodec('UTF-8')
            else:
                # No, there isn't.
                self._outSocket = None
                self._outStream = None
                self._inSocket = None
                self._inStream = None
                self._server = QLocalServer()
                self._server.listen(self._id)
                self._server.newConnection.connect(self._onNewConnection)
    
        def isRunning(self):
            return self._isRunning
    
        def id(self):
            return self._id
    
        def activationWindow(self):
            return self._activationWindow
    
        def setActivationWindow(self, activationWindow, activateOnMessage = True):
            self._activationWindow = activationWindow
            self._activateOnMessage = activateOnMessage
    
        def activateWindow(self):
            if not self._activationWindow:
                return
            self._activationWindow.setWindowState(
                self._activationWindow.windowState() & ~Qt.WindowMinimized)
            self._activationWindow.raise_()
            self._activationWindow.activateWindow()
    
        def sendMessage(self, msg):
            if not self._outStream:
                return False
            self._outStream << msg << '\n'
            self._outStream.flush()
            return self._outSocket.waitForBytesWritten()
    
        def _onNewConnection(self):
            if self._inSocket:
                self._inSocket.readyRead.disconnect(self._onReadyRead)
            self._inSocket = self._server.nextPendingConnection()
            if not self._inSocket:
                return
            self._inStream = QTextStream(self._inSocket)
            self._inStream.setCodec('UTF-8')
            self._inSocket.readyRead.connect(self._onReadyRead)
            if self._activateOnMessage:
                self.activateWindow()
    
        def _onReadyRead(self):
            while True:
                msg = self._inStream.readLine()
                if not msg: break
                self.messageReceived.emit(msg)
    

Here is a simple test program:

    
    
    import sys
    from PySide.QtGui import *
    from QtSingleApplication import QtSingleApplication
    
    appGuid = 'F3FF80BA-BA05-4277-8063-82A6DB9245A2'
    app = QtSingleApplication(appGuid, sys.argv)
    if app.isRunning(): sys.exit(0)
    
    w = QWidget()
    w.show()
    app.setActivationWindow(w)
    sys.exit(app.exec_())
    

