I have created an html file for a tree diagram using the python package pyvis (version: 0.3.2). I would like to load this html file in a GUI using QWebEngineView of PyQT6 but I am getting the following error:
js: Uncaught ReferenceError: vis is not defined.
In the html file created, it contains some embedded JavaScript for importing 'vis' from an online repository which I suspect is not being executed. One thing I'd like to point out is that I can load this html file on my web-browser (edge, google chrome). On google chrome, its console does say the following even though the file is loaded as intended:
DevTools failed to load source map: Could not load content for https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/vis-network.min.js.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE
Here is a simple version of the Python code for recreating the issue:
from pyvis.network import Network
import numpy as np
import os, sys
from PyQt6.QtCore import QUrl
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout
from PyQt6.QtWebEngineWidgets import QWebEngineView
# Example dataset
dataset = [["A", "B"], ["B", "C"]]
net = Network()
# Add nodes
nodes = list(set(np.concatenate(dataset)))
nodes_index = {}
for index, entry in enumerate(nodes):
net.add_node(index, label=entry, shape="circle")
nodes_index[entry] = index
# Add an edge with hover content
for entry in dataset:
net.add_edge(
nodes_index[entry[0]], nodes_index[entry[1]], title="Pi-Pi Occupancy = 10%"
)
net.save_graph("tree_diagram.html")
path = os.sep.join([os.getcwd(), "tree_diagram.html"])
url = QUrl.fromLocalFile(path)
class WebView(QWidget):
def __init__(self):
super().__init__()
self.window_layout = QVBoxLayout()
self.setLayout(self.window_layout)
self.web = QWebEngineView()
self.window_layout.addWidget(self.web)
self.web.load(url)
if __name__ == "__main__":
app = QApplication(sys.argv)
page = WebView()
page.show()
sys.exit(app.exec())
And here is the html file created (if in case it is useful):
<html>
<head>
<meta charset="utf-8">
<script src="lib/bindings/utils.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/dist/vis-network.min.css" integrity="sha512-WgxfT5LWjfszlPHXRmBWHkV2eceiWTOBvrKCNbdgDYTHrT2AeLCGbF4sZlZw3UMN3WtL0tGUoIAKsu8mllg/XA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/vis-network.min.js" integrity="sha512-LnvoEWDFrqGHlHmDD2101OrLcbsfkrzoSpvtSQtxK3RMnRV0eOkhhBN2dXHKRrUU8p2DGRTk35n4O8nWSVe1mQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<center>
<h1></h1>
</center>
<!-- <link rel="stylesheet" href="../node_modules/vis/dist/vis.min.css" type="text/css" />
<script type="text/javascript" src="../node_modules/vis/dist/vis.js"> </script>-->
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6"
crossorigin="anonymous"
/>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf"
crossorigin="anonymous"
></script>
<center>
<h1></h1>
</center>
<style type="text/css">
#mynetwork {
width: 100%;
height: 600px;
background-color: #ffffff;
border: 1px solid lightgray;
position: relative;
float: left;
}
</style>
</head>
<body>
<div class="card" style="width: 100%">
<div id="mynetwork" class="card-body"></div>
</div>
<script type="text/javascript">
// initialize global variables.
var edges;
var nodes;
var allNodes;
var allEdges;
var nodeColors;
var originalNodes;
var network;
var container;
var options, data;
var filter = {
item : '',
property : '',
value : []
};
// This method is responsible for drawing the graph, returns the drawn network
function drawGraph() {
var container = document.getElementById('mynetwork');
// parsing and collecting nodes and edges from the python
nodes = new vis.DataSet([{"color": "#97c2fc", "id": 0, "label": "A", "shape": "circle"}, {"color": "#97c2fc", "id": 1, "label": "B", "shape": "circle"}, {"color": "#97c2fc", "id": 2, "label": "C", "shape": "circle"}]);
edges = new vis.DataSet([{"from": 0, "title": "Pi-Pi Occupancy = 10%", "to": 1}, {"from": 1, "title": "Pi-Pi Occupancy = 10%", "to": 2}]);
nodeColors = {};
allNodes = nodes.get({ returnType: "Object" });
for (nodeId in allNodes) {
nodeColors[nodeId] = allNodes[nodeId].color;
}
allEdges = edges.get({ returnType: "Object" });
// adding nodes and edges to the graph
data = {nodes: nodes, edges: edges};
var options = {
"configure": {
"enabled": false
},
"edges": {
"color": {
"inherit": true
},
"smooth": {
"enabled": true,
"type": "dynamic"
}
},
"interaction": {
"dragNodes": true,
"hideEdgesOnDrag": false,
"hideNodesOnDrag": false
},
"physics": {
"enabled": true,
"stabilization": {
"enabled": true,
"fit": true,
"iterations": 1000,
"onlyDynamicEdges": false,
"updateInterval": 50
}
}
};
network = new vis.Network(container, data, options);
return network;
}
drawGraph();
</script>
</body>
</html>
Adding the following fixed the issue:
self.web.settings().setAttribute(QWebEngineSettings.WebAttribute.LocalContentCanAccessRemoteUrls, True)
This allows the QWebEngineWidget
to access online resources, which is disabled by default. https://doc.qt.io/qt-6/qwebenginesettings.html#WebAttribute-enum