I'm trying to call a Python function, defined as a Slot from JavaScript code running inside a QWebView instance. I've been able to set everything up, more or less, but for the life of me can't figure out (or find any documentation) on the types of arguments passed to the Python-implemented Slot when the function is called from within JavaScript with complex arguments (e.g. an array, JSON object or a JavaScript object such as an ErrorEvent object).
The following code is a bit complex but demonstrates the problem:
import sys
from PySide.QtGui import QApplication
from PySide.QtCore import QObject, Slot
from PySide.QtWebKit import QWebPage, QWebView, QWebElement
class JavascriptApi(QObject):
OBJ_NAME = 'MyApi'
JS_API_INIT = ("window.addEventListener('error', function(e) { "
" %(objname)s.log_error([e.message, e.filename, e.lineno, e.column]); "
"}, false);"
"window.addEventListener('load', %(objname)s.window_loaded, false);"
"console.log('JavaScript API initialized');") % {"objname": OBJ_NAME}
def initialize(self, page):
f = page.mainFrame()
f.addToJavaScriptWindowObject(self.OBJ_NAME, self)
f.evaluateJavaScript(self.JS_API_INIT)
@Slot(list)
def log_error(self, error):
print error
#print "JavaScript Error: %s [%s:%d:%d]" % (message, filename, lineno, column)
@Slot(QWebElement)
def window_loaded(self, window):
print "JavaScript window.onload event reported"
class InstrumentedWebPage(QWebPage):
def __init__(self, *args, **kwargs):
super(InstrumentedWebPage, self).__init__(*args, **kwargs)
self._js_api = JavascriptApi()
self.mainFrame().javaScriptWindowObjectCleared.connect(self._init_javascript_api)
def javaScriptConsoleMessage(self, message, lineNumber, sourceID):
print "JavaScript Console Message: %s (%s:%d)" % (message, sourceID, lineNumber)
def _finished(self, status):
print "Finished!"
QApplication.instance().quit()
def _init_javascript_api(self):
self._js_api.initialize(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
view = QWebView()
view.setPage(InstrumentedWebPage())
view.setHtml('<html><body>This is some HTML'
'<script>foo_bar("syntax error here);</script>'
'</body></html>')
view.show()
sys.exit(app.exec_())
If you run it, you will notice that the following message is logged to the console:
TypeError: incompatible type of argument(s) in call to log_error(); candidates were
log_error(PyObject) (undefined:0)
So what would be the right type to use in the @Slot() for log_error? BTW the whole reason for using an intermediate JavaScript function between window.onerror and my Python code is for the same reason - window.onerror calls my code with an ErrorEvent JS object, and the only way I could catch it was with a @Slot(QWebElement), but then I couldn't figure out how to access the object properties.
@Slot('QVariantList'). The webkit bridge is definitely under-documented and marshalling data between JS and Python is frustratingly arcane.'QVariantList'works for me too. Thanks!