How to accept "open document" events in py2app based Python app when the app is already running?

678 views Asked by At

I've been building a 64 bit Python 3.4.2 app on OS X 10.10, which I bundle as a Mac app using py2app 0.9. I have adapted the app's Info.plist file, so that OS X knows that files with a certain file name suffix can be opened by my app.

When a user double-clicks a file with a certain file name suffix in the Finder, this opens the app and sends the name of the double-clicked file as an argument to the app.

If the app is already running, though, and I double-click a second file with a matching file name suffix, this file name doesn't seem to be handed over to my app.

And this is exactly what I try to implement: no matter if my app is already running, if I double-click a matching file in the Finder, it should be opened in my app.

I have seen that py2app creates the file Contents/Resources/boot.py, which seems to catch the odoc Apple Event sent by the Finder, and sends it to my Python app.

I added some logging to the boot.py file and saw that boot.py doesn't seem to be invoked when my py2app bundled Python app is already running and I double-click a file in the Finder.

Any input would be appreciated.

Thanks a lot in advance,

André

2

There are 2 answers

3
André Aulich On BEST ANSWER

I just learned, that Tk on a Mac can process some AppleEvents, like e.g. opening documents.

There's a good example at code.activestate.com/lists/pythonmac-sig/23079 and the Mac specific Tk functions are listed at tcl.tk/man/tcl/TkCmd/tk_mac.htm. Basically you just add something like

tk.createcommand("::tk::mac::OpenDocument", doOpenFile)

to your Tk event loop, where doOpenFile needs to point to a function like this:

def doOpenFile(*args):
     for f in args:
         do something

This works well in Python 2.7 and Python 3.4.2 (haven't tested other versions).

0
Vignesh Arunachalam On

If someone is wondering how to do this with PyQt and py2app:

from PyQt6.QtWidgets import QApplication, QMainWindow, QPlainTextEdit
from PyQt6.QtCore import QEvent


class MyApp(QApplication): # subclass the QApplication class
    def __init__(self, argv):
        super().__init__(argv)

        self.mainWindow = QMainWindow()
        self.textEdit = QPlainTextEdit()
        self.mainWindow.setCentralWidget(self.textEdit)
        self.mainWindow.show()

    def event(self, event: QEvent): # override the event method
        if event.type() == QEvent.Type.FileOpen: # filter the File Open event
            filePath = event.file() # get the file name from the event

            with open(filePath, 'r') as f:
                text = f.read()
            self.textEdit.setPlainText(text)

        return super().event(event)


if __name__ == "__main__":
    app = MyApp([])
    app.exec()

Refer: https://doc.qt.io/qtforpython-5/PySide2/QtGui/QFileOpenEvent.html

Tried this on PyQt6 and python3.11.