Sep-11-2018, 02:28 PM
To be more specific, here are the details. I use QtDBus as a command line interface. When the application is launched, it verify if a dbus already exist. If it does, it simply pass the command throught it and exit. Else, it create a new instance of the program. Therefore the app is opened only once and can receive commands system wide.
I use the example below in many of my apps, just by replacing "foo" with the app name. Therefore I would like to use qdbus.py as a module without having to modify it's code manually every time. To do so I need to customize the content of Q_CLASSINFO dynamically, or to find an alternate way to apply the same settings on the class object.
In the attempts above, no error occur, but the dbus object is not created with the appropriate header. So I thought that perhaps, there might be other ways to set "D-Bus Interface" and "D-Bus Introspection" properties, that would be more suitable for portable code.
__init__.py
I use the example below in many of my apps, just by replacing "foo" with the app name. Therefore I would like to use qdbus.py as a module without having to modify it's code manually every time. To do so I need to customize the content of Q_CLASSINFO dynamically, or to find an alternate way to apply the same settings on the class object.
In the attempts above, no error occur, but the dbus object is not created with the appropriate header. So I thought that perhaps, there might be other ways to set "D-Bus Interface" and "D-Bus Introspection" properties, that would be more suitable for portable code.
__init__.py
#!/usr/bin/python3 from PyQt5 import QtDBus import sys def main(): # Look for the dbus object bus = QtDBus.QDBusConnection.sessionBus() interface = QtDBus.QDBusInterface("org.foo.session", "/org/foo/session", "org.foo.session", bus) # Pass the arguments to the existing bus cmd = "%".join(str(arg) for arg in sys.argv[1:]) if interface.isValid(): interface.call("parse", cmd) sys.exit(0) else: # Create a new instance import foo foo.main() if __name__ == '__main__': main()foo.py
#!/usr/bin/python3 import os import sys from PyQt5 import QtWidgets, QtCore, QtDBus import qdbus class Main(QtWidgets.QMainWindow): def __init__(self, parent): super().__init__() self.parent = parent self.bus = qdbus.QDBusObject(self) self.bus.cli.connect(self.parseCommands) def parseCommands(self, cmd): if "action" in cmd: for action in cmd["action"]: print("exec:", action) if "echo" in cmd: print(cmd["echo"]) if "quit" in cmd: self.parent.exit() def main(): app = QtWidgets.QApplication([]) app.setQuitOnLastWindowClosed(False) daemon = Main(app) sys.exit(app.exec_())qdbus.py
#!/usr/bin/python3 from PyQt5 import QtCore, QtDBus global name; name = "foo" class QDBusObject(QtCore.QObject): cli = QtCore.pyqtSignal(object) def __init__(self, parent): QtCore.QObject.__init__(self) self.__dbusAdaptor = QDBusServerAdapter(self) self.start() def start(self): bus = QtDBus.QDBusConnection.sessionBus() bus.registerObject(f"/org/{name}/session", self) bus.registerService(f"org.{name}.session") return bus class QDBusServerAdapter(QtDBus.QDBusAbstractAdaptor): QtCore.Q_CLASSINFO("D-Bus Interface", f"org.{name}.session") QtCore.Q_CLASSINFO("D-Bus Introspection", f'<interface name="org.{name}.session">\n' ' <method name="parse">\n' ' <arg direction="in" type="s" name="cmd"/>\n' ' </method>\n' '</interface>\n') def __init__(self, parent): super().__init__(parent) self.parent = parent @QtCore.pyqtSlot(str) def parse(self, cmd): # Serialize the string of commands if cmd: commands = {} current = "" for arg in cmd.split("%"): if arg.startswith("-"): current = arg.lstrip("-") elif current: commands[current].append(arg) if current not in commands: commands[current] = [] self.parent.cli.emit(commands)