Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QtSingleApplication for PySide or PyQt

Is there a Python version of the C++ class QtSingleApplication from Qt Solutions?

QtSingleApplication is used to make sure that there can never be more than one instance of an application running at the same time.

like image 211
Johan Råde Avatar asked Oct 03 '12 16:10

Johan Råde


People also ask

Why Qt classes are not available on PySide?

Therefore Qt classes such as QStrings, QStringLists, and QVariants are not available on PySide. Instead, you should simply use native Python datatypes.

What's the difference between PyQt and PySide?

In 2009 Nokia, who owned Qt toolkit at the time, wanted to make the Python bindings for Qt available in a more permissive LGPL license. It's called PySide because "side" is Finnish for "binder". The two interfaces were basically equivalent, but over time development of PySide lagged behind PyQt.

Why does PyQt use Qt instead of Python?

This avoids many tedious conversions to and from Qt types, and thus eases programming and avoids many errors. PyQt also supports this modern API, and uses it by default for Python 3, but not for Python 2 to maintain backwards compatibility.

Should I use PySide or qt6 for Python bindings?

However, the Qt project has recently adopted PySide as the official Qt for Python release which should ensure its viability going forward. When Qt6 was released, both Python bindings were available shortly after. Which should you use? Well, honestly, it doesn't really matter.


2 Answers

You can have a look to this blog entry. It is for Pyside but I guess that it will work too with PyQt4.

like image 38
Vicent Avatar answered Oct 06 '22 19:10

Vicent


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. 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_())
like image 76
Johan Råde Avatar answered Oct 06 '22 17:10

Johan Råde