Monthly Archives: February 2011

Quick first steps – qtbubblelevel 2D

Recently updated QML projects showcase encouraged me to start learning more about QML. Two examples gathered my attention especially. The first of them is the Bubble Level application which uses the accelerometer reading to provide a leveling tool, and another a really cool game called Quick Hit.

As the latter has rather complicated structure with animations, multiple windows and plugins, I’ve left it for ‘dinner’ and started looking into the leveling app. I first looked into the “BubbleLevel.qml” file which was indicated as the UI starting point. The structure of the UI is very simple and I’ve found myself quickly around the controls’ definitions. Most of them have the typical height/width/anchors/margins attributes for quick UI creation. Additional features include function call on the event like:

onClicked: bubbleLevel.minimizeApplication()

where “minimizeApplication()” is the public SLOT in the app definition, so binding the QML UI with CPP functionality is extremely easy.

One of the puzzling elements was the definition of some UI elements. Some of them like “Image”, “MouseArea” or “Flipable” are already defined in the framework, others are defined in a separate file provided by the application like “Tube” and “Button”. It seems that the name of the control is taken directly from the qml file name so the Tube is defined in the Tube.xml file and Button in the Button.xml file respectively.

While there’s a lot more to learn about the UI in this app, I thought to extend it’s functionality to ^2, by adding the second dimension to the bubble movement. So in the first place I created/modified the graphic resources to support the second dimension. These include:

  • air bubble (is more or less round now)
  • tube (now became something like a football pitch)
  • vertical shadow
  • vertical scale

Notice that new files need to be added to the .qrc resource file.

To support the new dimension I had to look into the C++ code where the accelerometers readings are fetched. The function provides already 3 readings, so I didn’t have to modify it, just add the “y” dimension to the rotationChanged signal (now watch out, in case of Maemo the “y” axis has to be inverted to work in the same manner as the “x” axis; for Symbian it’s yet to be checked, as I couldn’t install the Qt 4.7.1 on my test phone yet). This started a chain of inconsistencies, as the SLOT connected to this signal needs to be changed. These connections are defined in the main.cpp file so tracking them down didn’t cause much trouble. There were also two functions from the settings.h which needed another argument, and these are saveCorrectionAngle and correctionAngle.

When the application was already compiling I launched it and of course didn’t work yet, because the necessary QML bindings were not defined for the second dimension. Moreover the bubble stopped moving as the functions were not compatible anymore. Luckily running the application in the Qt Simulator or from the Shell Console on Nokia N900 you can see the debugging messages. In this case they helped to localize the mistaken bindings.

// Signaled when correction angle is saved
signal saveCorrectionAngle(variant angleX, variant angleY)

// These functions are used as Qt slots
function handleRotation(degX, degY) {
horTube.rawangleX = degX
horTube.rawangleY = degY
}

function setCorrectionAngle(degX, degY) {
horTube.angleconstantX = degX
horTube.angleconstantY = degY
}

Now a bit more (but still not too much) work was needed to modify the Tube behavior. When the new readings are set to the tube, only the item’s property rawangleX/Y change and the position is updated automatically. With the new dimension, we had to add the new function to calculate the variation of the bubble from the center of the tube. The original behavior was to reach the limit of the tube every 20 degrees horizontally (this was defined in a bit obscure way; the order of “/” and “*” operations was hard to guess), so we I did the same for the vertical axis.

The final refinements included changing buttons anchors

top: parent.top
 //verticalCenter: horTube.verticalCenter

and changing the tube’s height to the actual proportions occupied on the background image

width: parent.width * 0.775; height: parent.height * 275/480

There was a problem running the example on Symbian phone due to unavailability of the qt libraries (also qt_installer.sis from the SDK failed for some security reason) but let’s hope this get fixed in the nearby future.

Here is the modified source as well as the installation packages:
QtBubbleLevel.sis (Symbian^1)

QtBubbleLevel_installer.sis (Symbian^1 with smart installer)

qtbubblelevel_1.3.0_armel.deb (Maemo)

qtbubblelevel-1.3.0-1.i586.rpm (MeeGo)

qtbubblelevel_2D-src.zip (source code)
As you can see, there’s also an extra package for MeeGo device. It’s neither compliant with the Intel AppUp specification nor fully functional (the bubble doesn’t move but it’s hard to say why at this stage). But the package can be installed properly, the icon is available on the desktop, and all the QML is rendered as expected.

So these were the only changes needed to have the working 2D example. I must say that’s much cooler to show to a friend in a pub and to test his/hers ability to level properly after a pint 😉
But also imagine you can now apply this example to the game for steering.