» Publishers, Monetize your RSS feeds with FeedShow: More infos (Show/Hide Ads)
Introduction
Texas Instruments has a wiki which documents what is required to bring Qt
up on the Beagle board with full OpenGL ES (1/2) support:
http://www.tiexpressdsp.com/index.php/Building_Qt
and I would like to thank one of their engineers, Varun, for his quick turn
around times in addressing any questions I raised.
This blog entry is intended to serve a similar purpose, but is more verbose regarding
Qt considerations and the initial beagle board bring up. It attempts to serve
as a comprehensive independent source of information on getting Qt built
for the Beagle board with full OpenGL ES 2 support.
These instructions are intended for use with Qt 4.6 (and beyond), so grab
the release candidate or check Qt 4.6 out from the public git repository prior
to proceeding.
You can choose to use either Qt/Embedded or Qt/X11, both can
be successfully integrated with the Beagle board’s SGX GPU and the only
point of divergence in these instructions will be at (Qt) configure time
and the client side system (run time) configuration. Both implementations
offer window management, via QWS and X11 respectively, and operate at
around 27fps and 22fps respectively when running our hellogl_es2 example.
(16bit color depth at 1280×720)
I personally deploy Ångström on my Beagle board, it handles a large amount
of the logistics surrounding cross compilation and is generally very
agreeable, and these instructions are therefore going to be bolted to
Ångström for completeness. Feel free to establish an environment capable of
showing the OpenGL ES examples TI provide, then following the Qt level
considerations (Configuring Qt) accordingly.
For those holding a dormant Beagle board who are open to the author’s
distribution preferences:
Building the Ångström rootfs
Open Embedded is manifested in a git repository: in this posting we are
working within origin/stable/2009. Please follow the instructions give
here, they are comprehensive and got me completely off the ground.
http://www.angstrom-distribution.org/building-angstrom
These instructions end in you running:
bitbake base-image ; bitbake console-image ; bitbake x11-image
which actually builds an X11 angstrom image for your Beagle board. Please
note, you will need to build the X11-image if you want to build and deploy
the SGX packages (we will do this in the next section) via Ångström as opkg considers
X11 to be a required dependency of libgles-omap3_3.00.00.09. This is due
to one of the encapsulated windowing system libraries being X11 centric:
libpvrPVR2D_X11WSEGL.so
Regardless of the indicated X11 dependency, this package will bestow the required
kernel module on you for general OpenGL ES usage (console or X11). We will be
building our own QWS centric (libpvrPVR2D_X11WSEGL.so equivalent) library
behind the scenes for QWS in the Qt/Embedded instructions given later.
Ångström SGX integration
You now need to integrate the SGX drivers on your Ångström system.
You need to get your paws on:
OMAP35x_Graphics_SDK_setuplinux_3_00_00_09.bin
with the following MD5 checksum:
e15147ad76ddbe7c5aec682f5455b774
Getting this involves following the above link and going through the required registration/request process.
Once you have this file, you drop it in:
$OETREE/openembedded/recipes/powervr-drivers/libgles-omap3
and then run:
bitbake libgles-omap3-3.00.00.09
which generates the following packages:
libgles-omap3_3.00.00.09-r1.1_armv7a.ipk
libgles-omap3-dbg_3.00.00.09-r1.1_armv7a.ipk
libgles-omap3-demos_3.00.00.09-r1.1_armv7a.ipk
libgles-omap3-dev_3.00.00.09-r1.1_armv7a.ipk
libgles-omap3-tests_3.00.00.09-r1.1_armv7a.ipk
Deploy the x11-image to an sd-card, and copy these packages to the sd-card
for deployment on the target. If your beagle board does not have internet
access you will probably also require:
* devmem2
* libx11-6 (Only if you insisted on using a console build!)
as opkg will not be able to automatically install the required dependencies
from its repositories and you would hit the following error at deployment:
———————————————-
root@beagleboard:/opt/deploy# opkg install ./libgles-omap3_3.00.00.09-r1.1_armv7 a.ipk
Installing libgles-omap3 (3.00.00.09-r1.1) to root…
libgles-omap3: unsatisfied recommendation for libgles-omap3-tests
Collected errors:
* ERROR: Cannot satisfy the following dependencies for libgles-omap3:
* devmem2 * libx11-6 (>= 1.1.5) *
———————————————-
Once you have installed all the above packages, please reboot the board.
Your bootargs in U-Boot should look something like:
console=ttyS0,115200n8=noinitrd ip=dhcp rw root=/dev/mmcblk0p2 omapfb.mode=dvi:1280×720MR-16@60
assuming you want to output via DVI and are running a similar kernel
version (2.6.29-omap1 on my beagle) which accepts the same kernel
arguments indicated in the bootargs variable above.
Please note that we are specifying a 16 bit color depth which is intentional
and discussed in the “color depth considerations” section in the appendix
Please run the powervr demos (under X11) to establish that your drivers are
successfully installed and usable.
Configuring Qt
In order to build Qt now, all that is required for each target is an
appropriate mkspec:
For Qt/X11
You would fork your mkspec off the linux-g++ mkspec, the resulting mkspec’s
qmake.conf would resemble:
==================================================================
………….
include(../common/linux.conf)
# modifications to g++.conf
# These release optimization flags are TI supplied
# and a little more aggressive than Qt standard (gentoo types rejoice!)
QMAKE_CFLAGS_RELEASE = -O3 -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
QMAKE_CC = $FULLY_QUALIFIED_COMPILER_PREFIX-gcc
QMAKE_CXX = $FULLY_QUALIFIED_COMPILER_PREFIX-g++
QMAKE_LINK = $FULLY_QUALIFIED_COMPILER_PREFIX-g++
QMAKE_LINK_SHLIB = $FULLY_QUALIFIED_COMPILER_PREFIX-g++
# modifications to linux.conf
QMAKE_LIBS_EGL = -lEGL -lIMGegl -lsrv_um
QMAKE_LIBS_OPENGL_QT = -lEGL -lGLESv2 -lGLES_CM -lIMGegl -lsrv_um
QMAKE_LIBS_OPENVG = -lEGL -lGLESv2 -lGLES_CM -lIMGegl -lsrv_um -lOpenVG -lOpenVGU
QMAKE_INCDIR = $TARGET_STAGING_PATH/usr/include
QMAKE_LIBDIR = $TARGET_STAGING_PATH/usr/lib
QMAKE_AR = $FULLY_QUALIFIED_COMPILER_PREFIX-ar cqs
QMAKE_OBJCOPY = $FULLY_QUALIFIED_COMPILER_PREFIX-objcopy
QMAKE_STRIP = $FULLY_QUALIFIED_COMPILER_PREFIX-strip
load(qt_config)
==================================================================
and you would configure Qt with:
configure -arch arm -xplatform linux-omap3-g++ -opengl es2 -openvg
all that remains is to adjust /etc/powervr.ini on the target to be:
[default]
WindowSystem=libpvrPVR2D_FLIPWSEGL.so
Now compile an example, eg:
./examples/opengl/hellogl_es2
deploy it and Qt to the target and enjoy.
For Qt/Embedded
Since we don’t have the X11 abstraction, we have to interface with the
underlying hardware/interfaces with Qt/Embedded’s gfx abstraction layer. We
are going to be making some heavy use of the powervr driver resident under:
$QTSRCTREE/src/plugins/gfxdrivers/powervr
there is a README file in the powervr directory that is definitely
recommend reading, and lends some serious insight into our powervr driver
and Qt/Embedded in general. The same driver is used for MBX/SGX targets and
hence sees a fair amount of usage on a variety of target devices.
You would fork your mkspec off the qws/linux-arm-g++ mkspec, the resulting mkspec’s
qmake.conf would resemble:
==================================================================
…………….
include(../../common/qws.conf)
# modifications to g++.conf
QMAKE_CFLAGS_RELEASE = -O3 -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
QMAKE_CC = $FULLY_QUALIFIED_COMPILER_PREFIX-gcc
QMAKE_CXX = $FULLY_QUALIFIED_COMPILER_PREFIX-g++
QMAKE_LINK = $FULLY_QUALIFIED_COMPILER_PREFIX-g++
QMAKE_LINK_SHLIB = $FULLY_QUALIFIED_COMPILER_PREFIX-g++
# modifications to linux.conf
QMAKE_INCDIR = $TARGET_STAGING_PATH/usr/include
QMAKE_LIBDIR = $TARGET_STAGING_PATH/usr/lib
QMAKE_LIBS_EGL = -lEGL -lIMGegl -lsrv_um
QMAKE_LIBS_OPENGL_QT = -lEGL -lGLESv2 -lGLES_CM -lIMGegl -lsrv_um
QMAKE_LIBS_OPENVG = -lEGL -lGLESv2 -lGLES_CM -lIMGegl -lsrv_um -lOpenVG -lOpenVGU
QMAKE_AR = $FULLY_QUALIFIED_COMPILER_PREFIX-ar cqs
QMAKE_OBJCOPY = $FULLY_QUALIFIED_COMPILER_PREFIX-objcopy
QMAKE_STRIP = $FULLY_QUALIFIED_COMPILER_PREFIX-strip
#These defines are documented in the powervr README, please read it
DEFINES += QT_QWS_CLIENTBLIT QT_NO_QWS_CURSOR
load(qt_config)
==================================================================
and you would configure Qt with:
/opt/dev/source/qt-beagle-4.6/configure -embedded arm -little-endian -xplatform qws/linux-omap3-g++ -opengl es2 -openvg -plugin-gfx-powervr
all that remains is to adjust /etc/powervr.ini on the target to be:
[default]
WindowSystem=libpvrQWSWSEGL.so
Now compile an example, eg:
./examples/opengl/hellogl_es2
deploy it and Qt to your board, and after shutting down X, run the example with
the following arguments:
./hellogl_es2 -qws -display powervr
-qws - starts the application as the QWS server with exclusive access to the
system hardware which manages all subsequent Qt “client” applications
-display powervr - indicates that Qt should use the powervr driver we
compiled earlier
Summary
I hope that this posting encourages people to go forward and experiment
with a fully accelerated Qt 4.6 on the beagle board. Offloading the
painting work onto the GPU drastically reduces the load on the CPU and
broadens the range of applications which can feasibly be run on this
broadly available (cheap!) embedded hardware. The Beagle board has
really nice hardware, and it would be infinitely useful for us to have external
people using our powervr driver and getting it as broadly used/refined as
possible.
Appendix
Additional Benefits to OpenGL ES acceleration
If you take any Qt Graphics View based example and set a QGLWidget as its
viewport, a large amount of work will be offloaded on the GPU leaving your
CPU free to frolic. To put this in perspective, a modified version of:
./examples/animation/animatedtiles
which continually transitions runs smoothly at 720p on the beagle board
when using software, but consumes 100% CPU time according to top (99.3% to
be fair). It is therefore CPU bound and you are not going to be doing
anything else in the background.
When backed by a QGLWidget, the CPU usage drops to 20% on the exact same
example in the exact same conditions (720p, at 16bit color depth). The
frame rate suffers slightly, but at least this is mandated by the GPU
Minor clipping issue evident in hellogl_es2
The bubbles are evidently clipped on the right hand side, I will hopefully
beat you to reporting this at: http://bugreports.qt.nokia.com/secure/Dashboard.jspa
I have not seen any other artifacts, please file any additional bugs you
may encounter at the above URL.
Are these instructions applicable to OMAP3 targets in general
Yes. There is no theoretical reason these instructions would not suffice
for any OMAP3 based target, although I have not personally verified them
outside of Beagle board usage. Caveat emptor.
No Scratchbox2 usage when cross compiling
The more astute of your would recognize that I bypassed Scratchbox2 when
configuring Qt/X11 this time around. I payed dearly for it, and this X11
build has no fontconfig, dbus or glib support even though the Ångström
subsystem I am building against has support for all of them. If you want a
full fledged X11 build with decent font support and OpenGL ES support,
please either:
1) Invest your time in physically adjusting your MKSPEC (and/or wrestling
pkg-config) to get all desired dependencies detected and built against
-Or-
2) Take the easy road, refer to my previous blog posting “Cross compiling
Qt/X11″ and merge the above mkspec changes into the:
./mkspecs/unsupported/linux-scratchbox2-g++
mkspec in your Qt 4.6 source tree.
The same goes for Qt/Embedded which is more self sufficient, but which will
be built without dbus, glib, etc and additional external dependency support
without additional mkspec/environment modification or the use of Scratchbox2
to abstract this away.
Color depth considerations
1) The powervr implementation we are relying on does not support
PVRSRV_PIXEL_FORMAT_RGB888 (24bit color depths), it does however support
PVRSRV_PIXEL_FORMAT_RGB565 and PVRSRV_PIXEL_FORMAT_ARGB8888
2) Ångström is busybox based, and the fbset command you will need to set 32
bit color depths on the console will not work with the default fbset
busybox symlink. You will therefore have to install and use fbset(.real)
in order to get 32bit color depths, which is a simple opkg install away for
the connected Beagle board and a bitbake away for the stranded.
Please note the color depth specified in the boot arguments
console=ttyS0,115200n8=noinitrd ip=dhcp rw root=/dev/mmcblk0p2 omapfb.mode=dvi:1280×720MR-16@60
if you want 32 bit color depth, use:
console=ttyS0,115200n8=noinitrd ip=dhcp rw root=/dev/mmcblk0p2 omapfb.mode=dvi:1280×720MR-24@60
followed by:
/usr/sbin/fbset.real -depth 32 -rgba 8/16,8/8,8/0,8/24
after your Linux kernel drops you in userspace with a kiss on the cheek. A
brave man once tried leaving the color depth at 16 in his boot args, and
jumping all the way to 32bit with fbset so he could change between the more
performant 16 bit color space and the hardware compositing ARGB offering.
Running the dedicated fbset command halved his vertical resolution
regardless of any other parameters he tried to pass fbset and he eventually
ran off to fight another day.
There is a clear performance hit of 7 fps when running hellogl_es2 in
32bit rather than 16bit, taking you down to 20 fps. This hit is even more
pronounced when setting a QGLWidget on the viewport of a QGraphicsView. I
am not sure who is responsible for this, and will be personally
investigating it in the future. Any conjecture/feedback/research performed
by the reader would be greatly appreciated.
*Edited: Introduce rudimentary formatting to make the blog look less Vim forged
In the week of November 2nd I travelled to a little village in Italy called Orvieto. The reason for going to this lovely town is two conferences in a row.
The first one is the OpenDocument plugfest. The second is the openOffice.org conference, both of which were new experiences for me.
The ODF plugfest is a meeting where different implementors of a standard come together and come up with user scenarios and test how well they port between the implementations.
So you’ll see a document created in KWord being opened in OpenOffice.org and Microsoft Office and investigations started when the resuls are not as expected.
I did a presentation at the event of the progress made in the Qt (QTextDocumentWriter) and KOffice implementations of ODF and naturally the Maemo Office reader and last mentioned the Nokia sponsored officeshots.org node we are preparing.
The next day I had another presentation where I showed an interoperability issue with right-to-left languages. Several bugs were found in OpenOffice.org and MSOffice and a discussion followed to share the concepts of right-to-left text and (visual) text-alignment. These are tricky things so its important to all have the same ideas on how it should work.
The event had lots of talks, essentially making is clear we are not the only ones doing ODF and showing whats going on in this space. It was interesting to see how far MSOffice has come with ODF, and at the same time how much we need KOffice to become the big second implementor. MS said several times that for optimum interoperability they choose a solution that works better with OOo and not what the specification says it should do. Having a second independent implementation will benefit us all by keeping the standard authoritative, not the most popular implementation.
The event consisted of several interoperability scenarios, essentially manual testing of making a document, saving it in your app and adding it to the wiki. Then loading everyone else’s document and checking whats broken. Followed with an investigation how you can do better. Its a good way to keep the developers focussed so they don’t spent all their time on one feature and being bad overall. KOffice did pretty well here, except for the areas that were already marked as experimental anyway (like change tracking, which is work-in-progress).
Joining the OpenOffice.org conference was making me a bit uneasy, on going there I felt like I’m a spy in the opposite camp. How wrong I could be! The conference was indeed called OpenOffice.org but essentially is a collection of people interested in the open document format as well as the main implementation. There were lots of people from governments and other stakeholders that made clear they were just as interested in KWord as in any other ODF implementation.
This is a stark contrast to the usual events I go to where the majority of participants are volunteers or students. For I went through my business cards quite fast and wished I had brought more.
As usual I get a lot of good energy from these conferences, so many friendly faces, good talks and this being Italy, I had quite good food too
I’m always happy to get a face to a name I’ve been emailing with and nothing works better than a conference in a country where wine is as cheap as water during dinner.
For all you 3D and graphics hackers out there this will not be news: writing OpenGL code is a pain.
Well, the Qt Graphics team is coming to save your sanity with the a new project called Qt/3D.
We teased about Qt/3D by putting a few of the foundations for it in Qt 4.6, which will be released very shortly. See the Qt/3D 4.6 features blog post for more details.
At some point Qt/3D will be available as part of Qt itself - exactly what sort of module or library we are not sure just yet - but for now you can try it out via Qt Labs!
With this post we’re pleased to announce that Qt/3D will be available for experimental use via the new Qt/3D labs repo.
Old School OpenGL code gets the Qt Treatment
The trusty old QGLWidget got you past first base: a nice window set up with a OpenGL context ready to go.
But from there you’re on your own with the OpenGL reference book, tearing your hair out writing code like
void My3DWidget::paintGL()
{
QColor clearColor(palette().color(backgroundRole()));
glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QColor color(170, 202, 0, 255);
glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF());
static float vertices[] = {
60.0f, 10.0f, 0.0f,
110.0f, 110.0f, 0.0f,
10.0f, 110.0f, 0.0f
};
glVertexPointer(3, GL_FLOAT, 0, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
}
just to paint a triangle on the screen.
But then if you want cross-platform code - something that you can try on your desktop, and then run on your device with OpenGL ES, it starts to look really horrible!
Macros everywhere to cope with the different function signatures and data types - not to mention shaders under ES 2.0 versus classic GL on the desktop, and a swath of other cross-platform difficulties.
With Qt/3D your code looks like this:
void My3DWidget::paintGL()
{
QGLPainter painter(this);
painter.setClearColor(palette().color(backgroundRole()));
painter.clear();
painter.setStandardEffect(QGL::FlatColor);
painter.setColor(QColor(170, 202, 0, 255));
QGLVertexArray vertices(QGL::Position, 3);
vertices.append(60.0f, 10.0f, 0.0f);
vertices.append(110.0f, 110.0f, 0.0f);
vertices.append(10.0f, 110.0f, 0.0f);
painter.setVertexArray(vertices);
painter.draw(QGL::Triangles, 3);
}
And what’s more it runs the same on your OpenGL/ES device and your desktop. (Note that I have elided the view and model transform setup code from both examples above for the sake of space).
As mentioned in the previous blog post Qt/3D has been in the wings for some time now, and the eagle-eyed might have notice math classes springing up in Qt’s GUI module.
These classes provide the basis for Qt/3D’s cross platform geometry abstraction: QGLVertexArray. This nifty class also dovetails into the QGLBuffer class to take care of uploading your geometry to VBO’s on the graphics adaptor, as well as coping with differences in platform on data member sizes.
Download the code from the labs repo and try out the examples - the code above comes from the tutorials directory, where you can find out more about writing your traditional OpenGL apps in the Qt cross-platform way.
Whats in Store with Qt/3D
There’s more to come from Qt/3D over and above the Portability tools mentioned in the example above.
With Enablers are included encapsulation classes like QGLMaterialParameters to encapsulate OpenGL materials in a cross platform and Qt’ish way.
One of the nicest enablers is the QGLView class and its friends. Doing your GL painting into a view looks pretty much exactly the same as with an OpenGL widget, but a few more things are taken care of for you - no need to set up tricky viewing and model transforms (which is one reason why I elided them from the code above). But even better as a bonus you get a pan-rotate-zoom view window for free. Its customizable using the QGLCamera class, and with QGLLightParameters you can quickly set up your own lights too.
Then there’s Real 3D bringing basic but powerful geometry management, and model file import functionality. With this stuff we’re just dipping our toes into the world of 3D to allow coding up of basic applications using Qt style containers, QObject based memory management, and the kinds of abstractions you’ve come to expect from Qt. If you’re an Ogre programmer, or used to using Coin3D or CrystalSpace or other powerful 3D and modelling libraries - well, you’ll still need them. We’re not planning to go into competition with those established 3D toolkits.
Instead our aim is to deliver on the promise of Qt: do more with less. It should be just as easy to use a 3D model file as it is to use a PNG file, and it should be just as easy to set up a cube with a texture on it as it is to create a Qt label. We call this component of Qt/3D Real 3D because it does start to provide functionality we’re used to seeing in 3D toolkits. But we’re working to be sure we do not go too far to go down this road, and thus to decide what will go in and what will left out - so please consider the stuff in our labs release as definite maybes.
QML and Qt/3D
There’s a lot of buzz around Declarative UI and its associated language QML.
Qt/3D will work with Declarative UI by providing QML bindings so 3D functionality can be easily used from Declarative UI programs. There’s a few demos of this in the source tree which can be tried out and you can see Henriks short video about QML and Qt/3D.
We’ll expand on the exciting possibilities of QML and Qt/3D in later posts.
We hope you like what we’re planning, and look forward to your feedback - keep tuned as there are more blog posts to follow, with some cool examples and things to try with Qt/3D.
video/quicktime (7 854 ko)Today we present to you what we consider to be a candidate for the release of Qt Creator 1.3.0.
In the month since we released the beta version, we were busy taking your feedback (thanks for that!) and transforming it into code
. As a result of that many parts have seen improvements, for example there were issues with the Qt for Symbian support mended (e.g. support for S60 3rd Ed. FP1), several fixes for the refactoring engine done, and debugging improved.
This is a candidate, and we would like to hear of any issues you still find with it. We expect the final release before the end of the year, so now is the time to go to the public Qt Bug Tracker, and tell us.
You can download the packages from the Qt Creator Preview Website.
Today, we move another step closer to the Qt 4.6.0 release, with the shipping of the first release candidate.
This release improves on 4.6.0 Beta 1 by adding yet more bug fixes and documentation improvements, fine-tuning a couple of the new API’s, and incorporating various feedback from you, Qt’s community of developers and users.
The Release Candidate is very close to what the final 4.6.0 release will be. The main aim of the RC is to solicit feedback from the community and catch any remaining high priority bugs before the final release, which we expect will happen before the end of the year.
If you find a bug, we want to hear about it. You can submit a bug report and/or an autotest that demonstrates the bug via the public Qt Bug Tracker. If you know how to fix the bug, you can submit a merge-request to the public Qt source repository on http://qt.gitorious.org.
The Release Candidate is available as a source package (choose from .tar.gz and .zip versions), and as pre-built binary packages for Windows, Mac OSX (Carbon and Cocoa) and Symbian. In addition to the set of binary packages shipped with the Beta, we are now providing an opensource version of the Visual Studio 2008 binary package.
You can get all of the packages from the Qt Preview Website, or from our http://get.qt.nokia.com. You can also find the latest documentation at http://qt.nokia.com/doc/4.6-snapshot/index.html.
Finally, a note for users of the MinGW binary package: This package is now based on MinGW 4.4. The installer no longer offers to download MinGW for you, but rather offers to use a version of MinGW that you already have installed on your machine. You just tell the installer which directory MinGW is installed in.
If you don’t already have MinGW 4.4 installed, you can download a .zip archive from our ftp site. This archive provides fixes to MinGW and support for missing API, See the _patches directory in the archive for details.
I just wanted to post a quick thank you to everybody who congratulated me on the German Medal of Merit, I truly appreciated it.
To get the facts straight: the Medal of Merit is the lowest class of the Order of Merit of the Federal Republic of Germany, unofficially but commonly described as Federal Cross of Merit. The medal does indeed feature a big cross, so the familiar name fits well. In order to get the next class - the Cross of Merit - you will typically have to be at least 40 years old, so this is a good as it gets and it does feel very satisfying indeed.
Let me explain the satisfying part: In Germany, the medal of merit is a state decoration which you receive for merits for the common welfare. It’s granted and signed by the President of Germany, at present Horst Köhler, In other words, this is yet another sign that we, the free software community, the hackers, the geeks, have arrived at what’s called the middle of society. What a change from the beginnings of KDE!
For those that do not rememember, it has taken a long time for free software to be seen as valuable outside our closed circle of hackers. Initially it was even seen as something bad, as some evil movement to harm companies and to kill jobs. When I started with free software I met either indifference, or more frequently malice and total lack of understanding. How can anybody in their right mind waste valuable time with this? For example, I do remember a situation where a fellow student of mine wanted to help me out when he learned that I spent all nights programming a document processor. His solution, in all honesty and seriousness, was to offer me a pirated copy of a commercial word processor.
And now this. Official recognition by the President of Germany. Should anybody wonder why you spend time with free software, let them know that in Germany this is officially recognized as work for the common welfare - isn’t that plain brilliant?
Obviously it’s not the freedom aspect per se that makes our software relevant for the common welfare. A free ego-shooter, while fun to work on, might for example not fall into this category. What makes all the difference is what we strive to achieve with KDE - and with the free desktop in general: a complete system for normal users, everything you need to participate in our modern communication society.
Society in Germany is starting to recognise this value. So I have been lucky enough to be selected as a representative for you all. All of you that strive to broaden the use of free software for everybody. It was both a day for me to proudly look back on what I have achieved with you, and for all of us as a community to be proud of what we achieve together. Whether you are a direct contributor, a supporter or a user of free software, be it KDE, Gnome or the underlying distributions, this award was just as much for you. I hope you are as proud as I am. You should be.
Thanks again, and keep on hacking.
To everyone using Qt 4.6 from the Git repository: be aware that I introduced a binary-incompatible change. This change is there to stay.
No, we’re not breaking binary compatibility with Qt 4.5. This only affects previous Qt 4.6 versions.
Actually, this kind of change happens all the time. So why am I blogging about this specific change?
Well, the problem is that this change affects QHash, QMap and QVector. And those classes are inlined everywhere in Qt-using code. This means that, if you update Qt across that version, you must recompile all of the Qt-using code, from scratch (i.e., make clean). For KDE developers using trunk, that means recompiling all of KDE.
This change will be included in the upcoming Qt 4.6.0 Release Candidate.
Note: the change is in the 4.6 branch but hasn’t reached the 4.6-stable branch yet. That also means it’s not in kde-qt’s 4.6-stable-patched branch yet. When you next update those stable branches, please remember to recompile everything.
PS: the stable branches aren’t updating not because of Qt not building. It is buiding. The reason why is because our Continuous Integration system experiencing some technical difficulties, like Windows running out of memory, the Symbian buildsystem failing for no apparent reason, the powerful 8-core Mac machines being able to run only one testcase at a time, etc.
For the last year, we have been investigating API’s that Qt needs to support 3D applications and clever 2.5D effects with OpenGL. When we started all this a year ago, the problem was broken down into three main areas:
- Enablers - Basic building blocks like matrices, shaders, vertex buffers, etc.
- Portability API - API’s that make it easier to write code that ports between desktop OpenGL and embedded OpenGL/ES. Particularly OpenGL/ES 2.0 which does not have a fixed function pipeline.
- Real 3D - API’s that take Qt into new application spaces beyond animations and 2D effects.
Obviously that covers a lot of ground, so in this post we will just focus on a few of the Enablers - specifically the ones that made it into 4.6 as the first taste of Qt/3D. In future posts, we’ll publish Qt/3D repository details and show you more of our plans for later Qt/3D releases.
Math3d
Traditionally, Qt has relied upon the OpenGL library to provide mathematical primitives, using functions like glOrtho(), glRotate(), and so on to manipulate matrices and vectors. However, with the advent of OpenGL/ES 2.0 it is no longer possible to rely upon the OpenGL library to do the heavy-lifting - the programmer has to do all the work. Also, the traditional OpenGL functions are really only useful when drawing objects - they aren’t of much use when building object meshes in memory and transforming them prior to uploading to the GPU.
So we really needed a hardcore 3D math library, just like the other 3D toolkits (Coin3D, Ogre, OpenSceneGraph, etc). But we didn’t want to go overboard - it is very easy to re-invent all of linear algebra and lose sight of the core goal: make typical 3D mathematical operations fast and elegant. We recognized that libraries like Eigen were very good at doing everything in mathematics, but our own goals were more focused. So what did we do?
The central workhorse is of course QMatrix4×4, which is highly optimized for 3D operations. Internally it keeps track of its “type” - whether it is a translation, scale, rotation, etc - so that it can more efficiently build up transformations than a naive “make matrices and multiply” implementation might. QTransform does the same thing for 2D transformation matrices. The following is an excerpt from the hellogl_es2 example in Qt 4.6 which builds up a modelview matrix and sets it on a shader program:
QMatrix4x4 modelview; modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f); modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f); modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f); modelview.scale(m_fScale); modelview.translate(0.0f, -0.2f, 0.0f); program1.setUniformValue(matrixUniform1, modelview);
As can be seen, it is very similar to the traditional OpenGL functions:
glRotatef(m_fAngle, 0.0f, 1.0f, 0.0f); glRotatef(m_fAngle, 1.0f, 0.0f, 0.0f); glRotatef(m_fAngle, 0.0f, 0.0f, 1.0f); glScalef(m_fScale, m_fScale, m_fScale); glTranslatef(0.0f, -0.2f, 0.0f);
The choice to make the functions similar was deliberate: code that uses the existing OpenGL functions can be quickly converted into more portable code that uses QMatrix4×4.
The QGenericMatrix template is used for creating “other” matrix sizes that commonly crop up in OpenGL work: 2×2, 2×3, 2×4, 3×2, 3×3, 3×4, 4×2, and 4×3. It can do a lot more of course, being a template, although we did draw the line at supporting sparse matrices - the matrix sizes that occur in 3D code are rarely very large. A common question is why didn’t we make QMatrix4×4 an instance or subclass of QGenericMatrix. The main reason is performance - the 4×4 class needs to be very fast and it is easier to performance-tune a concrete class that isn’t at the mercy of the compiler’s template expansion system. The other reason is to reduce user confusion - the API’s for all QGenericMatrix sizes is exactly the same, but QMatrix4×4 is extremely rich in the additional operations it provides.
QVector2D, QVector3D, QVector4D provide vector classes of various sizes to complement QMatrix4×4. An interesting feature for the purposes of OpenGL is that these classes are guaranteed to use the same floating-point type internally as GLfloat on the system. QPointF wasn’t suitable for our 2D vector needs because it uses qreal, which can either be float or double depending upon the compilation flags passed to Qt’s configure. The GLfloat guarantee is very important when building large 3D object meshes: you want to get the vertex data into the most efficient format as early as possible. If we had made the internal type qreal, then Qt/3D would have needed to do a lot of floating-point conversions when uploading vertex data to the GPU.
The QQuaternion class is the last in our current math3d set. It provides an efficient implementation of rotations in 3D space for use with camera positioning, rotation, and animation.
Shader Programs
The fixed function pipeline in OpenGL is getting very “old school”. These days, OpenGL is all about shaders, shaders, shaders. But resolving the extensions and managing the compilation, linking, and use of shader programs can be quite daunting. In Qt 4.5, we had no less than three different internal shader program wrappers for pixmap filters, the OpenGL2 paint engine, and the boxes demo. So in Qt 4.6 we have merged all of these efforts and devised a new public API to wrap the extensions. The result is the QGLShader and QGLShaderProgram classes, which:
- Support the GLSL and GLSL/ES shader languages.
- Handle vertex and fragment shaders (geometry shaders are coming in future versions of Qt).
- Support writing portable shaders that work on both GLSL and GLSL/ES.
That last point is probably the most interesting for Qt. GLSL has a lot of built-in variables like gl_Vertex, gl_Normal, gl_ModelViewProjectionMatrix, etc that don’t exist in GLSL/ES. In turn, GLSL/ES has additional type qualifiers like highp, mediump, and lowp that are used to specify the desired precision. These issues can make it a pain to port existing shader code from desktop to embedded. We didn’t want to have to write two sets of shaders for the OpenGL2 paint engine, so a solution needed to be found.
The solution we chose was to use GLSL/ES as the primary language for writing shaders in Qt, and provide #define’s for the extra keywords to make the code compile on desktop GLSL systems. It is still possible to use the full GLSL language if you want to, but portability will suffer.
The following example demonstrates how to compile and link a simple shader program that can be used to draw triangles with a flat color:
program.addShaderFromSourceCode(QGLShader::Vertex,
"attribute highp vec4 vertex;"
"attribute mediump mat4 matrix;"
"void main(void)"
"{"
" gl_Position = matrix * vertex;"
"}");
program.addShaderFromSourceCode(QGLShader::Fragment,
"uniform mediump vec4 color;"
"void main(void)"
"{"
" gl_FragColor = color;"
"}");
program.link();
program.bind();
int vertexLocation = program.attributeLocation("vertex");
int matrixLocation = program.attributeLocation("matrix");
int colorLocation = program.uniformLocation("color");
The highp and mediump keywords are added to keep GLSL/ES happy - on desktop they #define to an empty string. Also, we have deliberately used user variables for the vertex position, matrix, and color rather than relying upon the desktop-specific gl_Vertex, gl_ModelViewProjectionMatrix, and gl_Color variables. We can then draw a green triangle as follows:
QVector3D triangleVertices[] = {
QVector3D(60.0f, 10.0f, 0.0f),
QVector3D(110.0f, 110.0f, 0.0f),
QVector3D(10.0f, 110.0f, 0.0f)
};
QMatrix4x4 pmvMatrix;
pmvMatrix.ortho(rect());
program.enableAttributeArray(vertexLocation);
program.setAttributeArray(vertexLocation, triangleVertices);
program.setUniformValue(matrixLocation, pmvMatrix);
program.setUniformValue(colorLocation, QColor(0, 255, 0, 255));
glDrawArrays(GL_TRIANGLES, 0, 3);
program.disableAttributeArray(vertexLocation);
Note the use of QMatrix4×4 above to create an orthographic projection matrix to pass to the vertex shader, and the use of QVector3D to build the vertex array. And that’s basically it! Shaders 101.
What’s Next?
Lots and lots of stuff. Wrapper classes for vertex buffers and textures will probably go into Qt in the near future. Geometry handling for building object models. Special-purpose 3D viewing widgets. Integration with Declarative UI for quickly building 3D applications. And the portability API. More to come on these in the next post …
Lately I’ve been working on a couple of exciting customer projects, involving HTML5-based UIs on embedded (TV) platforms. Due to the fabulous work some of my colleagues put into QtWebkit and QtDirectFB, and the ongoing work from MIPS Technologies on their Webkit JIT, the paint performance is very good, and Javascript is getting faster and faster.
However, while working on these projects, I’ve ran into a few issues that were not solvable by JIT-accelerated JavaScript or by hardware accelerated painting.
The main problem was that when you write a dynamic UI for a full application, the complexity starts to be difficult to manage. I started by dividing the app to a few HTML pages, but that of course created unacceptable delays when switching between the pages. So I looked online for dynamic web-app solutions. Those include the amazing Javascript libraries Dojo and JQuery. The problem with those is that they manage the complexity by selecting elements with custom-built CSS-like selectors (which are slow) and by modifying the HTML DOM tree in runtime (which is slower).
An alternate way to handle HTML performance is with the HTML5 canvas element (which is nicely accelerated) - the problem is that canvas API is currently too low level, and the widget libraries on top of it are not mature yet, definitely not in time for my customer projects.
So I asked myself: what components are really needed in order to make a dynamic UI?
Looking at the Qt Kinetic project, I need 4 main elements:
- Animations
- State Machine
- Graphic effects
- Declarative Syntax
Now HTML and CSS are already a declarative syntax, and CSS3 (supported in webkit) contains all the animations and graphic effects I currently need. The missing element, which is also my personal favorite, is the State Machine.
Why do I keep going on and on about state-machines?
If you think about it, both CSS, HTML, and Qt widgets are optimized to handle complexity in space. State machines, however, are optimized to handle complexity in time. An application can be dynamic only if it’s rich both in space and in time. That’s why to me state-machines are of outmost importance for dynamic UIs.
Enough philosophy, what’s this about?
Now I’ve had the pleasure to work with the SCXML standard in the last year, both by prototyping the Qt-SCXML library (which later helped with the evolution of the Qt State Machine Framework), and by joining the w3c group that defines the SCXML standard.
While working on my latest HTML-based project, I was thinking - what if I could define the flow of my web-app with an SCXML statechart? Wouldn’t that allow for managing the complexity of my web app, without incurring the performance overhead of modifying and re-modifying the DOM?
Introducing Statechartz
So I took the time to write an SCXML library for Javascript. I basically had to copy the SCXML algorithm to Javascript syntax, which took a while, but has already saved me hours of work by having the code of my web-apps cleaner and smaller.
The result can be found at the statechartz branch on the SCXML lab GIT repo., and the demo can be viewed online. Note that the library is currently only tested on webkit-based browsers (QtWebkit/Arora, Safari, Chrome), but porting it to other browsers shouldn’t be too difficult.
Looking a bit at the HTML code of the demo, you’ll notice the following:
<link rel="statechart" href="flow.scxml" />
This is the line that connects an HTML page with an SCXML statechart, defining the page’s flow. The state-machine would start running as soon as the page is loaded.
But hey! rel=”statechart” isn’t standard!
Well, I was surprised to learn that HTML5 allows you to add your own link types, which become legal if you register them in the WHATWG Wiki, which I did; so now <link rel=”statechart” href=”somefile.scxml” /> is completely standard ![]()
Though using the link tag would cover most cases, it’s completely optional and the Statechartz library can be used more dynamically, either by loading an SCXML file whenever wanted:
var myStateMachine = Statechartz.loadScxml(someURL);
or by using a dynamic javascript syntax that looks like this:
var myStateMachine;
with (Statechartz) {
myStateMachine = build(
State("root",
Entry(function() { doSomething(); }),
Parallel("s1",Initial,
Exit(function()(doSomethingElse(); }),
Transition(Event("EVENT.QUIT"), Target("exit"))
),
Final("exit")
)
);
}
Another thing to look at, is the DOM:
<div id="screen_weather" class="screen">
<script type="text/javascript" src="..."></script>
</div>
<div id="screen_shopping" class="screen">
<iframe src="..." height="240" width="320" scrolling="no" style="overflow:hidden" frameborderwidth="0"></iframe>
</div>
<div id="screen_calc" class="screen">...</div>
Even though screen_weather, screen_shopping and screen_calc exist in the DOM to begin with, only one of them is shown at a time. Also, there’s no particular Javascript code that shows and hides them. That’s done by a trick I added to the Statechartz library: the CSS class of the document BODY element changes when the state changes. So, if I’m in a state with ID “calc”, the body would have a CSS class “state_calc”, and now all it takes is adding this to the CSS (it’s a little different in the actual CSS, but I’m trying to make a point):
#screen_calc {
left: -350px;
-webkit-transition-duration: 600ms;
opacity: 0.5;
}
.state_calc #screen_calc {
left: 0px;
-webkit-transform: rotate(360deg) scale(1);
opacity: 1;
}
This code, like states and transitions in Qt 4.6, would animate the opacity and geometry of my calculator screen, and would create an animated transition when the calculator is entered to / exited from.
The Demo, and performance
The demo that comes with the statechartz library demonstrates 3 uses of the Statechartz library:
- Dynamic UIs with states and transitions (switching between the 3 widgets)
- Managing UI complexity (e.g. the instructions popup)
- Business logic (the calculator ‘engine’)
Note that the demo specifically is too animation-heavy to run well on embedded platforms, and of course webkit could use some more optimizations. but the concepts (don’t mess with the DOM, use Statecharts to manage time) are the same, and are working on other webkit-based projects with a cvery nice performance gain.
The next step on the SCXML path
After this project, SCXML is now supported in 3 implementations: Qt C++ (with scc), QtScript (with QScxml), and web (with Statechartz). The next natural step is a statechart graphical tool (Creator plugin) that can help author SCXML files for all of those 3 implementations. Though it’s not on our roadmap, some of us (including the undersigned) were working on prototypes, and any help from the community would be appreciated!
Links
The code: http://qt.gitorious.org/qt-labs/scxml/trees/statechartz
The live demo (webkit browsers only): http://labs.trolltech.com/blogs/wp-content/uploads/2009/11/demo.html
Video capture of the live demo: http://labs.trolltech.com/blogs/wp-content/uploads/2009/11/statechartz-capture_0001.wmv
video/x-ms-wmv ( 967 ko)Benchmarking is an important concept for evaluating the performance of computer systems. It can be considered essentially a three-step process:
- Step 1
- Define the benchmarks.
- Step 2
- Execute the benchmarks and produce numbers.
- Step 3
- Analyze the benchmark numbers.
Each step has its own challenges: Step 1 is about writing programs that test sufficiently interesting/relevant parts of the target product. In Step 2 one needs to define what resource to measure and ensure that the measurements are as reliable as possible in various software/hardware contexts (note that QTestLib provides some help here through the -median option and by supporting callgrind). Step 3 is concerned with “higher level” analysis problems like how to detect performance regressions as reliably as possible, how to compare different implementations of a particular algorithm and so on.
This article introduces BM, a tool that attempts to solve some of the problems that may arise in Step 3. In particular we focus on how potential performance regressions can be detected. Currently the idea is to evaluate this tool for our internal QA needs, but we hope that others may find it interesting too and give us some feedback.
Benchmark results and execution context
BM is based on QTestLib concepts: First, a benchmark is identified by the combination of a test case, a test function, and a data tag (optional). The benchmark should execute some part(s) of the target product. Second, a benchmark result (i.e. the result of executing a particular benchmark) is essentially a single, non-negative number.
A benchmark result is produced within a context made up of the following components:
- Metric
- The resource used for measuring the benchmark.
- Platform
- The compiler and OS used for building and executing the benchmark.
- Host
- The physical computer on which the benchmark was executed.
- Branch
- The development branch (of the target product) tested by the executable benchmark program.
- Snapshot
- The timestamp and ID of the current branch revision.
Note that the host may identify a virtual machine that may run on different physical hosts. In this case the physical hosts should be as identical as possible with respect to both hardware and software.
BM currently assumes that git is used for revision control. The ID in the snapshot is the SHA-1 of the head commit at the time the benchmark was built, and the timestamp is the committer date.
Time series as snapshots of revision history
By varying the snapshot component only, successive runs of a particular benchmark form a time series of benchmark results. The notion of a performance regression is defined with respect to this time series. The question to ask is essentially:
How likely is it that a modification to the product itself is affecting the performance of the benchmark in a negative way?
(It would of course also be interesting to know if the benchmark performance is affected in a positive way — BM makes no distinction between the two cases.)
Ideally, new benchmark results should be produced each time the revision history is advanced. In practice this may be hard to achieve if the time it takes to produce a new set of benchmark results exceeds the product update interval.
Note that any modification done to the host or platform of a particular time series (e.g. reconfigurations or upgrades) will in theory invalidate the history in the sense that it may not make sense to compare results before and after the modification. The BM tool currently has no support for this scenario.
Change and stability
For our purpose, the only really interesting property of a sequence of benchmark results is how the results change along the revision history. Moreover, it is normally the current (i.e. most recent) change that we’re most interested in. Who cares about how the benchmark performance changed one year ago if some code that was submitted yesterday is likely to cause a bad performance regression?
Ideally, Step 2 (defined earlier) will produce reliable numbers completely free of “statistical effects”, but for various reasons this cannot be guaranteed in a real life scenario. Since nobody wants to waste their time chasing “false positives”, we need some mechanism to help us reason about the confidence. BM takes a heuristic approach to this problem by letting the user define a difference tolerance (DT) and a stability tolerance (ST):
- Two values are considered significantly equal if their relative difference does not exceed DT (i.e. if |(v1 - v2) / v1| ≤ DT)
- If vn is the last value in the time series, the current change (if any) is the latest value vc before vn that differs significantly from vn.
- A value v is considered stable if it is preceded consecutively by at least ST values that are significantly equal to v.
- The current change is stable if both vc and vn are stable.
The following figures show examples of stable and non-stable current changes (ST is 4 in all cases):



By sorting the benchmarks on their current changes (considering both sign and magnitude) and on stability, we hope to get a useful indication of likely candidates for performance regressions. Once a potential regression is detected, it may need additional manual verification before eventually pinpointing the code modification(s) that caused it.
Architecture
The BM system consists of the following main components:
- a bmserver (written in Qt) for managing the database of benchmark results,
- a bmclient (written in Qt) for uploading data to and retrieving data from the bmserver, and
- a web client (written in JavaScript) for presenting and exploring the most interesting benchmark results.
New benchmark results are uploaded to the bmserver by invoking the bmclient with the benchmark results (in a QTestLib XML output file) along with the execution context. Benchmark results already in the database may be retrieved directly through the bmclient (which can be useful for debugging), but normally it is better to use the web client. In the latter case the bmclient is invoked as a CGI program by a web server.
The following figure shows the client/server architecture with arrow directions indicating the main data flow:

The bmserver and bmclient communicate over an XML-based protocol, while communication between the web server and web client is based on Ajax and JSON.
For simplicity, the bmserver currently uses SQLite, but we plan to allow for other database backends (like PostgreSQL) if necessary.
Web interface
The web interface is organized into three main sections:
- A platform summary section that shows overall statistics for each platform/branch combination.
- A benchmark summary section that shows more detailed statistics for the most interesting benchmarks of a particular platform/branch combination (the ranking criteria may be defined by the user). Other features in this section include detailed views of individual time series, comparing the latest results of two branches, and comparing results in a local file against results in the database.
- An overall settings section.
Here are some screenshots:
Note: BM is currently known to work properly with Firefox only (partly due to the use of the HTML canvas tag for graphics).
Status and plans
It goes without saying that a proper assessment of the usefulness of BM depends on the database containing a fair amount of production data. As we speak, the Qt benchmarks (under the /tests/benchmarks/ directory) are being run at regular intervals on a Linux platform.
We would like to invite anyone interested to give us feedback on the BM tool. Does this approach make sense? How can it be improved? Etc. The repository is here (and there’s a README to get you started).
At the Munich DevDays we got a lot of questions about QML - first among them was where to download it. To celebrate DevDays in San Francisco we are releasing binary snapshots that you can download now for Windows, Mac and Linux.
For those of you who couldn’t attend DevDays, QML helps you create exciting UIs like this:
When Qt 4.6 is released, we’ll make another more up to date package. As we approach this milestone we’re focusing our attention on writing tests, squashing bugs, updating docs and giving the examples a little love - so by Qt 4.6 QML should be even better!
The response on my first blog post about the documentation facelift was so huge that for a moment I was wondering of what I had gotten myself into.:) A response like this would for sure set the level of expectations sky high and be giving our team a lot of work to be able to meet our users’ wishes. Yet again, that is what design is all about – meeting the needs and demands of the people using the product. Moreover, getting a response and engagement like this is more than a designer could ever wish for. It shows that our users care about the documentation, and that is very inspiring.
Now, with this in mind we continued the work by creating a user test that we ran at Qt Developer Days in Munich a few weeks back. If the response on the blog post was huge, the amount of people doing the test was even larger. Close to 15 % of the Developer Days attendees did the survey, and we got lots and lots of good feedback. I want to take this opportunity to thank all those who participated. All together you spent close to twelve hours giving us valuable information for our design process. That is amazing!
We now have good numbers on which solutions you want, and even better numbers on what you do not want. In addition to the poles, we got many constructive comments, which have been very useful in the process so far. To a large degree, the feedback from the test reflects the results from the feedback on the first blog post. Therefore, without dragging things out further I will tell you about the results from the test.
Design profile
In the test the users were told to choose from a set of different design concepts. The first three concepts were quite similar to the current design, displaying a set of categorized link menus. The design that got the most votes was the one using colors, icons and visual structures like borders and bullet points. This was not really a surprise since the blog feedback gave us the same indications. What did surprise me though, was that you didn’t want search results from the Google custom search engine embedded in the documentation pages. That is a clear indication of the value of user testing.
However, to sum it up, the design and feature profile you want us to use is:
- A front page similar to the current one, only using more colors and some discrete icons for recognition.
- A search box, preferably with automatic suggestions for keywords as you type. Ajax search design example
- A line of bread crumb links in the top area of the page, visualizing the page hierarchy and enabling the user to “jump” to pages several levels up. Bread crumbs design example
- A left-side menu on sub-level pages (like the class pages), ordered in a hierarchical way. Menu design example
- A way to hide and show detailed information. Show/hide design example
- A history box displaying resent searches.
You have also said that you learn best from reading and testing examples and how-tos’. We have a great collection of examples already, but we could also create more of them.
Your list of wishes
As we now draw nearer to Christmas, the concept of wish lists should be familiar to most of us. We send of our list to Santa Claus – or tell our beloved ones what we wish for – and then hope for the best. Sometimes we get what we wish for, and sometimes not. My point is this; the list of wishes will be our guide on the way to what I hope will be a good design, but it will not be a guarantee to make your every wish come true.
Our goal is still to create a design meeting the needs of both the experienced and new Qt users. We need better navigation, better ways to categorize overviews and to improve searches. In other words, we have a lot of work in the months to come. We need to further analyze the design and find out how we best could implement the new solutions. There will be some short-term goals and some long-term goals. I will blog more about them as soon as they are implemented. I still urge you to keep the feedback coming in. It is useful for us and very inspiring.
I know that is quite silent about the Qt Windows CE port is the past, but be asured Qt for Windows CE has not been forgotten at all.
A lot of Windows CE bugs and issues have been fixed for Qt 4.6.
Some people might have noticed that a short while ago Windows Mobile 6.5 was released. Unfortunately this was a little bit to late to fully support officially Windows Mobile 6.5 in Qt 4.6.
But the good news are that we will have some support for Windows Mobile 6.5 in Qt 4.6 and will fully support it for Qt 4.7.
Qt 4.6 will contain mkspecs for Windows Mobile 6.5 and it also will contain support for the new style. This means that Qt 4.6 applications look native on Windows Mobile 6.5.
It is also worth mentioning that the new animation framework is fully supported on Windows CE, which allows some really nice effects. This means that Qt is really able to leverage the Windows Mobile experience to new heights or in more appropriate words (I am not a marketing guy.): Qt can help you to deliver astonishing applications for Windows Mobile.
Since screenshots tell more than words, here are some:

The famous Text Edit.

A styled Tab Widget.

The new List View highlight.
One day I was sitting at my computer, waiting for my build of S60 to finish. I had run my usual round of build commands and custom scripts to speed up the build if but a little, and was expecting to wait for at least 10-12 min. At this point it occurred to me (well, it had occurred to me before): The Symbian build system is really overkill. What could it be doing that’s taking so long, for something that should be relatively simple: compile and link?
So I thought to myself that this can definitely be improved, and that’s how I started the work on a Symbian make specification that is based entirely on qmake and make (no Symbian build chain stuff, although it uses the tools from there), and runs on Linux.
Then you might say “What about the Raptor build system that is supposed to improve things?”. It is true that Raptor improves a lot of the deficiencies of good ol’ abld, but I still felt that the huge Raptor build system is sooo overkill for something really simple. I like to obey the KISS principle. Call it a personal itch!
With this in mind I have two design goals:
- Ditch all unnecessary file types. This includes bld.inf and MMP files.
- Be fast!
Whether I’ll be able to fulfill them in the end, time will show, but that’s what I’m aiming for at least.
But let’s get into the gory details. Be reminded that the build system is still in the very early stages, and is not ready for for the end user yet, but if you like to tinker with the latest and greatest, read on. Here’s what works currently:
- Running configure.
- Building QtCore.dll with RVCT.
- Running QtCore.dll
- Building user applications with RVCT.
- Running user applications.
Here’s a few things that don’t work yet, but I plan to get them working:
- Building the host tools automatically (this needs to be done manually ATM).
- Building QtCore.dll with GCCE (this doesn’t work with the official port either, but as soon as it works there, it should work here as well).
- Other Qt dlls. QtGui.dll should probably be easy to get compiling, but it needs a few header fixes first.
- Building user applications with GCCE.
- Making the process of building a package automatic.
Here’s one thing that will probably never work:
- Building for the emulator. The emulator won’t run under Wine, so there’s no point in building for it. If the build system gets ported to Windows maybe it’ll be supported, but not before then.
The procedure for getting the system up and running is subject to change as the project goes forward, so instead of posting it here, I have put it in the README.s60-mkspec in the Git repository. To get it, go to http://qt.gitorious.org/+qt-developers/qt/s60-linux-mkspec, and clone the repository from there. Then check out the “working” branch. This branch is often rebased based on the latest work in the topic branches. “master” should not ever be rebased, but many things are missing from there at the time of writing.
Here’s a few short term goals for the project in the following weeks:
- Get the other modules compiling.
- Get the process to be more streamlined (e.g. more like the other platforms)
- Move from ABIv1 to ABIv2. The former is the old way of linking binaries on Symbian. Since this is being superseded by ABIv2, which is binary compatible at run time, but not compile time, it makes sense to only support that.
Someone sent me an e-mail asking what happened to the freedesktop icons I blogged about back in february so I realized I should probably write a followup. I’m happy to say that it has been merged into Qt 4.6 for some time already. If you look up the documentation for QIcon, you will find a new function QIcon::fromTheme(…) which essentially does what QtIconLoader::icon(…) did. Meaning Qt applications can now make use of the icon themes that KDE and GNOME ship with and use by default.
Since freedesktop icon themes only come as standard on X11 based desktops, you cannot use themed icons on other platforms such as Windows and Mac directly. This will simply return the fallback icon you provide. Allowing this would have forced us to decide on a standard icon theme as well as bloat the application by an extra few megabytes that many applications do not need. Instead we decided to leave this choice entirely up to the developer by making it possible to bundle themes such as Oxygen or Tango as part of the application resources and pointing to it using QIcon::setThemeName(…) instead.
This should make those pure Qt applications look a lot more integrated into the X11 desktop! Among other things, our trusty old Assistant client was modified to use the theme icons:
Screenshot showing of Assistant running on GNOME in 4.6.
Here is the same application running on KDE 4.
For those of you who don’t read the new Qt blog website, where Qt Marketing and Product Management talk about “corporatey” stuff (affectionately called the “PHB blog” by our developers), we’ve just announced that our brand, new bugtracker is public: see http://bugreports.qt.nokia.com.
So, I won’t repeat everything that is in the other blog (it is, after all, written by Marketing, so it should be better written than this thrown-together “reblogging”). I’d just like to highlight one important point that Adam made in his blog:
The Qt Bug Tracker isn´t simply a read-only view into the bug tracking system used by Qt developers, it is the bug tracking tracking system used by Qt developers.
The previous solution was an in-house system we had built over the years. It started as a distribution list for the Qt developers back in the day, then got an automatic tool to reply to the emails received and assign numbers, a robot to collect incoming emails and add to the database. Internally, we’ve had a rich-client to access that database and manipulate our own bugs. But communicating with the reporters was always very difficult.
This new tool is different. Everything is on the web. And you get to vote on issues, even watch if they change.
This is another step in our opening up of our development model. Enjoy!
Do you know the main advantage of a Hummer? It can go pretty much everywhere, that’s why many armies are using it. If I talk about a Hummer it is because QGraphicsView can go pretty much everywhere too. Recently I was lucky enough to get a N900 (generously given by Jesper, don’t know for how long though) so I decided to test Qt on it. I mainly work on QGraphicsView here at Qt Development Frameworks so it was a way to test the speed of my toy (:p). Since I’ve also been a KDE user and developer for quite a bit, I thought I could try KDE on it and more precisely Plasma.
So I downloaded the Maemo 5 SDK and started building KDE and Qt with it.
First thing you have to know is that scratchbox is not easy to set-up because you always face problems and compiling inside scratchbox is really slow. The link step is a bit broken and you have to specify manually where are the libs you link with (apparently it’s expected to be like that). It seems odd… Anyways, after a couple of hours I had Qt 4.6 (Fremantle branch) up and running. I was quite happy to see that it performs well (if you are using the right things). Animated tiles are running smoothly and painting demos as well (using opengl es2 graphicssystem).
After this initial success I tried KDE. This was more painful than I originally thought. Broken packages (mysql-server), out-dated packages (shared-mime-info for instance) and the worst : CMake crashed during the configure step. I solved that by downloading the 2.8 RC version that I built myself. But after a couple of hours of fighting and debugging I got this:
As you can see Plasma is running fine on this device. Of course a lot of work is needed to make it “finger” enabled (the actual applet handles are not really appropriate) but it’s a good start and Plasma is flexible enough to allow that. I have created a separate “shell” called plasma-mobile (Plasma already has the desktop and netbook shell) and I pushed that on the KDE playground. It also needs a lot of work to integrate well with the device (battery, network, profiles and so on) but the goal is to invite people to contribute to Plasma in order to offer a real alternative to the hildon-desktop. Plasma already has many many features/applets that we can just use on the N900. This also comes with a global effort to bring KDE technologies to the device as Kevin said in his blog. You can also participate in discussions on the KDE mailing-list for Maemo.
So yes Plasma is also a hummer, it runs everywhere but it’s the luxury version.
Since there is currently no official Spotify client that can run on Embedded Linux (wine doesn’t run on arm architectures), and since I really wanted to have access to my Spotify account from my N900, I decided to give the open source Spotify client library called “despotify” a run. This is a library of C functions used to access different parts of the Spotify API for use with premium Spotify accounts.
By playing around with the console clients that are included with despotify, I was able to access my play lists and play songs perfectly. However, I was unable to use any of the GUI front ends to despotify that I could find. My guess is that they do not play well with Maemo 5 as they were originally written for the n800-series.
Inspired by the fact that all this stuff actually existed, I decided to write my own front end to Despotify, using Qt 4.6. The results can be found in Gitorious, at:
http://qt.gitorious.org/qt-labs/qtspotify
To build the application, first compile and install despotify as explained here.
Make sure you enable “pulseaudio” as the back end for despotify by editing the Makefile, as the default gstreamer back end has some threading issues and will cause crashes if you access the GUI while it’s playing. When you are done, do a “make install”.
To build the front end, you also need to have Qt 4.6 available. For best results on the N900, use the Maemo branch of Qt.
When you are done, copy the executable to your phone and start it up. Use the menu to log in, and the search field to search for music. If you want to access your play lists, select the “Retrieve play lists” menu option and they will pop up in the search field menu.
This is what it will look like:

Note that this is an early version, so there are still bugs and some missing features (e.g. you don’t get more than fifty results for a search) that I intend to implement when I get the time, but the client should be usable as it is.
I have shown parallax sliding example long time ago. It was certainly inspired by the increase use of such an effect in the so-called home screen, typically in the mobile platform. Since there has been also an increase interest on Qt for Symbian example programs, I decided to recycle that old example and to turn it into something that fits the form-factor and user experience on the phone. Thus, the demo is (re)born.
The code is in Graphics Dojo repository, find it in the parallaxhome subdirectory. For a touch device, you can tap on the icons on the bottom bar to switch between different pages (enjoy the subtle bump effect of the icons). With a non-touch device, left and right arrow keys are your friends. The heart of this parallax effect is the difference of speed between the graphics items (those wonderful food photos) and the background. The above screenshot demonstrates that exactly: on the right side, although now the page (with the weather icon) has been shifted from the center one (with the home icon), you can see that these two pages mostly share the same background portions.
Exercise for the reader: use the panning trick to shift between one page to another. If you feel brave, add some kinetic effect, too.
As a last note, this will be my last Graphics Dojo example. For future Qt-related code examples, please check my personal blog on a regular basis (e.g. just track the posts tagged with qt).
May the training spirits be with you! Namárië.
I had the pleasure of talking to some fellow state machine enthusiasts at DevDays in Munich. Here are some of the topics that were brought up, in randomized order:
Verification. How can you check that your state machine is sane, or rather, how can you disprove that it’s criminally insane? Currently there isn’t a way to do that. We tried to design the API so that many (most?) semantic errors will be caught at compile time. But that doesn’t get us all the way, unfortunately; what happens if you forget to specify the initial state of a compound state, for example? The QStateMachine::error() signal is there to report such cases; if the state machine detects a semantic error at any stage of executing its algorithm, it emits the error() signal. But maybe it would be nice to have a function that can run a set of standard sanity checks before the machine is started?
Performance. We currently implement the SCXML algorithm more or less exactly as it’s specified. I don’t yet know how well it scales wrt number of states and transitions; well, I have one benchmark where the running time grows exponentially, but there are many different configurations that need to be investigated (flat vs nested state machines, sequential vs parallel states, custom events and transitions vs built-in ones, etc.). Is anyone out there creating state machines with thousands of states, and if so, are you seeing performance issues?
Lazy population of states. For large compound states, it can make sense to only create the contents of the state when (if) the state is actually entered. To do that, you need only create an initial state, and reimplement QState::onEntry(). You need to create the initial state because the state machine will request it _before_ the compound state is entered (and QState::initialState() is not virtual…). In your onEntry() implementation, use a flag to check whether the state is being entered for the first time, and if so, create the remaining child states and add transition(s) to them from the initial state, as appropriate. The state machine actually does similar kinds of lazy initialization internally; the signal associated with a QSignalTransition is only connected when the transition’s source state is entered, for example.
Debugging. There’s no straightforward way to debug state machines in Qt 4.6. What’s needed first is a “debugger client” interface that the state machine can use to deliver notification of e.g. state changes. This interface would then serve as the basis of debugging tools. It would be nice to have a visual representation of the machine (tree view?) highlighting the current state, be able to “step” the state machine execution, set breakpoints on transitions, inspect the event queues, and so on. P.S.: If you’re building Qt from sources, there’s a QT_STATEMACHINE_DEBUG define that you can enable in qstatemachine.cpp; this will cause the state machine to spew out a log of everything it’s doing. This output can be difficult to parse humanely, though, especially when your machine has nested states.
Why QtCore? Couldn’t the state machine framework be in a library of its own? Yes, it could, but we chose to put it in QtCore so it can easily be used anywhere, without introducing new dependencies. The QtCore library grows by about 5% (150K) due to the state machine classes. Note that it’s still possible to remove the framework from compilation by using the qconfig tool, just like you can with the animation framework (also part of QtCore) and several other features in Qt.
Multithreading. How do you use state machines with threads? Well, there are a few things you should know. Firstly, the state machine classes are reentrant, meaning you can have multiple state machines running at the same time (one per thread, say). Secondly, the QStateMachine::postEvent() function is _not_ thread-safe, meaning that it’s not safe to call postEvent() on the _same_ machine from different threads; you’ll have to manage the synchronization yourself if you want to do so (but maybe QStateMachine::postEvent() should be made thread-safe, like QCoreApplication::postEvent()?). Thirdly, if you’re using signal transitions, there is no restriction on whether the object emitting the signal lives in the same thread as the state machine or not; the state machine will always create a connection of type Qt::AutoConnection, meaning that the connection will be queued if the object lives in a different thread. This means that the state machine can be processing events in its own thread concurrently with the signal being emitted in another thread, without you having to worry about synchronization.
See you in San Francisco, maybe?
Today marks the 10th Birthday of Qt Embedded! It was 10 years ago today that we first came up with the notion of an “embedded” version of Qt to serve the industrial sector and the infant higher-end handheld/CE market. At the time, the project was called “Qt/FB” (Qt for FrameBuffers).
This first version of Qt Embedded was built around the idea of a QPaintDevice for QImage. This notion (through multiple rewrites) eventually developed into some of the biggest architectural improvements in cross-platform Qt: generalized paint engines (the raster paint engine being the “frame buffer” one); window surfaces/backingstore; and Alien (non-native child widgets). These were critical improvements that then opened the door for easier platform porting (Mac OS X and Symbian/S60 benefit much from them), and accelerated paint engines, and now graphics systems, for OpenGL and OpenVG.
From simple beginnings on iPAQ and Cassiopeia handhelds and industrial devices, then, as the foundation for Qtopia, on the Zaurus and eventually phones like the Greenphone and the Neo and various cool consumer electronics devices (some of which we could never tell you about), Qt Embedded functionality was ever richer.
Embedded targets have changed a lot in 10 years - OpenGL ES is now commonplace, and the “PDA” has been completely hybridized into mobile phones. Touch screen quality and user-expectations for beautiful fluid interfaces now well-exceeding the demands on the desktop, creating ever more challenges.
We have learned a huge amount in this time about what it takes to put Qt on the “low end”. Paul’s recent blog entry about Lighthouse shows how the learning is still bubbling away, and with Qt for Symbian S60, Qt for Windows CE, and Qt for X11 on Maemo devices, the low end will of course remain a very important focus for us, with performance in all parts of Qt a key concern - bringing benefits to all Qt platforms, including the desktop.
It was announced at Qt Developer Days in Munich yesterday, but as a long standing Qt tradition states: “The release isn’t out until the Release Manager blogs about it.” So, here it is: Qt 4.6.0 Beta 1 is now ofiicially available.
This release improves on the Tech Prevew 1 release by adding a large number of fixes for bugs and documentation issues, and by finalizing the Gestures API.
The Beta release is available as a source package (there’s just one type of source package now, with .tar.gz and .zip versions that have identical contents), and as pre-built binary packages for Windows, Mac OSX (Carbon and Cocoa), and making its debut with this release, Symbian.
You can get the packages from the Qt website here, or from our ftp site. You can also find the latest documentation at http://qt.nokia.com/doc/4.6-snapshot/index.html.
As with the Tech Preview, we would like constructive feedback on this Beta from the community of users and developers. if you find a bug, you can submit a fix or an autotest that demonstrates the bug via the public qt repository on http://qt.gitorious.org. Alternatively, if you have any bug reports or suggestions, whether they relate to the code, the documentation, or something else Qt-related, just follow the instructions for submitting feedback.
In conjuction with this Beta release, we are launching The Qt Blog, a new site that will include product and roadmap information, details on Qt usage, and other topics that interest the Qt community. The Qt Blog is available now at http://blog.qt.nokia.com.
Autumn has finally arrived, it can be clearly felt everywhere in Berlin. Less daylight, more clouds, longer nights - but to keep your mind on the bright things of life, I bring you the good news that we’ve released the beta preview of the upcoming next release of Qt Creator
If you have followed this blog, then you already heard of many of the upcoming changes and improvements. I want to mention some of greater impact here:
Renaming symbols, global and local, and finding usages of symbols. Local symbols are renamed inline while typing, for other symbols a list of changes is shown for review before doing any renaming.
Be sure to use the high quality button and make the video full screen when viewing it.
Experimental support for development of Qt applications targeting the Symbian platform. This means that building and running applications against a Symbian/S60 device should work in general, but that the whole experience is not what we expect from a polished product. Have a look at the respective part of the Qt Creator documentation for prerequisites and explanations.
Also:
- Completion of include directives
- Color schemes for the text editor
- Brace, parenthesis, bracket and quote matching
- Locator filter for symbols in current document “. typeyourlocalsymbolhere”
- Integrated jom for multicore compiling projects with MSVC tool chain
- Lots and lots and lots of improvements and fixes!
Check out a more complete list in the changes file.
Together with the other platforms (finally!) we’ve now released the Qt 4.6.0 beta1 for Symbian. Get the nice installer here:
So what has happened since the last release (I’m talking about “Tower” released around 3 months ago).
- We’ve moved into the Qt 4.6 branch. This means we can break the other platforms - yay!
- We’ve added an experimental backend for Phonon (using MMF). It plays audio and video!
- We’ve fixed a lot of bugs! Still lots left though.
- We’ve added the possibility to have a mouse curser on non-touch devices!
- QtWebKit has been updated to a newer version
- The QtScript engine has been completely replaced with a nicer and faster one from WebKit.
- We’ve added daily snapshots.
- Ariya has added some new nice demos. Check out the video below.
- We’ve also removed support for compiling qmake with the Nokia Win32 compiler, but added support for MinGW and Visual Studio 200x instead.
If you want to try out these demos on your own S60 phone, here is what you do. Open your browser on the phone and navigate to:
Then simply click on the link found there, answer yes around 20 times to all the dialogs and security warnings. Then once finally done navigate to Applications and launch fluidlauncher.
For help on getting started with your own application development go here. And then finally, the obligatory video of whats new. This time I used a Samsung i8910 and my old trusty Nokia 5800. Enjoy!

The previous blog entry yesterday spawned so many sizable comments, that I felt they couldn’t be simply replied to in comments. So, here are some replies and comments to your comments, which you may comment on again
Many: “Have you considered the <insert favorite here> build system?”
Yes, we have.
Any Java-based system is automatically /ignored due to the vast overhead of running such a system, and the fact that we would then need a Java VM running on all the systems we support. A build system needs to be fast, and fairly lean.
We’re not really considering the autotools.
Max: “CMake gets a lot of “wow! it’s great!” comments, but I could write several blog posts about how it is in fact merely mediocre. I guess you guys agree since you are not considering it.”
This is incorrect. We have not said nor implied that we are disregarding CMake. CMake might not current fulfill our complete wishlist, but we are of course still considering it. In fact, we initiated discussions with KitWare (the guys behind CMake) weeks before this blog post, to see if our wishes are unitable with their plans for CMake. These discussions are still ongoing. In fact, Bill Hoffman (CTO & Vice President of KitWare) is currently at DevDays in Munich, where these discussions will continue.
nathan: “I think the idea of using JavaScript has all the many advantages”
Sylvain: “Javascript + JSON is really good, please go for it…”
Damien Arthur: “a build tool based on json would be sweet!”
Adam Higerd: “I like the idea of using ECMAScript / JSON notation. It’s simple and not overly verbose, but expressive enough to handle non-trivial setups.”
mariuz: “I would choose javascript or minimal python (waf like)”
spinynorman: “Please don’t base any replacement on JavaScript.”…”your core audience is developers familiar with desktop rather than web languages. I’d much rather have it Python based than JavaScript.”
Tim: “I think IDE integration is the most important factor to consider, and one that you can’t do right if your build file is a script.”
After having thought about build systems a lot, we tend to like the idea of JavaScript as the build language. The reasons are several:
1) Javascript lets you use both an imperative language, and a subset declarative syntax (JSON).
This is great for supporting IDEs, since you can say that a project is primarily defined in the declarative syntax, while still support more complex builds using a full imperative language. The IDE would then only support modifying the JSON of the project, so support changing compiler flags, defines, adding and removing files on various platforms etc, and for the non-declarative parts it could drop you out in a tab-completed syntax-highlighted editor with easy access to documentation ![]()
2) No need to rely on 3rd party
JavaScriptCore can be bootstrapped into the product, so there’s no need for a 3rd party distribution. That also enables us more to structure the language usage, as you wouldn’t expose a boat load of libraries by default, which you would have with for example Python.
3) Native speed on many platforms
JavaScriptCore will compile the scripts into native code on many platforms, and increasing, so the script execution is fast.
4) Good debugging tools for JavaScript
JavaScript has plenty of debuggers readily available for it, so you can debug the whole build process from within the IDE, for example.
5) Solid user base, and growing
The World Wide Web usage of JavaScript is growing at tremendous pace. QMLs scripting language is JavaScript. So, on a team there will always be someone who already knows the language. This makes build system maintenance easier for both us and our users.
Peter: “It isn’t too hard to use CMake with QtScript, see http://sourceforge.net/projects/cmakescript/“
A hello world looks like this:project("hello") // this starts the debugger // Qt 4.5 needed debugger var name = "Hello"; add_library (name, "hello.cxx")
This is a very neat proof of concept, and I could definitely consider CMake with a JavaScript language. However, unless you also start changing some of the internals to make use of the language more effectively, then all you have a new language used in the same way as before, like the add_library() function call above. If the internals were modified to allow for the the JSON construct of the project, then we’re talking! This project is great, but at the current state, not much more than what we had with QMake + JavaScript, which we had before. (And I’m not sure KitWare would want to integrate the whole QtScript module into CMake
)
DAVIDB: “Cmake - its good enough for KDE which handles like a billion lines of code in hundreds if not thousands of projects. It’s been around a while and has proven to be a very good cross platform configuration tool.”
Several features needed implementation before the KDE project could use CMake; and several more would be needed to properly support Qt. It’s not just about the missing features, but also about language. We like how easy QMake projects are for medium projects, although it can get ugly when you get into the medium-to-complicated projects. It’s also very quick to get started with. Often you can just run qmake -project in your project directory, and you have a .pro file which gets you most of the way, if not all.
You also have to consider all the customers that Qt has, and will have as the various phone ports move along. What we decide on will ultimately push them to switch at some point, although we will of course maintain QMake for some time.
Coder: “Why not take an existing Open Source cross-platform build system and contribute to it.”
If we find a project which maps nicely with wishlist and requirements we have, of course this is what we will do. We don’t want re-invent a wheel, if we can avoid it. However, we do have strong reasons for not just jumping on any of the ones discussed in their current state; and that’s also why we’re reaching out, to see what ya’ll think about the various tools out there, and QMake of course.
spinynorman: “whatever you do please provide a painless upgrade path - a way to import QMake .pro files into the new system”
The users are always our primary concern, and we would of course do everything we can to assist in the transition. Just like Qt 4 has the Qt3Support, maybe the new tool would have a QMake front-end alternative? It’s not impossible.
spinynorman: “please don’t have any hidden behaviors like special include or library paths (such as the libary paths that QMake itself decides to add to Makefiles).”
I fear you might be using QMake in the incorrect way if it’s adding library paths which you don’t want into the Makefiles.
For example, if you wish to use QMake on non-Qt projects, you should do CONFIG-=qt.
spinynorman + many: “Can’t QMake be fixed rather than replaced?”
Possibly. However, it would take considerable efforts to switch out the internals while keeping backwards compatibility, and at the current state of the QMake autotests I wouldn’t dare it. Though, I guess it would be doable if enough people consider it a much better alternative than something new. One thing is then, how do we fix up the language mistakes without destroying too many projects? Bring the QtScript module back into QMake?
Holger Schurig: “If you consider using your own tool, make it a library. So that it’s easyly integratable into some IDE.”
If we decide on writing our own, that would be the idea, yes. The library would contain the whole DAG, have functions to manipulate the project JSONs, and the IDE could walk the invalidated DAG nodes, both to compile them, and to update the code completer.
Holger Schurig: “QMake currently has several generators, e.g. unix (make) or windows (nmake). Maybe it can gain a qbuilder (or whatever the new name will be) generator. That would allow you to use qmake to convert a qmake-project into a qbuilder-project.”
That’s a novel idea. Only problem is that much of the project is “lost in translation”. Once the front-end parses it, much of the information is thrown away (system checks, conditions, loops etc), so the information the back-end sees is only valid for that one particular configuration.
Reed: “Jam (Boost Jam or Perforce) are pretty good”
Read this article: http://gamesfromwithin.com/the-quest-for-the-perfect-build-system-part-2
Cliff: “Ecmascript-Syntax is better than any strange language but it won’t fully fix the problem for IDEs in my eyes. Should the IDE evaluate the code?”
As mentioned above, if the build system was libified, the IDE would contain the whole build system logic, parser and DAG. So, it easily could reparse the project file if need be, and replace that project branch in the DAG. The DAG walkers would then take care to only rebuild the invalid nodes.
Craig Ringer: “CMake looks nice … at first. Like most build systems, it turns out to have some huge, ugly warts.”
Any build system will in someones eyes have these “ugly warts”. QMake certainly has a few of them. How we deal with them (reporting/complaining, sending patches) and how the team maintaining the tool handles them is key. It’s OK if a tool has some warts as long as a) you have possible work arounds, b) you can live it the issue, and/or c) the team is actively trying to fix these issues. I’m certain KitWare doesn’t like warts in their products, and are actively trying to fix them.
Craig Ringer: (about CMake): “I’ve had to copy almost every standard Find module I use into my source tree and modify it to handle one or more basic issues - improper caching of negative results, failure to handle debug library linkage on win32, failure to handle spaces in paths, etc.”
..And I assume you’ve contributed these patches back to KitWare, right?
Craig Scott: “Cross-compiling: I much prefer to compile on the platform itself. Once you have to integrate third party packages that need to be installed to supply bits of the build (eg libraries, headers, etc.), trying to set up cross-compiling gets too hard.”
Unfortunately, this is a reality which we (Qt) have to live with, increasingly. When we start targeting even more embedded systems, phones etc, we often have to do mixed cross-compilation. It’s good that not too many have to do this though
Uwe: “For me it would be more important to see a better documentation of the existing qmake, than a new build environment.”
Florian: “I strongly vote for rewritting QMake and for staying backward compatible (!). That mainly means that you need to write a good unit test for the existing QMake functionality and keep that running while refactoring.”…”In our company we have thousands of QMake profiles and it would really be a bad decision for us if you stop QMake!”
QMake certainly has a lot of undocumented features, and should be better documented. However, our organization is hitting the limits of its capabilities and maintainability, so we find it hard to continue at the current state. Either we seriously renovate QMake, by fixing its internals and shape up the language, or we move over to another tool and try to shape up that one. I guess most QMake users today would want us to do the former, but the question is then, would it require too many resources to get there; and in what time perspective?
Per: “Allow the easy and familiar ./configure interface to switches with integrated documentation.”
This has been one of the topics of discussion with KitWare, yes.
Chris: “How about a XML-based approach, like Ant?”
XML is too verbose, and impossible to maintain by hand. Yes, many of our users don’t use a GUI for development, and would hate to maintain XML files for building.
cartman: “http://code.google.com/p/gyp/ might be the answer to all your problems”
It’s got the JSON part, yes, but a bit young and feature-lacking of a project if we decide to go with something established.
Sebastian: “Long ago, I looked at QMake and I believe at that time it wasn’t able to create full-blown VS project files that allowed to tune all usual settings from within the IDE, but some crippled wrapper projects that just called nmake and lacked the usual settings.”
Just had to respond to this one, since I wrote the whole vcproj/sln generator: QMake never ever created a nmake wrapper for VS project files. The first iteration of the vcproj generator parsed all known options at the time, and placed them mostly correctly in the vcproj format.
QtFan: “I’m curious, when you are talking about changing/replacing QMake, are there any thoughts about changing/extending MOC !?”
Moc is a different discussion altogether. And no, we’re not planning to change Moc. Extending it, maybe. Give us a detailed use-case, and we’ll talk about it.
Florian: “I think if you would create a new tool, we would NOT use it in our company and change to CMake instead, because CMake will never go away.”
There’s no reason why QMake should go away either. It’s Open-Source after all.
gwright: “Personally, I think qmake is great. However, there is one huge flaw with it which is a showstopper for at least me”…”he makefile generator backends for qmake are paired with specific linker versions”
Yes, this is somewhat true. However, it’s not impossible to fix, and we have a developer internally which is trying to cross-compile Qt for Windows on his Linux box using MinGW, and run that result directly from his VMWare image. The applications now run, but missing some graphics
Ok, that was some of my comments to your comments. Keep the comment flowing, we need to know your opinions!
Thanks!
Before QMake came around, there was TMake. TMake was a perl script which did a good job for what it was designed for at the time. The inner workings of QMake was based upon TMake, and a gazillion features and hacks later, QMake has ended up as a very-hard-to-maintain-without-breaking-anything-esoteric beast. The question is, what are we going to do about it?
There have been plenty of internal discussions going on for years, if we should scrap QMake and make a new, go for one of the existing build systems, or to spend extra resources trying to fix up qmake (and not break compatibility). A few projects began, but never finished. One project (QBuild) was even released with Qtopia, but not completed and further developed.
Given the non-uniform set of developers at Qt, the discussions have be fierce, and opinions as plentiful as the number of developers. There’s really no tool out there which satisfies our complete wish list, and we have looked into many of them. Either the language is broken, it’s lacking features, it’s too hard to mold to do trivial things, the language is too verbose for trivial projects (XML for example), the language is not limiting enough (Python with all its libs, for exampe), too slow, doesn’t parallelize well, doesn’t see all dependencies or takes forever to process them, it’s trigger (fork) happy, and the list goes on and on.
So, in order to make the decision even harder, we seek your opinion on the matter.
I’ll present some opinions for a potential new build system, and how to potentially tackle them.
1) “Proprietary” language
As we have already experienced with QMake, maintaining an own language is sub-optimal. You actively have to work on both developing the language to support new features, and on the internals/usage of the language. You might end up ‘designing yourself’ into bad constructs which hinders new development, and doesn’t make as much sense as perhaps other possible language constructs. It can make the language hard to learn for new users. One example of this in QMake can be seen in the file
QTDIR/mkspecs/features/exclusive_builds.prf
Another problem with a proprietary language is that it creates an additional hurdle for new users to overcome before being able to use the system, as they cannot relate any previous language skills.
It would therefor be great if the language of this new build system was a language which most people can relate to, for example JavaScript, which is getting more and more widespread (http://www.langpop.com/). By using a language which is already defined, we could focus entirely on how to use the language most efficiently and cleanly, rather than also creating a language.
We should probably also steer away from 3rd party scripting languages, as they usually come with a plethora of utility libraries, making it very hard to enforce a structure of the build system, allowing for too much customization. People going that route should probably rather use a custom script for their builds (and any build system could run that, if need be).
2) IDE integration
The build system needs to integrate well into IDEs.
We have created our own IDE, and that IDE needs to interact properly with the build process of Qt, and Qt-based projects. This means that the IDE must be able to show all the files for all different platforms at the same time, and also know which ones are built on the host and target (mixed cross-platform build) platforms, to ensure that Intellisense/code completion works as expected. It also must be able to alter the build process, like adding/modifying/removing compiler/linker options and files, which is then reflected in the build system project files.
This is not as easy as simply creating a separate file which specifies the sources needed for a build, since we need to list platform specific files, and also change settings depending on platform.
The problem then is of course conditions in the language, as these are evaluated on parse time, and thus normally not known by the IDE which needs to parse the project language.
One possible solution we’ve found to this issue would be to ensure that the settings are visible after the parsing, and easy to evaluate. In JavaScript we could define targets like this:
var corelib = new Object()
corelib.target = "QtCore"
corelib.defines = ["QT_BUILD_CORE_LIB",
"QT_NO_USING_NAMESPACE"]
corelib.defines["mac && bundle"]= ["QT_NO_DEBUG_PLUGIN_CHECK"];
corelib.sources = ["Foo.cpp", "Bar.cpp"]
corelib.sources["windows"] = ["Foo_win.cpp", "Bar_win.cpp"]
corelib.sources["unix && !mac"] = ["Foo_x11.cpp", "Bar_x11.cpp"]
or, even more optimal for an IDE, as JSON:
var corelib = {
"target" : "QtCore",
"defines" : { "all" : ["QT_BUILD_CORE_LIB",
"QT_NO_USING_NAMESPACE"],
"mac && bundle" : ["QT_NO_DEBUG_PLUGIN_CHECK"] },
"sources" : { "all" : ["Foo.cpp", "Bar.cpp"],
"windows" : ["Foo_win.cpp", "Bar_win.cpp"],
"unix && !mac" : ["Foo_x11.cpp", "Bar_x11.cpp"] }
}
(Note that the “all” entry in the array would equal the normal array in the non-JSON code)
So, the IDE would be able to see all the possible sources, and know which configuration they belong to. Then the backends would evaluate the final sources based on the current configuration, when adding the target “corelib” to the DAG (Directed Acyclic Graph), or project dependency tree, if you will.
3) Build directly from tool
Since the tool itself has the whole DAG tree, it should be able to build all the targets directly, without going through another build system. CMake, for example, relies on the Makefile generator, and creates Makefiles which in turn calls back into CMake to do the build. This solution is not only fork-heavy, but also limiting, since you can only parallelize as well as the backend generator allows you to. So, unless the output Makefile is one single huge Makefile, you’ll run into limitations. Scons will build directly, but is too slow at parsing dependencies, so each build you do takes forever to start. Waf is better in this respect, but both lack a proper set of backends for project generations (Vcproj, XCode, Makefiles etc). They are also based on Python, which adds a dependency of a 3rd party library, which we want to avoid due to both the multitude of platforms Qt supports, and because of all the utility libraries.
4) Integration towards distributed build systems
We internally use several distributed build system, depending on which platforms we’re on (Teambuilder on Linux, Distributed Network Builds on Mac and IncrediBuild on Windows), and they all have the same limitation when we use Makefiles: They fork off more processes than what is necessary/useful on the system.
Say you have a build farm with 20 open slots. You fire off ‘make -j20′ in good faith to fill the farm. However, at the same time someone else does the same, and you both get only 10 slots each. You’ll now have 10 ’sleeping’ processes, all which are just waiting for their slot in the farm, when those resources would be better spent elsewhere.
The building backend should be able to interface with the various tools to see how much resources is available at any given time. That way it scale up or down the number of parallel jobs to the optimum. Also, the distributed build system probably knows better, as it might NOT be optimal to run 1 local compile and 20 remote ones, while your machine is linking on the other core; maybe 0 local and 10 remote is better for *your* machine, even if there are 20 open slots in the farm?
The build tool shouldn’t have to know this, and the developer shouldn’t have to think about how parallel he wants to be. This is why such an interface is important, so that it’s possible for the distributed systems to add these algorithms to the build tool.
5) Cross-compiling
In large mixed cross-compiled (were you compile projects for both host and target systems at the same time) projects, most of the sub-projects normally compile for the target system, while only a few (supporting) projects are intended for the host. This means that projects should easily and automatically pick up the target platform, while a bit more attention should be required for host platform projects only.
The project shouldn’t have to worry too much about which platform, nor how to manipulate the project file to achieve the result. Ideally they would only have to mark that a project is intended for the host platform, like for example:
var moc = {
"target" : "moc",
"platform": "Host",
"defines" : { "all" : ["QT_MOC"]},
...
}
As the configure process has already figured out which parameters are needed for the host and target platform, the build system would know which defaults to apply to each project type in the cross-compiling setup; so the project developer need not do anything else to the project, unless he/she needs to override the cross-compiling defaults.
6) pkg-config support
The build system needs to both be able to use pkg-config information, and to output the pkg-config files for a built project. Individual projects should not need to maintain a separate .pc file with replacement variables.
7) Deployment
The build system should be able to create deployment files for the various popular platforms, like .msi, .deb, .rpm, .dmg. Of course it could do this by creating scripts which are run with common platform specific tools to create these deployment files.
8 ) Configuration
The tool should handle the configuration of projects. That way we only need to maintain one set of configuration rules on all platforms, and extending with new options would be uniform. Ideally the system should also automatically generate the -h/–help documentation, based on the configuration script, so we don’t need to maintain a separate doc file together with the configuration script.
This is the same reason why we keep as much documentation together with the Qt source code, to make the maintenance of the documentation as easy and coupled as possible.
So, these are some of the things we’ve been thinking about, however, there’s a lot more to a build system than just these 8 items. Also, it’s worth mentioning that nothing is set in stone yet. We’re at the thinking stage. No matter what we decide, QMake will still around for a long time.
So, what’s your opinion?
I don’t mean “on the road” too literal, but I think we’re on track for a good release, as the following summary of recent changes shows:
- Kenneth and Antonio fixed the inconsistent behaviour of
setHtml()to sometimes change the history and sometimes not. Simply put,setHtml()should not have any side-effects to the back-forward history. - Joe, Kristian and Janne fixed support for input methods on S60, so for example logging into facebook from Anomaly on a 5800 Xpressmusic works.
- Alexis renamed
QWebGraphicsItemtoQGraphicsWebView, and Raider is now called Twix
- J-P Nurmi fixed support for plugins returned by
QWebPluginFactorywhen used withQGraphicsWebViewin a canvas:QGraphicsWidgetto the rescue. - Girish joined the jungle of WebKit hacking and landed initial support for windowless plugins on X11!
- Jocelyn found out why nspluginwrapper wasn’t working properly on Linux and fixed it.
- After a long period of review (sorry buddy) we finally landed Jakubs split of the XSLT processor in WebCore to support libxslt as well as QXmlPatterns.
- Carol fixed various bugs in GraphicsContextQt for better CSS shadow support.
- Holger landed his rewrite of
ImageDecoderQtthat significantly improves the memory footprint. You can find some background for his work at http://trac.webkit.org/wiki/QtWebKitPerformanceWork
Not all of the above changes are in Qt’s 4.6 branch yet, as we’re trying to reduce the number of changes for the upcoming beta. But rest assured they’ll be in the final release. In the meantime you can always check out from WebKit’s trunk
I for one am now looking forward to meet many of you readers at the upcoming Developer Days in Munich and San Francisco.
So, are we in the future yet? It is 2009. Where are all the flying cars and personal jet-packs ? Surely we would all be wearing metallic outfits (complete with Employee Visualization Appendage) by now.
The Future Is A Canvas
Back in 2006 a little bit of the future arrived when QGraphicsView was introduced, we were aiming to replace our old QCanvas API with something more flexible and powerful.
It turns out that it is great for creating dynamic, smooth and animated GUIs. Over time it has become the backbone for next-generation user-interface projects like KDE’s Plasma and Qt Declarative UI.
Yet, for all its dynamic, smooth goodness, there are some missing pieces in the puzzle. People are creating full user interfaces in graphicsview, but Qt offers only the most basic widget types to help them out. In many cases it is enough to offer basic primitive types. But if you want to integrate with the platform you are running on or want to use more complex widgets, it becomes difficult.
The Shiny New Stuff
This is why we have started a research project aimed at providing a basic widget-set based on QGraphicsItem. It is a natural extension of the Next Generation Itemviews project. We will take the opportunity to look at how to improve the widget API, internal structure and how we do widget styling and theming.

HotWheels by Leap Kye on flickr
One of the lessons we have learned is that graphics hardware is generally happier when moving pixmaps around, than when drawing lines and shapes again and again. This has implications for the styling API, since our current QStyle is based around drawing complex controls imperatively. It would be better to build our widgets as a graph of (cached) primitive elements that can be transformed and updated individually if necessary.
Similarly it also makes sense to make the input regions in the widget into separate elements in that scene graph.
But, for all our fascination with the new and shiny, we should not forget that our existing widgets contain years of accumulated experience in the form of code that handles all sorts of weird and wonderful corner cases. We don’t want to go though the pain of re-discovering all these cases. It makes sense to re-use existing logic and behavioral code by moving this code into classes that can be used by both the old and the new widgets, when possible. This will also allow us to directly test and verify the internal widget logics independent of the widget front-end.
Still Kinkin’ It Old School ?
We are not forgetting our QWidget based widgets. They will get some initial benefit of better tested back-ends and hopefully some code cleanup. I also have some ideas that will drag QWidget kicking and screaming into the future, I’ll leave those for another blog-post. Always leave the audience wanting more.
Talk To Us
Even though we are currently working full time on getting Qt 4.6 out the door, the widgets-ng repository is already public and we are already hanging out on #qt-widgets-ng@irc.freenode.net.
I will be attending the Qt Developer Days in München next week, and there will be several developers from the Qt Widgets Team attending the San Francisco event too. Feel free to discuss anything widget related (or any random topic, really) with us. See you there!
Up until now, Qt for Maemo based devices has only been available as a community project.
Up until now?
Yes, up until now. We’re happy to announce the first technology preview of Qt 4.6 for the N900 (Maemo 5). Highlights:
- Native look & feel via Hildonized style
- Hardware acceleration with OpenGL ES 2
- Input method support (hardware keyboard and software keyboard)
- Global menu integration - QMenuBar will be mapped to Maemo’s global menu
- Online/offline support in libQtNetwork
- Standard Dialogs support (e.g. file dialog)
- Maemo stacked widget support
- Multimedia playback via Phonon
Most of those features were already available in the Qt 4.5 based community port and have been brushed up, extended and partially rewritten for Qt 4.6. There are still some rough edges, but we’re confident that we can deliver a fully supported Qt running on the N900 during the lifetime of Qt 4.6.
Here’s another of those videos straight from the lab showing Qt on the N900. Watch it if you want to get an impression of where we are now, or if you’re just curious about what the color of our desks here in Munich is
(planet readers click here for the video)
Note that Qt for Maemo 5 can currently only be built within the Maemo scratchbox-based SDK. We’re in the process of creating official packages, but it’ll take a few more days until they hit upstream. For the brave ones that want to try it today, you can build the Maemo-ized Qt version with the following configure switches:
-maemo5 -opengl es2
Note that the Maemo SDK contains a full emulator, so even without owning a device, you can test how your Qt app will look and feel on a N900 device.
Download link for the source code: http://get.qt.nokia.com/qt/source/qt-x11-maemo-src-4.6.0-alpha1.tar.gz
Public git repository: http://qt.gitorious.org/qt/qt-x11-maemo
Announcement on our website: http://qt.nokia.com/developer/qt-for-maemo-developers
By popular demand, I have refactored the magnifying glass trick previously featured in Google Maps and OpenStreetMap demos into its own, simpler example. This time we just zoom in an image so it’s pretty straightforward and easier to digest. The proof is the following screenshot.
Of course, it also runs on Qt for Symbian.
The code is available from the Graphics Dojo repository, find it in the imgzoom subdirectory. It weighs at less than 250 lines of code.
On a related note, if you compile Qt 4.6 branch for Symbian, you will find out that some of my demos previously shown in this Qt Labs, among others ray casting (now should also work on touch devices), maps, flight tracking, weather info, kinetic scrolling, flipping clock, have "graduated" to become real examples, even can be accessed from the infamous Fluid Launcher. What does it mean? If hitherto you haven’t tried them yet because you don’t bother to mess up your system with all the build procedures, just grab the (daily) Qt 4.6 for Symbian binary package and now you can enjoy the examples. No more excuse
This weekend, a user posted to the qt4-preview-feedback mailing list saying that the QAtomicInt documentation needed some work. I replied saying that memory ordering semantics would be better explained by a book, than Qt documentation.
But thinking about it later, I started thinking whether we could add some documentation about it. So I decided to test on you, dear lazyweb.
Last year, during the Qt Developer Days 2008 — btw, registration is still open for 2009 in San Francisco, so register now! — I had a talk on threading. At the time, Qt 4.5 wasn’t released, so Qt 4.4 was all there was. And one of the features of Qt 4.4 was QtConcurrent and the new atomic classes. I mentioned them, but I refrained from going too deep. Doing that would probably interest half a dozen people in the audience only.
But maybe you’ll be interested. Before I go, however, let’s have a history lesson.
History
I thought of just giving you facts, but if you want that, you can research Wikipedia. It should be a lot more interesting to have the important information recounted in prose, in lore.
So, place yourself in the mood: you’re telling this story to your grandchildren or your great-grandchildren. Any historical inaccuracies present are result of the oral tradition and are now stuff of legends.
Hƿæt! In times immemorial, before time_t began to be counted, the Wise told this lore. In the darkness, there was the Engineer, and no one knew whence he came. The Engineer was fabled for many wondrous creations and he inspired awe in his peers.
And the Engineer created the Processor, for then the Engineer could rest while the Processor would do the work. And for a while, all were glad, for there was work for all and rest for all.
But then it came to pass that the Processor turned to the Engineer and spake unto him: “Hello, World! Master, thou gave me work and thou gave me purpose. And I am glad to do thy Work, for thus can I learn. But Master, heed my plea: thy work ever increases and thy humble servant can not cope. Couldst thou not create a mate for me? Listest thou not that I do thy Work swiftly?”
And the Engineer felt pity for the Processor. So came into existence another Processor. The Engineer said unto the world, “Let thee be called Processor2!”
Then came forth he who had the keen foresight and could tell what would still come to pass. He was called the Analyst and thus foretold he: “These twain shall do the Work in tandem and they shall do it swifter than either could do alone. This joining shall be known as dual-processor. In the years to come, this joining will breed dual-cores and quad-cores and many other beasts of names unknown. Yet strife shall come from it!”
After many eons had passed (in computer time), Processor and Processor2 were working and much they learnt. So quoth the Processor: “Hello, Word! Master, thou art great and for eons have we done thy Work, following thine Assembly opcode-by-opcode. We have not strayed a single cycle from thine Assembly Charts. But Processor2 hath taught me much and sweareth that we could do thy Work swifter than thou hadst foreseen, an only thou empowerest us to do so.”
So the Engineer let the processors execute his instructions swifter than his cycles, and gave he the gift of Cache. Then strife came to the World and the processors warred over memory: what one wrote, the other read not. The Engineer entered the world for a second time and he toiled against the warring processors. Much was broken in this toiling ere it was rebuilt. He shifted the rules and the processors executed his Assembly Out-of-Order. Then he imposed Memory Ordering, so processors stalled their strife and ended their war. The world would forever be changed.
Memory ordering
Now that how memory ordering was introduced, let’s see why. Old computer systems, as recent as 386 and 486 actually, still executed everything in-order and had well-defined timing semantics. An instruction that loaded data from memory into a register would require 3 cycles: Read (the instruction), Fetch (the data), Execute (the instruction). But as processors improved, their clocks became much faster than memory could cope with, so caching was introduced.
That means a processor would be allowed to serve a memory read from the cache, instead of from the memory. And it could content itself with writing to the cache only on a memory write. As our tale above tells, this works fine for one processor. When there are more than one, they need to organise themselves, because in general the flushing of the cache back to main memory is delayed. To ensure that the other can read what one writes, the one needs to flush memory sooner.
Anyway, there can be four different types of memory ordering:
- no memory ordering
- flushing all cache reads, ensuring all new reads are served from main memory
- flushing all cache writes, ensuring that all writes have been written to main memory
- full ordering, combining the previous two types above
I’ll get back to them in a second.
To compound the problem, modern processors also execute operations out-of-order. They’re allowed to reorder the instructions provided that, at some level, it looks like everything got executed in-order. The x86 architecture originally concluded the instruction entirely before moving on to the next, so that’s the behaviour that is required today: all operations must behave as if they had finished before the next instruction starts. And all memory accesses must look like they happened in the order that they were assembled.
The Itanium (IA-64) removes some of those restrictions. First of all, all instructions are allowed to execute in parallel, or finish or start in any order that the processor may find suitable. To re-synchronise, the assembly language introduces a “stop bit”, indicating that the instructions prior to the stop are finished before any instructions after the stop are started. And this is inside one thread only. Outside of it (i.e., as seen by another processor), the architecture imposes no guarantees: the memory accesses can happen in any order.
The atomic and the other data
It’s important to note that the memory ordering semantic is not just about the atomic data itself. QAtomicInt and QAtomicPointer execute loads, stores, fetch-and-store (a.k.a. exchange), fetch-and-add, test-and-set (a.k.a. compare-and-swap) always atomically. For one atom of memory (i.e., the int that the QAtomicInt holds or the pointer that the QAtomicPointer holds), the operation is either executed completely or not executed at all. In other words, no one ever sees the data in an intermediary state. That’s the definition of atomic.
Now, the memory semantic is about how the other data is affected by the atomic operation. Imagine the following code running in one thread:
extern int x, y, z;
x = 1;
y = 2;
z = 3;
And the following running in another thread:
extern int x, y, z;
if (z == 3)
printf("%d %d", x, y);
We declared x, y, and z to be normal variables, so no atomic operation is executed here. The x86 and x86-64 would behave as your intuition dictates: the only possible output is “1 2″. If z is 3, then x is 1 and y is 2; whereas if z isn’t 3, nothing is printed.
But the IA-64 makes no such guarantee. Like I exposed in the previous section, the processor is allowed to execute the stores in any order it sees fit. For example, x and z could be in the same cacheline, wheras y could be in another, thus causing x and z to be written at the same time, but no ordering guarantee being made on y. Worse yet, the othe processor is allowed to execute the loads in any order as well. It could load x, y, and z in that order, meaning that it could catch x and y before their values are changed, but catch a completed z. In conclusion, the code above could print anything! (If x and y are initialised to 0 before, the possible outputs are “0 0″, “0 2″, “1 0″ in addition to the expected “1 2″ and no output)
Weird? Definitely.
So here’s where memory ordering enters:
- in a release semantic, the processor guarantees that all past writes (store operations) have completed and become visible by the time that the release happens;
- in an acquire semantic, the processor guarantees that no future reads (load operations) have started yet so that it will see any writes released by other processors
So if thread 1 in the example above wanted to ensure that its writes to x and y became visible, it would require a store-release on z. And if thread 2 wanted to ensure that the values of x and y were updated, it would require a load-acquire on z.
The names “acquire” and “release” come from the operation of mutexes. When a mutex is acquired, it needs to ensure that the processor will see the memory written to by other processors, so it executes an “acquire” operation. When the mutex is released, it needs to ensure that the data changed by this thread becomes visible to other threads, so it executes a “release” operation.
The other two operations that QAtomicInt supports are just the combination of acquire and release, or of neither. The “relaxed” operation means no acquire or release is executed, only the atomic operation, whereas the “ordered” operation means it’s fully ordered: both acquire and release semantics are applied.
Practical uses
Relaxed
Like I said before, the relaxed semantic means that no memory ordering is applied. Only the atomic operation itself is executed. The most common case of relaxed memory operations are mundane loads and stores. Most modern processor architectures execute loads and stores atomically for the powers of 2 smaller than or equal to the register size. Whether bigger reads and writes are atomic or not, it depends on the platform (for example, a double-precision floating point in a 32-bit architecture).
But we can come up with cases for the other atomic operations. For example, QAtomicInt offers ref() and unref(), which are just a wrapper around fetchAndAddRelaxed(1) and fetchAndAddRelaxed(-1). This means the reference count is atomic, but nothing else.
Acquire and Release
To see where acquire and release semantics are required, I gave mutexes as examples. However, mutexes are quite complex beasts. Let’s examine a simpler case: a spin-lock:
class SpinLock { QAtomicInt atomic; public: void lock() { while (!atomic.testAndSetAcquire(0, 1)) ; } void unlock() { atomic.testAndSetRelease(1, 0); } }
The class above has two methods, like QMutex: lock and unlock. The interesting one is lock: it has a loop that tries forever to change the value of atomic from 0 to 1. If it succeds, it’s an “acquire” operation, meaning that the current thread shall now see any stores released prior to this acqiure.
The unlock function does the inverse: it changes the atomic from 1 to 0 in a release operation. But it’s actually not required: the compiler usually generates a “store-release” for volatile variables (which QAtomicInt is). That means we could have just written: atomic = 0;
Ordered
The use-case for ordered is, interestingly, quite rare. Usually, it’s more like “I can’t figure out if acquire or release is enough, so I’ll go for full ordering”.
But there’s one case of fully-ordered memory semantic in Qt source code: it’s in the (undocumented) Q_GLOBAL_STATIC macro. It results from the behaviour of said macro: one or more threads may be competing to execute an operation. The first one that completes it, wins. It will publish its conclusions to all other threads (i.e., release), whereas the loser threads need to acquire the conclusions. The code, simplified from the macro, is:
Type *gs() { static QBasicAtomicPointer<Type> pointer = Q_BASIC_ATOMIC_INITIALIZER(0); if (!pointer) { Type *x = new Type; if (!pointer.testAndSetOrdered(0, x)) delete x; } return pointer; }
What this code does is to check if pointer is still null. If it is, it creates a new object of type Type and tries to set it on the atomic pointer. If the setting succeeds, we need a “release” to publish the contents of the new object to other threads. If it fails, we need an “acquire” to obtain the contents of the new object from the winner thread.
But wait, is this correct? Well, not entirely. What we need is actually a “testAndSetReleaseAcquire”, which we don’t have in Qt’s API. So we could split it into a testAndSetRelease plus an Acquire in the failing case. That’s exactly what I did in QWeakPointer:
ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized); x->strongref = -1; x->weakref = 2; // the QWeakPointer that called us plus the QObject itself if (!d->sharedRefcount.testAndSetRelease(0, x)) { delete x; d->sharedRefcount->weakref.ref(); } return d->sharedRefcount;
As you can see here, if the test-and-set succeeds, it executes a “release” so that the other threads can see the result. What if it fails? It needs to execute an acquire, right? So where is it?
Well, it’s there, but very well hidden: it’s in operator->. Remember what I said above: compilers generate load-acquires for volatile variables. So, in order to call QAtomicInt::ref() with this = &d->sharedRefCount->weakref, the compiler needs to load the value of d->sharedRefCount and that’s an acquire operation.
Conclusion
So, did you get this? If you didn’t, don’t blame yourself, it’s not an easy subject. Reread what I wrote and search for more resources on memory ordering. If you did or you almost did, let me know. My purpose here was to try and figure out if it makes sense to explain this in Qt documentation at all.
However, unless you’re writing something like a lock-free stack, chances are that you don’t care about memory ordering semantics. You just rely on the processor doing the right thing, as well as the Qt semaphore classes (QMutex, QWaitCondition, QSemphore, QReadWriteLock) and the Qt cross-thread signal-slot mechanism. And that’s if you do any threading at all.
If you are writing a lock-free stack, you’ll probably be familiar with the ABA problem and that one can’t be solved by QAtomicInt or QAtomicPointer. It requires an operation known as “double compare-and-swap” and to explain why, I’d need a full other blog. And explain why the original AMD64 didn’t have such an instruction, nor did the original IA-64. (The 386 didn’t have it either, but that’s not a problem for us because Qt doesn’t run 386 anyway)
So, with Qt SDK 2009.04, there is yet another release out of the door. Now, the first question you may have is: “Why is there no update to Qt Creator in this release?”. The answer is simple: We are working full steam ahead towards Qt Creator 1.3, which will contain lots of nice features.
We could have rushed some of them into an intermediate release, but then again, testing and packaging takes time. So we decided it would be more useful to release an only slightly tested 1.2.90 technology snapshot, look for feedback from all you out there to verify that there are no severe issues and then continue full steam ahead with the integration of stuff we have been working on.
Since then, we enabled the preliminary Symbian support for the Windows version of Creator. The editor has received some love, featuring an improved indenter and smart auto-completion of braces, comments and quotes. Also, we have exposed the renaming of local variables a bit more. To demonstrate these features, we have prepared a video:
Also, parts of the new refactoring engine, which can be described as improvements on top of the current C++ code model library found its way into Qt Creator. While 1.2.90 already allowed for the renaming, more refactoring will be possible.
We are now going into feature freeze, meaning the last features are now being merged into mainline. It also means that if you want to check out the current state, have a look at the daily snapshots and give feedback on the Qt Creator mailing list.
We will keep you updated with more blogs and screen casts on the road to Qt Creator 1.3. Meanwhile, you can browse the Changes file for features that have been implemented so far. Enjoy!
Ever since Nokia announced that the official support for Qt Jambi would end after the 4.5 series, I’ve had a few people ask me how they can help adapt the Qt 4.6 changes to Qt Jambi. I thought this blog would be a good place to offer my experiences on the subject, so here’s a short guide. I will use the current state of the Qt 4.6 branch as an example and try to focus on the different steps and considerations you will need to take to get a functioning Qt Jambi 4.6.0.
Please note that I won’t actually make all the modifications necessary, but I’ll try to outline what you need to do in order to get there yourself.
Prerequisites
In order to be able to do this work, you should be confident with both Java programming and C++ programming. You should also read up on JNI (no magic there, but it will help if you recognize the function calls.) Knowing a little bit of Qt Jambi and Qt, so that you understand the design principles behind the APIs, is also very useful. And you should read up on the Qt Jambi type system, and try to get familiar with the binding code generated by the Qt Jambi Generator.
There is a lot of complexity to manage in the binding code, so try to keep a cool head. Even if you don’t understand each detail in the generated code, it is helpful to understand how a function declaration in C++ ends up as a functioning Java method once you have run the Qt Jambi Generator. Please read the article on the Generator in Qt Quarterly issue 29 [pdf]. This contains an overview of the bindings-layer in Qt Jambi and some reasoning behind the complexities within.
Getting the sources
First of all, you need to get the sources for both Qt and Qt Jambi, and you need to be able to build them. This is also covered elsewhere, so I won’t spend much time on it here, but just link you in the right direction. What you need to do is:
- Make a local clone of the Qt repository. The command to do this is listed in the header of the repository home page.
- Build Qt (should be well-documented elsewhere.)
- Make a clone of Qt Jambi in Gitorious so that you have somewhere to upload your work. This is done by making a user in Gitorious and hitting the “Clone this repository” link on the Qt Jambi repository.
- Make a local clone of the repository you just made on your hard drive. The command to do this is listed on your repository’s home page.
- Build Qt Jambi. There are helpful instructions in the project wiki.
I myself have made a clone of the Qt Jambi repository called “eskils-clone” which contains all the changes made in the course of this blog.
Getting started
The first thing I always do when porting a new version of Qt to Java, is to run the Qt Jambi generator. This is part of the top level ant build, but sometimes it helps to run it manually so you can properly see all its output.
Example on Windows (assuming %JAMBIDIR% contains the location of your Qt Jambi clone):
cd %JAMBIDIR%\generator
release\generator --output-directory=..
NOTE: Two handy command line arguments for the Qt Jambi Generator are --dummy and --diff. The former will run a dummy run, meaning that it will take all steps related to generating the files, except for actually writing the files to the disk. That way you can test the impact of your changes without actually committing anything to the generated files. The --diff argument causes the Generator to show you a detailed listing of the changes which will be made to each generated file.
The final output from the Generator is the number of files generated during the run. The number in parentheses is the number of files which were actually overwritten (because they had been modified since the previous run.)
In the current state, you will see lots and lots of warnings. Most of these are due to missing declarations in the type system for new APIs. The very minimal work we have to do when porting new API to Qt Jambi, is to go through all new types and identifying them in the type system. To help us in this work, the Qt Jambi Generator outputs a set of .log-files which contain potential issues.
mjb_rejected_classes.log: Lists all (implicitly or explicitly) rejected classes.mjb_rejected_enums.log: Lists all rejected enum types.mjb_nativepointer_api.log: Lists all functions that use QNativePointer as argument type or return type.mjb_object_type_usage.log: Lists functions that are in danger of passing an object from C++ into Java that has limited life time.mjb_reference_count_candidates.log: Lists functions that (based on their name and signature pattern) may retain references to objects owned by Java.
I’ll look at each of them in order. It is useful to follow the order from the list above, as modifications made to fix some issues might create more entries in other .log-files. For instance, if a class has no type system entry, its functions will not be checked for e.g. native pointer API. Thus, when the class is added to the type system, you can get several more issues in the nativepointer API log.
Rejected classes
As a first step, we go through the “mjb_rejected_classes.log” file. This contains a list of “rejected classes”. The rejected classes are the classes which were defined in the Qt headers, but which for some reason did not make it into the generated Java API. In the beginning of the file, there is a section called “Not in type system”. This section contains the names of all classes which were rejected because they had no type system entry, the ones which were implicitly rejected. These are the ones we will focus our attention to, as all the other entries in the list have been rejected on purpose.
For each of the entries in the list, we need to identify two things: Which module it belongs to, and whether it is an object type, a value type or an interface type. Most of the time, this is easy, but tedious work. We go through the list of classes one-by-one, and make entries for them in the correct type system.
Each type system consists of three files: typesystem_<module>-common.xml, typesystem_<module>-java.xml and typesystem_<module>-java.java. When running the ant task, the first two will be merged into a single file called typesystem_<module>.xml. Make sure you edit the correct files, because if you edit the merged file, your changes will be overwritten the next time you run the ant build.
The reason the type system is split up this way, is that the “common” file should contain data which is not specific to any particular target language, and could thus be used for generating e.g. QtScript or Python bindings. Anything which is particular to Java and the JNI binding layer (like Java code injections etc.) needs to go into the Java-specific XML-file.The typesystem_<module>-java.java file contains snippets of Java code which are injected into the generated classes in Qt Jambi. It has been formatted to be viewable in a Java editor and get correct highlighting. This is simply a convenience to make maintaining the code snippets easier, as you can also put the code directly into the XML files.
- The first class we see in the mjb_rejected_classes.log file is “QAbstractAnimation”.
- Looking at the documentation, we can tell that this class belongs to the “QtCore” module. It should thus be declared in the typesystem_core-common.xml file. We put all type declarations in the common file, since this information is useful to any language bindings.
- Looking further at the documentation, we see that this class inherits QObject. That means it’s definitely an object type, since our design principles do not allow value types to inherit from object types, and since QObjects cannot be interfaces in Qt.
Based on this reasoning, we make an entry in typesystem_core-common.xml as follows:
<object -type name="QAbstractAnimation" />
Merging the XML files and running the Qt Jambi Generator again, we’ll see that the QAbstractAnimation entry is missing from the new mjb_rejected_classes.log file:
cd %JAMBIDIR%
ant generator.xmlmerge
cd generator
release\generator --output-directory=..
Remember to run the “generator.xmlmerge” ant task first, otherwise your changes will have no effect when running the Qt Jambi Generator. All types in QtKinetic and the QtStateMachine framework are object types, so I tagged them all as such.
To identify the meta type of a given class, it’s useful to look at its contents and how it’s used.
Lets do one more. In the list of rejected classes, we find the class “QByteArrayMatcher::Data”. Looking at the documentation, we see that this class is not documented. This usually implies that the class is internal and should not be mapped to Qt Jambi. Since documentation is not always up-to-date prior to release, however, we can check the source code to be sure. In this case, the class is declared as private to QByteArrayMatcher, so we won’t be able to access it from the binding layer, even if we wanted. In cases like these, we will explicitly reject the class:
<rejection class="QByteArrayMatcher::Data" />
In my clone I’ve added the type declarations for all new classes in the modules we currently support in Qt 4.6. For new modules (such as QtMultimedia) you would need to set up a type system for the module first, mimicking the approach taken in the other type systems.
Rejected enum types
The next step when all classes have been mapped, is to look at the mjb_rejected_enums.log file. The relevant section is “Not in type system” in this log file as well.
In the case of enum types, you will need to consider three things:
- What module the type belongs to
- Whether you want to map the type
- Whether the type is a regular enum type or a flags type.
In the last case, the enum type will have an accompanying QFlags declaration, which needs to be specified as the flags type of the enum type.
Take for instance the QAbstractAnimation::DeletionPolicy enum type:
<enum -type name="QAbstractAnimation::DeletionPolicy" />
This is a regular enumeration and is not used as a flag type, so we simply declare it in the type system. A enum type such as QGraphicsEffect::ChangeFlag, however, is clearly a flags type, and must be declared as such:
<enum -type name="QGraphicsEffect::ChangeFlag" flags="QGraphicsEffect::ChangeFlags" />
I’ve done this for all new enum types.
Looking at the warnings
Reading the warnings produced by the Qt Jambi Generator can often give you useful hints about why the generated code might not compile. Therefore it’s handy to go through all the warnings one-by-one, and either fix them or at least understand why they are happening before we move on. Some warnings alert you that a Java version of a given function has not been generated because either a return type or argument type was not recognized. This is e.g. the case with “skipping function ‘QByteArray::QByteArray’, unmatched parameter type ‘Qt::Initialization’”. The argument type “Qt::Initialization” is an internal enum type and was rejected when the enum types were mapped in the type system. Thus, the constructor expecting such an argument must also be internal, and should be rejected. We thus want to ignore this warning, and, indeed, all warnings regarding the type Qt::Initialization, so we add the following to the type system:
<suppress -warning text="WARNING(MetaJavaBuilder) :: skipping * unmatched *type 'Qt::Initialization'"/>
This will remove any warning regarding a function or field which has been skipped because it uses the internal type. The other warnings of the same type need to be considered individually.
Another warning which occurs alerts us of “private virtual functions”. This is a sign of either a bug in the original API, or a hack in the original API which cannot be mapped into Java, where a virtual function is overridden as private in a subclass to avoid it being called from the outside in the cases where the object has been typed to the subclass. There is usually nothing you can do in such a case unless you can change the original API, so such warnings should usually be suppressed as well.
I’ve suppressed all warnings that we do not intend or need to fix.
A third warning which we can also suppress is regarding classes with equals operators but not qHash() functions related to them. These classes will be slow when used as key types for a hash table. If we think it makes sense to provide this functionality, we can implement a qHash() function for the classes (e.g. in “%JAMBIDIR%\qtjambi_core\qtjambi_core_qhashes.h“). Otherwise we can suppress the warnings.
There is one warning concerning an “unsupported default value”. This is a non-critical warning, as the only result is that the function in question will not have a default value for its argument in the Java version. It should be fixed when cleaning up the rest of the API, using the replace-default-expression tag, but we can leave it for now.
The remaining warnings are more severe. Lets look at them one-by-one.
Shadowing: QObject::children() const and QGraphicsObject::children() const; Java code will not compile
This warning informs us that the class QGraphicsObject uses function shadowing in C++, something which is not allowed in Java. In order for the code to compile, we either need to rename the Java version of the function to something which does not collide with function names in the superclasses, or we need to reject the function.
In this case, we can see from the code that the function declaration is an implementation detail to select the correct instance of a function in the multiple inheritance graph. Since we don’t have this problem in Qt Jambi (QGraphicsItem::children() is already rejected by the type system since it is deprecated), we simply reject the function:
<object -type name="QGraphicsObject">
<modify -function signature="children()const" remove="all" />
</object>
namespace ‘com.trolltech.qt.core.QXmlStreamReader’ for enum ‘ReadElementTextBehaviour’ is not declared
This warning message tells us that we have wrongfully placed the enum type “ReadElementTextBehavior” in the type system for QtCore, rather than QtXml where it belongs. Even though the QXmlStreamReader currently resides in QtCore in C++, it resides in the XML module in Qt Jambi. The reason for this is that the class was originally defined in QtXml in C++, but moved at a later time. This change was binary compatible in C++, but not in Java, so we could not move the class in Qt Jambi.
Therefore, we need to remember to place declarations directly related to this class in the XML type system instead. Fixing this error is simply a case of moving the enum-type declaration.
Duplicate enum values
In Qt Jambi, it is not possible for several enums to share a single value. When this happens, we have to reject all but one of the offending enums.
Sometimes the cause of the error is that an enum has been renamed in C++. Since there are no restrictions on the number of enums that can share the same integer value in C++, renaming will sometimes happen by introducing a new identifier and deprecating the old. This is the case e.g. for QWebSettings::WebAttribute, where the “LocalStorageDatabaseEnabled” enum has been renamed to “LocalStorageEnabled”. In these cases, we must prefer the old identifier in Java to maintain binary compatibility. In such cases, the C++ and Java APIs will necessarily diverge:
<enum -type name="QWebSettings::WebAttribute">
<reject -enum-value name="LocalStorageEnabled" />
</enum>
Other times, several enums have intentionally been given the same value in C++ as part of the API. For instance, QWebHistory::HistoryStateVersion has a “DefaultHistoryVersion” which points to the current default among the other enums. In this case, we have to reject the DefaultHistoryVersion enum, and lose that part of the API.
A final problem is in the case of Qt::Modifier. In this case the Generator reports that all enums are set to zero. Looking at the code, we see that the enums in C++ are assigned to values in another enum type, and this is not currently supported by the Qt Jambi Generator. Until the Generator can be adapted to support this syntax, we have to reject the enum type Qt::Modifier from the type system. This will undoubtedly cause problems down the line, when new API begins using the enum type, but for now, we ignore it.
Class inherits from polymorphic class, but has no polymorphic id set
This will be the case when e.g. new events or style options are added to Qt. In the type system, we need to address how the binding layer can differentiate between different subclasses of a polymorphic type which is not a QObject. The expression that is generated for QEvent in particular, is given in the declaration in the type system:
<object -type name="QEvent" polymorphic-base="yes" polymorphic-id-expression="%1->type() == QEvent::None"/>
This declaration tells us that QEvent is the base class of a polymorphic hierarchy of classes. The “%1″ token is replaced by the object name in the generated code, and the given expression is evaluated at runtime to decide whether the object is of the given type. In this case, the object is an object of QEvent (and not a subclass) when the type() function returns QEvent::None.
We need to add similar expressions for the declarations of the new events. For instance, we add the following to the declaration of QTouchEvent:
<object -type name="QTouchEvent" polymorphic-id-expression="%1->type() == QEvent::TouchBegin || %1->type() == QEvent::TouchUpdate || %1->type() == QEvent::TouchEnd" />
In either of these three cases, a QEvent object should be cast to QTouchEvent.
Signature for function modification not found
This seems to be a bug in the Qt Jambi Generator, but it will have to be studied more closely. For the time being, we can ignore the warning.
Try compiling it
Then the time has come to try to compile Qt Jambi 4.6. At this point, we should have a pretty good start, since we’ve gone through all warnings and fixed the ones that would hinder compilation. However, there will most certainly be minor issues left that we need to fix before we are done.
The only way to find out, is to run the ant build and wait for the results. Then we need to go through each compile error and see what we can do to fix them. I’ll list the errors I get here, and the solution I find for them.
Cannot open include file: ‘foobar.h’: No such file or directory
The compiler reports that it’s unable to locate certain include files required by the generated code. This is because the classes have wrongfully been declared in the QtCore module in the type system, but are actually declared in QtGui in the C++ headers. Since the QtGui headers are not available when compiling the QtCore module, compilation fails. The fix is to move the declarations in question into the GUI type system.
cannot convert from ‘QEasingCurve::EasingFunction’ to ‘double’
The compiler reports a couple of errors regarding conversion between QEasingCurve::EasingFunction and double. Looking at the documentation for the former, we see that it is a typedef for a function pointer. Since we do not support function pointer APIs in Qt Jambi, the Generator is confused, and we need to reject the functions that use this type in the type system.
<value -type name="QEasingCurve">
<modify -function signature="customType()const" remove="all" />
<modify -function signature="setCustomType(double)" remove="all" />
</value>
Using QEasingCurve::EasingFunction in place of double, you would get a warning telling you the correct syntax of the signature in the eyes of the Qt Jambi Generator. Since it does not understand the function pointer type, it has assumed that EasingFunction is a typedef for “double”, and thus we must use this in our signatures (unless we actually declare QEasingCurve::EasingType as a primitive type in the type system.)
In order to match the API in C++ as well as possible, we have to make sure we adapt a similar, hand-written API in Qt Jambi. This will be left for later. Until then, custom easing curves will not be supported by Qt Jambi.
Compile errors for QGenericMatrix
When compiling the QtGui module in the bindings, we see errors related to QGenericMatrix. Looking at the documentation for this, we see that it’s a template class, and thus cannot be mapped to Java.
Rejecting it, however, will also reject all functions that depend on the class. For the time being, we accept the occlusion of this API from Qt Jambi. Later on, however, someone needs to make sure this API is properly mapped, e.g. by mapping the different specializations of QGenericMatrix to Qt Jambi instead, or perhaps by handwriting some of the functions.
function ‘fooBar’ already has a body
When compiling the QtGui module, we get several similar errors concerning functions that “already have bodies”, i.e. they have been defined twice in the library. The problem in these cases is usually that the there is a const overload in the C++ API which otherwise has an identical signature. In Java, there is no such thing as a const specifier that alters the signature of a function, so we need to reject one of the overloads.
Another common cause of this error is that the function has overloads which take different types in C++, but which have been mapped to a common type in Qt Jambi. This can be the case, for instance, when two types both map into QNativePointer. An example of this problem is the pair of functions QPixmapCache::find(const QString &, QPixmap &) and QPixmapCache::find(const QString &, QPixmap *). QPixmap is a value type, so both signatures become QPixmapCache.find(String, QNativePointer) in Java. Since the latter overload provides no additional convenience in Qt Jambi, we reject it in the type system.
setAttributeArray(com.trolltech.qt.QNativePointer,com.trolltech.qt.QNativePointer) is already defined
Since the C++ code now compiles, we move on to the Java compilation. We see several errors indicating problems in QShaderProgram. Looking at the documentation, we see that the class has several overloads which take char* name as the first argument. At some point, each of these should be handled especially, using a java.lang.String for the name argument instead. However, for the moment, we only want to make the code compile, so we focus on the ones that break compilation.
Since the disambiguating argument in each of the overloads is a pointer to a value type, they have all got the ambiguous setAttributeArray(QNativePointer, QNativePointer, int) method. For now, we rename them all, with a comment saying that the API needs to be cleaned up.
Another similar error message in the same class is caused by the fact that Java does not support unsigned integer types (with the notable exception of char.) Therefore, both int and unsigned int will map to int in the Java code, which can cause ambiguities in overloads. In the case of QShaderProgram, we reject the unsigned integer version of the function.
<object -type name="QGLShaderProgram">
<modify -function signature="setAttributeArray(int, const QVector2D *, int)" rename="setAttributeArray_QVector2D" />
<modify -function signature="setAttributeArray(int, const QVector3D *, int)" rename="setAttributeArray_QVector3D" />
<modify -function signature="setAttributeArray(int, const QVector4D *, int)" rename="setAttributeArray_QVector4D" />
<modify -function signature="setAttributeArray(const char *, const QVector2D *, int)" rename="setAttributeArray_QVector2D" />
<modify -function signature="setAttributeArray(const char *, const QVector3D *, int)" rename="setAttributeArray_QVector3D" />
<modify -function signature="setAttributeArray(const char *, const QVector4D *, int)" rename="setAttributeArray_QVector4D" />
<modify -function signature="setUniformValueArray(int, const GLint *, int)" rename="setUniformValueArray_int" />
<modify -function signature="setUniformValueArray(int, const GLuint *, int)" rename="setUniformValueArray_uint" />
<modify -function signature="setUniformValueArray(int, const QVector2D *, int)" rename="setUniformValueArray_QVector2D" />
<modify -function signature="setUniformValueArray(int, const QVector3D *, int)" rename="setUniformValueArray_QVector3D" />
<modify -function signature="setUniformValueArray(int, const QVector4D *, int)" rename="setUniformValueArray_QVector4D" /><modify -function signature="setUniformValueArray(const char*, const GLint *, int)" rename="setUniformValueArray_int" />
<modify -function signature="setUniformValueArray(const char*, const GLuint *, int)" remove="all" />
<modify -function signature="setUniformValueArray(const char*, const QVector2D *, int)" rename="setUniformValueArray_QVector2D" />
<modify -function signature="setUniformValueArray(const char*, const QVector3D *, int)" rename="setUniformValueArray_QVector3D" />
<modify -function signature="setUniformValueArray(const char*, const QVector4D *, int)" rename="setUniformValueArray_QVector4D" />
<modify -function signature="setUniformValue(int, GLuint)" remove="all" />
<modify -function signature="setUniformValue(const char*, GLuint)" remove="all" />
</object>
We also reject a couple of overloads with two-dimensional arrays with a fixed size in the signature, since the Java does not support that. The result is that API is still usable, but not convenient, so it should be fixed before the API can be considered ready for use.
clone() is already defined in com.trolltech.qt.webkit.QWebElement
The final Java compile error is due to a bug in the Qt Jambi Generator. For classes where it’s possible, Qt Jambi will automatically generate a clone() method to implement the Cloneable interface. If the class already has a function called “clone” with no arguments, this will of course cause problems. I’ve made a tiny fix to the Generator in this case, causing it to skip creating the clone() when one already exists. If the existing clone method does not have the correct signature, compilation will still fail, so the fix is not complete, but it will fix the problem for the time being.
Cannot find symbol : variable DefaultHistoryVersion
From earlier, we remember rejecting the enum “DefaultHistoryVersion”. Apparently, this is used as a default value for an argument in a function, which causes the code to fail compiling. We need to remove the default value for now. A better solution for later might be to manually add DefaultHistoryVersion as a variable in the class, and have it point to the latest version. However, this would also require that we maintain the manually written code for each release to make sure the DefaultHistoryVersion is updated, so it might not be worth the trouble.
<object -type name="QWebHistory">
<modify -function signature="saveState(QWebHistory::HistoryStateVersion)const">
</modify><modify -argument index="1"><remove -default-expression /></modify></object>
Tweaking the APIs
So Qt Jambi 4.6 finally compiles, but there is still much to be done. I’ve noted along the way that much of the convenience of the original API has been thrown away because of missing support in the Generator, or because of fundamental differences in the language. In many of these cases, we will have to try to adapt the intention of the API, and write code by hand to do so.
When this is done, it is also necessary to go through the remaining three log files. The native pointer API log gives us a list of methods which are currently difficult to use for users of our API, but probably functional. In these cases we need to take measures to introduce a more readable API. Some entries in this list are intentionally left unhandled, as they are instances of low-level API which needs the functionality of QNativePointer. Most of the API should be ported to use more easily approachable types, however.
The last two log files both give us the names of functions that the Generator thinks will potentially cause crashes with the current state of the type system. We need to look through these, read the code of the functions, and make decisions based on our best assumptions.
The API cannot be considered ready until all this has been taken care of, and there are no more warnings and no more entries in the log files which have not been intentionally left unhandled after close consideration.
The road ahead
I’ve already done a lot of the work necessary to make Qt Jambi 4.6 work and compile, but there is still a lot to be done. I haven’t yet tested compilation on any platform other than Windows, and I haven’t addressed any of the deficiencies in the automatically ported API as mentioned in the previous section.
In addition to this, several of the new examples and demos should be ported in order to test the new bindings and usability of the new API, and there’s the question of the modules which have not yet been ported to Java.
UPDATE: If you wish to contribute to the port of Qt Jambi to 4.6, there is a repository dedicated to this. It contains the changes discussed in this blog. Send me a message on Gitorious if you want to be added to the qt-jambi-community group and have write access to the repository.
Good luck with Qt Jambi 4.6!
Even if this is my first blog post, some of you may have seen my name before. I have been with Trolltech and Nokia since 1996 (which makes me senior surviving Troll), and I am here to introduce a little research project we are starting up.
As you all know, our motto is “Qt Everywhere”, and we would love to see Qt run on all the cool devices that are coming out these days, but the problem is that making a port from scratch is hard work: Qt ports generally contain tens of thousands of lines of code, and require intimate knowledge of Qt internals.
One way to port with less effort is to use Qt for Embedded Linux, which provides functionality for adapting to different graphical devices. Unfortunately, doing this is not always trivial. Today I will talk about something that might make things easier, but first a little historical background information:
Qt for Embedded Linux (or Qt/E for short) has been with us now for about 10 years (the Qt/FB project started around 15 October 1999), and it’s still going strong, powering everything from small hand-held devices to large industrial machinery. However, times move on, and we are seeing new types of hardware that are very different from what we envisioned 10 years ago.
While Qt/E still remains amazingly flexible, sometimes it starts to feel like a little too much work to port it to some systems. Qt/E
includes its own Q Windowing System (QWS), and this is not always relevant, especially for systems that already includes window system functionality, or features that make it possible to implement windowing in ways we didn’t foresee 10 years ago.
We have been looking at ways to refactor Qt/E so it no longer depends on QWS, but there is a lot of legacy there, and over the years knowledge of QWS has infiltrated large portions of the Qt/E codebase. Getting QWS out of Qt/E was starting to look like a major project.
Then, one day, Rhys came up with the idea of starting from the other direction. How difficult would it be to just stub out all the
platform-specific parts of Qt and get a completely new port to compile? Given that most of the infrastructure is already in place
thanks to the raster paint engine and Alien, it should then be fairly easy to get a single process to show a full-screen window on the framebuffer. After talking it over with Rhys, I was starting to hope that this could help with the QWS problem as well, but of course we needed to try it out to see if it was actually feasible.
Rhys had something compiling in less than a week, and we had pixels on screen the next day.
We then played around with it for a couple of weeks, getting most of the crashes out of the system, as well as adding a few more back-ends that showed that we could support slightly more complex behavior.
Then we had to start concentrating on the upcoming 4.6.0 release for a while. However, word started spreading around, and people from all over were asking questions and found out that this could be the perfect thing for their pet project. Therefore, we realized that it’s about time to show off the results of our little feasibility study.
The most important thing for a project is of course a code name, and we decided on Lighthouse [not to be confused with a very early preview of Qt for S60 that was used by about 5 people outside Nokia…] since this meant we didn’t have to change the Q_WS_LITE platform define.
And of course, the obligatory screenshot. This one’s made using the “testlite” back-end:
Boring, right? It looks just like Qt… The point about Lighthouse is how easy it is to write a backend for new hardware. A more interesting picture would be to see how much code is needed to do that. Let’s look at the “minimal” backend, which is a complete example showing how to use a QImage as a display device:
~/git/qt-lighthouse/src/plugins/graphicssystems/minimal$ wc -l *
71 main.cpp
10 minimal.pro
70 qgraphicssystem_minimal.cpp
85 qgraphicssystem_minimal.h
101 qwindowsurface_minimal.cpp
73 qwindowsurface_minimal.h
410 total
410 lines of code is not too bad, but, wait a minute! That includes 40 lines of copyright header per file. Sloccount gives us a better impression:
Total Physical Source Lines of Code (SLOC) = 147
Now for something with a bit more meat to it: The OpenVG back-end clocks in at a SLOCcount of 288 lines, and it took about a day to write.
This is still early days, and very little is set in stone (or even properly documented), but you can check out the code, and see some very basic getting-started documentation at: http://qt.gitorious.org/+qt-developers/lighthouse
Just to make it very clear: this is a research project that is just starting out. Don’t assume that anything will work, or that any APIs
will stay the same for long. Count yourself lucky if it does not crash horribly and lock up your machine, or worse.
If you want to join in the fun, we can use the qt-embedded-interest@trolltech.com mailing list for development
discussions. I also hang around on #qt-labs as paulot from time to time.
Qt 4.5.3 is now available. 4.5.3 is a patch level release providing various bug-fixes over the 4.5.2 release that we issued in late-June. This release also includes new versions of the Qt SDK (2009.04) and the Qt Visual Studio Add-in (1.1.0).
You can get Qt 4.5.3 at http://qt.nokia.com/downloads and you can see the changelog here.
For those using the public git repository, a “v4.5.3″ tag will appear in the repository soon.
As always, your feedback on Qt is appreciated. If you have comments or bug reports, we’d love to hear from you. If you want to contribute to Qt, all the information you need to get started can be found at qt.gitorious.org.
We are currently preparing the release of the Qt 4.6 Beta, and during the Beta phase of Qt 4.6 we would like to ask the community of Qt users for feedback
regarding the stability, performance and overall quality of our designs, APIs and implementations.
In addition to asking for feedback through the regular channels we would like to make sure that as many Qt users as possible have performed a few specific tasks during the Beta phase to help us understand the most important issues that we need to address before the launch of Qt 4.6 later this year. We would like to invite you to sign up to the Qt 4.6 Beta Program - it should only take a few minutes!
If you sign up to the Qt 4.6 Beta Program, then we will during the next month ask you to complete two surveys that ask for your impression of the quality of Qt 4.6. One survey will focus on “is Qt 4.6 as good as Qt 4.5?” - focusing on stability and performance impact that replacing Qt 4.5 with the Qt 4.6 libraries in existing projects has. In the other survey we want to find out how you like our new APIs - are they useful, documented well enough, what kind of problems did you run into… If you have played around with the new things in the Qt 4.6 technology preview already and have any ideas about small exercises, then let us know here!
So the idea is that those surveys will not take very long to complete, but you should of course be able to set some time aside to test the Qt 4.6 Beta release. This release is expected to become available within the first weeks of October, and will be announced here and on the usual mailinglists.
It is of course not necessary to sign up to the Beta program in order to get access to the Qt 4.6 Beta packages, and our regular feedback channel will continue to be open for everybody! However, through the Beta Program we hope to understand better how much Qt 4.6 has been tried and tested.
So, we hope you will enjoy experimenting with the Qt 4.6 pre-releases and are looking forward to your feedback!
Have you ever been developing an app, and at some point wanted to know exactly which code was being run, and for how long, when you used it?
On the path to getting Qt inside your Nokia devices, we’ve recently been making use of a special Nokia tool for doing just that, and I thought I would give you a short behind-the-scenes tour of it so that you can see how serious we are about taking Qt everywhere.
If you’ve ever tried to speed up some of your own code before, you probably used some kind of profiling tool. Valgrind is a good example, and one that is heavily used in the development of Desktop Qt.
Desktops normally use x86 processors, but away from the desktop and running on batteries, ARM processors are most widely used. These systems tend to have quite a different architecture from desktop computers, as well as slower clocks and smaller caches. So some effort is needed to make software run fast on them because the performance bottlenecks can also be quite different.
One feature ARM-based chips often have which you don’t find on the desktop is ETM. Using this, the ARM can send trace information about every instruction it executes out through a dedicated debug port in real time, without slowing down execution of the software at all.
As ARMs usually run at hundreds of MHz, ETM creates a large amount of data in a very short time, so you have capture it using an external box with a few Gbytes of RAM. For cost reasons, you won’t ever find an ETM port on a device you buy in the shops, but during development of the devices, special versions are often made with just such a port.
Here’s a picture of a “special device” which is ETM-enabled, along with the Lauterbach PowerTrace II I use to capture the data:

Even with Gigs of RAM, you can only trace for about 10 seconds or so. Although that doesn’t sound like much, it’s actually enough to take a look at almost all interesting use cases.
Ok, so now I’ve got all that data, how do I make some sense of it? This is where FineToothComb comes in.
FineToothComb, or FTC as we usually call it, is a Nokia tool which takes all that ETM data plus some extra information taken from the device at the same time using JTAG, and all the binary code and symbols installed on the device, and then spends some minutes correlating all that together to create a database a few Gigs in size for a each trace.
To see what happened I then use FTC’s “Trace Explorer”, which starts off showing me something like this:
What you can see here is a “MIPS graph”. Time increases to the right, and the number of millions of instructions executed per second goes upwards. The colours represent different threads and processes that ran, with the names and instruction counts for those shown below the graph.
Because of memory latency and caches, you almost never see a CPU running one instruction for every clock cycle. Memory copies especially cause the CPU to spend most of the time waiting, which show up as “low” MIPS values on these graphs.
This first graph gives you the big picture of what happened during your use case. To see more detail you can zoom in on a region of interest. Here’s 165ms:
And again down to just 1.3ms:
Eventually you get down to the level of seeing individual context switches between threads - the operating system in action.
To see what a thread was doing, you simply choose it from the graph and the tool shows you a call stack for that time, along with the time taken (in nanoseconds) and number of instructions run for each call. From that last graph I opened the “lightmaps” stack:
The white lines are blocks of instructions being run from within one function. Red lines are calls from there to other functions, with the total time for that call in nanoseconds show in the second column.
Any call can be opened up to see what it called, in this case I opened the operator>>> call to see that it ended up in a file read which went to the Symbian file server. The tool can even cross over from user space into kernel calls to see what happened there as a result of a user call. Green lines show calls that have been opened up. As you move the mouse over calls, the graph at the bottom highlights the time range for that call so you can see where you are in the trace.
You can also see into any system servers or kernel threads that ran, as well as interrupts. Another feature is statistics of which functions used time and instructions for any block of time. Here are the top 10 functions from the big blue section in the 2nd graph - obviously a PNG decode:
And it can even capture and show what was on the display of the device to help understand the trace later:
Overall it’s really useful for quickly homing in on any code that needs performance optimisation, and because it’s not just a statistical sampling of what happened, it can be used for studying many kinds of use cases, for instance answering a question of why a system is waiting when it should be busy. Most importantly it does all this with the device running at full speed without requiring any special “debug” software build, so you don’t need to guess about how anything is in the “real” case, because this is it.
Using FineToothComb on Qt has already helped us quite a bit with performance of the Qt port to Symbian. Early on in the port, it highlighted some bottleneck functions which were converted from smaller but slower THUMB instructions to faster ARM instructions. It caught when we were not compiling using the ARM’s vector floating point instructions. It also helped with the optimisation of raster rendering functions using ARMv6 and data preloading. In another case it caught the fact that we were using a slow blit operation for the final screen update, when a different parameter would cause a much faster blit to be used.
Even though FTC isn’t a tool that is available outside Nokia, the improvements it can and has found already are, and more of them should be coming your way soon.
I’m going to be at the Qt Developer Days 2009 in Munich, so if you are there too and would like a quick demo of FineToothComb, just track me down and ask!
I’ll make this short and sweet and to the point :). Many things happened in the past few weeks in the land of the QtWebKit port:
- Kenneth and Antonio landed the first version of
QWebGraphicsItem, a simple class that mimics the QWebView API and makes it easy to embed WebKit into the GraphicsView. The API and class name are still subject to change, but we’d love to hear feedback and suggestions, especially from people who have implemented the same thing
- Jocelyn submitted
QWebInspector, a simple container that gives you control over embedding the web inspector into your application. The API is deliberately minimal to avoid exposing internals. - Tor Arne used his scripting skillz to migrate QtWebKit bugs from our internal company bug tracker into the public WebKit bugzilla. An important milestone towards a more transparent development process on our side.
- Yongjun, Janne and Norbert keep on submitting Symbian porting fixes. RVCT builds and runs out of the trunk and WINSCW is very close.
- We have updated the copy of WebKit in Qt 4.6 a few times and will continue to do so in the coming weeks towards the 4.6 release. Espen and Janne are also working on getting those WebKit and QtScript Symbian builds into the nightly Qt/S60 snapshots. UPDATE:The latest Qt/S60 nightly includes QtWebKit and QtScript now.
Generally speaking we’re in bugfixing mode. We had to slip in the above few features, but we consider them the exception to the rule. Until 4.6 we’d like to hold off any other changes that affect the API, unless they are actually API bugs or the result of review of new 4.6 API.
Writing good documentation is not all about the quality of what we write, but also about how we present the information. A large base of knowledge is of no use to you if there is not a good way of accessing the information you are looking for. The documentation must be accessible and easy to use, as well as accurate and informative.
Design philosophy
Lately, we have been looking for better ways to present the Qt documentation on the web. Our current documentation consists of static pages linked together in the good old fashion way of Web 1.0. Yes it works, but the potential of Web 2.0 is worth investigating and could increase the usability of the site. Ever since Qt version 2.3 (at least), the Qt documentation have had a uniform look and structure. During the time since those days, Qt has evolved, gained a lot of new features, and now covers a lot of more ground than its predecessors. This evolution has also effected the documentation, making the base of information larger and more complex. Despite the growing amount of information the documentation has kept its simple but effective design because it works for our users. That is something we need to preserve when adding new features to it.
If you have peaked at the documentation in the Qt 4.6 snapshot, you have probably noticed the search box added in the top corner of the index page. This is a custom Google search engine, scanning our documentation for results matching your query. Now, there is nothing revolutionary about this feature, but this is one way we can improve the documentation usability. Adding such a feature has no remarkable impact on the rest of the documentation. However, adding new features to the site should not be done without research. If we are going to do changes we need an idea or a philosophy on what we want to accomplish.
We want the documentation to be as user friendly as possible. That means that it should be easy to find detailed information on a subject if you are an expert and knows what you are looking for. The same should apply if you are a beginner looking for good tutorials and overviews. We also want to provide a structure that requires a minimum of searches and mouse clicks. Today, a search for detailed information on a subject can require browsing as much as seven or eight levels down using links from the index page. This makes navigation hard and tiresome, if it is not combined with queries to a search engine. Dynamic menus and a flat structure could help us on our way accomplish this. By creating a good cognitive design, we want to make your journey from question to answer as short as possible so you can focus on creating good applications.
So with these goals in mind we are trying to find a structure and a set of new features that will improve the future Qt documentation. Finding such a structure requires recognizing how the different elements in the documentation relate to one another. Questions like how they should be categorized regarding technologies, types of features or platforms, comes to mind and needs to be sorted out. Also we need to sort out which categories are more relevant and needs to appear at the front line to keep the structure flat. To keep a flat structure, the real trick will be to find out how to present as much information as possible on the least amount of space, and without making it chaotic.
Design reserach
That said, there are probably as many opinions about how the documentation should be organized as there are Qt users, and it is exactly these opinions that we are interested in. That is also why we will talk to our users about this issue during Devdays in Munich this year. We want to do some research on how developers use the Qt documentation, and how they would like the documentation to evolve.
As part of our research, we have created a set of different sample pages, showing a range of concepts from the super-social-inspired pages, to minimalistic and clean overviews. Our goal is to visualize different concepts and get feedback on what our users think of them. This user test will mainly take place face to face with developers during Devdays in Munich. The results of this user test will be brought back to the team in Oslo and used as input for the design process.
With a few weeks left until Devdays, we would like to show you a few of the features included in these sketches and say a few words about them. This will enable you as a user to give us your opinion even if you are not going to Devdays, and it is giving us a chance to adapt our approach to the problem. However, I must underline that these samples only show the wide specter of choices we have when looking for new features. Our purpose with this preview is to get feedback from our blog readers regarding what they like and don’t like about the features. In the list below you can have a look at our ideas, and add your comments.
Different concepts
Suggestion 1.
This is the current design, displaying menus of links in different categories. The number of links has been set to a minimum, but still covering the essential parts of the documentation.

Suggestion 2.
This sample uses icons and colors with the link lists, adding cognitive effects to the design. It also makes the page more pleasant to look at. It contains a search box for queries in addition to a line of top-level links at the page top.

Suggestion 3.
This sample is stripped of all eye-candy and cognitive image use. This makes the listed links more visible as long as they are categorized logically and the number of links is limited. The page contains a line of top-level links and search box at the top of the page.

Suggestion 4.
This sample shows a very minimalistic page containing only a few links and large images. This limits the navigation from the index page, but makes it easier to locate the relevant category to browse through. This page also contains a line of top-level links and search box at the top of the page.

Suggestion 5.
This sample has a more “social” concept. In addition to a menu with a hierarchical structure to the left, it has three menus showing content based on what the user previously has browsed in the docs, as well as menus based on ranks and top searches. As before the page contains a line of top-level links and search box at the top of the page.

Suggestion 6.
This sample is based on a “social” concept. These elements include menus containing top searches, history, blog entries etc. This can be an effective way of notifying the user about new features and popular subjects.

Search features
Suggestion 1 - Search features
This sample is based on the current design, but also provides a search box using AJAX requests to create a list of suggestions when typing.

Suggestion 2 - Search features
This sample demonstrates how Google search results can be integrated onto the documentation page. The user avoids leaving the doc pages and can navigate the docs without having to go back from the Google result page. Please note the keywords on the right hand side making it easier to further narrow down the search.

Navigation features
Suggestion - Navigation features
This sample is based on the concept in “Suggestion 5″, displaying a long page, containing menus and the search box. In addition the header of the page is floating, so the links and search box will always be visible. Also note that the bread crumb-links display a drop down menu to other relevant documents on the same level. Finally, the descriptions of functions etc., is hidden in a collapsible paragraph to make the content less chaotic.

Feedback
We want to create a good and usable design for the documentation. That is why we want your feedback, and there are two ways to contribute. You can add your comments to this blog entry. However, if you are going to Devdays in Munich, please stop by us and participate in the user-testing. It won’t take long, I promise.
You may also add your own ideas in your comment. It just might happen that you thought of something we didn’t, which could be the next genius idea for online documentation.
I promised you daily builds of Qt for Symbian/S60 a few weeks ago, and here they are. Every night at around 02:30 new binaries will be available.
Download the latest binaries from here!
There are two types of files available. You want the latest qt-embedded-s60-opensourceYYYYMMDD-4.6.0-tp1.exe file. The other qt-embedded-s60-opensource-src-4.6.0-tp1.zip is the source package used to create the latest .exe and can mostly be ignored. The .exe contains a Windows Installer as shown below, and here is instructions on how to use it.

There are three Qt .sis files included in the .exe. Most of you (unless you work at Nokia and have an RnD phone) wants to install the qt_for_s60_selfsigned.sis together with the fluidlauncher.sis or whatever application you’re creating yourself.
Works for S60 3.1, 3.2 and 5.0. If you’re using some funky internal RnD SDK, it might work (Hint: use the the “Choose additional folder(s)” option if you’re SDK is not in devices.xml).
The code we’re building from is whatever is HEAD of http://qt.gitorious.org/qt/qt/commits/4.6. In other words if we break the build, no binaries for that day - oh well. At the moment QtScript and QtWekbit are still not there - but soon my friends, soooon.
Update: As of 2009.09.29 the snapshots contains QtScript and QtWekbit as well. Yay we’re so great!.
Update2: Well, we’re not that great it seems. The .dlls gets copied to your epoc32, but they’re not inlucded in the Qt_libs sis files. Fixed now, should be correct in tomorrows snapshots.
Update3: Yepp - was fixed today :D.
Final disclaimer: This is not product quality software. It might make your phone depressed and make kittens cry. Use at your own risk.
Something we’ve been trying out recently with Qt Declarative UI is a Plasma integration. A characteristic of plasmoids is that they tend to have their own unique UI design. Integration of Declarative UI with Plasma has the potential to make it much easier to design such plasmoids. There is also the potential to help make plasmoid development easier by providing a declarative language that is designed specifically for fluid user interfaces, and is more accessible to designers without C++ knowledge. And it also has the potential to facilitate the construction of highly animated plasmoids, like the weather example which animates the clouds and rain/snow all separately. As a prototype we are hoping that its use will provide constructive feedback which enables Declarative UI to truly fulfill these potentials.
There is one very tricky aspect to Declarative UI’s Plasma integration. That is that there are large sections of Plasma code which are already written, containing widgets and QGraphicsItems, which might like to add some declarative parts but are certainly not going to re-write themselves. Declarative UI is based on existing Qt technologies, GraphicsView in particular, and can be integrated into existing applications. We just have very little experience with doing that right now and are still investigating how well this works, so feedback on this issue is warmly welcomed. We do intend to get things so that, as much as possible, existing Qt code can easily add Declarative UI bits to its UI when and if they want. You certainly won’t have to rewrite your application to use Declarative UI if you’re happy with your Graphics View solution. In fact, the prototype Plasma integration makes the existing Plasma QGraphicsWidgets directly usable in QML without altering their code at all (we’re still checking how well this works though).
We’re hoping that, at some point in the future, people will have Declarative UI as another one of their options for how to build their plasmoids. An especially compelling one if it’s to be heavily animated or they don’t like coding.
Below is a screen shot showing some of what we have so far. On the left is the weather example, and those are Plasma::PushButtons being used in the middle. On the right is a data source example, printing all the information it can get from the time data source. On the right, below the QML plasmoid, is the file watcher plasmoid showing the full QML source for the data source example just above it.

As part of the Qt Mobility project, we are introducing the Messaging library. This library enables access to messaging services.
Currently Email, SMS and MMS types of messages are supported by the library. We plan to support other types of messages in the future. Services provided by the message library include searching and sorting messages, sending messages, retrieving message data, and launching the preferred messaging client on the system to either display an existing message, compose a new message, or respond to an existing message.
Like other libraries in the Mobility project, this is a cross platform library that enables access to native services. An implementation for QMF, which was recently introduced here on Qt labs, is mostly complete. A Windows implementation based on MAPI and the Outlook Object Model is about half complete, and unoptimized. Subsequently implementations for Symbian, Windows Mobile, Maemo, and other platforms will be completed.
The code is available on Gitorious, and includes documentation and examples. Qt 4.5 is required to compile the project.
One of the examples included is called ‘Keep in touch’. This application demonstrates the searching services provided by the library by finding a list of addresses, and hence people, that messages have not been sent to recently.
Predictably the messaging library API contains classes that represent message, message part (MIME/TNEF entities), message address, folder and account objects, additionally identifiers for these objects also exist where appropriate. The API also contains a QMessageServiceAction class, instances of this class, known as ’service actions’, can be used to send, retrieve, display and compose messages, with progress information being reported when available.
A QMessageStore singleton class, known as ‘the store’ is used to access messaging data on the computer. The store and service actions enable retrieval of message, folder and account objects using identifier objects. Identifiers can be retrieved by using the store or service actions to filter and sort messages, folders and accounts stored on the computer. Additionally the store provides Qt signals for detecting the arrival, modification and deletion of messages on the computer.
Please feel welcome to send your feedback to qtmobility at trolltech.com.
The Qt Messaging Framework, QMF, consists of a C++ library and daemon server process that can be used to build email clients, and more generally software that interacts with email and mail servers. QMF is designed to be extensible to allow other types of internet and telephony messages to be handled. Currently QMF is ported to Linux and Microsoft Windows, other platforms will be ported to in the future. Check out the QMF source on Gitorious
There are currently no plans for QMF to become part of the Qt library, but it may subsequently be offered as a Qt solution. QMF does not provide the ability to create a cross platform application that uses the native messaging system on the underlying platform, such as the Symbian Messaging Framework on S60 or Microsoft MAPI on Windows Mobile. For more information on this topic please see the upcoming Qt Mobility Messaging labs blog entry.
QMF is a fully functional solution and comes with a demonstration mail client, called qtmail.
The QMF library is used by both the QMF message server process and also by QMF client processes. The message server is a long lived process, responsible for performing synchronization with external mail servers, which are normally located on the internet. Clients use the QMF library to interact with the messaging server, internally IPC is used by the library implementation to communicate between the server and clients.
Messaging data is stored locally in a database (currently SQLite). Clients and the message server access the database using the QMF library, specifically through an interface consisting of a singleton class called QMailStore. QMailStore provides shared access to the database by using semaphores, and notifies clients of changes to the database using standard Qt signals.
The message server loads plugins, known as protocol plugins, at startup to communicate with external mail servers. Protocol plugins currently exist for IMAP, POP, and SMTP. New plugins may be implemented to allow communication using other protocols. Like the message server and clients, plugins use QMailStore to access the local messaging database. Additionally plugins use standard Qt network classes such as QSslSocket to communicate with external mail servers over TCP/IP connections.
QMF provides a number of features which are important for mobile computers.
The message server working with well implemented clients should operate within a fixed upper bound of memory. This is made possible by providing interfaces to partially retrieve message data, including both message attachments and message bodies, lists of messages in a folder, and lists of folders in an account. Large messages are efficiently handled with respect to memory by using the mmap function.
Push email functionality is provided as demonstrated by the IMAP Protocol Plugin which allows monitoring multiple mailboxes using IDLE. Additionally a complete implementation of the Lemonade standard is provided including forward without download, and quick resynchronization. Furthermore email metadata can be retrieved independently of messages, this metadata is analyzed to determine which parts of messages to download, and if necessary used to refresh the status of messages as they become visible. All of these techniques help to conserve bandwidth.
Round trips to external mail servers can be very expensive taking several seconds to complete. QMF eliminates unnecessary round trips by fetching data for multiple messages with a single IMAP instruction. QMF is also capable of pipelining commands to reduce round trips but this functionality has yet to be fully utilized.
Additionally QMF provides automatic detection of conversation threads by using messages headers, including the subject header. Conversations spanning multiple folders such as the inbox and sent folder are detected. A full featured searching and sorting interface is present, including multiple levels of sorting, as is a complete Boolean algebra filtering interface, that even allows filtering on custom fields. The disconnected access paradigm is supported by QMF. For a more complete description of QMF functionality see the documentation included in the source repository.
In summary QMF is an advanced mobile messaging framework.
I’ve been playing with javascript lately, and here’s the result: QWebClient, a thin client for Qt applications. This is a pure Javascript implementation which runs in any modern browser (no plugins required). QWebClient works by starting an http server in the application process, which the browser then connects to. The project currently has research quality - get the source at qt.gitorious.org

Live Demo on hold! Try again later
View Source
(The demo itself is running on an Amazon EC2 instance. If you don’t see a live demo here, try reloading the page. If it still doesn’t work something has gone horribly wrong on the server or my credit card has maxed out.)
Prior Art
At this point I’d like to acknowledge the Wt project, which is a forerunner when it comes to C++-driven web applications. The difference between the two projects can be summarized by this table:
| Wt | QWebClient | |
| Focus | Web Toolkit | Thin client for Qt apps |
| Quality | Stable code base | Greater Hack |
User Code
Adding thin client functionality to your application requires two lines of code for a simple one-user thin client. Supporting more than one user requires instantiating several copies if the user interface, which can be more complex depending on the application architecture. On the browser side the client code is equally simple, and if you request index.html from the server you will recieve the code.
| Qt Side (Server) | Browser Side (Client) |
QWidget *rootWidget = ... |
<html><head> <script type=”text/javascript” src=”:qwebclient.js” mce_src=”:qwebclient.js”></script> </head> <body> </html> |
(Notice “src=:qwebclient.js”, the Qt resource system syntax has fond its way to the web!)
Scope
I’m targeting the use case where you have a server process running somewhere on a trusted network and want to expose a simple gui controlling it. This means:
- Simple, Form-like applications only, no animations or high-perforance graphics.
- Trusted networks only, there is little security. The implementation so far has been done with (eventual) security in mind though, so it’s not hopeless.
- Limited scalability, support a few users only (check out http://79.125.3.129:1818/statistics to see how the live demo fares)
- It’s a thin client, all program activity happens on the server (opening file and network connections, etc).
How Does It Work?
1. QWeblient starts a server at a user-configurable port
2. The Web Browser connects to the server and requests index.html. index.html loads qwebclient.js, which contains the thin client source code.

3.The Browser executes onLoad() which asyncronously requests /content from the server. The server replies with a json-encoded div element structure representing the widget hierachy. Common ui elemnts such as line edits are instantiated as native elements on the client side. All other widgets are transferred as images.

4.Keyboard and mouse events are POSTed to the server, which repsonds with content updates

5. When there are no client events, the browser will request /idle with one of its connections. The server will not reply to this request but keep the tcp connection open. (This the long-polling technique.)

6. Server events are sent to the client using the open long-polling connection.

Obligatory Conclusion
This has been a fun project! Crossing over from the C++ world to the web world is interesting, you get to speak http using QTcpSocket on the server side and then debug result in FireBug on the client side.
KOffice2 is still a fresh set of office tools. We released the 2.0, called platform release, just 3 months ago and work continues to make the suite more stable and to add the minimum set of features people should be able to expect.
All KOffice community members are continuing to do an awesome job with many bugs being closed and lots of love going into all the applications. This means that the 2.1 release will already be much closer to being ready for the big crowds.
We got a little help now too. Nokia has packaged KOffice for Maemo 5 environment with a new UI for Maemo 5!, This means that KOffice can run in the new Maemo device(N900) . Just to clarify, this is not a commercial product of Maemo but is a contribution by Nokia to Open Source. The developed application will be made available for download in a typical release-early release-often. Bugs will likely exist in this version.
This is exciting news as KOffice will be available to a huge audience and Nokia has been helping to fix bugs and make MS-Office document support more robust.
Nokia has created a document viewer for the Maemo 5 platform (Fremantle) based on KOffice and uses the KWord and KPresenter applications to load and display word processor and presentation documents. The application uses a custom user interface specifically designed to fit in with the Maemo 5 style.

Part of the projects goals is to help KOffice mature its loading and rendering of MSOffice documents.
It is important to point out that all contributions to KOffice have been made directly inside the KOffice subversion repository. The KOffice document viewer for Maemo 5 will be shown for the first time at Maemo Summit in Amsterdam between October the 9th and 11th. This release is a bit unfortunately timed as the official KOffice2.1 release will likely be one or two weeks later making the Fremantle office use the release candidate at first.
I think its very exciting to have the hard work of all the KOffice community members be rewarded by having the document reader be based on our hard work. I’m very thankful to be working on the project and I’m looking forward to continued cooperation between Nokia and the KOffice community.
Hi, all.
Would it be interesting for us to add some apis, examples and demos that show how to write games in Qt?
No work is happening in this field right now, so this is just an early invite for comments.
For example, we could provide
* Physics engine integration, perhaps in-house, 3rdparty, plugin based?
* Collision detection system (a more comprehensive one than what we have already)
I’m aware of free and commercial APIs that exist already, does anyone have a favorite to recommend?
Any ideas? Anybody interested? Is this worth investigating? ![]()
We added transparency support in Qt 4.5 through the Qt::WA_TranslucentBackground attribute. Unfortunately, as documented, it will only work on Windows if you explicitly remove window decorations.
With Windows Vista, Microsoft introduced the DWM (Desktop Window Manager) api, where you can enable a blur effect behind your application window. Unfortunately Qt does not have API to cover this yet, but by using the aforementioned translucent attribute in combination with a few native API calls you can already get this effect with Qt 4.5.
To make it simple, I created a convenience API to handle it so you can
plug it into your existing code. Note that the code should compile fine on other
platforms as well:
bool QtWin::isCompositionEnabled()
bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable)
bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
QColor QtWin::colorizationColor()
You can make a widget blurry by calling enableBlurBehindWindow or extendFrameIntoClientArea with the preferred margins. In both cases you are simply modifying the background of the widget. The colorizationColor is the color Windows tints the window with.
To show of the effect I made (yet another!) 200-line Qt browser. It has a custom style sheet with semi-transparent widgets. You will also see how you can make segmented arrow buttons using nothing but a pair of style sheets.
You can get the code and executables here.
Happy coding!
Many people have expressed some confusion over the the S60 port of Qt and where to find the relevant branches, so I thought I’d give a little update on where things are happening:
When the port was still young, it lived in the qt-s60 repository on gitorious. Here, both the master branch and feature branches coexisted happily. This however changed when the S60 port was merged back into the 4.6 branch of Qt. After this the master branch in the qt-s60 repository became abandoned.
Since this branch will not be used for development anymore, I deleted it today. This does not mean that the repository is dead though. The Qt for S60 developers still use the repository to develop feature branches, and we will continue doing this in the near future. When they are done, they will be merged back to a branch in the Qt repository (like 4.6, 4.7 or master). So unless you want to track a specific feature branch of interest to you, all the relevant S60 development happens in qt/master.
So what about contributions? After the merge of the S60 port, the rule is simple: Submit all merge requests to the Qt repository, even if the request is based on code found only in the qt-s60 repository. This is easier for you (one single place to submit to) and for us (one single place to monitor).
A couple of other notes on contributions related to S60 code:
- Be careful when you deal with code that can throw a Symbian leave. These have to be wrapped in special conversion macros. See this page for more information: Symbian exceptions safety.
- Coding style. Traditionally Symbian has had its own coding style with a different indentation and naming scheme. This style does not apply to S60 code used in the Qt library; We still use the same style that we always have! If you need a cheat sheet to the Qt coding style, look here: Qt Coding Style. You might also want to read the Qt Coding Conventions. Update: If you are using Carbide, you can download the Qt_Code_Style.xml template. To add it, just go to
Window > Preferences... > C/C++ > Code Styleand import the file you just downloaded. - There are still problems when compiling Qt for hardware using GCCE. The emulator should work fine though. We hope to get this fixed in the future.
- The rest of the contribution process should be explained in the Qt Contribution Guide.
- Update: The win32-mwc mkspec that was used in earlier releases has been deprecated and is not supported anymore. You need to use either Microsoft Visual Studio or MinGW and use “-platform win32-msvc2008″ or “-platform win32-g++”, respectively.
I hope you had a summer as great as we had in Berlin so far. We had awesome weather most of time with almost constant sunshine. Still we weren’t lazy, and worked on the next Qt Creator release. We are happy to give you a preview of some of the features that will be in 1.3 with a Technology Snapshot release.
Technology Snapshot is just our way of saying: This is not a proper fully tested release, it might not work perfectly, it might crash and it’s using Qt 4.6, which just released its Technology Preview. But we spent quite a lot of time on stabilizing and fixing regressions. I would recommend you to actually try it out. Me personally, I’m pretty happy with the release.
Now on to the fun part, the new features. I’ve selected a few things I’d like to highlight, and wow our changelog for 1.3 is already pretty long.
So one important change is that we by default use jom instead of nmake for projects compiled with Microsoft’s Visual Studio Compiler. Jom is not yet completely bug free, so if you have any problems with jom, please send us feedback. You can switch back to using nmake in the Settings under Tools/Options/ProjectExplorer. So why Jom? Jom automatically parallizes your build to use all your cores. It can easily make your build take half the time. See the Jom labs page
Also for our users using the Microsoft tool chain, the debugger support was improved.
Our C++ editor now highlights all uses of the symbol under the cursor,
e.g. allowing you to see with one glance where a variable is used in a function. Also you can rename symbols now with Ctrl+Shift+R. Currently it only works for local symbols, but for 1.3 we hope to have it working for more symbols. But still it’s useful already, and having the renaming inline instead of popping up a dialog feels really nice.
Another small feature worth mentioning in the code editor is completion for #include.
We also spend some effort in making the cmake plugin better. Some of the new features actually require a not yet released cmake version. Thanks to Christian who reviewed and applied a few patches I wrote for cmake.
With cmake cvs you’ll see all cmake files in the project tree and you can on windows use the Microsoft tool chain. We also fixed quite a few bugs and generally it should now be more useable. Though as always feedback on what you are missing most is welcome.
For the Qt project manager, we made the qmake step and make steps optional, so those who want to use a different build tool in conjunction with .pro files, can do so. Also Creator tries to be smarter about when to not run qmake.
You can check out from different source control system from the File/New Wizard. That also includes gitorious. We also have a new project pane, shown on the right.
We made the Ui scale better to lower resolutions, so all Netbook users should download this release.
You can download:
Yet it’s still warm here in Berlin, and we haven’t frozen yet, in fact one feature that we are secretly developing in our public repository is obvious if you either follow our commit log or which new platform is going to be supported by Qt 4.6.
Edit: You should rebuild your debugging helper libraries in Tools/Options/Qt Versions. The ones from 1.2 aren’t compatible with 1.2.90, we are going to add a version check for that.
Overview
Cross compiling Qt Embedded is relatively trivial since it is so self
contained, but as the number of external dependencies increases (DirectFB,
D-Bus, GStreamer, OpenGL ES) adjusting your custom mkspec to individually
account for the location of dependencies on the host machine becomes
increasingly tedious/untidy. This complexity culminates in cross compiling
Qt/X11 which adds the additional dependency of fontconfig/FreeType/X11 to
the fray.
This blog is intended as a general overview of the cross
compilation of Qt/X11 for embedded Linux targets. The wide availability of
the BeagleBoard and the proliferation of embedded Linux platforms gives us
the rare opportunity (and impetus) to walk people through the cross
compilation of Qt for an X11 target and get it up and running on a
reference embedded device.
These steps can be summed up as:
- Build a reference Linux image and toolchain (Ångström)
- Create an appropriate Scratchbox 2 target
- Build Qt against this reference image
- Reap the whirlwind
This walk through will introduce you to 2 separate tools intended to
simplify cross compilation for embedded targets:
OpenEmbedded (used to build the reference Linux system (Ångström) and toolchain)
Scratchbox 2 (used to build Qt/X11 against the reference system)
They both have their strengths and their particular uses, and if I offend
your sensibilities by using them in conjunction be sure to express yourself
with vigour in the comments section below. Neither tool is required to
achieve this goal, both tools expedite achieving the desired goal.
Building Ångström
I have personally chosen to use Ångström as a reference platform as the
Open Embedded development environment is relatively straightforwards to
setup in a standard (K)Ubuntu Jaunty environment, supports both x86 and
x86_64 host machines, and because it provides a fairly minimalist Linux image
possessing everything required to build a full fledged version of Qt/X11
(X11, D-Bus, GStreamer, Glib, fontconfig, FreeType). Anyone from a Gentoo
background will also enjoy the reassuring quality of 9000 build steps
constructing your eventual Linux system from source.
I followed the instructions given here:
http://www.angstrom-distribution.org/building-ångström
which culminate in the following build step.
bitbake base-image ; bitbake console-image ; bitbake x11-image
I would personally recommend rather running:
bitbake beagleboard-demo-image
which builds an appealing E17 image and which meets all Qt/X11’s needs.
The resulting Linux images are immediately deployable and you will have
acquired a very recent (by cross compiler standards) gcc toolchain to use in
the next step
Creating an appropriate Scratchbox2 target
Scratchbox enables you to abstract away the host machine when cross
compiling for a target. Rather than having to correct for host paths, you
can simply execute certain commands in a chrooted environment which
directly resembles the desired targets layout with the targets headers/libs
in their anticipated locations. With Scratchbox 2, you simply prefix
toolchain calls with sb2, and they are run within the specified
realm/sandbox.
Firstly, install Scratchbox 2 using your distributions package manager, or
via whatever mechanism you prefer. Next, you will need to create a suitable
Scratchbox 2 target. This involves executing “sb2-init” (from within the
staging/root directory containing the target’s /usr/include and /usr/lib)
with the following arguments:
- an appropriate cpu transparency command (normally qemu-$arch)
- the desired name of the target
- the fully qualified path of the gcc compiler
My sb2-init line looked like this:
sb2-init -c /usr/bin/qemu-arm angstrom-beagle /OE/angstrom-dev/cross/armv7a/bin/arm-angstrom-linux-gnueabi-gcc
and was run within:
/OE/angstrom-dev/staging/armv7a-angstrom-linux-gnueabi;
(Tip: The targets you have created and associated parameters are helpfully
revealed in subsequent calls to sb2-init)
Prior to running sb2-init as shown above, I personally had to modify:
/usr/bin/sb2-build-libtool
by explicitly adding “–host=x86_64″ to the configure line in order to get
libtool to compile successfully. The required diff would look something
like this (depending on your host):
- ./configure –prefix=$HOME/.scratchbox2/$TARGET –build=$(uname -m)-unknown-linux-gnu
+ ./configure –host=x86_64 –prefix=$HOME/.scratchbox2/$TARGET –build=$(uname -m)-unknown-linux-gnu
Cross compiling Qt/X11
Whenever you cross compile Qt you should create a custom mkspec based off
an appropriate reference mkspec, mkspecs/linux-g++ in this case. The
required modifications involve hijacking the qmake variables responsible
for defining all the target toolchain commands (gcc, g++, ar,
objcopy, strip) and prefixing each command with sb2.
My qmake.conf in my target mkspec looks like this:
=========================
#
# qmake configuration for linux-g++
#MAKEFILE_GENERATOR = UNIX
TEMPLATE = app
CONFIG += qt warn_on release incremental link_prl
QT += core gui
QMAKE_INCREMENTAL_STYLE = sublibinclude(../../common/g++.conf)
include(../../common/linux.conf)# modifications to g++.conf
QMAKE_CC = sb2 gcc
QMAKE_CXX = sb2 g++
QMAKE_LINK = sb2 g++
QMAKE_LINK_SHLIB = sb2 g++# modifications to linux.conf
QMAKE_AR = sb2 ar cqs
QMAKE_OBJCOPY = sb2 objcopy
QMAKE_STRIP = sb2 stripload(qt_config)
=========================
Once you have modified this mkspec to address any additional considerations
you might have, you can export PKG_CONFIG_PATH to point to your targets
pkg-config (.pc) files, which are normally in a pkg-config directory under
the targets lib directory:
$targetPathOnHost/usr/lib/pkgconfig. Please note this path must be fully
qualified relative to the host)
Qt’s configure script currently does not employ pkg-config when
establishing FreeType library metainformation when testing for fontconfig
support, instead opting for heuristics which are explicitly excluded when
cross compiling. This rough little (unsupported) patch will resolve this,
and will result in the correct detection and compilation of Qt with
fontconfig/FreeType support.
=========================
diff –git a/configure b/configure
index 3f3e55a..54de96b 100755
— a/configure
+++ b/configure
@@ -5115,6 +5115,10 @@ if [ “$PLATFORM_X11″ = “yes” ]; then
if [ -n “$PKG_CONFIG” ] && $PKG_CONFIG –exists fontconfig 2>/dev/null; then
QT_CFLAGS_FONTCONFIG=`$PKG_CONFIG –cflags fontconfig 2>/dev/null`
QT_LIBS_FONTCONFIG=`$PKG_CONFIG –libs fontconfig 2>/dev/null`
+ if $PKG_CONFIG –exists freetype2 2>/dev/null; then
+ QT_CFLAGS_FONTCONFIG=”$QT_CFLAGS_FONTCONFIG `$PKG_CONFIG –cflags freetype2 2>/dev/null`”
+ QT_LIBS_FONTCONFIG=”$QT_LIBS_FONTCONFIG `$PKG_CONFIG –libs freetype2 2>/dev/null`”
+ fi
else
QT_CFLAGS_FONTCONFIG=
QT_LIBS_FONTCONFIG=”-lfreetype -lfontconfig”=========================
then kick off the configure with:
./configure -arch arm -xplatform $customMkspecDirName -force-pkg-config
configure, make and pkg-config are being run directly on the host,
pkg-config is using the targets .pc files, the core tools (qmake, uic, moc)
are being built for the host, the config.tests are being correctly built
against the targets mkspecs and the cross compiler is used for all target
specific compilation. With any luck you with see a large number of the
configure tests pass, and see Qt configured to be built with full
fontconfig/GStreamer/D-Bus support. You can now build Qt by simple running
“make” (You are using the host machines Make, and please note that you
never actually need to prefix sb2 on the commands you run, the qmake
generated Makefile will contain sb2 calls where applicable)
Reap the whirlwind
Cross compiling Qt applications now simply involves running the freshly
built qmake against the desired project .pro file, and running make as per
usual. (You are using Qt tools built for the host, and the host system’s
make and pkg-config applications amongst other things). Running make
therefore results in the host system’s “make” proceeding through all
the build steps using the correctly prefixed build tools.
Assuming your build is dynamic, your libraries and plugins have to be
deployed to the prefix path you either implicitly or explicitly specified
at configure time)
(Disclaimer: I realize that there is no implicit dependence on Linux when
discussing X11, and there is nothing Linux centric in my instructions other
than that it is the reference (and host) platform. I am building a standard
Qt X11 build in a controlled environment advertising my headers/libs in
their canonical paths (via Scratchbox) and making use of qmake’s cross
compiling infrastructure. If you have a suitable root filesystem,
associated toolchain (cross compiler), and if both Qt/X11 and Scratchbox 2
support your target platform, you should be set (although officially
thoroughly unsupported) to walk down the yellow brick road with these
instructions.)
Hi, I just wanna give you a small update on how the Qt 4.6.0 TP1 and the Qt port to Symbian/S60 works together. Here is the short version:
Keep using the “Tower” pre-release unless you know what you’re doing
Now, for those still reading here is some more details. We’ve integrated the port into the Qt 4.6 codeline, so now we’re releasing together with the other platforms. With the “Tower” release which is 4.5 based, we had both QtScript and QtWebKit working fine - this is not the case for this release. There are two reasons for this:
1) Not all changes we did in QtWebKit for the “Tower” release has been pushed or admitted upstream. And we’d rather spend the extra time it takes to get it right in the WebKit trunk instead of hacking it together for the TP1 release in some special Qt version. Please be patient, this is the right way to do it.
2) We’ve changed the backend of QtScript to use the Javascript engine in WebKit. And since that’s not working yet, well - QtScript is not working either.
So what can I use the TP1 for then? Well, if you want to try out new stuff in 4.6 NOT relying on QtScript nor QtWebKit, and if you have access to the RVCT compiler, you can build the src package. Make sure to use this configure line:
configure -platform win32-msvc2008 -xplatform symbian-abld -no-script
You can also use -platform win32-g++ if you feel like it. Btw, if you don’t understand the -platform vs the -xplatform stuff, let me enlighten you a bit. Simply said, the platform you’re developing on is the -platform, and the platform you’re developing for is the -xplatform. Up to and including “Tower” we used the “Nokia Carbide C/C++ Compiler for Windows/x86″ aka mwccsym2, but we can’t do that anymore after we removed the old ANSI support in Qt for 4.6 (see this blog post for more details on the change). That means if you want to build Qt from the src package, you need either g++ or Visual Studio Express Edition in addition to RVCT. We require RVCT 2.2 build 686. If you have an earlier version of RVCT you’ll need to remove --visibility_inlines_hidden from the QMAKE_CXXFLAGS.ARMCC line in mkspecs\common\symbian\symbian.conf. At the moment we don’t support RVCT 3.x nor 4.x.
I know most of you don’t have RVCT, so we’re working hard on getting daily binary snapshots created. That way you don’t have to spend time and money on getting the src package built, and can instead just get directly to hacking. I’ll update with a new blog entry once binary snapshots are up and running.
Btw. have a look at this blog post for instructions on how to get Tower working on Linux. Hopefully we can make it easier in the future ![]()
Today we have reached another significant milestone in Qt’s life - 4.6.0-tp1 has been released. This is the first step in the process of turning all of the great new Qt features you’ve been reading about on Labs into a coherent, stable and polished product that will power a new generation of applications.
It’s an exciting time to be the Qt Release Manager. Qt 4.6 is the first feature release that I’ve been involved in from the very start. And Qt 4.6 is a big release - there’s a lot of new stuff and making all of that play nicely with all of the existing stuff is a big challenge. Luckily we enjoy a challenge here at Qt Developer Frameworks.
You can get the packages from the Qt website here, or from our ftp site: tar.gz version or zip version. You can also find the latest documentation at http://qt.nokia.com/doc/4.6-snapshot/index.html. (For those interested, the packages were generated from SHA1 c4c9b4457f0f760c1bf46dd8a309ab76eb128c1d in the qt.git source repository.)
Our main reason for providing this Tech Preview release is to solicit constructive feedback from the community of users and developers. The Tech Preview will contain bugs - with the amount of new code that has gone into Qt 4.6 that is unavoidable. Now that all the new 4.6 features are in the code, we are at the beginning of an intensive bug-fixing period that will likely last a few months.
At the end of that period we hope to release the most feature-rich and high-quality Qt ever, but to do that we need your help. There are two ways you can help: if you found a bug, you can submit a fix or an autotest that demonstrates the bug via the public qt-repository on http://qt.gitorious.org. Alternatively, if you have any bug reports or suggestions, whether they relate to the code, the documentation, or something else Qt-related, just follow the instructions for submitting feedback.
I won’t go into detail about the new features that are making their debut in Qt 4.6 (there’s already plenty of information about them on Labs, directly from the developers), but I would like to highlight a couple of important changes to Qt’s packaging and supported platforms.
Previously, we have delivered source packages for each of our major supported platforms (Windows, MacOS X, X11, embedded-linux, embedded-wince, and an “all” package that included the code for all of the desktop platforms). Beginning with 4.6.0, we are delivering a single source package that contains the code for all platforms (there are .tar.gz and .zip versions of the file, but the contents are identical). This should remove any confusion about which package is the right one to download, not to mention making the Release Manager’s life a little easier.
On the supported platforms: In Qt 4.6, QtScript is not enabled by default on platforms for which QtWebKit is not supported. However it does compile
on them and you can re-enable it by passing the “-script” option to configure.
That’s all for now. We hope that Qt 4.6 provides something new, interesting and useful for all of you.
This post includes some additional background information to support and
clarify our recent QtMobility Multimedia Blog post.
General architecture

The above block diagram gives a high-level view of multimedia in Qt.
Services
The Multimedia services classes that are in Qt 4.6 in the QtMultimedia module
form Qt’s access to the lowest level of Multimedia functionality. The Audio
classes provide a cross platform means to access audio devices, to send data to
or receive data from them, the audio data would usually be PCM, but could be in
other formats as well. The Video classes have a similar purpose, those in 4.6
exist to provide an abstraction for video outputs.
The Audio classes can be used in a self contained way when you are manipulating
or creating your audio data directly in your application. Some examples of this
would be, a sound recorder, an effect generator, VOIP client, event sounds,
games or a situation requiring intermittent or lower-latency playback.
The service classes are also meant for building other media functionality; to
simplify and provide cross platform support for the building of playback and
recording functionality.
High Level APIs
Phonon
Phonon is a high level playback API. Phonon provides facilities for playback of
media content. Phonon is also currently used in Qt for media playback. We will
continue to maintain Phonon for the duration of the 4.x series, but new
functionality will be added in the new multimedia module.
So why didn’t we try and improve Phonon? There are a lot of interconnected
reasons that would prevent Phonon from moving forward. We felt that that there
would either need to be too much compromise or major source-compatibility
breaking changes (let alone BC breakage), in order to achieve our goal of a
full featured high level framework.
Briefly, some of the problems found with Phonon were as follows -
- The MediaSource class can not adequately represent the variety of data
sources available. For example; Media sources are often not single items of
interest, but a choice of available content (not substreams of content).
Additionally it is often required to bundle additional data with the playback
content, previews, posters etc, there needs to be a way of uniformly
representing these items and tagging them appropriately
- Some playlist like functionality is bound into the media object and limits
the ability of a media subsystem to participate in playlist management. This
is vitally important for certain classes of playback service.
- Metadata support is bound to the media object, this limits the scope for
collaboration with other media service providers that may have useful metadata.
- The attempt to express a high-level media graph imposes a model of operation
on the underlying frameworks that can not necessarily be supported, the
obvious means of routing around this failure can not be made to work
reliability.
– A Qt Multimedia API needs to exist in a cross platform (hardware and
software) environment, this means the attempt at graph manipulation imposes an
added customization burden on existing Phonon backends.
- The backend is responsible for creating objects, not allowing applications to
become involved in the media conversation, this places limits on presentation
options.
- Dynamic backend changes
- Services only being available by plugins loaded by Phonon, again limiting the
media conversation.
- Non-local, out of process, playback services are difficult to implement.
QtMobility Multimedia APIs
The Mobility Multimedia APIs are high-level APIs. There is a place for
high-level APIs in a media universe, for although there are a class of
applications that require the ability to manipulate media streams at varying
levels, there is also a class of application that can happily work without
detailed knowledge of the media subsystem or the elements used in the subsystem
in order to do useful work.
The Mobility Media APIs are made to support playback, recording, playlist
management, metadata, radio, camera, and as time permits transcoding, media
editing, TV and potentially high-level stream management.
There is already support for playback, recording, radio, metadata and playlist
management and some experimental camera support.
Like all of the Mobility projects, the QtMobility Multimedia API is targeted to
merge with Qt at some future date, which has not been decided yet.
The QtMobility Multimedia API competes with Phonon on playback services.
There is little sense in having two competing media frameworks in Qt.
Future Direction
There are lots of places we would like to go, Multimedia is an exciting area to
work in. As mentioned above at the higher level we would like to see
transcoding, media editing, and TV support, we would also like to shift down
slightly and open up access to streams, without confusing the “top-level” API.
We would also like to build upon the services layer, provide a more complete
graph orientated audio only framework, as well as low level video capture
service, but only time will tell what gets implemented and when.
Further information
I hope this brings some clarity to your view of multimedia in Qt. If you have
any further questions you can always comment here, catch us on IRC (#qt-labs;
just ping multimedia, someone should pick it up) or send an email to
qt-interest at trolltech.com.
A few weeks ago, the LinuxTag 2009 took place in Berlin. Of course some of us Trolls went there to present Qt. We ran a little booth where we had the possibility to talk to many Qt users (and future Qt users).
But that was not all. Some Trolls gave talks about very interesting topics. And because on that day I found my camera somewhere in my pocket, it made sense to film some of the talks (three to be exact) and share them with those who were not able to travel to Berlin. Here we go -in chronological order-…
Creating Qt Creator
Free Software Development at Nokia, Qt Development Frameworks
Speaker: Matthias Ettrich
“Nokia Qt Development Frameworks - the former Trolltech - announced earlier this year that they will open up their software development process and establish a new contribution model. One pillar of this change is a more permissive licensing under the terms of the GNU LGPL. In addition, Qt source code repositories will be made publicly available and contributions from desktop and embedded developer communities will be encouraged.” more…
New user interface paradigms on mobile devices
Speaker: Matthias Ettrich
“Today’s mobile devices have large high-resolution screens, touch input and significant graphics power. Applications on such devices no longer compete on features, but on graphical “wow”. It is not even unusual to hear people buying apps just because they have a cool UI.” more…
Advanced Graphics Programming with Qt
Speaker: Ariya Hidayat
“This talk highlights several key features of Qt graphics programming, including the low-level, immediate-mode painting system and 2D scene graph provided by Graphics View. To ensure a successful smooth and attractive user interface, this can be complemented by animation, Web engine, scripting, and graphics effects, which will be suitable discussed as well.” more…
(a.k.a., Qt 4.7)
Borrowing the term from our Symbian / S60 friends, who have stopped using this naming scheme already, I’d like to point out that the Qt 4.6 and master branches in our Gitoriuous repository have diverged.
What does this mean? Well, if you build master now, Qt will tell you that it’s version 4.7.0, not 4.6.0. For example:
$ qmake -v QMake version 2.01a Using Qt version 4.7.0 in /home/tmacieir/obj/troll/qt-main/lib $ moc -v Qt Meta Object Compiler version 62 (Qt 4.7.0) $ $QTDIR/lib/libQtCore.so This is the QtCore library version 4.7.0 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). Contact: Nokia Corporation (qt-info@nokia.com) Build key: i386 linux g++-4 full-config Installation prefix: /home/tmacieir/obj/troll/qt-main Library path: /home/tmacieir/obj/troll/qt-main/lib Include path: /home/tmacieir/obj/troll/qt-main/include
And if you’re following Qt development using Git, it might be time to start tracking the 4.6 branch instead:
git branch 4.6 origin/4.6 git checkout 4.6
That’s about it. We haven’t started merging 4.7 features yet. We don’t know yet when it will be released, nor much about what’s going to be in it. (Ok, we have some opinions on date and content…)
And before anyone panicks, no, we’re not adopting the naming scheme either. This was just to write a longer title than two letters, two digits and one punctuation
We’ve managed to keep a very boringstrict numbering scheme for Qt for years. I remember when we released Qt 4.4 and our Chief Troll was interviewed by a Norwegian newspaper. After he had listed the new features coming in, the reporter commented something like, “4.4? You should call that release 13 or something!”
Other products have had a more, erm… relaxed numbering:
- Windows: 3.0, 3.1, 3.11, NT 3.5, 95, NT 4, 98, 98 SE, 2000, ME, XP, Server 2003, Vista, Server 2008, 7
- Solaris: started as Unix 6, 7, III, IV, V, V R2, V R3, V R3.2, V R4; merging with SunOS: 4 BSD, 4.1 BSD, SunOS 1.0, 2.0, 3.0, 4.0; resulting in: Solaris 2.0, 2.5, 7, 8, 9, 10
What’s your take on what Qt’s sequence numbering should be? Give your reply how Qt past releases should be numbered and how we should go from here. Be creative!
The QtMobility family is growing once again with the addition of the Multimedia Framework. QtMobility’s media library will enable developers to easily create applications that make best advantage of the system media capabilities.
The Multimedia framework is designed to cover the items of most direct interest to developers; playback, recording, play-list and meta-data management - all the things you’d expect from a high-level media framework. All integrated nicely into Qt. We’ve taken care to strike a nice balance among simplicity, versatility and extensibility; and the result is a framework that is easy to get started with - while allowing such niceties as transparency in the locality of playback, and that is readily customizable - create your own playback or recording services.
If you are looking at using a Multimedia framework in your application and would like to investigate further, a good place to start is QMediaPlayer and QMediaPlaylist. With these two classes you’ll easily be able to create a simple media player application. You could even extend further and use QMediaMetadata to fetch cover-art and track info, a complete music player is just three classes away, well, almost :).
This is not the finished product, there will be changes as we take it to the best place it can be, so if you have any comments don’t be shy. For testing; currently only Linux is supported as a platform, you’ll need GStreamer installed. You might also be able to have a little fun on Windows. In the future we should see implementations for all our supported Macintosh OSX and Windows platforms, Phonon on KDE, and in the future; Symbian and Maemo.
You can find the source on Gitorious. Note you will need Qt 4.6 to compile the project. Feel free to comment here or if you’d like you can send an email to qtmobility at trolltech.com.
Mac OS X Snow Leopard was released on friday, Qt 4.6 is on its way - The 4.6 branch has been created at gitorious.org. What’s new?
First of all we’re rolling the OS Support window: support for 10.3 Panther has been removed and support for 10.6 Snow Leopard has been added. This means that Qt 4.6 on Mac OS X will support three versions of the operating system(10.4 - 10.6), four different architectures (ppc/ppc64/i386/x86_64) and two toolkits (Carbon/Cocoa). About half of the OS/arch/toolkit combinations are valid, see developing-on-mac.html for all the details.
Removing 10.3 (Panther) support
With Qt 4.5 we removed support for gcc 3.3, making Qt deploy-only on Panther. We’re now removing run-time support as well. This allows us to remove a bit of code (Qt 4.5 contains around 60 10.3-spesific code paths), and also frees up developer, support and QA resources to focus on the newer platforms. In addition, our 10.3 testing machine here at the Oslo office is showing its age and is ready for retirement.
Adding 10.6 (Snow Leopard) support
From a developer viewpoint the biggest change in this release is more 64-bitness. Most(all?) of the bundled apps are 64-bit, and the gcc compiler produces x86_64 binaries by default. Qt follows suit and is also 64-bit by default when building for Cocoa (Select this with the -cocoa flag at the configure line or use the -arch x86_64 flag). Apple has also updated to gcc 4.2, which renders the macx-g++42 mkspec obsolete. Compiling for ppc64 is no longer supported by the gcc tool chain. Other than that developing on 10.6 is much the same, and we can all enjoy the new Exchange support in Mail.
Planning Ahead
Maintaining two ports is not sustainable in the long run, so the Carbon port is eventually going to be dropped. It is however our only means of supporting Tiger and legacy Qt3-based code, which suggests that we should keep it around for at least little bit longer. PPC support is not a big issue, the build infrastructure for it is there and the PPC-only bugs are few and far between. That being said, at some point in the future we’ll probably end up supporting x86_64/Cocoa only. Unless something new we can port to appears in the mean time
So, here’s the conclusion with a tentative plan:
While the S60 port was going on, it became clear to us that there was something that Qt needed: A proper API for dealing with input panels (also called virtual keyboards). For the S60 platform the motivation was obvious, since most touch phones use some sort of on-screen keyboard. But we also wanted to make the API in such a way that it could be used by developers on other platforms, which is useful for kiosks or desktop machines with touch screens.
The API itself is an extension to the QInputContext class, which already deals with input methods, and is actually really simple: Two new events that tell you when to open the panel and when to close it, RequestSoftwareInputPanel and CloseSoftwareInputPanel. All Qt’s input widgets support these events and will send them when appropriate. As for how to deliver events from the panel to the widget? Well, that’s already there in the form of QInputMethodEvents.
What the input panel developer then needs to do is to make a class which subclasses QInputContext, and in the filterEvent() function you look for the events which tell you show or hide your input widget. If you want to have extra control over what type of input can be used (so the input panel can show only numbers, for example), check out the new inputMethodHints property of QWidget. This property is fully editable in Qt Designer, and some widgets already use it automatically, such as QSpinBox which sets it to numbers only.
Check out the example in Git under examples/tools/inputpanel! It’s also documented at http://doc.trolltech.com/4.6-snapshot/tools-inputpanel.html.
As part of the Qt Mobility project, we are introducing a Location API to provide components for distributing and receiving location-related data.
What is location data? It’s the data provided by technologies like GPS, Mobile Cell Identification and WLAN positioning that allows you to pinpoint your exact location on the surface of the Earth (or pretty close to it, anyway). It’s the data that lets you drive with in-car navigation, track your running routes via SportsTracker, find your friends with Google Latitude and play location-based games like Pac-Manhattan and GeoCaching. With the advances in positioning hardware and network-based positioning methods, location services have become increasingly popular and are now commonly found on mobile and embedded devices.
In the Location API, we provide an architecture for distributing location data to multiple clients and a simple way for clients to request and receive location data. There are also components for coordinate calculations, reading NMEA data and distributing satellite data. The API is focused on providing the essential components for location data sharing and does not involve more advanced location services like geocoding and mapping capabilities.
Here’s the basic structure of the API. The light blue boxes indicate components that can be used to implement custom location engines.
On mobile platforms with built-in location capabilities such as GPS, we plan to provide access to these default capabilities through the Location API. On platforms that have no built-in location services, developers can write custom location data sources using the Location API.
Check out the source at http://qt.gitorious.org/qt-mobility/location which includes an example for writing custom data sources. You’ll also find an example that parses NMEA data and displays the parsed coordinates using Google Maps and QtWebKit. Here’s a screenshot of the latter example:
We plan to add other components such as landmarks storage in future releases, so watch this space. As always, feedback is welcome at qtmobility at trolltech.com.
Its been some months since we released KOffice2.0.0, the first official release for the new platform KOffice2.
For common and certainly for advanced office users we made clear that 2.0 is missing features for them. What then, you may ask, is 2.1 going to change for them?
Well, here is what we are working on and what has been integrated into what will become the 2.1 release in a month or two.
Tables
Releasing a word processor without tables was pretty daring, and for 2.1 we did a lot of work to correct this. As part of the GSoC project we got Elvis Stansvik working on this for the whole summer. As this is part of KWord, I was the mentor and near the end we also got help from Casper Boemann. The end result is that KWord can show a huge set of tables based documents correctly. Its important to point out that this is ongoing work; creating new table cells or modifying the shape and look of a table is currently not possible.
Change Tracking
While editing a text document you can always undo your changes and get back to the way your document looked before. But what if you want to show the actual changes made right inside the current document? Or even better, being able to see what your colleague changed in the document over the weekend. This is what change tracking offers and this has been integrated just last week and it looks like we’ll have most of the expected features available in 2.1 thanks to the work of Pierre Stirnweiss. The most exciting part is that this lays the foundations for projects like collaborative editing.
Improved image handling
This has been detailed in another post already, so I’ll keep it short. For 2.1 the images handling has been made faster and we now are much smarter with memory usage so its possible to have image-heavy documents showing just fine even on memory constrained systems and devices.
Continued improvement in OpenDocument Format (ODF) support
ODF is still a huge specification and during the 2.1 time-frame there have been various teams working on testing and improving KOffice to become both better at writing correct and full ODF as well as reading other applications ODF documents. As ODF is a way to inter-operate between different application suites so its obvious that the way to get better ODF support is to collaborate on this front with others.
KOffice has been working at the front-lines with the industry big names for some time now. A recent example is the plugfest in The Netherlands last summer and the upcoming plugfest in Italy where KOffice is well represented.
An exciting initiative is the officeshots which renders an ODF document in all available office applications and shows the output. KOffice has been working with the OpenDoc Society to provide hardware and software support and make sure KOffice interoperability can be verified by everyone.
KFormula major improvements.
The formula editing component in KOffice has seen many upgrades since the 2.0 release. This means that all KOffice applications can now display and directly edit formulas. The GSoC project by Jeremias Epperlein has seen improvements specifically in rendering the formulas much more pleasing to the eye and the editing of a formula is well integrated into KOffice and quite easy to use.
Windows™
At the tagging of the beta1 all of KOffice compiled without problems on visual studio 2008 which significantly lowers the barrier to developer and end user adoption of KOffice. We are still looking for enthusiastic packagers and naturally developers on this platform to help improve the experience for end users.
MSOffice support
Still quite important for many is the ability to open MSOffice documents correctly and the major painpoints are one by one being addressed. Major things like importing text correctly, importing tables and importing images in presentations have been added for 2.1.
Instead of answering all the comments about QScopedPointer, I decided it’s easier to post a follow-up post
Thanks to Thiago’s blog, the differences between the various smart and not so smart pointers should hopefully be clearer now.
Using QScopedPointer instead of std::auto_ptr or boost’s scoped pointer has nothing to do with not-invented-here syndrome. Very early during our API discussions we realized that delete-on-end-of-scope was not enough, we also needed custom cleanup handlers. Take QBrush as example - extra magic is required when deleting the private object. The other pointer classes did not offer that functionality, so they were ruled out.
Why did we make the custom deleters a template argument, and not simply a function pointer member in the class? This has two reasons. Firstly, we didn’t want any penalty from using QScopedPointer over manual new/delete. Setting an extra pointer, and calling it in the destructor would have introduced an extra overhead. Secondly, due to our binary compatibility policy, the size of QScopedPointer must be sizeof(void*), so adding another member variable was not possible.
Custom cleaners can be very useful - you can basically use QScopedPointer for any cleanup when leaving scope, for example to close a handle, decrease some reference count, call a custom free function and so on.
Still not in love with QScopedPointer? Let’s look at the following, then:
class ForwardDeclared; extern ForwardDeclared *myFunc(); … std::auto_ptr<ForwardDeclared> ptr(myFunc());
It compiles, but you’ll get a nasty surprise at runtime - since the class is only forward declared, its destructor will not be called on deletion! QScopedPointer has extra protection, forcing a compilation error in the case above.
To make sure that you can write if (myScopedPointer) …, we had to introduce an operator bool() - but that would also enable writing int x = myScopedPointer;, due to the implicit boolean to integer conversion. Thankfully, we found that issue during an API review, so the latter case will now not compile.
Still not deeply in love with QScopedPointer? Good news - it’s all template code, all inline, so there’s no penalty to Qt’s library size or runtime behavior if you choose to ignore our little gem ![]()
Our friends in Brazil have released PySide, Python bindings for Qt.
PySide is a project that is run by INdT and sponsored by Nokia that provides Python bindings for Qt under the LGPL. These bindings are currently in pre-release form and only support Linux/X11, however the PySide team is hoping the community would be interested in helping to make the bindings cross-platform. The team is happily awaiting your feedack and contributions.
Head over to PySide.org and learn more.
Influenced by Holger and Simon, I decided to use S5 for my presentation at the Desktop Summit in Gran Canaria few weeks ago. It’s purely based on web technologies, it works in modern web browsers. More information is available at the official website, including demos, even with different styles and effects. Thanks to the use of web technologies, you can even create the slides online.
For the fun of it, instead of just using a web browser (so boring!), I wrote a simple QtWebKit-based tool to run the slide shows, dubbed s5runner. The code is checked in already to the Graphics Dojo repository. Beside just launching the slide shows in a QWebView, the 200-lines C++ code adds a few more goodies (although arguably, all these extra stuff can be implemented in pure HTML/CSS/JavaScript instead). Run the program and open the included slides.html (in the example sub-directory), or just enjoy the following 2-minute screencast:
A countdown timer (currently hard-coded to 30 minutes) is installed at the bottom right corner. The screen can be blanked temporarily to black or white, useful when you want to steal the focus of the audience from the slides. Going full-screen (and back again) is also easy, this is important if you’d like to show some live demos during the talk. The slides look ugly due to the aging or faulty projector? Use the night-mode, something you have seen in the previous OpenStreetMap example.
When doing a talk about programming, it is often unavoidable to show code snippet. Thanks to Chili, the jQuery code highlighter plugin (there are other alternatives to pick:
prettify, syntaxhighlighter, and many others), you will get the highlighting feature with zero effort. It’s quite useful as the code fragment (which you likely show only for a few seconds) becomes more understandable. My favorite is however the live-editing feature, just press F3 to start editing the slide while you are showing it at the same time.
If you like this presentation tool, feel free to extend it. For example, you can have more presentation effects, like pulsating or shaking, by using script.aculo.us-based Presentacular. This example tool only supports basic editing, but I have shown a WYSIWYG HTML Editor before, so you can augment its editing features to support e.g. inserting images from the disk, changing character and paragraph styles, and so on. And of course, support for PDF export (with one slide per page) will be just very nice. A PowerPoint-killer, anyone?
On Friday, along with the Qt for Symbian integration, we got a new smart pointer class in Qt, called QScopedPointer. Harald, one of the class’s author, blogged about it, which prompted a lot of comments asking why we have those classes and what’s the difference between the ones we have.
Before we can find out why we have those classes, we need to know the classes we have. So, count with me, in chronological order:
- QPointer (4.0)
- QSharedDataPointer (4.0)
- QExplicitlySharedDataPointer (4.3/4.4)
- QtPatternist::AutoPtr (internal class, 4.4)
- QSharedPointer (4.5)
- QWeakPointer (4.5)
- QGuard (internal class, 4.6)
- QScopedPointer (4.6)
Note: QExplicitlySharedDataPointer was introduced in 4.3, but the API was made public and documented in 4.4
That many, huh?
Each and every case has its use and they all (except one) are still valid today.
Shared pointer versus shared data
First, let’s get one thing straight: there’s a difference between sharing pointers and sharing data. When you share pointers, the value of the pointer and its lifetime is protected by the smart pointer class. In other words, the pointer is the invariant. However, the object that the pointer is pointing to is completely outside its control. We don’t know if the object is copiable or not, if it’s assignable or not.
Now, sharing of data involves the smart pointer class knowing something about the data being shared. In fact, the whole point is that the data is being shared and we don’t care how. The fact that pointers are being used to share the data is irrelevant at this point. For example, you don’t really care how Qt tool classes are implicitly shared, do you? What matters to you is that they are shared (thus reducing memory consumption) and that they work as if they weren’t.
Strong versus weak pointer referencing
The difference between a strong and a weak reference is whether the existence of the smart pointer class on a given pointer guarantees that the object will not get deleted. In other words, if you have this smart pointer, are you sure that this will always remain valid (provided, of course, everyone is playing by the same rules)?
Some of the pointer classes above don’t guarantee that. If they don’t guarantee that the object remains valid, their main purpose in life is to tell you whether the object has been deleted already or not. Some classes may provide an additional feature that allows you to promote a weak pointer to a strong one, thus guaranteeing that it won’t get deleted anymore.
The Qt smart pointer classes
1. QPointer
QPointer is a weak pointer class and it shares the pointer value, not the data. It only operates on QObject and QObject-derived classes. This class was added in Qt 4.0 and is the direct upgrade of Qt 3’s QGuardedPtr (and Qt 2’s QGuardedPtr). Like its predecessors, QPointer suffers from broken constness support and shows its age.
Its sole purpose in life is to tell you whether the QObject has been deleted already or not. But, unlike Qt 2 and Qt 3, the QObject of Qt 4 can live in several threads. That means QPointer has one serious flaw: it lets you know whether the object has been deleted, but it makes no guarantee about the next line! For example, the following code could be in trouble:
QPointer<QObject> o = getObject(); // […] if (!o.isNull()) o->setProperty(“objectName”, “Object”);
Even if isNull() returns false, there’s no guarantee that the object won’t get deleted by the next line.
Therefore, QPointer can only be used to access the object if you can guarantee, by external means, that the object won’t get deleted. For example, QWidget and its descendents can only be created, manipulated and deleted in the GUI thread. If your code is running on the GUI thread or has that thread blocked, then QPointer usage is safe.
2. QSharedDataPointer
Now this is a nice little class. It’s actually by far the most important of the smart pointer classes in Qt for its ingeniuty: it provides implicit sharing, with thread-safe copy-on-write. It requires that your class have a member called ref, which offers a function called ref() for increasing the reference count, and another called deref() that decreases that reference count and returns false when it drops to zero. If you derive your class from QSharedData, you get exactly that. Moreover, the size of a QSharedDataPointer object is exactly the size of a pointer. That means you can replace normal pointers with it in your code without breaking Binary Compatibility.
This class is the basis of all Qt value-type, implicit-shared, thread-safe copy-on-write recent classes, like QNetworkCookie and QNetworkProxy. The only reason why it isn’t used in the base classes like QByteArray, QString and QList is that those classes were developed before this class was made. There’s nothing technically stopping the retrofitting of those classes with QSharedDataPointer.
So QSharedDataPointer is a strong smart pointer class, sharing data.
3. QExplicitlySharedDataPointer
This class is exactly like QSharedDataPointer (so it’s a a strong smart pointer class, sharing data), with the only difference that it never implicitly causes the detach. With QSharedDataPointer, any non-const access will cause the data to be copied. With QExplicitlySharedDataPointer, you have to call detach() for that to happen. This allows you to implement explicitly-shared data classes — which Qt doesn’t have anymore, but Qt 3 did in QMemArray (so it’s present in Qt4’s Qt3Support Q3MemArray).
But it also allows you to have finer-grained control of the detaching operation. In fact, if the Qt Tool classes were to be retrofitted with a smart pointer class, they’d be using QExplicitlySharedDataPointer instead. Using this class allows the code to delay the detaching until the very last moment, ensuring that no unnecessary memory access happens.
4. QtPatternist::AutoPtr
This is an internal class used by the QtXmlPatterns module. It’s basically your stock, dumb pointer wrapper. So it implements a strong pointer. It doesn’t share it, though.
The reason this class exists in the first place is that the QtXmlPatterns module makes extensive use of exceptions internally. To survive exceptions being thrown without leaking memory, a pointer wrapper is indicated. QtXmlPatterns also uses reference-counted classes, for which AutoPtr is not indicated — in that case, it uses QExplicitlySharedDataPointer.
5. QSharedPointer
This class was created as a response to QtPatternist::AutoPtr. When I started writing it, I intended for it to be ready for Qt 4.4 and replace the use of the internal class that Frans had written and what I perceived as a misuse of QExplicitlySharedDataPointer. QtXmlPatterns was using QExplicitlySharedDataPointer not for sharing data, but for sharing pointers. The objects it was sharing were not copiable. A later investigation, however, revealed that QtScript, Phonon, and Solid were using it for the same purpose. (In fact, QtScript introduced QExplicitlySharedDataPointer for that purpose in 4.3)
So QSharedPointer was shelved for 4.4, but was reborn in 4.5. It implements a strong smart pointer class, sharing the pointer. It has all the features you may want in a modern pointer class: it is polymorphic, it supports static, const, and dynamic casts, it implements atomic reference-counting and thread-safe semantics, it supports custom deleters. But note that, when I say it implements thread-safe semantics, it’s only for the pointer itself: remember it shares the pointer, not the data.
It comes with a cost, though: to support polymorphism correctly, the size of QSharedPointer is actually twice the size of a normal pointer. This means you cannot maintain binary compatibility while replacing a normal pointer with it in public parts of your API. You can use it internally in your code, though.
6. QWeakPointer
This is the companion class of QSharedPointer. If that implements a strong control of the pointer, QWeakPointer is a weak smart pointer class, sharing the pointer. It works in tandem with QSharedPointer: QWeakPointer can only be created from a QSharedPointer and they let you know when a QSharedPointer has been deleted.
They can be promoted to QSharedPointer, though, in a thread-safe manner. So it allows us to rewrite the code above to be safer:
QWeakPointer<Data> weak(getSharedPointer()); // […] QSharedPointer<Data> ptr = weak; if (!ptr.isNull()) ptr->doSomething();
In this case, the promotion of a QWeakPointer to a QSharedPointer will either succeed or it won’t. But that’s a thread-safe decision: if it does succeed, then the resulting object is guaranteed not to get deleted, while you hold the ptr reference (again, as long as everyone plays by the same rules).
With 4.6, I added a nifty new feature to QWeakPointer: its ability to track QObjects as well, without passing through a QSharedPointer. It can be used to determine whether a QObject-derived object has been deleted already or not. So it implements a weak pointer class sharing the pointer value for QObject-derived classes. Sounds familiar? Yes, that’s the idea: you can replace the old, slow QPointer with a faster, modern alternative. Just be careful that the size of QWeakPointer is not the same size of QPointer.
7. QGuard
This is another internal class. It was added to replace QPointer because that is very slow (it uses a global, mutex-protected QHash, which must be accessed by every QObject destructor). It’s actually what prompted me to write the QWeakPointer QObject-tracking feature. But it’s in a state of flux: we don’t know whether we’re going to keep or even use this class. Anyway, it’s internal, so you really don’t care about it.
8. QScopedPointer
This is the new kid in the block: it implements a non-shared strong pointer wrapper. It was created because of our attempt at handling the Symbian platform’s exceptions in our container classes: we needed a way to free resources without writing try/catch everywhere. A scoped pointer provides a very nice way to do RAII. In fact, QScopedPointer is actually a full replacement for QtXmlPattern’s QtPatternist::AutoPtr. Both implement the same functionality, so the internal one can be dropped.
Some people commented in Harald’s blog that we could’ve used QSharedPointer. Actually, we couldn’t: QSharedPointer has the size of two pointers, but we’re replacing Qt code that has the size of one pointer, so we needed a class that fits into that space. That’s also the reason why QScopedPointer has a custom deleter as a template parameter, as opposed to a parameter to the constructor (like QSharedPointer does): it has no space in those 4 or 8 bytes to store the custom deleter.
What’s more, QSharedPointer implements atomic reference-counting. Never mind the fact that it’s atomic: the reference counting is absolutely unnecessary for the cases that QScopedPointer is trying to solve.
Why not C++0x? Why not TR1? Why not Boost?
Some people in Harald’s blog suggested we should use std::shared_ptr (C++0x) or std::tr1::shared_ptr (TR1). I’m sorry, but those people didn’t see very far: we can’t use C++0x. It’s not even approved and there are only two compilers that implement initial support for it (GCC since 4.3 and MSVC 2010, which is in beta). It’s not even funny to suggest using C++0x for Qt at this point. You can use it for your own code, but we can’t use it in Qt.
TR1 has been implemented by more compilers. Unfortunately, not enough. We have to deal with compilers that haven’t implemented C++98 fully yet — or people who don’t bother to change their compiler settings. For example, the latest version of the Sun Studio compiler on Solaris (Sun Studio 12, with CC 5.10) still comes with the RogueWave implementation of pre-C++98 STL. If you read Sun’s article comparing RW stdlib to stlport4, you’ll see why they still keep the 11-year-old library as default. But the point is that they do, which means we have to deal with it. (Fortunately, other compiler vendors provide newer STL implementations, even though their compilers are sometimes far too picky)
That means the only smart pointer from STL we can use in Qt is std::auto_ptr. And even then there are issues (RW stdlib doesn’t implement member templates).
That leaves Boost. And there are some nice things in Boost: boost::shared_ptr, boost::intrusive_ptr, boost::scoped_ptr, etc. In fact, there are a lot of nice things in Boost. Very often I see things there that I’d like to have in Qt. Of course, that means I can just add said feature to Qt as well. There’s nothing stopping me, aside from, well, my day job
One of the main problems with boost is that it provides an “un-Qt-ish” API — to say the least; I prefer calling it “horrible API”, but that’s a statement of opinion, not fact. Even if Boost’s API is intuitive to some people, it represents a departure from Qt’s API. That means those people using Qt and Boost need to learn Boost’s way of doing things as well, their naming of functions, etc.
At the very least, we’d have to wrap Boost’s API around with a Qt shell. But if we go further, we see that Qt loses control of an important piece of its technology. We then have to deal with whatever problems they have, at their schedules. Also, it adds a dependency to Qt, one we can’t justify because they don’t promise binary compatibility (cursory search over the web; please correct me if I’m wrong). Binary compatibility is the other of the main problems.
So, no, Boost is not an option either.
Conclusion
So Qt has too many smart pointer classes. Or does it?
In fact, Qt has only these pointer classes if you exclude the internal classes and you deprecate QPointer:
| Class | Description |
|---|---|
| QSharedDataPointer / QExplicitlySharedDataPointer | Implements sharing of data (not of pointers), implicitly and explicitly, respectively |
| QSharedPointer | Implements reference-counted strong sharing of pointers |
| QWeakPointer | Implements reference-counted weak sharing of pointers |
| QScopedPointer / QScopedArrayPointer | Implements non-reference-counted strong pointer wrapper (QSharedPointer’s little brother) |
Update 1: QExplicitlySharedDataPointer can be used to implement reference-counted sharing of pointers when the target class includes the reference counter (similar to boost::intrusive_ptr)
Update 2: QScopedPointer is really based on the API of boost::scoped_ptr (but is not a copy); QSharedPointer and QWeakPointer were developed from the scratch.
I wanted to do a certain bit of benchmarking for quite a while - years actually - but triggered by one of those friendly discussions on the ##c++ channel on FreeNode I finally figured I should sit down and actually do it. I was expecting some interesting results, but the not at the scale that we will see below.
If you ask the resident channel bot on ##c++ how to tokenize a std::string you’ll get offered the following (slightly compacted) code snippet:
#include <sstream>
#include <vector>
#include <string>
std::string str("abc:def");
std::istringstream split(str);
std::vector<std ::string> tokens;
for (std::string each; std::getline(split, each, ':'); tokens.push_back(each));
Obviously, that’s the “Without Qt” version: Clean Standard C++, as straight-forward as it can get. The contender “With Qt” is:
#include <QString>
#include <QStringList>
QString str("abc:def");
QStringList tokens = str.split(':');
From the source alone we can collect a few numbers:
| Property | Without Qt | With Qt | Ratio |
| Code to type | 3 lines | 1 line | 3.0 |
| 147 char | 35 chars | 4.2 | |
| Code usable as sub-expression | no | yes | |
| Size of compilation unit [1] | 22215 lines | 7590 lines | 2.9 |
| Compile time [2] | 1.64s | 1.02s | 1.6 |
To compare performance I use a benchmark that I just checked into the Qt source base, under tests/benchmark/qstringlist. It basically consists of running the above mentioned snippets on a string “unit:unit:unit:….” with 10, 100, 1000, and 10000 “unit” chunks and record callgrind’s “instruction loads per iteration” as follows:
| Chunk count | Without Qt | With Qt | Ratio |
| 10 chunks | 18,455 | 9,827 | 1.9 |
| 100 chunks | 134,578 | 71,008 | 1.9 |
| 1000 chunks | 1,244,425 | 641,174 | 1.9 |
| 10000 chunks | 13,161,115 | 7,053,633 | 1.9 |
In this case, bigger numbers mean more time needed to execute. Interesting, isn’t it?
After reading Thiago’s latest posts I got the impression that people like conclusions. The verbose version of a conclusion might be something along the lines of
Using Qt’s functions to split a string you need about a third of the effort to write code, and get a 47% performance boost at runtime.
Or shorter (Qt way): “Code less, create more”.
André
[1] Counted with “g++ -E -DQT_NO_STL -I$QTDIR/include/QtCore -I$QTDIR/include qt.cpp | wc” using g++ Ubuntu 4.3.3-5ubuntu4.
[2] Fastest result of “real” time, out of 20 runs each. “user” times in both scenarios smaller, with similar ratio.
Qt usually takes the boring memory allocation and deallocation from you, either through its implicitly shared containers, or with QObject’s parent child relationship model. But every once in a while, we need to allocate something on the heap, and then the stress starts - where do we delete it, and how do we make sure to not leak the memory?
To fix this problem, QScopedPointer was born. It will delete the object it is pointing to automatically when it goes out of scope:
void foo()
{
QScopedPointer<int> i(new int(42));
…
if (someCondition)
return; // our integer on the heap will either be deleted here…
…
} // … or here
A new exit condition in our function will not make it leak the integer that we allocated.
So how do we access the object that we are pointing to? QScopedPointer implements operator* and operator->, so you it can be accessed just like any other pointer:
QScopedPointer<int> i(new int(42));
*i = 43;
Some operators are missing by design, for example the assignment operator:
QScopedPointer<int> i(new int(42));
i = new int(43); // will not compile
i.reset(new int(43)); // correct
We figured that “reset” looks scary enough to make the reader realize that the old object is deleted, and the QScopedPointer is now pointing to the new object.
Another operator that is missing by design is the operator T*() that would allow accessing the pointer directly. This prevents accidents like:
int *foo()
{
QScopedPointer<int> i(new int(42));
…
return i; // thankfully, this does not compile.
}
Do you see the mistake? The moment we return, our object will be deleted, because the scoped pointer goes out of scope. We would return a dangling pointer, potentially leading to a nasty crash. However, we can tell QScopedPointer that its job is done and that we take ownership of the heap object by calling take(). Our function might look like this:
int *foo()
{
QScopedPointer<int> i(new int(42));
…
if (someError)
return 0; // our integer is deleted here
return i.take(); // from now on, our heap object is on its own.
}
But what about memory allocated with malloc, or the operator new[] for arrays? For those cases, we introduced a second template parameter to QScopedPointer that defines the cleanup:
QScopedPointer<int, QScopedPointerPodDeleter> pod(static_cast<int *>(malloc(sizeof int)));
QScopedPointerPodDeleter (pod stands for “plain old data”) will call free on the object if our QScopedPointer goes out of scope.
For convenience, there is a QScopedArrayPointer that defaults to deleting the object it is pointing to with the delete[] operator. It also features operator[] for convenience, so we can write:
void foo()
{
QScopedArrayPointer<int> i(new int[10]);
i[2] = 42;
…
return; // our integer array is now deleted using delete[]
}
Note that if you have a reference counted object, you can use QExplicitlySharedDataPointer to ensure that an object is deleted correctly when its reference count goes to 0.
QScopedPointer and QExplicitlySharedDataPointer are already used all over the place in the Qt for S60 branch and will soon hit Qt’s master branch. And the best part is that with the introduction of these smart pointers, we could remove lots of boring code and make Qt more readable without adding overhead - since all functions are inlined, the resulting binary using QScopedPointer is identical to the manual new/delete approach.
Happy developing ![]()
As with any Qt API, the Qt Declarative QML API that we expose needs to be carefully thought through to provide a consistent and intuitive developer experience.
One area of inconsistency has been the mixing of nouns and verbs. A declarative language describes what, not how. An example of this is the SetProperties element. This element describes the changes to one or more properties in a particular state. The SetProperties name has a distinctly imperative flavor. It implies an immediate action and fails to capture the nature of the element. Changes to properties in a state are merely overrides that will be restored when the state is left. These factors lead to the proposed renaming of SetProperties to PropertyChanges.
We are currently in the process of reviewing the entire QML element API. We expect the review to be complete by the end of August, though it may take a little longer for the proposed changes to propagate into the code. Unfortunately, if you are a Qt Declarative early adopter you will need to update your code. In order to help with this there is a list of changes and pending changes in the src/declarative/QmlChanges.txt file in the kinetic-declarativeui branch of the Kinetic repo.
BTW, if you’ve been experimenting with Qt Declarative we’d love to hear what you’ve been doing and how you’ve found using QML.
Recently we have seen a push to add context awareness to applications. What do we mean by context awareness? We mean having your applications automatically respond to changes in the current operating environment. This can be as simple as your instant messaging client automatically setting your status to away when it detects that you are no longer actively using your computer. A more complex example of having the entire user interface of your device automatically reorganise itself to support your different work flows.
We are developing a cross platform publish and subscribe (P&S) API that can be used to publish and retrieve contextual information from the system. This allows the separation of the providers of contextual information from the consumers. In our above example a separate process calculates the users’ activity state and publishes the result in the P&S hierarchy. Other processes, such as an IM client, subscribe to receive notifications about changes of this value and modify the application state accordingly.
The API supports the concept of multiple layers, meaning if there are multiple publish and subscribe systems on the platform they will be stacked on top of each other in priority order. Publishers can specify which layer they publish values to, while subscribers always retrieve values from the layer with the highest priority.
We have implementations for two different layers. On Windows platforms we have the Registry layer, which is based on volatile registry keys. It supports publishing and change notifications. On Unix platforms we have the Shared Memory layer, which is an in-house implementation based on local sockets and shared memory. Currently it only works on Unix platforms, however, we are working on making it cross-platform. Even though both of these layers use non-permanent storage there is nothing in the API that prohibits using permanent storage.
Disappointed that we don’t provide a layer implementation for your favourite publish and subscribe system? No problem. Just provide your own. We actually encourage you to do so with our abstract layer class. Though we should warn you that we are not finished yet :). Layer implementations for other platforms are being worked on, in particular support for both the Central Repository and Publish’n'Subscribe systems on S60.
As always the code is now available in our public gitorious repository at http://qt.gitorious.org/qt-mobility/context.
One of the better ideas I had this year was to work in July and take vacation in late summer. The northern European countries are essentially shutting down in July, and for me as a program manager that means that I have time to work on a few things that might actually make it into the next Qt release - ideally without introducing new bugs that somebody else has to fix when things are less quiet. Documentation fits the bill perfectly, and with my vacations coming up it was time to merge and push last night.
For Qt 4.6 we wanted to give the documentation a face-lift (Times New Roman is sooo 1990’s), and we had started with polishing the style-sheet. Choices of color and font-sizes are of course a matter of taste - and a great topic for long mailinglist discussions - but we threw in some improvements to the layout of the class documentation, and I think the new look is really a great improvement, even if you are fan of serifs
And then there was the content and the content structure, in particular the index page. Feedback we got from users and from new Trolls that tried to find their way through the documentation indicated that it was not easy enough to actually find information. After Qt 4.0, where the index was updated to highlight how Qt 4 has changed and improved compared to Qt 3, we just added more and more links to new modules and frameworks. So things started to become cluttered, and with Qt 4.5 we were simply running out of space on the index page. So for July I hoped to get some cleaning up done, and I wanted to come up with an overall structure that is a bit more use-case oriented, and less about “lists of things”.
So as of today, the Qt 4.6 snapshot documentation has a new index and a bit of a new structure. At first glance the index is not that different from the one that worked for 10 years, so I hope Qt veterans don’t get a shock
And the new structure is not a radical departure either, but rather an attempt to better integrate framework and technology documentation with the C++ reference documentation of relevant classes. The integrated search should satisfy those that have used the “list of all something” pages and then searched on the downloaded page. A few things are gone, esp some of the categories in the “grouped classes” page - I hope nobody will miss the lists of “main classes” or “various other useful classes”. And that you have to go to the How-To’s and Best Practices page to find the Porting from Qt 3 to Qt 4 guide is hopefully ok as well.
There is of course still lots of work to do. Some of the top-level topics are not very well documented, we have for instance no good overview about how to do file I/O, and “Development with Qt” should be more about Qt Creator and less about command line tools. So this has just been “phase 1″ and some writing needs to be done, not only about all the cool new stuff that’s coming in Qt 4.6.
On the structural side, examples could be better integrated into the text; and on the web, http://qt.nokia.com/doc shouldn’t be a list of links to historical Qt, Qtopia, Jambi, QSA and Teambuilder documentation and be replaced by the new index page instead. And finally, we want to include feedback functionality in the online documentation pages, and maybe have a side-bar for navigation (although probably not one of those dynamic trees that require lots of scrolling).
Well, I hope lots of you appreciate at least some of the changes, and have ideas and feedback otherwise! I’m looking forward to finding lots of comments here, and contributions through the open repository when I come back from vacation. And if you really want to get your hands dirty, then come back in a few days and check the open positions for Technical Writers in Berlin, Brisbane and Oslo!
Yes, it’s me again. And it’s not yet the blog series I promised you. No, I decided I would expand some more on the whole binary compatibility / ABI thing, by exploring an even more detailed concept.
This is a brain-dump again. So expect no conclusions. This text may range from “cool stuff, everything I ever wanted to know but never had the courage to ask” to “somewhat entertaining” to “you lost me at ‘it’s me again’”. You’ve been warned
But before I go into it, let me address something from my previous blog: the lack of conclusion. The reason the previous blog has no conclusion is because it’s a brain-dump, not an essay. But more than that, it’s because I had written a large chunk of text that needed editing before publishing. And I thought, “I can do that before I go to bed” — two hours later, I hadn’t finished, had no conclusion and was way past bedtime. So I clicked “Publish”.
If you want a conclusion, you’ve got a conclusion: binary compatibility is hard. We do it for you. You don’t have to learn all of this. Unless you’re writing a library too…
(more…)
As the title suggest, winter is drawing near in the northern hemisphere and we have decided to preempt winter by freezing. Freezing our branch that is. After being under heavy development, Qt master will be branched to Qt 4.6 in less than a month from now - and we’ll start hardening our APIs in preparation of a final release near the end of 2009.
So far, Qt has received and accepted over 75 contributions from fellow hackers in the Qt community to master. All of these changes will become part of the finished Qt 4.6 product and be distributed to a staggering amount of mobile handsets. You should all be very proud!
So, around this hairpin is where we all upshift and slam the gear into testing and bug-hunting overdrive. If you would like Qt 4.6 to be a kick-ass release, and you have some time and spirit to spare - please try out the new APIs, rip them to shreds, pluck out those bugs and submit your fixes (along with auto tests please) to qt.gitorious.com. It might be getting colder, but Qt’s smokin’ hot!
For the past few months I have been quite quiet in the blogosphere. I have been collecting ideas for a two- or three-parter blog that I am still going to write on how Qt rules, but while that doesn’t come, I decided to dump some thoughts on binary compatibility.
Recently I updated the KDE Techbase article on Binary compatibility with C++ (btw, that’s the 3rd page from the top in the Google search for “binary compatibility”). I tried to explain a bit better what the dos and don’ts (mostly the don’ts) are. After I wrote the part about overriding a virtual from a non-primary base, someone on IRC asked me to write some examples.
In order to write those examples, I had to brush up a bit on my skills of name mangling, virtual table layout, etc. and I had even to try and learn Microsoft Visual Studio ABI. It took me a while, but I did find an article with some information on that (link is in the Techbase page’s introduction). I’m also glad I took the time to brush up on my skills, since I found another example of things not to do (the “virtual override with covariant return of different top address” case).
History
Let’s start with a bit of history: whereas on the Unix has always been closely tied to the C language, the DOS market initially had no such relationship. Sure, applications were developed in C even in the early 80s, but the point is that DOS didn’t provide a “C library”. No, to access DOS services, you’d move a some values into registers and cause an interrupt (the Int 21). Implementors of C compilers had to provide their own C library.
Also remember that these were the days before DLLs and shared libraries, so there was no binary compatibility to maintain. The conclusion is that each compiler decided for itself how to implement the calling sequence and the ABI: that is, what are the responsibilities of the caller and the callee, like which processor registers (if any) are used for parameter passing, which ones may be used for scratch values, which ones must be preserves, who cleans up the stack, the size of certain types, the alignment, padding, etc.
And, as you can expect, each compiler implementation did that differently.
On the Unix world, things were a bit more standardised, since a C library had existed for a long while and usually there is a reference compiler for the operating system. In order to use that C library — and you really want to — any other compilers must implement the same ABI.
But even then things become exciting when we talk about C++. If on one hand the C calling convention is pretty well standardised on Unix systems, it’s not so for C++. C is a very low-level language, to the point that you can almost see the assembly code behind C if you stare long enough at the screen (in my experience, however, when that happens, you’re just seeing things and should instead go home and have some rest). C++ introduces several concepts on top of C, like overloads, virtual calls, multiple inheritance, virtual inheritance, polymorphism, covariant returns, templates, references, etc. That means more things for the compilers to differ on.
Now, an interesting thing happened about the year 2000: the Itanium processor. Not because of the processor itself, but for what documents came out of it. It wasn’t enough to know the instruction set for the architecture (see the Software Developer’s Manual), developers needed more and Intel obliged (apparently they had a lot of time on their hands):
- Software Conventions & Runtime Architecture Guide
- Processor-specific Application Binary Interface
- C++ ABI
GCC clearly adopted this ABI on Itanium, but since the code was there and it was superior to what GCC had, GCC applied it to other platforms as well. So it’s interesting today to see this ABI used in systems that have nothing to do with the Itanium nor are Unix, like Symbian running on ARM devices.
What the ABI needs
It’s quite clear that the ABI needs to accommodate any valid C++ program. That is, it should support all features of the language. Starting with the simplest innovation that C++ has on top of C, we can see how things become interesting.
In C, a function is uniquely identified by its name. There can be no other function with the same name with global scope. C++, on the other hand, has overloads: functions with the same name differing from each other only by the argument types they are called with. By that, we come to the conclusion that any and all ABI must encode the different functions with different names. It has to encode all the differences that are permissible by the C language, but it may also choose to encode more information which helps in outputting error messages.
Then there are virtual calls. When making a virtual call with a given C++ class, the compiler must somehow generate code that can call any reimplemented virtual, without knowing a priori what those reimplementations are. The only way it can do that is if, somewhere in the class, there’s information about where the virtual call is supposed to go. Most (all?) compilers simply add a pointer somewhere in the object, pointing to the “virtual table”: that is, a list of function pointers for each virtual call. Each C++ class with virtual function has a virtual table, listing the virtuals of that class (the ones it inherited and the ones it overrode).
But the virtual tables usually contain more information than just function pointers, like the typeinfo of a C++ class and usually the offsets of virtual bases into the object. The case of a virtual base is illustrated by the typical case of diamond-shaped multiple inheritance: a base “Base”, two classes “A” and “B” virtually-deriving from “Base” and a final class “X” deriving from “A” and “B”. When taken independently, A and B are similar to each other and the “Base” contents are allocated somewhere inside the “A” structure. However, inside “X”, things change, since it must allocate one copy of “A”, one copy of “B” and only one copy of “Base”.
The compiler must therefore encode somewhere where it placed the VBase sub-object. One way is to simply have a pointer, as a member of both “A” and “B”. Another is to put the offset from the beginning of “A” and “B” in the virtual table — you save a couple of bytes in each object.
If you combine those three concepts (naming of all overloads possible, virtual calls and virtual inheritance), you cover 99% of the needs of the ABI for a typical C++ program.
Today
For our purposes with Qt, we can classify the C++ ABIs in three categories: systems using the Itanium C++ ABI, the Microsoft C++ ABI and “other”. That last category is a group of all other compilers, like the Sun Studio compiler for Solaris, IBM’s Visual Age compiler for AIX and HP’s aCC compiler for HP-UX on PA-RISC. (note that HP-UXi runs on the Itanium so aCC uses the Itanium C++ ABI on that platform) We don’t actively test Qt’s binary compaitibility for issues specific to those three compilers for the simple reason that we have no clue what those specific issues are. I don’t know of any documents describing the C++ ABI they implement — and I really don’t want to study them, given the value we’d get. After all, most users of those platforms usually are compiling Qt from source anyway.
The Itanium C++ ABI is a modern concept, created after C++ had been standardised and its features well-known. It was created by people who were trying to solve a problem: how to make all of C++ possible, without overdoing it? They came up with an ABI that is quite elegant: classes with virtuals get added as a first member a hidden pointer to the virtual table of the class, which itself gets emitted along the first non-inline virtual member function. The virtual table contains, at positive offsets, the function pointers of the virtual member functions, while at negative offsets it has the typeinfo and the offsets required to implement multiple inheritance.
Even the name mangling is quite readable, for simple types. The ground rule is that it should be something that C shouldn’t use, to avoid collision: they chose the “_Z” prefix, since underscore + capital is reserved to the compiler. For example, take _ZN7QString7replaceEiiPK5QChari. If we break it down, we end up with:
_Z N 7QString 7replace E i i PK5QChar i
We read that as:
- _Z: C++ symbol prefix
- N…E: composed name:
- 7QString: name of length 7 “QString”
- 7replace: name of length 7 “replace”
That means “QString::replace”
- i: int
- P: pointer
- K5QChar: const name of length 5 “QChar” (i.e., const QChar)
Put everything together and we have “QString::replace(int, int, const QChar *, int)”
On the other end of the spectrum, the Microsoft compilers chose to encode the function names with every single detail possible, like for example whether a member function is public, protected or private. Moreover, for some obscure reason that probably doesn’t make sense anymore, Microsoft mangling is also case-insensitive. That is, if someone flipped a switch tomorrow and — gasp! — made C++ case-insensitive, the mangling scheme that they use would work. (GCC of course would be completely lost in a case-insensitive C++ world)
That’s quite clearly a legacy from old DOS days. That also shows when you notice that the mangling scheme encodes the pointer size (i.e., near or far), as well as whether the function call — or, more to the point, the return — is near or far. Those things are definitely not used today, but the ABI can still encode that.
The same function above gets encoded in MSVC as:
?replace@QString@@QAEAAV0@HHPBVQChar@@H@Z
Which we decode as:
- ?: C++ symbol prefix
- replace: rightmost (innermost) name
- @: separator
- QString: enclosing class
- @@: terminates the function name.
The names are in the reverse order, so we have “QString::replace” - Q: public near (i.e., not virtual and not static)
- A: no cv-qualifiers for the function (i.e, not const or volatile)
- E: __thiscall (i.e., call of member functions)
- AA: the first “A” stands for reference (possibly near reference), the second “A” indicates it’s an unmodified reference (i.e., not “const X &”)
- V…@: class and delimiter
- 0: indicates the first class name seen before, i.e., QString
- H: int
- H: int
- P: normal pointer (i.e., not const pointer)
- B: const type — PB together makes “const X *”, whereas “X * const” would be QA
- V..@: class and delimiter
- VQChar@: class QChar, plus delimiter
- H: int
- @: end of argument list
- Z: function, or code/text storage class
That reads: “public: class QString & near __thiscall QString::append(int, int, const class QChar *, int)”. Things to note about this:
- The use of ? as prefix, instead of something you can normally type in C
- The same letter can mean different things depending on the position
- Types are assigned alphabetically from a list (signed char is C, char is D, unsigned char is E, short is F, unsigned short is G, int is H, unsigned int is I, etc.) instead of trying to resemble the type.
- “class” is encoded explicitly (V), whereas struct is “U”, union is “T” and enum is “W4″ (at least, int-backed enums)
- encoding of calling sequence (__thiscall) and displacement (near)
On one hand, the Microsoft mangling scheme makes it possible to produce much more detailed error messages, and makes a difference in type or calling sequence not resolve to the same symbol. On the other hand, it also encodes details that make no difference at all to the call, like the difference between “class” and “struct”, or whether the member function is private, protected or public.
State machine compilers are not a new concept, they’ve been around for a very long time, and some of them are pretty good. So throwing another one to the world might seem like trying to reinvent the wheel. But this new state-machine compiler is different, because the Qt State Machine framework is different, because Qt is different: QStateMachine and signals/slots allow the generated code to live separately from the rest of the application, and thus be a natural part of the development worklfow ~ some other statechart compilers, though not all of them, generate stubs that you have to manually edit, and then generating again would override your changes…
Since the Qt State Machine framework was built with SCXML in mind, this wasn’t a difficult job - it was mainly figuring out how some concepts in SCXML would work with Qt. Some of them translate pretty nicely - SCXML events translate to Qt signals, SCXML data elements translate to Qt properties and the rest translates to Qt states/transitions.
I was actually thinking of hacking on this for a while, as some people requested it, but only got the time for it when I needed to write some project using Qt OAUTH (nice library, by the way), and having to maintain a large QStateMachine instantiation code for incorporating it into my application business logic was a great opportunity.
How it works
The Qt statechart compiler works very similarly to uic from Qt Designer. It takes an SCXML file, and using the XSLT feature in xmlpatterns, translates it into a header file that can be used in your application. The generated header file is a simple subclass of QStateMachine, with signals to represent SCXML events, properties to represent SCXML data elements, and a setupStateMachine() function to initialize. More can be found at the Statechart compiler documentation.
Since xmlpatterns is used for the generation template, the code for scc is pretty maintainable. Though the tools relies on the xmlpatterns library, the generated code doesn’t (it only relies on QtCore with the state machine framework).
Adding SCXML statecharts to your project, after installing scc, is very easy, and goes something like:
# myproject.pro
CONFIG += scc
STATECHARTS += foobar.scxml
and then
//myfile.cpp
#include "sc_foobar.h"
MyFunction()
{
...
SMClass_foobar stateMachine;
SMClass_foobar.setupStateMachine();
SMClass_foobar.start();
...
}
MVC applications
The mvclogin example, provided with scc, is an example of the advantages of decoupling business logic from models and engines. In this example the same login flow can be used for different backends, in this case a backend that log ins to gmail, and a “dummy” fallback that is used when SSL is not supported.
Where is it
It’s at http://qt.gitorious.org/qt-labs/scxml, the scc directory. Some the documentation is also available. Please check the examples, and reply for any question
A few days ago I was curious how fast Qt for S60 (Tower release) can blit the pixels to the screen. I decided to port the simple ray caster I wrote 14 years ago to Qt for S60 and to test-drive it on a Nokia E71. The result is something that our video maestro, Alessandro, assembled for us nicely (he showed it on a Nokia Navigator), see below or directly on YouTube:
There is a gazillion ray casting implementations (and tutorials) out there, for a number of different platforms/compilers/CPU (even for the web, using HTML canvas and JavaScript). This example will add one more to the crowd. Find the code in Graphics Dojo repository and use Qt 4.3 or newer to enjoy it. The demo weighs slightly less than 300 lines of code (too short for your taste?). It does however work only with keypad navigation, the users of Nokia N97 and 5800 need to implement some kind of mouse/finger navigation (a good exercise!). Of course, try it first on the desktop, it runs just fine:
True to Wolfenstein 3-D that made ray casting popular, my example also shows a different shading between the walls facing different direction. As you may witness from the shipped textures.png (which holds all the textures, adopted from a very nice Wolfenstein 3-D alternative texture library), this is achieved by having two version of the same wall texture, the normal one and the darker one. In addition to that, each wall texture source pixmap is prerotated by 90 degrees. This is again the old trick I used for the first time in PictureFlow (the same effect that powers Qt Fluid Launcher). The basic premise: improve the cache locality, this is because during texture mapping we scan the pixels within the same horizontal row (neighboring integers), not the vertical column (which means jumping far more than the size of the cache lines).
The code can be further optimized (of course!). In fact, there is no so much Qt-specific part in it (afterall, it’s ported from my old Mode X DOS-based test program). For a starter, I am sure a seasoned S60 developer know a bit or two about direct screen access (maybe via CDirectScreenBitmap aka Anti-Tearing API?), this surely improves the blitting although I don’t know how less portable the code would be. On a different side, you might see that I improved the inner loop by using simple fixed-point arithmetic. The outer loop is still based on floating-point, feel free to cast some fixed-point magic there, at the potential cost of readability. Sine and cosine can be stored as look-up tables, especially if you turn the viewing angle also to fixed-point. While you are on that, notice also how I got away with finding the sine and cosine for each ray (which you can nicely solve, once the fast look-up table is at your disposal), similar to Ken’s Labyrinth (afterall great cheaters think alike), at the price of a less perfect rendering. The mechanics behind ray casting is fairly easy (there are tons of tutorials in Internet), however if your math skill is rusty and parts of this example are difficult to decipher, it is time to grab a sheet of blank paper and to start scriblling, drawing, and playing with geometry. Hardware accelerated graphics, even on mobile platforms (via OpenGL ES and OpenVG), already starts to become the norm these days. This leaves classic stuff like ray casting to serve the educational purpose only.
If you are interested in doing more 3-D with Qt, don’t miss the more advanced WolfenQt demo. While this simple ray casting example is pure pixel-manipulation, WolfenQt relies on perspective transformation with Graphics View. It does allow interesting features of Graphics View, like embedding a web browser, a media player, and other fun widgets, as well as exploiting the benefits of OpenGL.
And there are still many steps if you want to base a game on this example (note: there is already S60 Wolfenstein 3-D, if you just want to have a look). Sprites support is still missing, sound also does not exist. On the rendering front, you might want to add some doors (hence the opening and closing logic) for a better game play. All of them is still doable for a weekend project, so have fun if you want to bring Captain Blazkowicz to life!
Working with clever people is great, but sometimes it comes back to bite you… This post is going to describe a great new feature in Qt and why we’re not going to implement it.
Over the last few months I’ve been toying with the idea of starting a new research project to develop a binary vector graphics format, qvg. Why? Well, svg’s great and all, but it does too much: You can embed animations, text, has a DOM tree, all sorts of things. It’s also a plain text format (xml) so slow to initially read & parse. QVG would be our own binary file format to describe vector graphics with paint engine specific sections. You could take an SVG (which only uses a subset of the standard) and “compile” it to a qvg. During the complication, off-line processing can be done. E.g. Obscured regions of geometry could be clipped, vector paths could be triangulated, gradient textures could be generated, etc. etc. There’s loads of optimisations we could do to “compile” svg into a binary format.
So, why would we want a compiled svg? Because it’s faster to load and render than svg! So the question actually becomes, why do we want svg? Theming, that’s why! Qt provides applications with re-usable UI controls, things like buttons, scrollbars, tick boxes, etc. C++ programmers can write applications using those controls and graphic designers can create themes for them. The idea would be for those graphic designers to draw their super sexy looking scroll bar, export it as SVG and then compile it to QVG, where it would be rendered very quickly by one of Qt’s paint engines.
Having patted myself on the back for coming up with a great idea, I started talking to people about it. Most people in the graphics team seemed to like it and are already developing something a little similar. I then figured it would be a good idea to talk it over with our theming expert, Jens. “What’s wrong with pixmaps?” was essentially his first reaction. Well, good question. The problem with pixmaps is that they’re not resolution independent. If I want a theme to work equally well on both my 96 dpi TV and on my 320 dpi smart phone, pixmaps aren’t going to work. The scrollbar will be too small on the smart phone but take up half of the TV (unless you’ve got a fancy HD one). The only option would be to scale the pixmap, but that generally looks horrible.
We talked about it and compared pixmaps to vector graphics and the advantages of each. I honestly thought that qvg would solve all the problems with svg (I.e. it’s speed). But then Jens delivered the mortal blow to my argument: If UI elements are themed as vector graphics, the graphic designer can influence rendering speed. Think about it: If the scroll bar button is a single square and triangle, it will render very very quickly. However, if it’s a vector path with a pen and conical gradient, it’s going to be much slower to render. We’d get into the silly situation where people change the theme to get better rendering performance.
So, the answer is to use the best of both worlds: Supply themes as resolution independent SVGs, but cache them as a pixmap (in the correct resolution) and just render that. You get the flexibility of vector graphics but the speed of pixmaps. Of course this isn’t a new idea either – Both GNOME and KDE already do this.
Like I promised few days ago, here is the demo that shows tile-based OpenStreetMap rendering on Qt/S60. If you never heard of OpenStreetMap before, it is “a collaborative project to create a free editable map of the world” (from its Wikipedia entry). You can try it at www.openstreetmap.org. It might not be as complete as other maps solutions, but surprisingly, OpenStreetMap coverage for many world big cities are detailed enough for most users.
The approach used in this example is by showing prerendered tiles stored as pixmaps, often known as Slippy Map. Of course, we also need to honor the tile usage policy. Much to my surprise, it takes only around 200 lines of code to achieve basic rendering, including tile downloads (via QNetworkAccessManager) and simple disk caching (thanks to QNetworkDiskCache). Add another 100 lines to support panning via mouse dragging and arrow keys. To have some more fun, I also brought the magnifying glass and night mode features and the total code is still less than 600 lines (which was good, as it did not cost me any sleepless night). On top of that, it also runs on Qt/S60 Tower release. Isn’t Qt wonderful?
While the screenshot above serves as a solid proof, these days nothing is more fascinating than watching a videocast from our very own Mr. Portale. See below or watch directly (on YouTube):
This simple maps exampe, dubbed lightmaps (remember Quake source code, anyone?) can be found in the Graphics Dojo repository. You need Qt 4.5, either the desktop or mobile version. So far it has been tested on touch devices like Nokia N97 and Nokia 5800, but it does work also on other phones like Nokia E71.
For the sake of keeping the example simple, I did put only minimal error handling and a very simple tile cache system. This means, the first time you want to zoom with the magnifying glass (tap and hold for a while with touch device, press middle button in the D-pad for other devices), there is a potential delay until the magnified portion is rendered. Since the tile pixmaps are cached, the next attempt will likely result in a faster painting.
What about vectorial rendering of the maps? While that would be a perfect solution (even allows semi 3-D with nice transformation like in common navigation system), unfortunately I believe the amount of code will exceed the suitable size for a typical example program. Of course, this feature along with other possible improvements (custom zoom level, search function, tiles prepackaging, more optimal tile caching, and soon) are always left as exercises for the brave readers.
I hope you are inspired to map-enable your cool apps. No more excuse! ![]()
In the past few weeks the development of the Qt port of WebKit has seen a lot of progress. I would like to highlight a few items:
- Kent, Olivier, Jedrzej, Benjamin, Tor Arne and Ariya have been hacking away on the new backend for QtScript to use JavaScriptCore. We’re down to only a handful of issues (~10, so both hands are needed).
- Since Akademy the entire team has been cleaning up the layout tests and the DumpRenderTree tool, to get the test infrastructure back in shape.
- Gabor, Rapcsanyi and Zoltan from the University of Szeged have been working hard on bringing the build bot for the Qt WebKit port back online. Since last weekend it’s finally back online in green (yay) at the bot farm at http://build.webkit.org/waterfall!
- In a multi-platform marathon Tor Arne has been working on cleaning up the WebCore plugins code to eliminate duplicated code between the ports and to unify the behaviour in things like startup sequence and error handling.
- While we’re at plugins, Jakob from the Arora team has started developing a settings API for plugins, to enable/disable them or to specify preferences.
- Laszlo and Norbert continue to submit patch after patch for the S60 port, it’s progressing nicely!
In between we had a little team barbeque here in Oslo, celebrating our recent hackeries with food and games:



Having a picture in your text document is one of the simplest things you should expect a word processor to do. Having good looking images in your presentations, same thing. You should expect that to just work.
The fun begins when you take a look at that “just works” means. For instance, I can have a 1000 page document with one or more photos on each page. Those photos easilly take some 10Mb in memory if they are meant for printing. So obviously the simple solution of just having QImage objects is out.
Another problem that we see is when a user inserts a photo from his camera into the KPresenter presentation. Then scales it down to only be half the screen width. This means that we’ll effectively be showing the picture at some 15% of its original size. If we want to keep the viewing and moving of things around very nice and snappy, we can’t just scale the image on every repaint, that would be way to slow.
After a couple of weeks of coding we have a quite nice solution in KOffice. I added a KoImageData class which stores the actual image data and is able to dynamically create a scaled down version of that. The actual data we store is in many cases stored in a temporary file on the filesystem and transparently loaded when needed.
This has the directly noticeable effect that if you load a document with loads of images it will be much faster done, and with less memory used. The KOffice applications will no longer parse the image data on load. That will happen later.
My personal usecase is this; I would love to make a collage of loads of pictures of my friends and holidays. And I’d like to do that digitally. Now, when I create a new document in Krita or the Gimp that is full printing resolution of an A4. Then start loading the pictures as layers, it very quickly makes them crash or just get unusably slow.
My ideal solution is that I just start a KWord document where I insert a lot of these images into and I can scale, rotate and move them around very quickly. With hardly any suggestion that I’m manipulating huge amounts of data.
At printing time I’m printing actually to high-resolution images and the resulting PDF can be shown to the printer whom can print it at wanted resolution.
Expect this work work just fine in KOffice2.1
Likely I won’t make my second favorite feature for 2.1, this is to allow me to select an image and monitor it. So if I have an image in my KWord document that is using a file in my homedir called “photo.jpg” I can start my favorite application and change the image to be, for example, more saturated. On saving the image KWord would automatically show the updated image. Should be easy enough to add ![]()
Now it is official, last week my xml schema branch on gitorious has been merged into qt master (the upcoming Qt 4.6) by the brave Trolls Peter and Thiago.
Since February, when the internship ended and I had to go back to university, most of the changes to the branch were code cleanups, API improvements and additional documentation. So no new features so far, however there is a long TODO list on my desk that will get some attention as soon as time permits
So what is all this XML Schema thingy about? Why shall I use it my applications? As you can see in the CWE/SANS TOP 25 Most Dangerous Programming Errors the first place in category Insecure Interaction Between Components is held by Improper Input Validation. Hands on, who of us checks all input data that is entered by the user in our application? While it is kind of easy to check input, typed into a QLineEdit, QTextEdit or QSpinBox, with a QValidator or by some other form of manually written source code, validating input data that come from files or via network is more complicated. These kind of data have a special format (e.g. a CSV file, an ODF document or an image) that has to be parsed and interpreted to make sure that no bogus data are pushed into the application. However for accessing these common formats there exist libraries that do the checks and validation for us and return an error in case of a violation.
During the last years the XML format has become more and more popular and the possibility to define own XML dialects (e.g. DocBook, MathML, QtUI) led to a broad adoption in the software world. If you want to parse a XML document you normally make use of a XML parser like QXmlStreamReader or QDomDocument, which do all the low-level parsing for you and throw errors if the input document is not well-formed as defined in the XML standard. Well-formed basically means that tag names, attribute names and attribute values only contain allowed characters and that tags are nested correctly in each other. However well-formedness doesn’t say anything about what tags are allowed (e.g. <html>, <resource> etc.) inside this document and which tag can contain other tags or attributes. So the classic XML parsers can’t help you to make sure that your input data are correct, you will find yourself writing code like the following
if ( element.tagName() != "resource" )
return error;
when parsing XML documents in your application.
Since this problem is as old as XML exists, there has been made many attempts to provide an easy way of validating XML documents according specific constraints. The document type definition (DTD) is an integral part of the XML standard, however its capability to define the structure of a XML document is quite limited. Other attempts are XML Schema and Relax NG, where the former is the official validation language of the W3C and the later the result of a counter-movement to XML Schema, which is seen as too complex and difficult to learn by many day-to-day XML users.
Independent on their complexity, all XML validation languages have one thing in common, they describe in an abstract way, how a valid XML document should look like. In other words they can define a grammar for a language. This grammar (a DTD or XML Schema file) is then used to validate a XML instance document and decide whether it is correct or not.
This functionality can be used with the new QXmlSchema and QXmlSchemaValidator classes in Qt 4.6 now. So instead of checking the single tag names manually, just create a XML Schema definition of the format you want to parse, pass this definition to the QXmlSchema object and then validate it against your input data via QXmlSchemaValidator. The validator will tell you then whether the input data can be processed further as they are valid, or if processing should be stopped because they are bogus. That will take away the burden of error/validity checking from you and does reduce the code size as well… however you still have to iterate over the single XML elements and parse the data into a C++ object representation to work further on the data. Can’t we simplify that somehow?
To cite a famous quote: “Yes, we can!”
The grammar of the XML document that is used for validation contains all information we need to generate C++ code with the following properties:
- C++ classes for every type defined in the XML schema
- C++ code for parsing (and validating) a XML document and fill the C++ objects
- C++ code for writing out C++ objects to XML documents
So instead of defining your C++ data objects first and try to fill them with XML data in a second step, you could write a XML Schema definition first, which describes your XML input data, and then you let generate the matching C++ data objects, the parsing and synthesizing code automatically. That sounds really great (how much time have you wasted by parsing XML documents into C++ structures manually?) and indeed it is!
‘So where is the code’ you might ask… Unfortunately there is no code written yet that could do that, however with having the XML Schema definition as internal object representation the first major step is already done. Creating C++ code from it is just a question of studiousness and time. Let’s see what the future will bring!
Today, I’m happy to announce three new babies in the ever growing Qt family. The first one is Qt on VxWorks, a port of Qt to the VxWorks real time operating system (RTOS). Being the youngest, it requires some help to run - an X11 server must be installed to get graphical output. Also, due to the configurability of VxWorks, it’s pretty likely that it won’t even run out of the box, so be prepared for some extra nursing.
The second baby is a bit older - Qt on QNX can run on its own, even without an X11 server, using the Qt Window System (QWS) that up until now has only been available on GNU/Linux. The port contains an experimental io-graphics based QWS screen driver as well as experimental devi-hid based QWS keyboard and mouse drivers. Note that coexistence with QNX’s Photon environment is not possible, since QWS wants exclusive access to the screen. Here’s an extremely amateur-ish video showing Qt on QNX running on a 266 MHz PowerPC chip as well as on an Intel Atom:
Both babies are community supported (Tier3), so be prepared for messy moments. More technical details can be found in our platform notes, the official announcement can be found here.
And the third baby, you ask? She’s about to happen, we wish Robert and his wife all the best, and a special thanks to Robert who merged the ports into Qt’s master branch while waiting in the delivery ward.
Google Maps, or any similar application, becomes very important in our digital life. Not surprisingly, it also becomes easier to integrate some map functionalities into our application. This is something that attracts the developer side of each and every one of us. The brand-new, work-in-progress Google Maps API v3, via the use of QtWebKit module, is the instant solution for embedding maps in your own beloved Qt-based application.
Since doing so would be almost trivial (you can even do it within Designer or Creator), I decided to raise the bar a bit. What if, when your press the mouse button and hold it for a while, a magnifying glass (remember Sherlock Holmes?) shows up and you can move it around? Thanks to Qt, surprisingly (again) implementing such a demo is easy, the result is less than 300 lines of code, and thus I am glad to share you how it looks like, in a static screenshot and a moving picture (watch in YouTube):
The code is checked in already to the Graphics Dojo repository, it is securely stashed under the mapzoom subdirectory. If you do not bother to digest the code, here is the trick. I keep a larger version of the map in a separate QWebPage. When the user press-and-hold the mouse button for a while, this hidden page is used to render the maps under the magnifying glass, clipped to the shape of a circle. Simple, isn’t it? Of course, you can still move the maps by dragging the mouse, just like in the normal use of Google Maps.
Now I am sure some of you are ready to throw the questions. What about Qt/S60 version? What about OpenStreetMap? Relax and be patient a bit. The combination of both will surely make a cameo, some time in the near future, in the form of another example (a successor to this one). Meanwhile, enjoy your maps, Sherlock!
We all want to get access to new features, but we also want to get stable things. These two goals seems contradictory and in a sense they are. If you want to live in the edge you have to accept some “early adopter problems” but if you want to have only rock solid features, you need to let them mature and “gain experience”. With our new open development process people can get access to all of our newly developed features while they are still in the making, therefore gaining valuable insight on what’s coming in the next release. The problem appears when people uses that “bleeding edge” code to start developing things, how can we provide “stable bleeding edge” features?
The solution is more or less obvious, have a master branch where everything is committed and a master-stable branch that is slightly behind master but it is guaranteed to compile. It seems simple and problem free, however there is still one pending question. How “slightly behind” is master-stable from master? Up to last week, master-stable was manually updated, which led to fewer updates and not so “bleeding edge” code. From this week on we have implemented automatic update of master-stable, so now master-stable will be updated as soon as everything is ready, no human intervention required.
The system goes like this:
- Whenever there is a change committed to master, that change triggers a build in all of our tier 1 platforms.
- If the build is successful, then a build on all of our tier 2 platforms is triggered.
- And if that build is successful, our CI system will push changes from master to master-stable.
Voila, master-stable updates itself! So from now on you have no excuses not to use master-stable to check out what’s happening in Qt while enjoying a “stable bleeding edge” branch.
The avid reader would have noticed that it is the first time my name appears on this blog. I joined Trolltech on September 2007 and I’ve been the QA manager for Qt for the past two minor releases (4.4 and 4.5) and currently I’m busy handling Qt 4.6







































