From a52cd8f4a732e2f3cbb50c67f593c2d8a985d69e Mon Sep 17 00:00:00 2001 From: louisnw Date: Sat, 25 May 2024 13:36:54 +0100 Subject: [PATCH] add support for pyqt6, throw error and suggest downgrade for wx, streamlit, jupyter --- lightweight_charts/widgets.py | 88 ++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 21 deletions(-) diff --git a/lightweight_charts/widgets.py b/lightweight_charts/widgets.py index 630573b..3996813 100644 --- a/lightweight_charts/widgets.py +++ b/lightweight_charts/widgets.py @@ -10,18 +10,25 @@ except ImportError: wx = None try: - using_py6 = False + using_pyside6 = False from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtWebChannel import QWebChannel - from PyQt5.QtCore import QObject, pyqtSlot as Slot + from PyQt5.QtCore import QObject, pyqtSlot as Slot, QUrl, QTimer except ImportError: - using_py6 = True + using_pyside6 = True try: from PySide6.QtWebEngineWidgets import QWebEngineView from PySide6.QtWebChannel import QWebChannel - from PySide6.QtCore import Qt, QObject, Slot + from PySide6.QtCore import Qt, QObject, Slot, QUrl, QTimer except ImportError: - QWebEngineView = None + try: + using_pyside6 = False + from PyQt6.QtWebEngineWidgets import QWebEngineView + from PyQt6.QtWebChannel import QWebChannel + from PyQt6.QtCore import QObject, pyqtSlot as Slot, QUrl, QTimer + except ImportError: + QWebEngineView = None + if QWebEngineView: class Bridge(QObject): @@ -54,16 +61,31 @@ def emit_callback(window, string): class WxChart(abstract.AbstractChart): def __init__(self, parent, inner_width: float = 1.0, inner_height: float = 1.0, scale_candles_only: bool = False, toolbox: bool = False): + + # this isn't available at the moment + + raise ModuleNotFoundError('WxChart is not available in lightweight charts 2.0; please downgrade to an earlier version.') + + if wx is None: raise ModuleNotFoundError('wx.html2 was not found, and must be installed to use WxChart.') self.webview: wx.html2.WebView = wx.html2.WebView.New(parent) super().__init__(abstract.Window(self.webview.RunScript, 'window.wx_msg.postMessage.bind(window.wx_msg)'), inner_width, inner_height, scale_candles_only, toolbox) - self.webview.Bind(wx.html2.EVT_WEBVIEW_LOADED, lambda e: wx.CallLater(500, self.win.on_js_load)) + self.webview.Bind(wx.html2.EVT_WEBVIEW_LOADED, lambda e: wx.CallLater(1000, self.win.on_js_load)) self.webview.Bind(wx.html2.EVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, lambda e: emit_callback(self, e.GetString())) self.webview.AddScriptMessageHandler('wx_msg') + self.webview.LoadURL(f'file:///{abstract.INDEX}') + + # with open(abstract.INDEX, 'r') as f: + # html = f.read() + # self.webview.SetPage(html, '/Users/louis/Projects/lightweight-charts-python/lightweight_charts/js/') + + + # with open('/Users/louis/Projects/lightweight-charts-python/lightweight_charts/js/bundle.js', 'r') as f: + # self.webview.AddUserScript(f.read()) # self.webview.AddUserScript(abstract.JS['toolbox']) if toolbox else None def get_webview(self): return self.webview @@ -82,21 +104,25 @@ class QtChart(abstract.AbstractChart): self.bridge = Bridge(self) self.web_channel.registerObject('bridge', self.bridge) self.webview.page().setWebChannel(self.web_channel) - self.webview.loadFinished.connect(self.win.on_js_load) - if using_py6: + self.webview.loadFinished.connect(lambda: self.webview.page().runJavaScript(''' + let scriptElement = document.createElement("script") + scriptElement.src = 'qrc:///qtwebchannel/qwebchannel.js' + + scriptElement.onload = function() { + var bridge = new QWebChannel(qt.webChannelTransport, function(channel) { + var pythonObject = channel.objects.bridge + window.pythonObject = pythonObject + }) + } + + document.head.appendChild(scriptElement) + + ''')) + self.webview.loadFinished.connect(lambda: QTimer.singleShot(200, self.win.on_js_load)) + if using_pyside6: self.webview.setContextMenuPolicy(Qt.ContextMenuPolicy.NoContextMenu) - self._html = f''' - {abstract.TEMPLATE[:85]} - - - {abstract.TEMPLATE[85:]} - ''' - self.webview.page().setHtml(self._html) + self.webview.load(QUrl.fromLocalFile(abstract.INDEX)) + def get_webview(self): return self.webview @@ -104,7 +130,27 @@ class QtChart(abstract.AbstractChart): class StaticLWC(abstract.AbstractChart): def __init__(self, width=None, height=None, inner_width=1, inner_height=1, scale_candles_only: bool = False, toolbox=False, autosize=True): - self._html = abstract.TEMPLATE.replace('\n\n', '') + + + # this isn't available at the moment + + raise ModuleNotFoundError('Streamlit & Jupyter Charts are unavailable in lightweight charts 2.0; please downgrade to an earlier version.') + + with open(abstract.INDEX.replace("test.html", 'styles.css'), 'r') as f: + css = f.read() + with open(abstract.INDEX.replace("test.html", 'bundle.js'), 'r') as f: + js = f.read() + with open(abstract.INDEX.replace("test.html", 'lightweight-charts.js'), 'r') as f: + lwc = f.read() + + + + with open(abstract.INDEX, 'r') as f: + self._html = f.read().replace('\n', f'', + f'') + super().__init__(abstract.Window(run_script=self.run_script), inner_width, inner_height, scale_candles_only, toolbox, autosize) self.width = width