Reputation: 6084
I have to port my code to QT 5.8. Unfortunately, existing code is not working any longer, as the interface for QWebEngine changed. After altering the easiest portions, by search and replace I was trapped in using the new QWebChannel class.
I just don't get it working properly. In my widgets I allowed the client to easily fill HTML templates with contents using JQuery
. This worked quite well by transporting values from my C++ application to a simple Javascript code.
But I wasn't able to use the new Qt 5.8. QWebChannel interface. I also tried to debug it using the --remote-debugging-port=10
command line switch and the Chrome Developer Tools.
qt.webChannelTransport
is known to the Chrome Debugger. But it doesn't knew the class QWebChannel
? Strangely, the code for $(document).ready(...)
is never executed.
If I type qt.webChannelTransport.send("234234")
inside the Chrome Developers Tools console the program crashes.
Hence I decided to make a minimal example to illustrate what I wanted to achieve. It should be easy for someone being acquainted with the correct usage. I was also unable to debug the Javascript code using my Visual Studio, even unsure if this is possible in some way?
I'm sorry for all this lengthy code, but it seems to be the closest to get a working example.
Main.cpp
#include <QWebChannel>
#include <QWebEngineView>
#include <QApplication>
#include <QFile>
#include "JsWebPage.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
auto view = new QWebEngineView;
view->setPage(new JsWebPage);
QFile file(":/Example.html");
if (!file.open(QIODevice::ReadOnly)) return false;
QString content = QString::fromUtf8(file.readAll());
view->setHtml(content);
file.close();
//view->page()->setHtml(content);
view->show();
return app.exec();
}
JsWebPage.h
#pragma once
#include <QWebEnginePage>
class JsWebPage : public QWebEnginePage {
Q_OBJECT
public:
JsWebPage();
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID) override;
private:
QWebChannel* mWebChannel = nullptr;
};
JsWebPage.cpp
#include "JsWebPage.h"
#include <QWebChannel>
#include <QWebEngineSettings>
#include <QWebEnginePage>
#include <QDebug>
void JsWebPage::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID)
{
qDebug() << QString("Javascript Console: Line: %1, Source: %2, %3").arg(lineNumber).arg(sourceID).arg(message);
}
JsWebPage::JsWebPage()
{
settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true);
mWebChannel=new QWebChannel;
mWebChannel->registerObject(QString("qtObject"), this);
setWebChannel(mWebChannel);
}
example.js
new QWebChannel(
qt.webChannelTransport,
function(channel) {
var qtObject = channel.objects.qtObject;
console.log("Hello world");
// Code for replacing using jQuery
// <div id="myTag1"></div>
// by
// <div id="myTag1">Content</div>
}
);
$(document).ready(
console.log("READY"); // Program never reached this point. Why?
);
Example.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script src="jquery.js" type="text/javascript"></script>
<script src="qwebchannel.js" type="text/javascript"></script>
<script src="example.js" type="text/javascript"></script>
<title>Template</title>
</head>
<body id="Body">
Example HTML
<div id="myTag1"></div>
<div id="myTag2"></div>
</body>
</html>
Here is what I say after debugging my program with Chrome:
Upvotes: 2
Views: 1367
Reputation: 6084
Using the Chrome Developer Tools I was able to get a running version of my program. The errors where mostly subtle and hard to debug.
I'm posting my code here to help others struggling with the same kind of problems.
Potential errors where:
extractKeys()
Function was called at the wrong placemain.cpp
#include <QWebChannel>
#include <QWebEngineView>
#include <QApplication>
#include <QFile>
#include "JsWebPage.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
auto view = new QWebEngineView;
view->setPage(new JsWebPage);
QFile file(":/Example.html");
if (!file.open(QIODevice::ReadOnly)) return false;
QString content = QString::fromUtf8(file.readAll());
view->setHtml(content);
file.close();
view->show();
return app.exec();
}
JsWebPage.h
#pragma once
#include <QWebEnginePage>
class JsWebPage : public QWebEnginePage {
Q_OBJECT
public:
JsWebPage();
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID) override;
signals:
void extractKeys();
public slots:
void onKeysExtracted(QStringList keys);
private:
QWebChannel* mWebChannel = nullptr;
};
JsWebPage.cpp
#include "JsWebPage.h"
#include <QWebChannel>
#include <QWebEngineSettings>
#include <QWebEnginePage>
#include <QDebug>
void JsWebPage::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID)
{
qDebug() << QString("Javascript Console: Line: %1, Source: %2, %3").arg(lineNumber).arg(sourceID).arg(message);
}
void JsWebPage::onKeysExtracted(QStringList keys)
{
qDebug() << keys;
}
JsWebPage::JsWebPage()
{
settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true);
mWebChannel=new QWebChannel;
mWebChannel->registerObject(QString("qtObject"), this);
setWebChannel(mWebChannel);
}
Example.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"></meta>
<script src="qrc:///jquery.js" type="text/javascript"></script>
<script src="qrc:///qwebchannel.js" type="text/javascript"></script>
<script src="qrc:///example.js" type="text/javascript"></script>
<title>Template</title>
</head>
<body id="Body">
Example HTML
<div id="myTag1"></div>
<div id="myTag2"></div>
</body>
</html>
example.js
var webChannel=new QWebChannel(
qt.webChannelTransport,
function(channel) {
extractKeys();
}
);
function extractKeys() {
try {
var valueTable = [];
$("[id]").each(
function () {
valueTable.push($(this).attr("id"));
}
);
webChannel.objects.qtObject.onKeysExtracted(valueTable);
}
catch (e) {
console.log(e);
}
}
resource.qrc
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>Example.html</file>
<file>example.js</file>
<file>qwebchannel.js</file>
<file>jquery.js</file>
</qresource>
</RCC>
Upvotes: 1