Reputation: 95
In Qt's (now deprecated) QWebPage
class, there was a signal contentsChanged()
that was called whenever the html content of the web page was changed by either the user editing the page or the page being programmatically changed. There doesn't seem to be an equivalent signal in the newer QtWebEnginePage
classes. Given that the method of making the web page editable from the Qt application has changed from the QWebPage::setContentEditable
method to the native html5 javascript contenteditable
, this doesn't really surprise me.
My question:
Is there a way to "listen" for the QtWebEnginePage
content changing? Is this something I have to now somehow handle from javascript?
Note that I looked in the porting information Qt provides, but found nothing that struck me as related...
Upvotes: 3
Views: 1325
Reputation: 3143
Unfortunately, QtWebEngine
has much worse and poorer integration with the rest of Qt facilities than QtWebKit
. A lot of things QtWebKit
was able to do out of the box are only possible via JavaScript trickery with QtWebEngine
. I was able to solve this particular problem in the project of my own but it was not very easy.
First, I had to set up the interaction between C++ code and JavaScript code via QWebChannel
. It is too large topic to cover within this answer but on the bright side, the documentation on this is more or less good: see Qt WebChannel JavaScript API and its examples. In the end from C++ code you should be able to do things like
webChannel->registerObject(QStringLiteral("myObject"), myObject);
where webChannel
is a pointer to QWebChannel
and myObject
is a pointer to QObject
subclass which has public slots. This action would allow the public slots of myObject
be called by JavaScript code thus implementing the connection between JavaScript and C++.
The JavaScript's "native" solution for tracking the changes of DOM is MutationObserver. It is a JavaScript object one instantiates in order to listen to the DOM changes. On each DOM mutation the observer calls the callback function supplied to it at construction. In order to notify the C++ code of the change in DOM the callback should call the slot of some object exposed to JavaScript. In C++ code inside this slot you can react on the content change as you please - if there are multiple parts of C++ code which might want to subscribe to contentsChanged
signal, provide them with such a signal, emit it from the slot of myObject
.
Here's a simple example of MutationObserver
setup on the JavaScript side:
var observer = MutationObserver(function(mutations, observer) {
myObject.onContentChanged();
});
observer.start = function() {
this.observe(document, {
subtree: true,
attributes: true,
childList: true,
characterData: true,
characterDataOldValue: true
});
}
observer.stop = function() {
this.disconnect();
}
While this approach is significantly more complicated to set up than with QtWebKit
's contentsChanged
signal, in the end of the day I found it to be more flexible because with MutationObserver
you can see what exactly has changed within DOM and do some advanced processing:
Upvotes: 3