Add the ability to allow notifications, and add type hinting
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful

This commit is contained in:
Raoul Snyman 2024-09-27 13:34:01 -05:00
parent b96e08436f
commit 294dba50e8

View File

@ -55,7 +55,8 @@ class WebWindow(QtWidgets.QWidget):
""" """
A window with a single web view and nothing else A window with a single web view and nothing else
""" """
def __init__(self, app, title, url, icon, can_minimize_to_tray=False, canMinimizeToTray=False): def __init__(self, app: 'WebApp', title: str, url: str, icon: str, can_minimize_to_tray: bool = False,
allow_notifications: bool = False):
""" """
Create the window Create the window
""" """
@ -63,7 +64,7 @@ class WebWindow(QtWidgets.QWidget):
self._has_shown_warning = False self._has_shown_warning = False
self.app = app self.app = app
self.icon = QtGui.QIcon(icon) self.icon = QtGui.QIcon(icon)
self.can_minimize_to_tray = can_minimize_to_tray or canMinimizeToTray self.can_minimize_to_tray = can_minimize_to_tray or allow_notifications
self.setWindowTitle(title) self.setWindowTitle(title)
self.setWindowIcon(self.icon) self.setWindowIcon(self.icon)
self.setContentsMargins(0, 0, 0, 0) self.setContentsMargins(0, 0, 0, 0)
@ -71,12 +72,27 @@ class WebWindow(QtWidgets.QWidget):
self.layout.setContentsMargins(0, 0, 0, 0) self.layout.setContentsMargins(0, 0, 0, 0)
self.webview = QtWebEngineWidgets.QWebEngineView(self) self.webview = QtWebEngineWidgets.QWebEngineView(self)
self.webview.setPage(WebPage(self.webview)) self.webview.setPage(WebPage(self.webview))
if allow_notifications:
self.webview.page().featurePermissionRequested.connect(self._handle_notifications_requested)
self.webview.page().profile().setNotificationPresenter(self._present_notification)
for setting in SETTINGS: for setting in SETTINGS:
self.webview.settings().setAttribute(setting, True) self.webview.settings().setAttribute(setting, True)
self.webview.setUrl(QtCore.QUrl(url)) self.webview.setUrl(QtCore.QUrl(url))
self.layout.addWidget(self.webview) self.layout.addWidget(self.webview)
self.webview.titleChanged.connect(self.on_title_changed) self.webview.titleChanged.connect(self.on_title_changed)
def _handle_notifications_requested(self, origin: QtCore.QUrl, feature: QtWebEngineCore.QWebEnginePage.Feature):
"""Handle when notifications are requested and implicitly allow them"""
if feature != QtWebEngineCore.QWebEnginePage.Feature.Notifications:
return
self.webview.page().setFeaturePermission(
origin, feature, QtWebEngineCore.QWebEnginePage.PermissionPolicy.PermissionGrantedByUser
)
def _present_notification(self, notification: QtWebEngineCore.QWebEngineNotification):
"""Show a notification from the browser"""
self.tray_icon.showMessage(notification.title(), notification.message())
def _show_warning(self): def _show_warning(self):
""" """
Show a balloon message to inform the user that the app is minimized Show a balloon message to inform the user that the app is minimized
@ -84,7 +100,7 @@ class WebWindow(QtWidgets.QWidget):
if not self._has_shown_warning: if not self._has_shown_warning:
self.tray_icon.showMessage(self.windowTitle(), 'This program will continue running in the system tray. ' self.tray_icon.showMessage(self.windowTitle(), 'This program will continue running in the system tray. '
'To close the program, choose <b>Quit</b> in the context menu of the system ' 'To close the program, choose <b>Quit</b> in the context menu of the system '
'tray icon.', QtWidgets.QSystemTrayIcon.Information, 5000) 'tray icon.')
self._has_shown_warning = True self._has_shown_warning = True
def _update_tray_menu(self): def _update_tray_menu(self):
@ -144,7 +160,7 @@ class WebWindow(QtWidgets.QWidget):
self.tray_icon.activated.connect(self.on_tray_icon_activated) self.tray_icon.activated.connect(self.on_tray_icon_activated)
self.tray_icon.show() self.tray_icon.show()
def closeEvent(self, event): def closeEvent(self, event: QtCore.QEvent):
""" """
Override the close event to minimize to the tray Override the close event to minimize to the tray
""" """
@ -162,21 +178,21 @@ class WebWindow(QtWidgets.QWidget):
# Update the menu to match # Update the menu to match
self._update_tray_menu() self._update_tray_menu()
def showEvent(self, event): def showEvent(self, event: QtCore.QEvent):
""" """
Override the show event to catch max/min/etc events and update the tray icon menu accordingly Override the show event to catch max/min/etc events and update the tray icon menu accordingly
""" """
super(WebWindow, self).showEvent(event) super(WebWindow, self).showEvent(event)
self._update_tray_menu() self._update_tray_menu()
def hideEvent(self, event): def hideEvent(self, event: QtCore.QEvent):
""" """
Override the hide event to catch max/min/etc events and update the tray icon menu accordingly Override the hide event to catch max/min/etc events and update the tray icon menu accordingly
""" """
super(WebWindow, self).hideEvent(event) super(WebWindow, self).hideEvent(event)
self._update_tray_menu() self._update_tray_menu()
def changeEvent(self, event): def changeEvent(self, event: QtCore.QEvent):
""" """
Catch the minimize event and close the form Catch the minimize event and close the form
""" """
@ -185,7 +201,7 @@ class WebWindow(QtWidgets.QWidget):
self.close() self.close()
super(WebWindow, self).changeEvent(event) super(WebWindow, self).changeEvent(event)
def on_title_changed(self, title): def on_title_changed(self, title: str):
""" """
React to title changes React to title changes
""" """
@ -194,11 +210,11 @@ class WebWindow(QtWidgets.QWidget):
if self.can_minimize_to_tray: if self.can_minimize_to_tray:
self.tray_icon.setToolTip(title) self.tray_icon.setToolTip(title)
def on_tray_icon_activated(self, reason): def on_tray_icon_activated(self, reason: QtWidgets.QSystemTrayIcon.ActivationReason):
""" """
React to the tray icon being activated React to the tray icon being activated
""" """
if reason == QtWidgets.QSystemTrayIcon.Trigger: if reason == QtWidgets.QSystemTrayIcon.ActivationReason.Trigger:
if self.isVisible(): if self.isVisible():
self.close() self.close()
else: else:
@ -209,7 +225,8 @@ class WebApp(QtWidgets.QApplication):
""" """
A generic application to open a web page in a desktop app A generic application to open a web page in a desktop app
""" """
def __init__(self, title, url, icon, can_minimize_to_tray=False): def __init__(self, title: str, url: str, icon: str, can_minimize_to_tray: bool = False,
allow_notifications: bool = False):
""" """
Create an application which loads a URL into a window Create an application which loads a URL into a window
""" """
@ -219,7 +236,9 @@ class WebApp(QtWidgets.QApplication):
self.title = title self.title = title
self.url = url self.url = url
self.icon = icon self.icon = icon
self.can_minimize_to_tray = QtWidgets.QSystemTrayIcon.isSystemTrayAvailable() and can_minimize_to_tray self.can_minimize_to_tray = QtWidgets.QSystemTrayIcon.isSystemTrayAvailable() and \
(can_minimize_to_tray or allow_notifications)
self.allow_notifications = allow_notifications
if self.can_minimize_to_tray: if self.can_minimize_to_tray:
self.setQuitOnLastWindowClosed(False) self.setQuitOnLastWindowClosed(False)
self.setWindowIcon(QtGui.QIcon(self.icon)) self.setWindowIcon(QtGui.QIcon(self.icon))
@ -230,7 +249,8 @@ class WebApp(QtWidgets.QApplication):
""" """
Set up the window and the tray icon, and run the app Set up the window and the tray icon, and run the app
""" """
self.window = WebWindow(self, self.title, self.url, self.icon, self.can_minimize_to_tray) self.window = WebWindow(self, self.title, self.url, self.icon, self.can_minimize_to_tray,
self.allow_notifications)
if self.can_minimize_to_tray: if self.can_minimize_to_tray:
self.window.setup_tray_icon() self.window.setup_tray_icon()
self.window.showMaximized() self.window.showMaximized()