KDAB contributions to Qt 5.2
Qt 5.2 has just been released! Coming only five months after 5.1, the new release brings in a huge number of new features, as well as many bug fixes. For the first time ever, Qt is officially supported on two major mobile platforms: Android and iOS.
KDAB contributed over 300 commits to Qt 5.2, both in terms of new features and bug fixes, making it the second largest company contributing to Qt (after Digia itself). The commit stream has been constant, as you can see in this graph showing the last 16 weeks:
In this blog post I’ll show some of the notable features developed by KDAB engineers that you are going to find in Qt 5.2.
Official Android support
For more information about what you will find in Qt 5.2, check out the Qt on Android blog series authored by my colleague BogDan Vatra, who created the Necessitas project and originally ported Qt to Android.
QVariant and QMetaType improvements
Our engineer Stephen Kelly presented these features in his talk at the last Qt Developer Days (slides).
Custom conversion and comparison operators
QVariant and QMetaType have always supported working with user-defined data types, but somehow user types have always been “second class citizens”. For instance, QVariant is able to perform type conversions between Qt types:
QDate d(2013, 12, 11);
QVariant v(d);
qDebug() << v.toString(); // prints "2013-12-11"
However, the same code fails for user-defined types:
MyDate d2(2013, Dec, 11); // custom date class
QVariant v2 = QVariant::fromValue(d2);
qDebug() << v2.toString(); // prints ""
This happens because these type conversions are actually hardcoded inside Qt, and the user had no means to register custom conversion functions.
QVariant conversions between any pair of types has become possible starting with Qt 5.2. Now we can register a free function or a member function within Qt's meta type system:
QString myDateToString(const MyDate &d)
return QString("%1-%2-%3").arg(d.year()).arg(d.month()).arg(d.day());
// ...
qDebug() << v2.canConvert()<QString> << v2.toString(); // prints "false """
QMetaType::registerConverter(&myDateToString);
qDebug() << v2.canConvert()<QString> << v2.toString(); // prints "true 2013-12-11"
Of course, at least one of the types must be a user defined type -- we can't override the converters amongst Qt's built-in data types.
We can also register custom comparison operators (that will be used by QVariant's operator== and operator<) and custom QDebug streaming operators (that will be used when dumping a variant via the debugging streams, such as qDebug()).
Type-erased container iteration
This is a nice little feature that allows to iterate on any QVariant which is holding a sequential or an associative container (such as QList, QVector, QHash, but also std::vector, std::map, etc.), and doing that without knowing the exact type of the container held (that is, performing type erasure) and without paying the cost of copying the container out of the QVariant object.
Starting from 5.2, any QVariant object holding a sequential container or an associative container will report true when asked if it be converted to a QVariantList or a QVariantHash respectively. We can then use the special types QSequentialIterable (for sequential containers) and QAssociativeIterable (for associative containers) to iterate on the container's contents.
For instance, this code iterates in a type-erased fashion on a list stored within a QVariant object:
QList<int> intList;
intList << 42 << 51 << -24;
QVariant variant = QVariant::fromValue(intList);
if (variant.canConvert<QSequentialIterable>()) {
QSequentialIterable iterable = variant.value<QSequentialIterable>();
QSequentialIterable::const_iterator it = iterable.begin();
const QSequentialIterable::const_iterator end = iterable.end();
for ( ; it != end; ++it) {
qDebug() << *it;
}
}
Note that there's no mention within the cycle of either the container's type or the container elements' type.
Automatic smart pointer unwrapping
QVariant API is very convenient to use when it comes to value types, such as strings (QString), date/time objects (QDateTime), and so on. It's also possible to use it to hold an instance of a so-called identity type, most notably QObject subclasses -- or, better, hold a pointer to an instance of a QObject subclass. (This happens because identity types do not match QVariant requirements -- for instance, they are not copyable.)
Moreover, identity types have the problem of ownership: one can use the parent/child system (to delete the children when the parent gets destroyed), but also have a more complex ownership. For instance, one might employ shared ownership by using smart pointers, such as QSharedPointer (for strong ownership) and QWeakPointer (for weak).
Before Qt 5.2 it was perfectly possible to create a QVariant that encapsulates a smart pointer to an instance of a QObject subclass. Actually, Qt 5 even removed the need to declare the smart pointer metatype -- in other words, Q_DECLARE_METATYPE(QSharedPointer<T>) was no longer needed.
Starting with Qt 5.2 QVariant can also unwrap the raw QObject pointer:
class MyObject : public QObject
{
Q_OBJECT
// ...
}
QSharedPointer<MyObject> sp = QSharedPointer::create(arg1, arg2);
QVariant v = QVariant::fromValue(sp);
QObject *obj = v.value<QObject *>(); // works in 5.2
OpenGL improvements
Qt Quick 2 now works with the OpenGL Core Profile
As you might know, Qt Quick 2 contents are drawn using an OpenGL scene graph.
The renderer visits the QML object tree and builds a tree of QSGNodes that constitutes the scene to render. This scene is visited again and then drawn using OpenGL or OpenGL/ES 2 commands (depending on the platform); please refer to the above link for a more in-depth explaination about the renderer (which by the way got an overhaul in Qt 5.2).
However, the new renderer (and the old one) had a limitation: it required the usage of a so-called compatibility profile, that is, an OpenGL implementation which offers all the old, legacy functionality that has been deprecated in OpenGL 3.0 and removed from OpenGL 3.1.
Vendors are not mandated to offer such a profile -- the OpenGL standard lets the vendors decide whether they want to implement it, or just implement the non-deprecated set of functionality, i.e. the so called core profile. Such a vendor is for instance Apple: both in OS X 10.8 (Mountain Lion) and 10.9 (Mavericks) one can't create a >= 3.2 OpenGL compatibility profile context.
Hence, a developer targeting these systems couldn't for instance mix Qt Quick 2 with pure OpenGL content, if the content actually requires features introduced in OpenGL 3.2 or later! (For instance, geometry or tessellation shaders.)
We took care of this problem with a massive refactoring effort, which included extracting and adapting over 50 shader programs; we're happy to announce that it's now possible to use Qt Quick 2 with any OpenGL core profile (such as the OpenGL 4.1 profile offered by OS X Mavericks).
QOpenGLTexture
OpenGL is a key technology in Qt 5. For this reason, the OpenGL support was moved into QtGui, which since from 5.0 has offered OpenGL enablers -- convenience, high level classes to wrap the OpenGL APIs in a more object-oriented design.
We now have classes for wrapping buffer objects, vertex array objects, framebuffer objects, shaders and shader programs, and so on.
KDAB has contributed the QOpenGLTexture class to Qt 5.2, which encapsulates an OpenGL texture object. It offers all the features you'd expect from a modern texture class: immutable storage, texture views, a direct state access-like API (emulating it if necessary), and so on.
If you missed it, you can check out the awesome OpenGL in Qt blog post series that explained many of the features introduced in Qt 5.0 and 5.1.
QNX maintenance
As shown by the commit graph above, KDAB is still putting efforts at improving Qt support under the QNX operating system (used for instance on BlackBerry phones and tablets). Amongst the features you can find in 5.2 there is support for QNX's mm-renderer multimedia APIs in QtMultimedia, preliminary support for the BlackBerry native file dialog, improved camera handling, as well as many bug fixes.
Other contributions
QAbstractScrollArea
QAbstractScrollArea (and therefore its subclasses, such as QListView, QTableView, QGraphicsView, and so on) can now honour the size hint of the contents (the viewport), by setting the size adjust policy. This allows QAbstractScrollAreas to resize when the contents change (for instance, when new columns are added in a QTableView).
QCommandLineParser
Command line parsing is a very common task in console-based application. Qt now offers the QCommandLineParser class to ease the task for developers; my colleague David Faure took the initial contribution (coming from Laszlo Papp, of KDE and QtSerialPort fame), polished it and went through endless review iterations in order to merge it in time for Qt 5.2.
He also went further, and rewrote the command line parsing of Qt's own tools (moc, uic, etc.) to use the new class.
Conclusions
Qt 5.2 is the best release of Qt ever. It allows developers to target a broad range of devices and operating systems, from modern mobile platforms to the traditional desktops, while keeping the stability and the quality we expect from it. We're glad to be contributing to its success.
Great work! Looking forward to start using QOpenGLTexture
Great work KDAB!
What are your plans for Qt3D. Do you see it being [re]integrated into Qt any time soon? Maybe Qt 5.3?
Thank you!
About Qt3D: yes, we’re working for making it available in 5.3. We’ll definitely write about it and discuss the plans on this blog and on the Qt Project mailing lists, so stay tuned!
How to use QOpenGLTexture generate skybox? Can you give an example? Thank you
You can use QOpenGLTexture with the cubemap binding targets, and load the individual faces of your skybox with the setData / setCompressedData overloads which take a cube map face. Then you can just bind it and use it as usual (for instance by drawing a cube textured with the cubemap texture).
i began qt sevral months ago,i am a beginner.my project is based opengl,so i used QGUI and QtQuick of qt models,i am gratitude that QOpenGLTexture is available,but here is the problem:when debugged in DeskTop version, the texture can reveal,but in Android,there is no texture,not even a black model.i have been stuck for two weeks and have no clue,i can hardly believe QOpenGLTexture is not for android,could you help ?
If you have a minimal testcase showing the problem, please submit a bug report on https://bugreports.qt-project.org/ attaching your testcase. Be sure to be testing with the latest Qt, lots of OpenGL fixes for Android went in 5.3!
i submitted the report,but is there a possibility that QOpenGLTexture cannot work on android yet?otherwise i cannot figure it out why debugging in desktop and android can have a different result
Hello,
The registerConverter is a great piece of functionality.
My questions is:
Let’s say I use my custom type in QML. I have a property of my custom type and I want to assign a string to it. However, the fromString fuction which I registered using registerConverter is not called in this case and the QML assign statement fails. Why? Would it be possible to check using canConvert in QML also? It makes a good sense to me. Or am I missing something? Thank you