Sat, 26 Sep 2020 10:58:18 +0200

Detlev Offenbach <>
Sat, 26 Sep 2020 10:58:18 +0200
changeset 7717
parent 7716
child 7761

Changed the code to not rely on the Qt Resource system anymore (no .qrc files and no use of pyrcc5 anymore).

# -*- coding: utf-8 -*-

# Copyright (c) 2016 - 2020 Detlev Offenbach <>

Module implementing a scheme handler for the eric: scheme.

from PyQt5.QtCore import (
    pyqtSignal, QByteArray, QBuffer, QIODevice, QUrlQuery, QMutex, QMutexLocker
from PyQt5.QtWidgets import qApp
from PyQt5.QtWebEngineCore import QWebEngineUrlSchemeHandler

from ..Tools.WebBrowserTools import (
    getHtmlPage, getJavascript, pixmapFileToDataUrl

class EricSchemeHandler(QWebEngineUrlSchemeHandler):
    Class implementing a scheme handler for the eric: scheme.
    SupportedPages = [
        "adblock",          # error page for URLs blocked by AdBlock
        "home", "start", "startpage",       # eric home page
        "speeddial",                        # eric speeddial
    def __init__(self, parent=None):
        @param parent reference to the parent object
        @type QObject
        super(EricSchemeHandler, self).__init__(parent)
        self.__replies = []
    def requestStarted(self, job):
        Public method handling the URL request.
        @param job URL request job
        @type QWebEngineUrlRequestJob
        if job.requestUrl().path() in self.SupportedPages:
            reply = EricSchemeReply(job)
            reply.closed.connect(lambda: self.__replyClosed(reply))
            job.reply(b"text/html", reply)
            job.reply(QByteArray(), QBuffer())
    def __replyClosed(self, reply):
        Private slot handling the closed signal of a reply.
        @param reply reference to the network reply
        @type EricSchemeReply
        if reply in self.__replies:

class EricSchemeReply(QIODevice):
    Class implementing a reply for a requested eric: page.
    @signal closed emitted to signal that the web engine has read
        the data
    closed = pyqtSignal()
    _speedDialPage = ""
    def __init__(self, job, parent=None):
        @param job reference to the URL request
        @type QWebEngineUrlRequestJob
        @param parent reference to the parent object
        @type QObject
        super(EricSchemeReply, self).__init__(parent)
        self.__loaded = False
        self.__job = job
        self.__mutex = QMutex()
        self.__pageName = self.__job.requestUrl().path()
        self.__buffer = QBuffer()
    def __loadPage(self):
        Private method to load the requested page.
        if self.__loaded:
        lock = QMutexLocker(self.__mutex)
        if self.__pageName == "adblock":
            contents = self.__adBlockPage()
        elif self.__pageName in ["home", "start", "startpage"]:
            contents = self.__startPage()
        elif self.__pageName == "speeddial":
            contents = self.__speedDialPage()
            contents = ""
        self.__loaded = True
    def bytesAvailable(self):
        Public method to get the number of available bytes.
        @return number of available bytes
        @rtype int
        lock = QMutexLocker(self.__mutex)       # __IGNORE_WARNING__
        return self.__buffer.bytesAvailable()
    def readData(self, maxlen):
        Public method to retrieve data from the reply object.
        @param maxlen maximum number of bytes to read (integer)
        @return string containing the data (bytes)
        lock = QMutexLocker(self.__mutex)       # __IGNORE_WARNING__
    def close(self):
        Public method used to cloase the reply.
        super(EricSchemeReply, self).close()
    def __adBlockPage(self):
        Private method to build the AdBlock page.
        @return built AdBlock page
        @rtype str
        query = QUrlQuery(self.__job.requestUrl())
        rule = query.queryItemValue("rule")
        subscription = query.queryItemValue("subscription")
        title ="Content blocked by AdBlock Plus")
        message =
            "Blocked by rule: <i>{0} ({1})</i>").format(rule, subscription)
        page = getHtmlPage("adblockPage.html")
        page = page.replace(
            "@FAVICON@", pixmapFileToDataUrl("adBlockPlus16.png", True))
        page = page.replace(
            "@IMAGE@", pixmapFileToDataUrl("adBlockPlus64.png", True))
        page = page.replace("@TITLE@", title)
        page = page.replace("@MESSAGE@", message)
        return page
    def __startPage(self):
        Private method to build the Start page.
        @return built Start page
        @rtype str
        page = getHtmlPage("startPage.html")
        page = page.replace(
            "@FAVICON@", pixmapFileToDataUrl("ericWeb16.png", True))
        page = page.replace(
            "@IMAGE@", pixmapFileToDataUrl("ericWeb32.png", True))
        page = page.replace(
            "@TITLE@","Welcome to eric6 Web Browser!"))
        page = page.replace("@ERIC_LINK@","About eric6"))
        page = page.replace("@HEADER_TITLE@","eric6 Web Browser"))
        page = page.replace("@SUBMIT@","Search!"))
        if qApp.isLeftToRight():
            ltr = "LTR"
            ltr = "RTL"
        page = page.replace("@QT_LAYOUT_DIRECTION@", ltr)
        return page
    def __speedDialPage(self):
        Private method to create the Speeddial page.
        @return prepared speeddial page
        @rtype str
        if not self._speedDialPage:
            page = getHtmlPage("speeddialPage.html")
            page = page.replace(
                "@FAVICON@", pixmapFileToDataUrl("ericWeb16.png", True))
            page = page.replace(
                "@IMG_PLUS@", pixmapFileToDataUrl("plus.png", True))
            page = page.replace(
                "@IMG_CLOSE@", pixmapFileToDataUrl("close.png", True))
            page = page.replace(
                "@IMG_EDIT@", pixmapFileToDataUrl("edit.png", True))
            page = page.replace(
                "@IMG_RELOAD@", pixmapFileToDataUrl("reload.png", True))
            page = page.replace(
                "@IMG_SETTINGS@", pixmapFileToDataUrl("setting.png", True))
            page = page.replace(
                "@LOADING-IMG@", pixmapFileToDataUrl("loading.gif", True))
            page = page.replace(
                pixmapFileToDataUrl("box-border-small.png", True))
            page = page.replace("@JQUERY@", getJavascript("jquery.js"))
            page = page.replace("@JQUERY-UI@", getJavascript("jquery-ui.js"))
            page = page.replace("@SITE-TITLE@","Speed Dial"))
            page = page.replace("@URL@","URL"))
            page = page.replace("@TITLE@","Title"))
            page = page.replace("@APPLY@","Apply"))
            page = page.replace("@CLOSE@","Close"))
            page = page.replace("@NEW-PAGE@","New Page"))
            page = page.replace("@TITLE-EDIT@","Edit"))
            page = page.replace("@TITLE-REMOVE@","Remove"))
            page = page.replace("@TITLE-RELOAD@","Reload"))
            page = page.replace("@TITLE-WARN@",
                      "Are you sure to remove this"
                                        " speed dial?"))
            page = page.replace("@TITLE-WARN-REL@",
                      "Are you sure you want to reload"
                                        " all speed dials?"))
            page = page.replace("@TITLE-FETCHTITLE@",
                      "Load title from page"))
            page = page.replace("@SETTINGS-TITLE@",
                      "Speed Dial Settings"))
            page = page.replace("@ADD-TITLE@","Add New Page"))
            page = page.replace("@TXT_NRROWS@",
                      "Maximum pages in a row:"))
            page = page.replace("@TXT_SDSIZE@",
                      "Change size of pages:"))
            page = page.replace("@JAVASCRIPT_DISABLED@",
                      "SpeedDial requires enabled"
                                        " JavaScript."))
            self._speedDialPage = page
        from WebBrowser.WebBrowserWindow import WebBrowserWindow
        dial = WebBrowserWindow.speedDial()
        page = (
            .replace("@INITIAL-SCRIPT@", dial.initialScript())
            .replace("@ROW-PAGES@", str(dial.pagesInRow()))
            .replace("@SD-SIZE@", str(dial.sdSize()))
        return page

eric ide