Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open Custom File Extension (MacOS CFBundleTypeExtensions) #569

Open
jmitchel3 opened this issue Jul 11, 2020 · 5 comments
Open

Open Custom File Extension (MacOS CFBundleTypeExtensions) #569

jmitchel3 opened this issue Jul 11, 2020 · 5 comments
Labels

Comments

@jmitchel3
Copy link

Specification

  • pywebview version: 3.3.1
  • platform / version: macOS 0.15.5 and Windows 10

Description

First off. This is an amazing project. Thank you for creating pywebview!!

An event handler for when a file is opened for a specific file extension/type in macOS I believe it's CFBundleTypeExtensions in the plist. I'm able to get pywebview to open using this setting but unable to handle the file being opened. Here's the plist argument I'm passing in setup.py:

OPTIONS = {..
          'plist': {
                'CFBundleName': "MyApp",
                'CFBundleDisplayName': "MyApp",
                'CFBundleGetInfoString': "App it Up",
                'CFBundleIdentifier': "com.example.app",
                'CFBundleVersion': "0.1.0",
                "CFBundleTypeRole": "editor",
                "CFBundleTypeExtensions": ["appy-mc-apperson"],
                'CFBundleShortVersionString': "0.1.0",
                'NSHumanReadableCopyright': u"Copyright © 2020, Justin Mitchel, All Rights Reserved"
            }
}

The appy-mc-apperson represents something like my-project.appy-mc-apperson to, ideally, re-open our application and re-load the project. For context, .appy-mc-apperson is an arbitrary extension I made up for this post.

This works in Electron fairly simply as you can see here under fileAssociations. This would allow pywebview apps to resume projects that are being worked on which would be key for several projects I'm working on.

Practicalities

-YES. Happy to help however I can.
-YES. I am prepared to support this issue financially within reason of course. I'm trying not to use Electron as much since it's so bloated especially for tiny projects.

@r0x0r
Copy link
Owner

r0x0r commented Jul 14, 2020

I am not familiar with this API, but this definitely should be implemented.
Without dwelling into details, I believe an appropriate event handler should be added to cocoa.py. Other platforms should be investigated as well.

@r0x0r r0x0r added the future label Jul 14, 2020
@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale label Aug 26, 2020
@r0x0r r0x0r removed the stale label Aug 26, 2020
@Ksengine
Copy link
Contributor

Ksengine commented Dec 2, 2020

@jmitchel3 can you explain more

@jmitchel3
Copy link
Author

I wanted to add an update here based on something that's nearly working with py2app configuration.

OPTIONS = {
    "argv_emulation": True,
    ...
    "plist": {
        'CFBundleName': "MyApp",
                'CFBundleDisplayName': "MyApp",
                'CFBundleGetInfoString': "App it Up",
                'CFBundleIdentifier': "com.example.app",
                'CFBundleVersion': "0.1.0",
                "CFBundleTypeRole": "Editor",
                "CFBundleTypeExtensions": ["appy-mc-apperson"],
                "CFBundleTypeIconFile": "icon.icns",
                'CFBundleShortVersionString': "0.1.0",
                'NSHumanReadableCopyright': u"Copyright © 2020, Justin Mitchel, All Rights Reserved"
    },
}

Once you have "argv_emulation": True, the rest of your code will have access to another argument in sys.argv.

When you open your file extension, in this case I called it appy-mc-apperson which means if I double click my-project.appy-mc-apperson I see the following:

Screen Shot 2021-02-01 at 11 20 26 AM

Once you select your pywebview built app, my-project.appy-mc-apperson will always open your app with a new argument in sys.argv:

print(sys.argv[1]) 
# prints path/to/system/location/of/my-project.appy-mc-apperson

This sys.argv[1], if available, is a path to the my-project.appy-mc-apperson file. You can read this file as needed in your pywebview project.

If your app is not open, it works! (without changes to cocoa.py). However, f your app is open and you double-click to open an associated file you'll see this error:

Screen Shot 2021-02-01 at 11 24 33 AM.

I'd guess that pyinstaller might have a different way of implementing this same idea. It stands to reason that when you open any file on your system, the OS will open the application with an argument for that file path.

I think we still need to solve:

  • Errors on multiple file opening
  • Automatic system-wide file association on app opening
  • Cross platform support
  • Simple menu support (including cmd+o and cmd+s)

@alvinwan
Copy link

alvinwan commented Jun 25, 2023

For anyone that stumbles upon this issue, you can solve the above issue by following these three steps:

  1. Switch to the webview.start(gui='qt') engine, as it's more configurable.
  2. Turn off argv_emulation. Rely on the qt engine's event handling instead of py2app's event handling.
  3. Add an event handler to webview's qt engine, similar to this SO answer.

Here's a minimal change to the hello world pywebview script that shows the idea.

app.py

import webview
import webview.platforms.qt
from qtpy.QtWidgets import QApplication
from qtpy.QtCore import QEvent
import webview.platforms.qt  # needed for us to define a custom application


class MainApplication(QApplication):
    def event(self, event: QEvent):
        if event.type() == QEvent.Type.FileOpen:
            print(event.url())
        return super().event(event)


if __name__ == '__main__':
    app = MainApplication([])  # so that when pywebview calls `QApplication.instance()` your app is returned
    webview.create_window('Hello world', 'https://pywebview.flowrl.com/')
    webview.start(gui='qt')

setup.py

"""Simple setup script for actually building your application. See README"""

from setuptools import setup

APP = ['app.py']  # your main application
OPTIONS = {
    'plist': {
        'CFBundleURLTypes': [
            {
                'CFBundleURLName': 'MyApplication',
                'CFBundleURLSchemes': ['myapp'],
            },
        ],
    },
    'strip': True,
    'includes': ['WebKit', 'Foundation', 'webview'],
}

setup(
    app=APP,
    options={'py2app': OPTIONS},
    setup_requires=['py2app', 'pyqt6'],  # add other dependencies here
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants