Thursday, December 31, 2009

Installing Qt 4.6 SDK in Windows 7

I'm planning to do some Qt for Symbian development. Qt Creator 1.3 has some support for Qt+Symbian development, but only on Windows. Although I love Ubuntu, currently I have to bow to the powers that be. No need to fight this (eventually I believe it'd be as easy to develop Qt Symbian apps on Linux).

Preparing Qt Development

  1. Download Qt Development Environment for Windows. (choose the complete bundle)
  2. Install the Qt IDE package.
    During this step I noticed that current Qt 4.6 bundle uses MinGW 3.15 aka GCC 4.4. I can foresee some problems with Qt Mobility. But I'll save my headaches for later.
Here's what Qt Creator 1.3 welcome page looks like: (nothing much, I know)


Simple Greeting Application


Of course installation of powerful IDE won't be complete without creating a trivial application:


Add some code:

void MainWindow::on_nameEdit_textChanged(QString name)
{
    ui->greetingLabel->setText("Hello " + name);
}

And here's the app in its full glory ;-)



Qt Command Line Environment


To enable compilation of Qt apps/libraries (such as Qt Mobility library) from the command line/shell, you must launch the command prompt from "Qt Command Prompt" launcher.



If you're already on a command prompt, you can setup Qt command line environment by running:
C:\Qt\2009.05\bin\qtenv
Use the Qt location installed on your system.

Wednesday, December 30, 2009

Qt/C++ Programming vs Spring/Java Development

After a few days with Qt and reunion with C++ (after almost 10 years), I have some thoughts about Qt and C++ development when compared to my experience with Spring and Java.

FeatureQt/C++Spring/Java
Memory management
Qt makes C++ more bearable by cleaning up child objects automatically if its parent is destroyed. But still far from what Java has to offer, new and forget. ;-)
Java is clear winner here. Furthermore, Spring makes object lifecycle ("beans") even more automatic and controlled. You can have singleton beans, prototype scoped beans, etc. And autowiring.
Dependency Injection
Aside from Qt's standard signals and slots, and Qt Designer for wiring widgets, there isn't much. Or maybe I haven't found it.
Qt is no match for Spring's powerful dependency injection capabilities, whether using XML configuration or (even more) annotations. It's not a Java feature, but it's not specific to Spring either. Other frameworks like Guice and JBoss Seam also have this feature, especially with the recent WebBeans aka Java Context and Dependency Injection (CDI) aka JSR-299.
Event Handling
Qt has standard signals and slots, which is superior when compared to traditional C/C++, or even Java for that matter. (now I realized what the fuss with signals and slots is all about!)
No support for free-form publish-subscribe event handling, only declared signals.
Java has Observer pattern, Listener pattern, and recently (thanks to OSGi) the Whiteboard pattern.
The closest to direct connection in Java is properties with interface types, a.k.a.:
private ActionListener clickListener;
Spring can help with wiring, which reliefs much of the pain.
Granted, all of them are inferior compared to Qt's signals and slots, with agreed conventions semi-message-passing capability (with QueueConnection and BlockingQueueConnection).
Surprisingly, even Dojo has dojo.connect which is very similar (if not exactly) like Qt's signals and slots and dojo.publish for free-form publish-subscribe messaging/event handling.
Fortunately, both techniques are trivially implemented in Java with help of an integration library such as Apache Camel or Spring Integration. This really needs to be part of core Java specs.
Widgets
I guess this is the strength of Qt. I like it, and I like how it looks, especially with the new GTK+ style. Blends in with other Ubuntu apps.
I mainly develop web-based Spring apps with Dojo AJAX toolkit, not desktop ones, so I can't really compare. However, I've had some experience with Swing GUI and Eclipse RCP (SWT) apps. I can say Qt's feel smoother both visually and performance-wise.
Programming either Swing or SWT is more pleasant than Qt, due to Java.
Performance
Excellent. Both building and running.
Very good. Frankly, I don't think Java is that slow anymore. I haven't yet proven myself that Java apps can be faster than C++ counterparts, but I'm sure there are such cases.
Build & Dependency Management
Horrible!
Qt Creator and qmake did its job, but there's no dependency management, library hell, etc.
Dependencies must be compiled with their respective tooling, sometimes conflicting.
Real-life example: Qt Mobility 1.0 TP2 can't be compiled with GCC 4.4, needs GCC 4.3.
Excellent!
Pick your poison: Eclipse's, NetBeans', Maven, Ant + Ivy, or plain Ant. For some people, IntelliJ's.
Yes the tools are quite fragmented, but the most manual thing you needed to do upon tooling conflict is download the (binary! thank God!) dependencies manually and put them on correct locations.
Works on all platforms.

Conclusion

Overall, I'd say Spring/Java development is more enjoyable than Qt/C++ programming.

Java's lack of convenient event handling mechanism disturbs me. Although integration libraries cure that itch to some extent, most Java developers will code them manually. Besides, not every project uses integration libraries, or even if they do, they might use different libraries, leading to redundancy and other issues.

Tuesday, December 29, 2009

Qt Mobility Quickstart App

After successfully (though somewhat painfully) building Qt Mobility 1.0 Tech Preview 2, I'm ready to write and run my first Qt Mobility Application.

Okay... technically not my app, but the app from the Qt Mobility Quickstart example.

Building Qt Mobility Quickstart App

  1. Make sure to install Qt Mobility and set LD_LIBRARY_PATH environment variable to point to your Qt Mobility install/lib folder.
  2. Create a new Qt GUI Project. If you need help here, refer to Hello World Qt GUI App.
  3. Paste the following code into main.cpp :


    #include <QApplication>
    #include <QLabel>
    
    #ifdef Q_OS_SYMBIAN
    #include <qsysteminfo.h>
    #else
    #include <QSystemInfo> //(1)
    #endif
    using namespace QtMobility; //(2)
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        QSystemInfo s;
        QLabel *label = new QLabel(QObject::tr("hello ").append(s.currentCountryCode()));
        label->show();
        label->resize(100,30);
        return app.exec();
    }
    


  4. Qt Mobility Quickstart tutorial tells you to add this to your project's .pro file:


    CONFIG += mobility
    MOBILITY += systeminfo
    


  5. Build the project...
  6. At this point I get this error with QNetworkInterface:


    g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.6.0/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.6.0/include/QtCore -I/usr/local/Trolltech/Qt-4.6.0/include/QtGui -I/usr/local/Trolltech/Qt-4.6.0/include -I/usr/local/Trolltech/Qt-4.6.0/include/QtSystemInfo_tp -I/opt/qt-mobility-src-1.0.0-tp2/install/include -I. -o main.o main.cpp
    In file included from /opt/qt-mobility-src-1.0.0-tp2/install/include/QSystemInfo:1,
    from main.cpp:7:
    /opt/qt-mobility-src-1.0.0-tp2/install/include/qsysteminfo.h:50:29: error: QNetworkInterface: No such file or directory
    In file included from /opt/qt-mobility-src-1.0.0-tp2/install/include/QSystemInfo:1,
    from main.cpp:7:
    /opt/qt-mobility-src-1.0.0-tp2/install/include/qsysteminfo.h:183: error: ‘QNetworkInterface’ does not name a type
    make: Leaving directory `/home/ceefour/Sandbox/quickstart-mobility'
    make: *** [main.o] Error 1
    Exited with code 2.
    Error while building project quickstart-mobility
    When executing build step 'Make'
    


  7. Seems like Qt Mobility tutorial writer forgot to add dependency to network module that provides QNetworkInterface. Add the following to your .pro file:


    QT       += network


  8. Run the project.

Qt Mobility Quickstart in Action

The Quickstart project displays the following very simple dialog:


It looks very simple and harmless, yet it's so powerful.

Why powerful? Because you can build this very same app for all platforms supported by Qt Mobility, and it'll work just as well... that is, displaying the current locale.

Don't believe me? Build and run exactly the same source code on Windows (no changes whatsoever) and voila!




For those who have programmed in Java, this is similar to Java Mobile Edition (J2ME). The primary benefits are:
  • It's natively compiled. Therefore, the app runs optimally in all devices and platforms.
  • It uses the same underlying library: Qt library and Qt GUI widget toolkit. Unlike Java where you'll use Swing or SWT on the desktop, and Java ME widgets on the client. In all Qt Mobility platforms, you use Qt GUI.
  • No need for a Java Runtime Engine (JRE). Most Qt applications are dynamically linked with Qt shared libraries for size and other reasons. You can also statically link Qt libraries for platforms that doesn't have Qt preinstalled. In that regard, Qt app (therefore, Qt Mobility app) is indistinguishable from that platform's native apps.

About LD_LIBRARY_PATH


If you don't set LD_LIBRARY_PATH properly, your app still builds successfullly. However, you will encounter the following error when running the app:

/home/ceefour/Sandbox/quickstart-mobility/quickstart-mobility: error while loading shared libraries: libQtSystemInfo_tp.so.1: cannot open shared object file: No such file or directory

Error messages on Windows are slightly different, but same meaning: it cannot find the required binary library files.

c:/qt/2009.05/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../../mingw32/bin/ld.exe: cannot find -lQtSystemInfo_tpd
collect2: ld returned 1 exit status

To resolve this problem, either add the following to $HOME/.bashrc and restart your computer:

# Qt Mobility
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/qt-mobility-src-1.0.0-tp2/install/lib

or, set LD_LIBRARY_PATH from your project settings (not recommended):
  1. Switch to Projects mode (Ctrl+4).
  2. Choose your project.
  3. Under Build Environment, click Show Details.





  4. Select LD_LIBRARY_PATH, click Edit, and append (separated by colon ":") your Qt Mobility path there, e.g. :/opt/qt-mobility-src-1.0.0-tp2/install/lib
Run the app now and it should work fine.

Installing Qt Mobility Libraries on Ubuntu

It's time for me to jump into Qt Mobility development. Yaay!

Here's my steps to prepare Qt Mobility development. I'm using Ubuntu 9.10 Karmic Koala.
  1. Make sure you have installed Qt 4.6.
  2. Install checkinstall package if you haven't.
  3. Install network-manager-dev package. This will be used by the Bearer API and System Information API.
  4. Install libgstreamer0.10-dev package. This will be used by the Multimedia API implementation.
  5. Download Qt Mobility library sources.
  6. Unpack the Qt Mobility distribution to a folder.
  7. Open a terminal on that folder.
  8. Set the PATH to Qt 4.6.x libraries:

    $ export PATH=/opt/qtsdk-2010.01/qt/bin:$PATH
    
  9. Set PKG_CONFIG_PATH:

    $ export PKG_CONFIG_PATH=/usr/lib/pkgconfig
    
  10. Run:

    $ ./configure

$ ./configure 
Configuring Qt Mobility

Checking available Qt ... 4.6.0
Checking QMF ... Not Found
Checking NetworkManager ... OK
Checking CoreWLAN (MacOS 10.6) ... Not Found
Generating Mobility Headers...
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QNetworkConfiguration
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QNetworkConfigurationManager
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QNetworkSession
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QValueSpaceSubscriber
Create header /opt/qt-mobility-src-1.0.0-tp2/include/SymbianSettingsLayer
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QValueSpacePublisher
Create header /opt/qt-mobility-src-1.0.0-tp2/include/PathMapper
Create header /opt/qt-mobility-src-1.0.0-tp2/include/PathData
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QNmeaPositionInfoSource
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QGeoPositionInfo
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QGeoSatelliteInfoSource
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QGeoCoordinate
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QGeoSatelliteInfo
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QGeoPositionInfoSource
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QGeoAreaMonitor
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QServiceContext
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QServiceManager
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QServicePluginInterface
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QAbstractSecuritySession
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QServiceInterfaceDescriptor
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QServiceFilter
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QSystemInfo
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QSystemNetworkInfo
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QSystemDisplayInfo
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QSystemStorageInfo
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QSystemDeviceInfo
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QSystemScreenSaver
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactDetailDefinition
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactFilter
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactDetailDefinitionField
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactChangeSet
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactAbstractRequest
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactActionFactory
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactManagerEngine
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactAction
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactDetail
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactId
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactActionDescriptor
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContact
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactRelationship
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactSortOrder
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactManager
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QContactManagerEngineFactory
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaPlaylistProvider
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QVideoOutputControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMetaDataControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QLocalMediaPlaylistProvider
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaRecorderControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaImageViewer
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaPlaylistReader
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaPlaylistWriter
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaPlaylistIOPlugin
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QVideoEncoderControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaStreamsControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaService
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaPlaylistControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaPlayer
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaPlaylistNavigator
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QGraphicsVideoItem
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaServiceProviderHint
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaServiceProvider
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaRecorder
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QVideoRendererControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QAudioDeviceControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QAudioEncoderControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QRadioTunerControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QVideoDeviceControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QAudioEncoderSettings
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QVideoEncoderSettings
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QImageEncoderSettings
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaResource
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaPlaylist
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaPlayerControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QVideoWidget
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaServiceProviderPlugin
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QVideoWindowControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QImageEncoderControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QVideoWidgetControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaFormatControl
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QRadioTuner
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QAudioCaptureSource
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaObject
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QAudioFormat
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMediaContent
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageFolderFilter
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageFilter
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageFolderOrdering
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageFolder
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageId
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageContentContainer
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageStore
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageAccountOrdering
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessage
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageAddress
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageServiceAction
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageFolderId
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageContentContainerId
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageAccountFilter
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageOrdering
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageAccountId
Create header /opt/qt-mobility-src-1.0.0-tp2/include/QMessageAccount
Running qmake...
Reading /opt/qt-mobility-src-1.0.0-tp2/src/src.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/src/global/global.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/src/serviceframework/serviceframework.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/src/bearer/bearer.pro
Project MESSAGE: NetworkManager backend requires Qt DBus support
 Reading /opt/qt-mobility-src-1.0.0-tp2/src/location/location.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/src/contacts/contacts.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/src/multimedia/multimedia.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/src/publishsubscribe/publishsubscribe.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/src/versit/versit.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/src/systeminfo/systeminfo.pro
Reading /opt/qt-mobility-src-1.0.0-tp2/tools/tools.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/tools/servicefw/servicefw.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/tools/servicexmlgen/servicexmlgen.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/tools/vsexplorer/vsexplorer.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/tools/qcrmlgen/qcrmlgen.pro
Reading /opt/qt-mobility-src-1.0.0-tp2/plugins/plugins.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/plugins/contacts/contacts.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/plugins/multimedia/multimedia.pro
Package gstreamer-interfaces-0.10 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-interfaces-0.10.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-interfaces-0.10' found
Package gstreamer-audio-0.10 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-audio-0.10.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-audio-0.10' found
Package gstreamer-video-0.10 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-video-0.10.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-video-0.10' found
  Reading /opt/qt-mobility-src-1.0.0-tp2/plugins/multimedia/m3u/m3u.pro
  Reading /opt/qt-mobility-src-1.0.0-tp2/plugins/multimedia/audiocapture/audiocapture.pro
  Reading /opt/qt-mobility-src-1.0.0-tp2/plugins/multimedia/v4l/v4l.pro
Reading /opt/qt-mobility-src-1.0.0-tp2/doc/doc.pro
 Reading /opt/qt-mobility-src-1.0.0-tp2/doc/src/snippets/snippets.pro
  Reading /opt/qt-mobility-src-1.0.0-tp2/doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.pro

configure has finished. You may run make or gmake to build the project now.
  1. Run: sudo checkinstall
    If you can't or don't want to use checkinstall, do:


    $ make
    $ make install
    


  2. Be very patient (again!)
I'm having unexpected unpleasant surprise here, the build stops early with an error:

g++ -c -pipe -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -W -D_REENTRANT -fPIC -DQT_BUILD_CFW_LIB -DQT_MAKEDLL -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.6.0/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.6.0/include/QtCore -I/usr/local/Trolltech/Qt-4.6.0/include/QtNetwork -I/usr/local/Trolltech/Qt-4.6.0/include -I../global -I../../build/Debug/QtPublishSubscribe/moc -o ../../build/Debug/QtPublishSubscribe/qmallocpool.o qmallocpool.cpp
In file included from qmallocpool.cpp:64:
dlmalloc.c: In function ‘void QtMobility::dlmalloc_stats()’:
dlmalloc.c:4725: error: cannot convert ‘QtMobility::_IO_FILE*’ to ‘FILE*’ for argument ‘1’ to ‘int QtMobility::fprintf(FILE*, const char*, ...)’
dlmalloc.c:4727: error: cannot convert ‘QtMobility::_IO_FILE*’ to ‘FILE*’ for argument ‘1’ to ‘int QtMobility::fprintf(FILE*, const char*, ...)’
dlmalloc.c:4729: error: cannot convert ‘QtMobility::_IO_FILE*’ to ‘FILE*’ for argument ‘1’ to ‘int QtMobility::fprintf(FILE*, const char*, ...)’
make[2]: *** [../../build/Debug/QtPublishSubscribe/qmallocpool.o] Error 1
make[2]: Leaving directory `/opt/qt-mobility-src-1.0.0-tp2/src/publishsubscribe'
make[1]: *** [sub-publishsubscribe-make_default] Error 2
make[1]: Leaving directory `/opt/qt-mobility-src-1.0.0-tp2/src'
make: *** [sub-src-make_default-ordered] Error 2 

This is a known Qt Mobility bug with GCC 4.4, which Ubuntu 9.10 uses by default.

To solve this problem, install gcc-4.3 package and g++-4.3 package. Update the symlinks too:

$ sudo ln -sf gcc-4.3 /usr/bin/gcc
$ sudo ln -sf g++-4.3 /usr/bin/g++

Update: Even with GCC / G++ 4.3, I still experience yet another problem:

g++ -c -pipe -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -W -D_REENTRANT -fPIC -DQT_BUILD_SYSINFO_LIB -DQT_MAKEDLL -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.6.0/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.6.0/include/QtCore -I/usr/local/Trolltech/Qt-4.6.0/include/QtNetwork -I/usr/local/Trolltech/Qt-4.6.0/include/QtGui -I/usr/local/Trolltech/Qt-4.6.0/include -I../global -I../../build/Debug/QtSystemInfo/moc -o ../../build/Debug/QtSystemInfo/qsysteminfo_linux.o qsysteminfo_linux.cpp
qsysteminfo_linux.cpp: In member function ‘void QtMobility::QSystemStorageInfoPrivate::mountEntries()’:
qsysteminfo_linux.cpp:1370: warning: comparison between signed and unsigned integer expressions
In file included from qsysteminfo_linux.cpp:2073:
../../build/Debug/QtSystemInfo/moc/moc_qsysteminfo_linux_p.cpp: In member function ‘bool QtMobility::QSystemScreenSaverPrivate::isScreenSaverActive()’:
../../build/Debug/QtSystemInfo/moc/moc_qsysteminfo_linux_p.cpp:47: error: invalid use of qualified-name ‘QtMobility::QSystemInfoPrivate::staticMetaObject’
../../build/Debug/QtSystemInfo/moc/moc_qsysteminfo_linux_p.cpp:57: error: a function-definition is not allowed here before ‘{’ token
../../build/Debug/QtSystemInfo/moc/moc_qsysteminfo_linux_p.cpp:62: error: a function-definition is not allowed here before ‘{’ token
../../build/Debug/QtSystemInfo/moc/moc_qsysteminfo_linux_p.cpp:70: error: a function-definition is not allowed here before ‘{’ token
qsysteminfo_linux.cpp:2075: error: expected `}' at end of input
qsysteminfo_linux.cpp: At global scope:
qsysteminfo_linux.cpp:2075: error: expected `}' at end of input
make[2]: *** [../../build/Debug/QtSystemInfo/qsysteminfo_linux.o] Error 1
make[2]: Leaving directory `/opt/qt-mobility-src-1.0.0-tp2/src/systeminfo'
make[1]: *** [sub-systeminfo-install_subtargets] Error 2
make[1]: Leaving directory `/opt/qt-mobility-src-1.0.0-tp2/src'
make: *** [sub-src-install_subtargets-ordered] Error 2 

I reported this to Qt as bug QTMOBILITY-46. Hopefully it gets resolved soon, or a workaround is provided.

Update: I got word from Lorn Potter from Nokia/TrollTech/Qt. To patch it, run:

patch src/systeminfo/qsysteminfo_linux.cpp

then paste in:

diff --git a/src/systeminfo/qsysteminfo_linux.cpp
b/src/systeminfo/qsysteminfo_linux.cpp
index f795c4f..e0d1a4b 100644
--- a/src/systeminfo/qsysteminfo_linux.cpp
+++ b/src/systeminfo/qsysteminfo_linux.cpp
@@ -2065,8 +2065,8 @@ bool QSystemScreenSaverPrivate::isScreenSaverActive()
                 return reply.value();
             }
         }
-    }
 #endif
+    }
     return false;
 }

and press Ctrl+D.

After doing the above, I have successfully compiled Qt Mobility 1.0 TP2. Yaay!

Now you should add add /opt/qt-mobility-src-1.0.0-tp2/lib folder to your LD_LIBRARY_PATH environment variable.

To add Qt Mobility documentation in Qt Creator: Go to Tools -> Options -> Help -> Add. Then browse /opt/qt-mobility-src-1.0.0-tp2/doc/qch/qtmobility.qch.

See also:

"undefined reference to vtable" Error

I'm having a very strange problem with Qt library (and C++ in general), this message:

undefined reference to vtable `...SomeClass...`

It frustrates me at first. I still don't know why it happens, but I know how to solve it in my case.

As an example, this code:

#include <QObject>
#include <stdio.h>

class HelloWorld : public QObject
{
Q_OBJECT
signals:
    void done();

public slots:
    void sayHello() {
        printf("Hello World!\n");
        done();
    }

};

works fine when put into helloworld.h and called by main.cpp.

However, when it's put directly into main.cpp... it throws the (linker) error.

It seems all Qt objects must be put into their own H/CPP pair. At least that's what it makes me think.

Reference: qt-interest mailing list archive - undefined reference to vtable...

Syntax Highlight Blogger Posts Automatically

When posting source code in a blog post, you surely want it to be syntax highlighted. However, doing it manually is painful. I'll show you how to syntax highlight source code automatically, and works in Blogger.

Note: This isn't a Qt tip, but I bet you'll find it useful. :-)

My Old Technique: tohtml.com


At first I used tohtml.com's service to do syntax highlighting. Which works fine, by the way, but generates quite large HTML, especially if the code is long.

And it lacks the cool features like line numbering and copy-to-clipboard.

Enter... the JavaScript Syntax Highlighter!

Activating Alex Gorbatchev's JavaScript Syntax Highlighter


The syntax highlighting engine that we're gonna use is the excellent Syntax Highlighter by Alex Gorbatchev.

To install it, simply add the following code inside the blog template's HEAD:

<!-- Syntax Highlighter: Begin -->
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/> 
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/> 
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'></script> 
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPlain.js' type='text/javascript'></script> 
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'></script> 
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'></script> 
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'></script> 
<script language='javascript'> 
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
SyntaxHighlighter.all();
</script> 
<!-- Syntax Highlighter: End -->

To edit the template in Blogger, go to Layout -> Edit HTML -> Edit Template.

Using Syntax Highlighter


To use it in a blog post, surround the code you want to post with PRE tag and either class="brush: xml" or class="brush: cpp" depending on the programming language (XML or C++ respectively).

You need to escape the content first before pasting into Blogger's post editor, using Quick Escape.

Syntax Highlighted Examples


Syntax highlighting for C++ (Qt!) code:

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

Source HTML for the above is:

<pre class="brush: cpp">#include &lt;QtGui/QApplication&gt;
#include &quot;mainwindow.h&quot;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}</pre>

To get the following XML code syntax highlighted:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

Put these in "Edit HTML": (WARNING! The following may hurt your eyes!)

<pre class="brush: xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;ui version=&quot;4.0&quot;&gt;
 &lt;class&gt;MainWindow&lt;/class&gt;
 &lt;widget class=&quot;QMainWindow&quot; name=&quot;MainWindow&quot;&gt;
  &lt;/widget&gt;
 &lt;layoutdefault spacing=&quot;6&quot; margin=&quot;11&quot;/&gt;
 &lt;resources/&gt;
 &lt;connections/&gt;
&lt;/ui&gt;</pre>

Looks really ugly, huh? The escaping is unfortunately, necessary.

In Blogger, when you got from "Edit HTML" to "Compose" (WYSIWYG) it gets even uglier. This usually only applies for XML-ish code.

Quick Escape: My Version


As I'm writing this, the Quick Escape online service I previously mentioned goes down... leaving me powerless to escape my code examples.

Fortunately, escaping HTML is easy to do with any programming toolkit. Hereby I choose Ruby language.

Save the following code as escapehtml.rb:

#!/usr/bin/env ruby
require 'cgi'
print CGI::escapeHTML $stdin.read

You can use it by simply executing it in a terminal, typing something then press Ctrl+D. Or by piping any content or file into it.

Credits


I found this technique from Awesome syntax highlighting made easy by Carter Cole. In fact, I simply reiterate here what he wrote there.

Recommended Books

C++ GUI Programming with Qt 4 (2nd Edition) (Prentice Hall Open Source Software Development Series)


The Only Official, Best-Practice Guide to Qt 4.3 Programming

Using Trolltech's Qt you can build industrial-strength C++ applications that run natively on Windows, Linux/Unix, Mac OS X, and embedded Linux without source code changes. Now, two Trolltech insiders have written a start-to-finish guide to getting outstanding results with the latest version of Qt: Qt 4.3.
Packed with realistic examples and in-depth advice, this is the book Trolltech uses to teach Qt to its own new hires. Extensively revised and expanded, it reveals today's best Qt programming patterns for everything from implementing model/view architecture to using Qt 4.3's improved graphics support. You'll find proven solutions for virtually every GUI development task, as well as sophisticated techniques for providing database access, integrating XML, using subclassing, composition, and more. Whether you're new to Qt or upgrading from an older version, this book can help you accomplish everything that Qt 4.3 makes possible.
  • Completely updated throughout, with significant new coverage of databases, XML, and Qtopia embedded programming
  • Covers all Qt 4.2/4.3 changes, including Windows Vista support, native CSS support for widget styling, and SVG file generation
  • Contains separate 2D and 3D chapters, coverage of Qt 4.3's new graphics view classes, and an introduction to QPainter's OpenGL back-end
  • Includes new chapters on look-and-feel customization and application scripting
  • Illustrates Qt 4's model/view architecture, plugin support, layout management, event processing, container classes, and much more
  • Presents advanced techniques covered in no other book—from creating plugins to interfacing with native APIs
  • Includes a new appendix on Qt Jambi, the new Java version of Qt



Developing Software for Symbian OS 2nd Edition: A Beginner's Guide to Creating Symbian OS v9 Smartphone Applications in C++ (Symbian Press)


Many problems encountered by engineers developing code for specialized Symbian subsystems boil down to a lack of understanding of the core Symbian programming concepts. Developing Software for Symbian OS remedies this problem as it provides a comprehensive coverage of all the key concepts. Numerous examples and descriptions are also included, which focus on the concepts the author has seen developers struggle with the most. The book covers development ranging from low-level system programming to end user GUI applications. It also covers the development and packaging tools, as well as providing some detailed reference and examples for key APIs. The new edition includes a completely new chapter on platform security.

The overall goal of the book is to provide introductory coverage of Symbian OS v9 and help developers with little or no knowledge of Symbian OS to develop as quickly as possible. There are few people with long Symbian development experience compared to demand, due to the rapid growth of Symbian in recent years, and developing software for new generation wireless devices requires knowledge and experience of OS concepts. This book will use many comparisons between Symbian OS and other OSes to help in that transition.

Get yourself ahead with the perfect introduction to developing software for Symbian OS.



Porting to the Symbian Platform: Open Mobile Development in C/C++ (Symbian Press)


If you want to write mobile applications without the idioms of Symbian C++, have existing software assets that you'd like to re-use on Symbian devices, or are an open source developer still waiting for an open Linux-based device to gain significant market penetration, this is the book for you!

Beginning with an introduction to the native programming environments available and descriptions of the various technologies and APIs available, you will first learn how to go about porting your code to the Symbian platform.

Next, you will discover how to port to Symbian from other common platforms including Linux and Windows.

Finally, you can examine sample porting projects as well as advanced information on topics such as platform security.

The author team consists of no less than six Forum Nokia Champions, together with technical experts from the Symbian community, either working on Symbian platform packages or third party application development. With this book, you will benefit from their combined knowledge and experience.

In this book, you will learn:
  • How to port and make use of existing open source code to speed up your development projects
  • How to port applications from other popular mobile platforms to the Symbian platform
  • How to write code that is portable across multiple platforms
  • The APIs in the Symbian platform for cross-platform development, such as support for standard C/C++ and Qt.

Hello World Qt GUI Application

It's time to create a Qt GUI Application, that displays Hello World.

If you want a less cool yet more bare-bones version, see the Hello World Qt Console app.

A little 'warning', this is too trivial.
  1. In Qt Creator, create a Qt project by clicking File -> New File or Project, or press Ctrl+N.

  2. Choose Qt4 Gui Application.

From Kev's Qt Mobility Development
  1. Introduction and project location. Pick a name and location for your new project.

From Kev's Qt Mobility Development
  1. Select required modules. Choose the Qt modules you want (QtCore and QtGui is always required).

From Kev's Qt Mobility Development
  1. Class Information. Edit the class information if necessary. Choose if you want the Qt4 UI Designer feature ( Generate form).

From Kev's Qt Mobility Development
  1. Project Management. Review the options, there is support for adding to version control if you're using it for the project.

From Kev's Qt Mobility Development
At this point, you'll have a new GUI project with sensible default widgets.

Running this starter project gives you:

From Kev's Qt Mobility Development
Not very functional, but quite impressive. You already got a dockable toolbar that you can drag around! ;-)

In Qt Creator, double-click mainwindow.ui to reveal Form Editor, which is an Qt Creator-integrated version of Qt Designer (a standalone app).

From Kev's Qt Mobility Development
Reminds me of Borland Delphi very much! Oh, the good old days...
To get a Hello World message:
  1. Drag a Label from the left widget box under Display Widgets.
  2. Set its text property to “Hello World”. You can also right click the Label, and click “ Change plain text...
  3. Set alignment.Horizontal to AlignHCenter.
  4. Click the main window, and click the Lay Out Vertically toolbar button (Ctrl+L). This applies the QVBoxLayout and expand the Label to fill the window.
This is how the form looks like in Qt's Form Editor:

From Kev's Qt Mobility Development
Preview your form by clicking Tools -> Form editor -> Preview (Ctrl+Alt+R).

From Kev's Qt Mobility Development
Actually my job to demonstrate Hello World is already finished, but... it's too easy, right?

Behind the scenes, Form Editor produces the following XML.

To see the UI code, close the current Form Editor. Then right-click mainwindow.ui, and click Open With -> Plain Text Editor.

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>309</width>
    <height>189</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <widget class="QLabel" name="label">
      <property name="text">
       <string>Hello World!</string>
      </property>
      <property name="alignment">
       <set>Qt::AlignCenter</set>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>309</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>true</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

As you see, Form Editor / Qt Designer is very easy to use, and should be enough for most purposes. It also has its quirks, see a post about Fighting Qt Designer grid layout for more complex (and practical) examples.

Demonstrating Qt's Automatic Destructor

Mas Ariya Hidayat told me that Qt had automatic memory management / garbage collection features. It's one feature that made me more interested in Java, C#, Ruby, PHP, and Python, than C and C++.

In practice, this means that Qt objects are automatically deleted when its parent is deleted.

By "Qt object" I mean any object that inherits QObject.

From qt-interest discussion: Qt Class Destructor - No Need for Delete:
If the constructor for the class expects a QObject* parent parameter, and you pass it one, then you can expect that when the parent dies, the child will also die. If it does not expect such a parameter, or it expects one but you pass it 0, or do not pass it anything and thus it defaults to 0, then you will need to clean the object up yourself later with delete.

Demo-ing Automatic Destructor on Hello World App


Let's take my previous Hello World app and add a destructor.

helloworld.cpp

...

HelloWorld::~HelloWorld() {
    printf("Bye bye...!\n");
}

...

and use the new operator to create HelloWorld object:

main.cpp :

...

    HelloWorld *helloWorld = new HelloWorld(&a);
    QObject::connect(helloWorld, SIGNAL( done() ), &a, SLOT( quit() ), Qt::QueuedConnection);
    QTimer::singleShot(0, helloWorld, SLOT( sayHello() ));

...

Run the application, and we get:

Starting /home/ceefour/Sandbox/helloworld-console/helloworld-console...
Starting up...
Hello World!
Bye bye...!
/home/ceefour/Sandbox/helloworld-console/helloworld-console exited with code 0

Works as advertised! The HelloWorld::~HelloWorld() destructor is called, and there's no need to delete the object explicitly.

The secret recipe is this particular line:

HelloWorld *helloWorld = new HelloWorld(&a);

It creates the HelloWorld object as a child of Qt application.

In effect, when Qt application object is destroyed, the HelloWorld object gets destroyed first.

If we change it to this:

HelloWorld *helloWorld = new HelloWorld;

The destructor won't be called automatically, and we have to call it ourselves.

I don't think it's technically an automatic memory management with garbage collection, but when used properly, it's very useful.

Create a Hello World Console Application with Qt

A console application is usually used for daemon-style long-running background processes.

But just to get myself wet with Qt, here I create a Qt console application for displaying "Hello World".

Steps to Create The App

From Qt Creator, create a Qt Console application.

Right click the project, create a new class. Name the class HelloWorld and inherit from QObject.

Add sayHello() and done() methods so helloworld.h now looks like this:

helloworld.h :
#ifndef HELLOWORLD_H
#define HELLOWORLD_H

#include <QObject>

class HelloWorld : public QObject
{
Q_OBJECT
public:
    explicit HelloWorld(QObject *parent = 0);

signals:
    void done();

public slots:
    void sayHello();

};

#endif // HELLOWORLD_H

Implement the sayHello() method:

helloworld.cpp :
#include "helloworld.h"
#include <stdio.h>

HelloWorld::HelloWorld(QObject *parent) :
    QObject(parent)
{
}

void HelloWorld::sayHello() {
    printf("Hello World!\n");
    done();
}

In main.cpp, add some plumbing to use the HelloWorld class.

main.cpp :
#include <QObject>
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <helloworld.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    fprintf(stderr, "Starting up...\n");

    QCoreApplication a(argc, argv);

    HelloWorld helloWorld;
    QObject::connect(&helloWorld, SIGNAL( done() ), &a, SLOT( quit() ), Qt::QueuedConnection);
    QTimer::singleShot(0, &helloWorld, SLOT( sayHello() ));

    return a.exec();
}

Running the App


To run the app, click the Run button or press Ctrl+R.

Qt Creator should build the application, and show the output in the Application Output panel.

Starting /home/ceefour/Sandbox/helloworld-console/helloworld-console...
Starting up...
Hello World!
/home/ceefour/Sandbox/helloworld-console/helloworld-console exited with code 0

Application Logic


The main entry point deserves some explanation.
  • It creates a Qt Core application (QCoreApplication) in variable a.
  • Connects helloWorld's done() signal to the app's quit() slot/method, with a connection type of Qt::QueuedConnection.
  • Creates a single shot timer (QTimer) with 0 ms delay that triggers helloWorld's sayHello() slot/method.
See Qt's Signals and Slots for more explanation what what connect, signals, and slots are. It's basically a unified event handling mechanism for Qt applications.

a.exec() will run Qt's event loop, which will process incoming events:
  1. The timer event will be processed, therefore executing helloWorld.sayHello().
  2. sayHello() does its job (printing "Hello World!"), then it will call its done() signal.
  3. helloWorld.done() signal was connected to a.quit(), therefore telling Qt application to stop the event loop and quit the application.
P.S.: Queued Connection

A default connection calls the slot directly. However, I use Qt::QueuedConnection here so that the call is queued until the slot processes the message.

In this case it's actually not needed.

It's possible to:
  • Run helloWorld.sayHello() directly (without using QTimer), and it can still exit the application because the event is queued.
  • Leave out the Qt::QueuedConnection, and it can still exit the application because the direct a.quit() call happens after the event loop is started.
What happens if helloWorld.sayHello() is run directly, and Qt::QueuedConnection is not specified?

The app will not quit immediately, because the event loop will not have started when a.quit() is called, therefore having no effect. Which is incorrect logic.

Why Separate Header (.h) and Implementation (.cpp) Files?


In this example I separated helloworld.h from helloworld.cpp. You may be wondering if it's  possible to merge them into just one helloworld.cpp implementation file.

The answer is No. At least not if you use Q_OBJECT or other Qt macros. Snippet from C++ GUI Programming with Qt 4:
For moc to work correctly, we must put the class definition in a header file, separate from the implementation file. The code generated by moc includes this header file and adds some C++ boilerplate code of its own.
So, don't fight it. Besides, that's the convention in C++ world anyway.

Reference: qt-interest thread: QCoreApplication won't quit

Monday, December 28, 2009

Setting Up Qt Creator 1.3 with Qt SDK 4.5

I try to develop with Qt Creator 1.3 on Qt 4.5 built-in on Ubuntu, since Qt 4.6 is still building on my Core 2 Duo laptop.

Install package libqt4-dev using Synaptic to get the Qt 4.5 development library.
$ sudo aptitude install libqt4-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
Reading extended state information
Initializing package states... Done
The following NEW packages will be installed:
comerr-dev{a} libaudio-dev{a} libgssrpc4{a} libkadm5srv6{a} libkdb5-4{a}
libkrb5-dev{a} libmng-dev{a} libpq-dev{a} libqt4-dev libqt4-opengl-dev{a}
libsqlite0-dev{a} libssl-dev{a} libxcursor-dev{a} libxfixes-dev{a}
libxft-dev{a} libxi-dev{a} libxinerama-dev{a} libxmu-dev{a}
libxmu-headers{a} libxrandr-dev{a} qt4-qmake{a} x11proto-fixes-dev{a}
x11proto-randr-dev{a} x11proto-xinerama-dev{a}
0 packages upgraded, 24 newly installed, 0 to remove and 0 not upgraded.
Need to get 7,797kB of archives. After unpacking 43.1MB will be used.
Do you want to continue? [Y/n/?] y
Writing extended state information... Done
Get:1 http://id.archive.ubuntu.com karmic/main x11proto-fixes-dev 1:4.0-3 [13.9kB]
Get:2 http://id.archive.ubuntu.com karmic/main libxfixes-dev 1:4.0.3-2build1 [12.9kB]
Get:3 http://id.archive.ubuntu.com karmic/main libxcursor-dev 1:1.1.9-1build1 [32.4kB]
Get:4 http://id.archive.ubuntu.com karmic/main libxft-dev 2.1.13-3ubuntu1 [64.1kB]
Get:5 http://id.archive.ubuntu.com karmic/main libxi-dev 2:1.2.1-2ubuntu1 [84.2kB]
Get:6 http://id.archive.ubuntu.com karmic/main x11proto-xinerama-dev 1.1.2-5ubuntu1 [5,772B]
Get:7 http://id.archive.ubuntu.com karmic/main libxinerama-dev 2:1.0.3-2 [11.7kB]
Get:8 http://id.archive.ubuntu.com karmic/main libxmu-headers 2:1.0.4-2 [21.5kB]
Get:9 http://id.archive.ubuntu.com karmic/main x11proto-randr-dev 1.3.0-1 [37.7kB]
Get:10 http://id.archive.ubuntu.com karmic/main libxrandr-dev 2:1.3.0-2 [34.5kB]
Get:11 http://id.archive.ubuntu.com karmic/main libgssrpc4 1.7dfsg~beta3-1 [76.4kB]
Get:12 http://id.archive.ubuntu.com karmic/main libkdb5-4 1.7dfsg~beta3-1 [58.1kB]
Get:13 http://id.archive.ubuntu.com karmic/main libkadm5srv6 1.7dfsg~beta3-1 [73.0kB]
Get:14 http://id.archive.ubuntu.com karmic/main libmng-dev 1.0.9-1build1 [295kB]
Get:15 http://id.archive.ubuntu.com karmic/main libssl-dev 0.9.8g-16ubuntu3 [2,022kB]
Get:16 http://id.archive.ubuntu.com karmic/main comerr-dev 2.1-1.41.9-1ubuntu3 [41.4kB]
Get:17 http://id.archive.ubuntu.com karmic/main libkrb5-dev 1.7dfsg~beta3-1 [101kB]
Get:18 http://id.archive.ubuntu.com karmic/main libpq-dev 8.4.1-1 [201kB]
Get:19 http://id.archive.ubuntu.com karmic/main qt4-qmake 4.5.3really4.5.2-0ubuntu1 [1,322kB]
Get:20 http://id.archive.ubuntu.com karmic/main libxmu-dev 2:1.0.4-2 [60.2kB]
Get:21 http://id.archive.ubuntu.com karmic/main libaudio-dev 1.9.2-1 [513kB]
Get:22 http://id.archive.ubuntu.com karmic/main libsqlite0-dev 2.8.17-6build1 [217kB]
Get:23 http://id.archive.ubuntu.com karmic/main libqt4-dev 4.5.3really4.5.2-0ubuntu1 [2,459kB]
Get:24 http://id.archive.ubuntu.com karmic/main libqt4-opengl-dev 4.5.3really4.5.2-0ubuntu1 [39.4kB]
Fetched 7,797kB in 4min 19s (30.0kB/s)
Selecting previously deselected package x11proto-fixes-dev.
(Reading database ... 235068 files and directories currently installed.)
Unpacking x11proto-fixes-dev (from .../x11proto-fixes-dev_1%3a4.0-3_all.deb) ...
Selecting previously deselected package libxfixes-dev.
Unpacking libxfixes-dev (from .../libxfixes-dev_1%3a4.0.3-2build1_i386.deb) ...
Selecting previously deselected package libxcursor-dev.
Unpacking libxcursor-dev (from .../libxcursor-dev_1%3a1.1.9-1build1_i386.deb) ...
Selecting previously deselected package libxft-dev.
Unpacking libxft-dev (from .../libxft-dev_2.1.13-3ubuntu1_i386.deb) ...
Selecting previously deselected package libxi-dev.
Unpacking libxi-dev (from .../libxi-dev_2%3a1.2.1-2ubuntu1_i386.deb) ...
Selecting previously deselected package x11proto-xinerama-dev.
Unpacking x11proto-xinerama-dev (from .../x11proto-xinerama-dev_1.1.2-5ubuntu1_all.deb) ...
Selecting previously deselected package libxinerama-dev.
Unpacking libxinerama-dev (from .../libxinerama-dev_2%3a1.0.3-2_i386.deb) ...
Selecting previously deselected package libxmu-headers.
Unpacking libxmu-headers (from .../libxmu-headers_2%3a1.0.4-2_all.deb) ...
Selecting previously deselected package x11proto-randr-dev.
Unpacking x11proto-randr-dev (from .../x11proto-randr-dev_1.3.0-1_all.deb) ...
Selecting previously deselected package libxrandr-dev.
Unpacking libxrandr-dev (from .../libxrandr-dev_2%3a1.3.0-2_i386.deb) ...
Selecting previously deselected package libgssrpc4.
Unpacking libgssrpc4 (from .../libgssrpc4_1.7dfsg~beta3-1_i386.deb) ...
Selecting previously deselected package libkdb5-4.
Unpacking libkdb5-4 (from .../libkdb5-4_1.7dfsg~beta3-1_i386.deb) ...
Selecting previously deselected package libkadm5srv6.
Unpacking libkadm5srv6 (from .../libkadm5srv6_1.7dfsg~beta3-1_i386.deb) ...
Selecting previously deselected package libmng-dev.
Unpacking libmng-dev (from .../libmng-dev_1.0.9-1build1_i386.deb) ...
Selecting previously deselected package libssl-dev.
Unpacking libssl-dev (from .../libssl-dev_0.9.8g-16ubuntu3_i386.deb) ...
Selecting previously deselected package comerr-dev.
Unpacking comerr-dev (from .../comerr-dev_2.1-1.41.9-1ubuntu3_i386.deb) ...
Selecting previously deselected package libkrb5-dev.
Unpacking libkrb5-dev (from .../libkrb5-dev_1.7dfsg~beta3-1_i386.deb) ...
Selecting previously deselected package libpq-dev.
Unpacking libpq-dev (from .../libpq-dev_8.4.1-1_i386.deb) ...
Selecting previously deselected package qt4-qmake.
Unpacking qt4-qmake (from .../qt4-qmake_4.5.3really4.5.2-0ubuntu1_i386.deb) ...
Selecting previously deselected package libxmu-dev.
Unpacking libxmu-dev (from .../libxmu-dev_2%3a1.0.4-2_i386.deb) ...
Selecting previously deselected package libaudio-dev.
Unpacking libaudio-dev (from .../libaudio-dev_1.9.2-1_i386.deb) ...
Selecting previously deselected package libsqlite0-dev.
Unpacking libsqlite0-dev (from .../libsqlite0-dev_2.8.17-6build1_i386.deb) ...
Selecting previously deselected package libqt4-dev.
Unpacking libqt4-dev (from .../libqt4-dev_4.5.3really4.5.2-0ubuntu1_i386.deb) ...
Selecting previously deselected package libqt4-opengl-dev.
Unpacking libqt4-opengl-dev (from .../libqt4-opengl-dev_4.5.3really4.5.2-0ubuntu1_i386.deb) ...
Processing triggers for man-db ...
Processing triggers for doc-base ...
Processing 1 added doc-base file(s)...
Registering documents with scrollkeeper...
Processing triggers for install-info ...
install-info: warning: no info dir entry in `/usr/share/info/menu.info.gz'
Setting up x11proto-fixes-dev (1:4.0-3) ...
Setting up libxfixes-dev (1:4.0.3-2build1) ...
Setting up libxcursor-dev (1:1.1.9-1build1) ...
Setting up libxft-dev (2.1.13-3ubuntu1) ...
Setting up libxi-dev (2:1.2.1-2ubuntu1) ...
Setting up x11proto-xinerama-dev (1.1.2-5ubuntu1) ...
Setting up libxinerama-dev (2:1.0.3-2) ...
Setting up libxmu-headers (2:1.0.4-2) ...
Setting up x11proto-randr-dev (1.3.0-1) ...
Setting up libxrandr-dev (2:1.3.0-2) ...
Setting up libgssrpc4 (1.7dfsg~beta3-1) ...
Setting up libkdb5-4 (1.7dfsg~beta3-1) ...
Setting up libkadm5srv6 (1.7dfsg~beta3-1) ...
Setting up libmng-dev (1.0.9-1build1) ...
Setting up libssl-dev (0.9.8g-16ubuntu3) ...
Setting up comerr-dev (2.1-1.41.9-1ubuntu3) ...
Setting up libkrb5-dev (1.7dfsg~beta3-1) ...
Setting up libpq-dev (8.4.1-1) ...
Setting up qt4-qmake (4.5.3really4.5.2-0ubuntu1) ...
update-alternatives: using /usr/bin/qmake-qt4 to provide /usr/bin/qmake (qmake) in auto mode.

Setting up libxmu-dev (2:1.0.4-2) ...
Setting up libaudio-dev (1.9.2-1) ...
Setting up libsqlite0-dev (2.8.17-6build1) ...
Setting up libqt4-dev (4.5.3really4.5.2-0ubuntu1) ...
update-alternatives: using /usr/bin/moc-qt4 to provide /usr/bin/moc (moc) in auto mode.
update-alternatives: using /usr/bin/uic-qt4 to provide /usr/bin/uic (uic) in auto mode.
update-alternatives: using /usr/bin/lupdate-qt4 to provide /usr/bin/lupdate (lupdate) in auto mode.
update-alternatives: using /usr/bin/lrelease-qt4 to provide /usr/bin/lrelease (lrelease) in auto mode.

Setting up libqt4-opengl-dev (4.5.3really4.5.2-0ubuntu1) ...
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
Reading package lists... Done
Building dependency tree
Reading state information... Done
Reading extended state information
Initializing package states... Done
Writing extended state information... Done
Launch Qt Creator. Now you can create a new project and launch it.

Qt Creator should detect your Qt4 installation properly.


From Kev's Qt Mobility Development

You certainly want to enable the Debugging Helper.
  1. Go to Tools -> Options -> Qt4 versions.
  2. Under Debugging Helper, click Debugging Helper -> Rebuild.
  3. The Debugging Helper icon will turn from red to green check mark.

Qt Mobility API Features & Target Platforms

Qt Mobility is part of Qt's emerging new APIs.

Although it's obviously targeted for mobile devices, some of the specs are implemented on desktop platforms.

Target platforms supported by Qt Mobility:
  • Symbian S60 3rd & 5th Edition (pretty good)
  • Maemo
  • Linux/X11
  • Windows
  • OS X (Mac)
All target platforms support these features:
  • Service Framework
  • Bearer
  • Publish/Subscribe
  • System Information
Messaging feature is "half complete", on Symbian S60 the spec is partially implemented, on Linux/Mac it needs QMF, Windows needs Outlook & MAPI.

Currently, only mobile devices (Symbian S60 3rd Edition and 5th Edition) support these APIs:
  • Contacts
  • Location
Qt encourages independent vendors to develop engines/providers for these specs on desktop systems (Windows/Linux/Mac), however documentation for how to do so currently does not exist.

These APIs are incompletely implemented or non-existent in all platforms:
  • Multimedia

Starting Up Qt Development

I created this blog to document my pursuit on Nokia's Qt Mobility Contest.

I use Ubuntu Karmic Koala 9.10, which contains Qt Creator 1.2 and Qt 4.5. I want to use the new Qt Creator 1.3 and Qt 4.6.

This is what Qt Creator 1.3 looks like for you curious people:


From Kev's Qt Mobility Development

Before jumping on to Qt Mobility and (then) Qt for Symbian, first I need to get started with Qt.
  1. Download Qt Development Environment (Qt Creator and Platform SDK)
  2. Install Qt Creator 1.3. This part was easy, simply chmod +x (add executable permission) to Qt Creator 1.3 installer and run it. It launches GUI Installer which was fast and smooth.
  3. Install Qt 4.6. Unfortunately, Nokia/TrollTech didn't provide Qt binaries for Linux systems.
  4. Configure Qt Creator with Qt 4.6. (and rebuild the debugging helper.) This one is easy, see below.

Installing Qt 4.6 from Sources
  1. Install checkinstall package. This will help you uninstall Qt 4.6 easily.
  2. Install dependencies:
    $ sudo apt-get build-dep libqt4-core
  3. Unpack the Qt 4.6 sources.
  4. Open a Terminal on the extracted folder.
  5. Run:
    $ ./configure
    By default, Qt will be installed at /usr/local/Trolltech. You may want to use the -prefix argument to specify another installation folder.
  6. Run:
    $ sudo checkinstall
    In case you can't/don't want to use checkinstall:
    $ sudo make install
  7. Be very patient.
    I've been running the make for about an hour now and it still hasn't finished. Time to take a nap.
    Update: Oh, it's finished in about 2.5 hours! Yaay!
Configure Qt Creator 1.3 with Qt 4.6


From Kev's Qt Mobility Development

  1. Launch Qt Creator.
  2. Go to Tools -> Options.
  3. Click "Qt versions".
  4. Click the Add button, then browse for your Qt 4.6 installation folder. Choose the bin/qmake binary.
    In my system, it is: /usr/local/Trolltech/Qt-4.6.0/bin/qmake
  5. Under Debugging Helper, click "Rebuild"
  6. Make sure you set it as Default Qt version
Now you should be able to create, run, and debug* Qt apps right away.

* GDB 7.0 Problems?

Qt says GDB 7.0 has issues with debugging. Unfortunately, Ubuntu 9.10 uses GDB 7.0:
$ gdb --version
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
For Qt development, downgrading to GDB 6.8 is recommended for now.

And sure enough, I can't debug my simple Hello World Qt console application with GDB 7.0 installed:
&"warning: GDB: Failed to set controlling terminal: Invalid argument\n"
/home/ceefour/Sandbox/helloworld-console/helloworld-console: symbol lookup error:
/usr/local/Trolltech/Qt-4.6.0/lib/libQtGui.so.4: undefined symbol: _ZNK17QVariantAnimation10metaObjectEv