57 lines
2.1 KiB
Python
57 lines
2.1 KiB
Python
"""Pont JS ↔ Python (QWebChannel) utilisé par le mode "capture au survol"
|
|
et par la détection continue des liens de "suite" (voir link_detector.py).
|
|
|
|
QtWebEngine exécute la page dans un processus Chromium séparé : le seul
|
|
canal officiellement supporté pour qu'un script de la page appelle du code
|
|
Python est QWebChannel. On expose ici un unique objet `pdfscrapperBridge`
|
|
côté JavaScript, avec :
|
|
- une méthode `captureBlock(text)` que le script d'overlay (voir
|
|
block_picker.py) appelle au clic sur un bloc ;
|
|
- une méthode `reportLinks(json)` que le MutationObserver de
|
|
link_detector.py appelle à chaque (re)scan de la page.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from PySide6.QtCore import QFile, QIODevice, QObject, Signal, Slot
|
|
|
|
|
|
class Bridge(QObject):
|
|
"""Objet exposé côté JS sous `window.pdfscrapperBridge`."""
|
|
|
|
block_captured = Signal(str)
|
|
links_detected = Signal(str)
|
|
|
|
@Slot(str)
|
|
def captureBlock(self, text: str) -> None: # noqa: N802 (nom appelé depuis JS)
|
|
if text and text.strip():
|
|
self.block_captured.emit(text.strip())
|
|
|
|
@Slot(str)
|
|
def reportLinks(self, links_json: str) -> None: # noqa: N802 (nom appelé depuis JS)
|
|
self.links_detected.emit(links_json)
|
|
|
|
|
|
def load_qwebchannel_js() -> str:
|
|
"""Charge le script qwebchannel.js embarqué dans les ressources Qt."""
|
|
resource = QFile(":/qtwebchannel/qwebchannel.js")
|
|
if not resource.open(QIODevice.OpenModeFlag.ReadOnly):
|
|
raise RuntimeError("Impossible de charger la ressource Qt qtwebchannel/qwebchannel.js")
|
|
try:
|
|
return bytes(resource.readAll().data()).decode("utf-8")
|
|
finally:
|
|
resource.close()
|
|
|
|
|
|
def build_bridge_init_script() -> str:
|
|
"""Script injecté au tout début de chaque page pour établir le canal
|
|
QWebChannel et exposer `window.pdfscrapperBridge` une fois prêt."""
|
|
return (
|
|
load_qwebchannel_js()
|
|
+ """
|
|
new QWebChannel(qt.webChannelTransport, function (channel) {
|
|
window.pdfscrapperBridge = channel.objects.pdfscrapperBridge;
|
|
});
|
|
"""
|
|
)
|