Symsource Blog

We develop your apps on: iPhone, Symbian / S60, BlackBerry, Java J2ME, Windows Mobile, Mobile Web and Server
Apr 06
2010

Using Qt on Symbian Part 0: Introduction and Qt Basics

Posted by admin in Untagged 

Introduction

Over the course of three weeks earlier this year, Maurizio Scotti and I attempted to develop a Universal Inbox application using Qt on S60 here at Symsource, as a way of getting to grips with the framework and assessing whether it was ready for use in production quality applications.

Brainstorming with the rest of our team, we decided that a good learning project would be to write a simple aggregator that would gather together all of a users SMS, email, Twitter and Facebook messages in a single application. The main view of the application would be a date ordered summary list of messages, with additional views to support the viewing of message details and the composition of new messages.

This series of blog posts is a summary of what we did, how we used Qt to do it, and what we thought of Qt as a platform. By its very nature, it’s a selective look at Qt, as I can only write about the pieces of the platform we actually used. It’s also deliberately not a guide to the practicalities of getting Qt installed and running, this being admirably dealt with in the Qt Quick Start page on the Symbian wiki.

Qt basics from the perspective of a Symbian programmer

Before we dive into the specifics of what we encountered, it’s worthwhile spending a bit of time going through some of the basic ideas behind Qt.

Qt was originally designed as a cross-platform widget and UI library for use on Linux and Windows. It’s since spread to more platforms and offers a standard API that supports a lot more than just GUI programming. There’s a decent selection of network interfaces, for example, and a fairly comprehensive set of container classes.

The basic components of the the UI will be familiar to anyone who’s done any modern UI programming: widgets, views, dialogs, menus and commands. The novel thing is how they fit together - rather than having a system of callbacks and interfaces or providing a simple loosely typed message passsing mechanism, Qt uses signals and slots.

Together, these make up a generalised publish and subscribe service. Signals correspond to events being published, slots act as sinks for the events, and the connect function is used to subscribe a slot to a signal. It’s also possible to chain signals to other signals, again using the connect function. Both signals and slots are declared as methods on a class, but only slots have definitions. Signals are emitted using the special Qt emit keyword, and received by the slots as though they were conventional function calls.1

All the necessary scaffolding needed for a class to handle signals and slots is wrapped up inside the Qt base class, QObject, and the Q_OBJECT declaration macro. Simply derive a class from QObject and include the Q_OBJECT declaration at the beginning of the class declaration and you can create signals and slots at will.

Doing this doesn’t just get you signal handling. Also included as part of QObject are: child object cleanup; low level event interception for things like key presses; support for Qt’s timer mechanism; and a degree of runtime reflection and dynamism. As a consequence of some of these features, objects inherited from QObject have to be treated as though each one has a unique identity, which means that naive copying of QObjects is a bad idea. To prevent problems with this, the QObject assignment operators and copy constructors are automatically disabled.

This identity/value issue, plus the overhead required for the rest of the functionality means that not all Qt classes inherit from QObject. In particular, the string-like classes and containers are all outside the QObject hierarchy. Instead, these all have copy-on-write value semantics, meaning that they can be passed around and returned as though they were simple, small objects, like TInt or TReal, without fear of incurring huge copying costs.

The standard Qt string class, QString, is a full fledged unicode string class, which should be used whenever you are manipulating text internally. It has all the expected string manipulation, searching and conversion operations, and grows and shrinks dynamically as you add and remove data from it.

To handle arrays of bytes, Qt provides a QByteArray with much of the same functionality. The relationship between the two is much like that between TDes16 and TDes8 - one is for text, the other for binary data (that may just happen to be encoded text).

There are several different templated container classes available:

  • QLinkedList - a linked list
  • QVector - a resizable array
  • QList - a hybrid list/array (somewhat like C++’s std::deque)
  • QMap - a sorted associative array (with binary tree performance)
  • QHash - a hashmap

There are also assorted subtypes, including a stack, queue and multimap. In general, they are easier to use than the Symbian equivalents, particularly the QHash, which has built in hash functions for a much greater variety of types than Symbian’s equivalent. The only obvious thing missing is a set or hashed set class.

The split between two different types of classes, and especially the difference in their copy semantics is reminiscent of Symbian’s division of its classes into C, T and R classes. However, beware of falling into the trap of assuming that the distinctions are equivalent: they are not.

Qt uses error codes (plus the standard C++ bad_alloc exception) rather than leaves, so there is no need for a cleanup stack, or anything approximating to it, and no explicit two stage construction. This in turn means that there isn’t the same need for a clear correlation between the type of an object and whether it’s created on the stack or not. Instead, everything can equally be created on the stack or heap. If created on the stack, it gets cleaned up normally when the stack is unwound (either normally, or when an exception is thrown); if created on the heap, it either has to be managed manually, or the ownership can be assigned to a parent object derived from QObject, with the object then being automatically deleted when its parent is. This ownership pattern tends to lead to a tree of ownership, with the QApplication object at the root.2

One side effect of this lack of type specialisation on storage type is that there is no automatic zeroing of memory for any Qt-derived object. So you have to make sure that you manually zero anything you expect to be zeroed as part of the object’s construction.

Coming up next…

Tomorrow, I dive into the details of how we used Qt in our application, starting right at the beginning with the implementation of the main function, followed by a look at the way Qt uses the MVC pattern.

1. The signals and slots are supposed to be typesafe, with the arguments of the signal checked against those of the slot. But on a couple of occasions I successfully compiled what appeared to be mismatched signals and slots.

2. This has some implications for the stack/heap balance in applications. Symbian code is generally written with the assumption that the available stack is (by non-embedded standards) extremely small, so very little gets created on the stack. This pattern can be followed without too much difficulty if you are writing all your Qt code from scratch, but when porting code, or using third party libraries, this is not necessarily possible. The current documentation is a bit vague on how this should be handled, though it may be interesting to note that the Qt friendly MMP file generated by Carbide automatically contains this line:

EPOCSTACKSIZE 0×14000

Which corresponds to 80K - ten times that used by Series60v3 application by default.

Apr 06
2010

Sony-Ericsson, MIDP and Twitpic

Posted by admin in Untagged 

In a recent project we were creating a funky new Twitter client for Sony-Ericsson MIDP handsets. Sounds dull, but there were some cool features of this product which made it much more interesting than it sounds (no I can’t elaborate :-).

Part of this was upload of pictures to Twitpic. “Great”, we thought, “Twitpic - simple URL-based REST API. Should be easy enough”. As it turned out, not as simple as originally anticipated.

The problem is a mis-match between the behaviour of the Sony-Ericsson MIDP HTTP stack and the needs of the Twitpic server.

The Twitpic server requires a Content-Length header to be included, or else your picture post is rejected. The Sony-Ericsson HTTP stack, however, adopts HTTP/1.1 chunked encoding for any payload over a few kilobytes…. and HTTP/1.1 chunked encoding doesn’t supply a Content-Length header. Argh!
All attempts to explicitly set the Content-Length header in MIDP (via HTTPConnection::setRequestProperty("Content-Length", length) were soundly ignored by the Sony-Ericsson devices.

Double Argh!

The solution? Painful, but for Twitpic posts we use a socket connection and mock-up the HTTP communication, headers etc. including the Content-Length header. This meant more work, but in addition meant the application needed to be signed (i.e. Java Verified) in order for Twitpic to work - socket connections to port 80 require a trusted third party domain.

So, problem solved - in the end without any schedule impact - but with some consequences for the product deployment.

Apr 06
2010

Why it’s time to start taking Nokia’s Ovi Store seriously

Posted by admin in Untagged 

You could be forgiven for thinking Apple’s iPhone is the only platform with downloadable applications. That’s the impression many consumers have, and although other platforms have had apps and games for years, it has taken Apple to show them how it’s done, with great execution and a large investment in marketing creating a truly viable market for third-party downloads.

But while BlackBerry App World and Android Market are slowly gaining traction, only Nokia is putting its money where its mouth is with a TV, print and poster campaign that has already seen Ovi Store downloads increase 70% month on month, even before the campaign has really got going.

In this week’s Mobile Today, we suggest that now may be the perfect time to get your apps and content ready for Ovi Store. Read the full story at http://bit.ly/4w5YlB

Apr 06
2010

Android debugging on the T-Mobile Pulse (Mac OS X)

Posted by admin in Untagged 

Out of the box, the Android Eclipse development environment fails when attempting to debug on the T-Mobile Pulse with the following error:

java.io.IOException: device (????????????) request rejected: device not found
Launch canceled!

However, merely adding the vendor ID 0×12d1 to ~/.android/adb_usb.ini solves the problem, as detailed here: http://osdir.com/ml/Android-Beginners/2009-11/msg00529.html

Apr 06
2010

5 years old today

Posted by admin in Untagged 

Symsource is 5 years old today, so we just wanted to take this opportunity to thank all of our staff, partners, suppliers and of course customers past and present for making it possible for us to work in what is still the most exciting field in software, the fast growing, ever changing, never boring and arguably world changing field that is the mobile phone industry.

When we started out, there were no App Stores, no 3G, no GPS, no Wifi in our phones. We hoped that the market for innovative applications and services for the mobile phone would take off and we could ride that wave, and from humble beginnings with projects on Symbian and J2ME, we can now boast a track record across Windows Mobile, BlackBerry, Android and iPhone as well.

Here’s to another 5 years - you’ll be using your mobile to control your home, send voice commands to your car, track your pets location, stream HD (or 3D!) movies to your TV and maybe even figure out some reason for all that social data you’re collecting long before then. And at Symsource we hope we’re the ones who get to build it!

Apr 06
2010

Android 1.5 transparent view bug

Posted by admin in Untagged 

Nominally, you can make Android View or Layout transparent or semi-transparent by changing the android:background color definition in the layout XML. However, this doesn’t work quite as you might expect on Android 1.5.

For example, attempting to create a layout which includes an image as a background with a semi-transparent overlay like this:


<!-- Use a relative layout with background image, with a semi-transparent overlay in an enclosed LinearLayout -->


<RelativeLayout android:id="@+id/MainLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/default_bg">


<LinearLayout android:id="@+id/LinearLayout01"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical"
android:background="#99FFFFFF"
>
.....
</LinearLayout>
</RelativeLayout>

On Android 1.5, you will end up with a view with a white background. On Android 1.6, you (correctly) have the background image with a semi-transparent white overlay. I guess that is why the Android example code for translucent background uses a transparent PNG rather than setting the alpha in the background colour - there is a bug in 1.5 which prevents it working!