<commit_before># Copyright: <NAME> <<EMAIL>>
# -*- coding: utf-8 -*-
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html

import sys
from anki.hooks import runHook
from aqt.qt import *
from aqt.utils import openLink
from anki.utils import isMac, isWin
import anki.js

# Page for debug messages
##########################################################################

class AnkiWebPage(QWebEnginePage):

    def __init__(self, onBridgeCmd):
        QWebEnginePage.__init__(self)
        self._onBridgeCmd = onBridgeCmd
        self._setupBridge()

    def _setupBridge(self):
        class Bridge(QObject):
            @pyqtSlot(str)
            def cmd(self, str):
                self.onCmd(str)

        self._bridge = Bridge()
        self._bridge.onCmd = self._onCmd

        self._channel = QWebChannel(self)
        self._channel.registerObject("py", self._bridge)
        self.setWebChannel(self._channel)

        js = QFile(':/qtwebchannel/qwebchannel.js')
        assert js.open(QIODevice.ReadOnly)
        js = bytes(js.readAll()).decode('utf-8')

        script = QWebEngineScript()
        script.setSourceCode(js + '''
            var pycmd;
            new QWebChannel(qt.webChannelTransport, function(channel) {
                pycmd = channel.objects.py.cmd;
                pycmd("domDone");
            });
        ''')
        script.setWorldId(QWebEngineScript.MainWorld)
        script.setInjectionPoint(QWebEngineScript.DocumentReady)
        script.setRunsOnSubFrames(False)
        self.profile().scripts().insert(script)

    def javaScriptConsoleMessage(self, lvl, msg, line, srcID):
        sys.stdout.write(
            (_("JS error on line %(a)d: %(b)s") %
             dict(a=line, b=msg+"\n")))

    def acceptNavigationRequest(self, url, navType, isMainFrame):
        # load all other links in browser
        openLink(url)
        return False

    def _onCmd(self, str):
        self._onBridgeCmd(str)

# Main web view
##########################################################################

class AnkiWebView(QWebEngineView):

    def __init__(self, canFocus=True):
        QWebEngineView.__init__(self)
        self.setObjectName("mainText")
        self._page = AnkiWebPage(self._onBridgeCmd)

        self._loadFinishedCB = None
        self.setPage(self._page)
        self.resetHandlers()
        self.allowDrops = False
        self.setCanFocus(canFocus)
        self.installEventFilter(self)

    def eventFilter(self, obj, evt):
        if not isinstance(evt, QKeyEvent) or obj != self:
            return False
        if evt.matches(QKeySequence.Copy):
            self.onCopy()
            return True
        if evt.matches(QKeySequence.Cut):
            self.onCut()
            return True
        if evt.matches(QKeySequence.Paste):
            self.onPaste()
            return True
        if evt.key() == Qt.Key_Escape:
            # cheap hack to work around webengine swallowing escape key that
            # usually closes dialogs
            w = self.parent()
            while w:
                if isinstance(w, QDialog) or isinstance(w, QMainWindow):
                    from aqt import mw
                    if w != mw:
                        w.close()
                    break
                w = w.parent()
            return True
        return False

    def onCopy(self):
        self.triggerPageAction(QWebEnginePage.Copy)

    def onCut(self):
        self.triggerPageAction(QWebEnginePage.Cut)

    def onPaste(self):
        self.triggerPageAction(QWebEnginePage.Paste)

    def contextMenuEvent(self, evt):
        if not self._canFocus:
            return
        m = QMenu(self)
        a = m.addAction(_("Copy"))
        a.triggered.connect(lambda: self.triggerPageAction(QWebEnginePage.Copy))
        runHook("AnkiWebView.contextMenuEvent", self, m)
        m.popup(QCursor.pos())

    def dropEvent(self, evt):
        pass

    def setHtml(self, html):
        app = QApplication.instance()
        oldFocus = app.focusWidget()
        self._page.setHtml(html)
        # work around webengine stealing focus on setHtml()
        if oldFocus:
            oldFocus.setFocus()

    def zoomFactor(self):
        screen = QApplication.desktop().screen()
        dpi = screen.logicalDpiX()
        return max(1, dpi / 96.0)

    def stdHtml(self, body, css="", bodyClass="", js=None, head=""):
        self.setHtml("""
<!doctype html>
<html><head><style>
body { zoom: %f; }
%s</style>
<script>
%s
</script>
%s

</head>
<body class="%s">%s</body></html>""" % (<commit_msg>hack around broken qwebchannel behaviour<commit_after># Copyright: <NAME> <<EMAIL>>
# -*- coding: utf-8 -*-
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html

import sys
from anki.hooks import runHook
from aqt.qt import *
from aqt.utils import openLink
from anki.utils import isMac, isWin
import anki.js

# Page for debug messages
##########################################################################

class AnkiWebPage(QWebEnginePage):

    def __init__(self, onBridgeCmd):
        QWebEnginePage.__init__(self)
        self._onBridgeCmd = onBridgeCmd
        self._setupBridge()

    def _setupBridge(self):
        class Bridge(QObject):
            @pyqtSlot(str)
            def cmd(self, str):
                self.onCmd(str)

        self._bridge = Bridge()
        self._bridge.onCmd = self._onCmd

        self._channel = QWebChannel(self)
        self._channel.registerObject("py", self._bridge)
        self.setWebChannel(self._channel)

        js = QFile(':/qtwebchannel/qwebchannel.js')
        assert js.open(QIODevice.ReadOnly)
        js = bytes(js.readAll()).decode('utf-8')

        script = QWebEngineScript()
        script.setSourceCode(js + '''
            var pycmd;
            new QWebChannel(qt.webChannelTransport, function(channel) {
                pycmd = channel.objects.py.cmd;
                pycmd("domDone");
            });
        ''')
        script.setWorldId(QWebEngineScript.MainWorld)
        script.setInjectionPoint(QWebEngineScript.DocumentReady)
        script.setRunsOnSubFrames(False)
        self.profile().scripts().insert(script)

    def javaScriptConsoleMessage(self, lvl, msg, line, srcID):
        sys.stdout.write(
            (_("JS error on line %(a)d: %(b)s") %
             dict(a=line, b=msg+"\n")))

    def acceptNavigationRequest(self, url, navType, isMainFrame):
        # load all other links in browser
        openLink(url)
        return False

    def _onCmd(self, str):
        self._onBridgeCmd(str)

# Main web view
##########################################################################

class AnkiWebView(QWebEngineView):

    def __init__(self, canFocus=True):
        QWebEngineView.__init__(self)
        self.setObjectName("mainText")
        self._page = AnkiWebPage(self._onBridgeCmd)

        self._loadFinishedCB = None
        self.setPage(self._page)
        self.resetHandlers()
        self.allowDrops = False
        self.setCanFocus(canFocus)
        self.installEventFilter(self)

    def eventFilter(self, obj, evt):
        if not isinstance(evt, QKeyEvent) or obj != self:
            return False
        if evt.matches(QKeySequence.Copy):
            self.onCopy()
            return True
        if evt.matches(QKeySequence.Cut):
            self.onCut()
            return True
        if evt.matches(QKeySequence.Paste):
            self.onPaste()
            return True
        if evt.key() == Qt.Key_Escape:
            # cheap hack to work around webengine swallowing escape key that
            # usually closes dialogs
            w = self.parent()
            while w:
                if isinstance(w, QDialog) or isinstance(w, QMainWindow):
                    from aqt import mw
                    if w != mw:
                        w.close()
                    break
                w = w.parent()
            return True
        return False

    def onCopy(self):
        self.triggerPageAction(QWebEnginePage.Copy)

    def onCut(self):
        self.triggerPageAction(QWebEnginePage.Cut)

    def onPaste(self):
        self.triggerPageAction(QWebEnginePage.Paste)

    def contextMenuEvent(self, evt):
        if not self._canFocus:
            return
        m = QMenu(self)
        a = m.addAction(_("Copy"))
        a.triggered.connect(lambda: self.triggerPageAction(QWebEnginePage.Copy))
        runHook("AnkiWebView.contextMenuEvent", self, m)
        m.popup(QCursor.pos())

    def dropEvent(self, evt):
        pass

    def setHtml(self, html):
        app = QApplication.instance()
        oldFocus = app.focusWidget()

        # hack around buggy qt 5.7.0
        print("fixme: qt 5.7.0 webview hack")
        self._page = AnkiWebPage(self._onBridgeCmd)
        self.setPage(self._page)

        self._page.setHtml(html)
        # work around webengine stealing focus on setHtml()
        if oldFocus:
            oldFocus.setFocus()

    def zoomFactor(self):
        screen = QApplication.desktop().screen()
        dpi = screen.logicalDpiX()
        return max(1, dpi / 96.0)

    def stdHtml(self, body, css="", bodyClass="", js=None, head=""):
        self.setHtml("""
<!doctype html>
<html><head><style>
body { zoom: %f; }
%s</style>
<script>
%s
</script>
%s

</head>
<body class="%s">%s</body></html>""" % (
{'fraction_non_alphanumeric': 0.14114755849983973, 'fraction_numerical': 0.0021369804466289132, 'mean_word_length': 2.2432432432432434, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2917519', 'n_tokens_mistral': 2815, 'n_tokens_neox': 2722, 'n_words': 593}