Making a "Promise" with QtWebKit
The latest version of Nuxeo Drive included a new HTML5 UI and embedded WebKit, providing more reactivity, consistency between operating systems and a nicer look and feel. This UI uses a specific drive object to communicate with the core software written in Python and QT. Here's an in-depth look into how we created that drive object, using the QtWebKit module, a web content rendering engine based on the open source WebKit project.
@QtCore.pyqtSlot(str, str, result=str)
def update_password(self, uid, password):
return self._update_password(uid, password)
The code showing our Promise object implementation is available on Gist.
The Worker is already an object that encapsulates a thread. This way you can simply modify your API object like this (see: drive_api.py):
@QtCore.pyqtSlot(str, str, result=QtCore.QObject) def update_password_async(self, uid, password): return Promise(self._update_password, uid, password)
So now the sequence is like this:
Our Promise looks good and works well except for the "small" log we get whenever we use it:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Promise(0x1753220), parent's thread is QThread(0x1766d40), current thread is QThread(0x1049240)
The issue is that Qt is wrapping the exposed QObject with another internal object, and while doing that it calls the reparent to attach the exposed object. But the QObject was already moved to another thread by the Worker mechanism. We had to solve this by using a wrapper: PromiseWrapper. This is the object that will be hosted in the Promise thread. The Promise object can then stay in the main thread (see: drive_api_final.py).
This small line of log disappeared now! (It was, by the way, killing the application under Linux. So thanks to the bug reporter :) )
Nuxeo Drive can now display a better animated button when something is happening in the background after a user interaction.
Category: Product & Development