WebEngine Notifications Example#

Python port of C++ WebEngine Notifications

Notifications Example Screenshot
"""PySide6 WebEngineWidgets Notifications Example"""

import sys
from pathlib import Path

from PySide6.QtCore import QUrl, QCoreApplication
from PySide6.QtWidgets import QApplication
from PySide6.QtWebEngineCore import QWebEnginePage
from PySide6.QtWebEngineWidgets import QWebEngineView
from PySide6.QtGui import QDesktopServices

from notificationpopup import NotificationPopup


class WebEnginePage(QWebEnginePage):
    def __init__(self, parent):
        super().__init__(parent)

    def acceptNavigationRequest(self, url: QUrl, *_):
        if url.scheme != "https":
            return True
        QDesktopServices.openUrl(url)
        return False


if __name__ == '__main__':

    src_dir = Path(__file__).resolve().parent
    QCoreApplication.setOrganizationName("QtProject")
    app = QApplication(sys.argv)
    view = QWebEngineView()

    # set custom page to open all page's links for https scheme in system browser
    view.setPage(WebEnginePage(view))

    def set_feature_permission(origin: QUrl, feature: QWebEnginePage.Feature):
        if feature != QWebEnginePage.Notifications:
            return

        view.page().setFeaturePermission(origin, feature, QWebEnginePage.PermissionGrantedByUser)

    view.page().featurePermissionRequested.connect(set_feature_permission)
    profile = view.page().profile()
    popup = NotificationPopup(view)

    def presentNotification(notification):
        popup.present(notification)

    profile.setNotificationPresenter(presentNotification)
    view.resize(640, 480)
    view.show()
    view.setUrl(QUrl.fromLocalFile(src_dir / "resources" / "index.html"))

    sys.exit(app.exec())
from PySide6.QtCore import Qt, QTimer, QPoint, Slot
from PySide6.QtWidgets import (QWidget, QHBoxLayout, QLabel, QVBoxLayout, QSpacerItem, QSizePolicy,
                               QPushButton)
from PySide6.QtWebEngineCore import QWebEngineNotification
from PySide6.QtGui import QPixmap, QMouseEvent


class NotificationPopup(QWidget):
    def __init__(self, parent) -> None:
        super().__init__(parent)
        self.notification = None
        self.m_icon, self.m_title, self.m_message = QLabel(), QLabel(), QLabel()
        self.setWindowFlags(Qt.ToolTip)

        rootLayout = QHBoxLayout(self)
        rootLayout.addWidget(self.m_icon)

        bodyLayout = QVBoxLayout()
        rootLayout.addLayout(bodyLayout)

        titleLayout = QHBoxLayout()
        bodyLayout.addLayout(titleLayout)

        titleLayout.addWidget(self.m_title)
        titleLayout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding))

        close = QPushButton("Close")
        titleLayout.addWidget(close)
        close.clicked.connect(self.onClosed)

        bodyLayout.addWidget(self.m_message)
        self.adjustSize()

    def present(self, newNotification: QWebEngineNotification):
        if self.notification:
            self.notification.close()

        self.notification = newNotification

        self.m_title.setText("<b>" + self.notification.title() + "</b>")
        self.m_message.setText(self.notification.message())
        self.m_icon.setPixmap(QPixmap.fromImage(self.notification.icon())
                              .scaledToHeight(self.m_icon.height()))

        self.show()
        self.notification.show()

        self.notification.closed.connect(self.onClosed)
        QTimer.singleShot(10000, lambda: self.onClosed())

        self.move(self.parentWidget().mapToGlobal(self.parentWidget().rect().bottomRight() -
                  QPoint(self.width() + 10, self.height() + 10)))

    @Slot()
    def onClosed(self):
        self.hide()
        if self.notification:
            self.notification.close()
        self.notification = None

    def mouseReleaseEvent(self, event: QMouseEvent) -> None:
        QWidget.mouseReleaseEvent(event)
        if self.notification and event.button() == Qt.LeftButton:
            self.notification.click()
            self.onClosed()