Over the past weeks I spend my time at the Qt Companies R&D office in Berlin. Other than drinking hot chocolate and sampling a wide array of cookies and sweets, I was working on adding support for Python based extensions to QtCreator.
Now if you never heard of Qt before (like me before applying for the internship), you might not know what the QtCreator is. Well, you could have a look here, but in short it’s just a standard IDE with some extra functionality, aimed at Qt specific development. It supports custom plugins written in C++, but writing these is rather cumbersome and there is not a huge amount of documentation (outside of reading the source).
Enter Python: Equipped with an embedded CPython and modules which allow access to the applications internal APIs, it would be possible to write extensions with just a few lines of code.
So that is pretty much what I did.
So how does this whole thing work? Well, it uses an in-house piece of software called ‘Shiboken’, which is responsible for generating CPython bindings from C++ code. Since this is the same way the people from Qt for Python generate their bindings, this project pretty much gets all of these bindings for free.
From there, everything was simply a matter of jumping through a few hoops (like this one) and coming up with a simple system for loading the extension. Once that was done, I gave a presentation on the whole thing and got to write a post for the Qt blog.
The whole system is designed to feel as much as normal Python as possible. Each extension lives within a folder, which contains at least a
main.py. Any other Python files can be
imported like you would when running python normally. There is also a good deal of code that makes sure the extensions all appear separated from the developers perspective, even though they all run in the same interpreter.
All this said, a hello world version of such an extension would look something like this:
from PythonExtension import QtCreator menuId = "Python.HelloWorld.Menu" menu = QtCreator.Core.ActionManager.createMenu(menuId) menu.menu().setTitle("Hello world") menu.menu().addAction("Say hello", lambda: print("Hello World!")) QtCreator.Core.ActionManager.actionContainer("QtCreator.Menu.Tools").addMenu(menu)
If you ever tried to write a C++ extension for the QtCreator (or any serious C++ code) before, you will appreciate how simple this Python snippet is.