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:
- Ignore the changes you are not interested in.
- Remember the previous DOM state for further undo/redo implementation purposes.
- Pause listening to DOM changes for periods when DOM needs to be changed by your manually executed JavaScript code - sometimes it's convenient to not notify the C++ code of such changes since it's hard for C++ code to distinguish between changes caused by text editing and changes caused by some script execution.
- Log the exact occurred change - was some node added or removed or changed etc.