Monthly Archives: May 2011

Adding QML into an existing Qt project

Earlier today i got an email from someone about SymFTP which amongst other things said this:

when I look at the Help tab in SymFTP is won’t scroll so I can only see what’s on the screen and not what’s further down.

The user was trying to use kinetic / flick scrolling to navigate the help tab, which is what you’d normally expect in any mobile based app. Qt currently doesn’t have native support for Kinetic scrolling and won’t do till Qt 4.8 (we’re currently at 4.7 and when the SymFTP interface was written it was 4.6.3). So the only way to actually scroll through the tab was to grab and drag the scroll bar on the right hand side:

However QML has a flickable class which handles kinetic scrolling perfectly, so i figured i’d just rewrite that tab and insert the QML code into my existing app. I’d already covered mixing QML and Qt in my previous blog post but this was almost doing the opposite, integrating QML into an existing Qt app.

First i needed to add QtDeclarative to my .pro file:
QT       += core gui network declarative
Then i needed to add the QDeclarativeView header into the file i was going to set the new QML view in:
#include <QDeclarativeView>
Next qml code for the had to be written:

import QtQuick 1.0

Rectangle {
    id:root
    width: 355
    height: 370
    color: "black"

    Flickable{
        width: parent.width
        height: parent.height

        contentWidth: parent.width
        contentHeight: col.height

        Column{
            id:col
            spacing: 10

            Text{
                width: parent.width
                color:"white"
                text: "Start SymFTP by pressing the big power button on the main 
screen, if a valid wifi network is found the server address will change 
and the button will turn green"
                wrapMode: Text.Wrap
            }

            Image{
                source: "qrc:/images/images/serveraddress.jpg"
            }

            Text{
                width: parent.width
                color:"white"
                text: "On your computer open the file browser and enter 
the full server address string into the location bar at the top then
 press enter. If you're using an FTP client such as filezilla
 (recommended!)  then enter the address (without the ftp:// prefix)
 into the address and port fields."
                wrapMode: Text.Wrap
            }

            Image{
                source: "qrc:/images/images/explorerfilezilla.jpg"
            }

            Text{
                width: parent.width
                color:"white"
                text: "Now you can begin to transfer files to and from your 
device over wifi without needing your usb cable!"
                wrapMode: Text.Wrap
            }

        }
    }
}

and finally tell the existing C++ code to call the new file:

//setup help tab
    QDeclarativeView *view = new QDeclarativeView(  );
    view->setSource( QUrl("qrc:/qml/Help.qml") );
    ui->helpLayout->addWidget(view);

Using QtCreators design view i added a layout called helpLayout to the main tab widget. The layout was needed to hold the QDeclarativeView object.

I also added the Help.qml file which is why its referenced using qrc:/ instead of using QUrl::fromLocalFile("Help.qml") which would normally be done for local files.

And thats it! New builds of SymFTP will have this new Help tab, which (based on a couple of other points from the same email) will also have its content fleshed out a bit more too!

Ovi Store App Updates

Finally something I’ve been looking forward to since i had my first app SymFTP published. Every time I put an update out to the Ovi store, the only way for users to get the updates was for them to uninstall the app and then re-download it. This was great for Free apps but for paid for apps there was only a download limit of 5 which was really annoying and limiting, meaning you could be asked to pay for Apps again that you’d already paid for! The Android market handles things differently where once you’ve paid for an app you can download it as many times as you like (which in my opinion is a much better way of doing things!).

Anyway the Ovi publish blog has a new post detailing how the new app update system will work. Whilst its not quite as good as the Android system that automatically notifies you when updates are available, the new Ovi update system is certainly welcome. You are only notified of app updates once the store has been launched and will hopefully be rolled out to Symbian^3 devices in the next week or so!

A recent update to the Ovi publishing site now sees the apps version number extracted whenever a new file is uploaded to the publishing area and I assume this is what is used to compare and determine whether or not an app needs updating!

Hopefully a new minor update of SymFTP will be published in the next week or so and we’ll be able to test the update process out!

Speech Recognition In Google Chrome

I don’t know how I’ve never noticed this before or why i don’t recall seeing this in any of the other web dev blogs i read but Google Chrome can now do speech recognition (well has been able to do so for some time actually)!!

I didn’t actually come across it myself it was my brother who first noticed it on isohunt.com, the tiny microphone which is right justified within the search box at the top of the page that looks a little something like this:x-webkit-speechThe code actually being used to add the icon is Google’s custom webkit property:

x-webkit-speech

Which is an attribute of the HTML “input” tag, and can be used as such:

<input name="speech" type="text" x-webkit-speech="" />

Clicking on the icon opens up a small window that tells you to “Speak Now”, it also presents a few bars the indicate that sound is being recorded. Once you’ve spoken the sound clip is sent off to Google’s server and i assume is processed by some super awesome algorithm and the interpreted text is returned and populates the input tags value field.

I’ve not seen it used anywhere else but the tests I ran on isohunt.com we’re fairly accurate with and whilst it might not be used that much by most people it would certainly help those who have accessibility issues and or really bad spelling :P and is generally all around pretty awesome!

Mixing Qt And QML

Whilst QML is great for making awesome super smooth user interfaces, in its current form its not great at doing things like image painting and getting access to other system properties. This post will talk about exposing Qt variables to QML and i will do a follow up post soon about exposing Qt widgets to QML.

In my Meme Generator i needed to get hold of a list of drives for the end user to select as a save path for the Meme Images. Whilst QML can access the file system using FolderListModel, it cannot just return a list of the root directories on a system like the Qt Class QDir‘s static function drives.

The following method could be included into your QML application’s main.cpp or as a new Class or Header file (I had it in a class called DriveData!).

static QStringList getDrives() {
    QFileInfoList fileList  = QDir::drives();
    QStringList drives;
    foreach( QFileInfo file, fileList ){
        if( file.isWritable() && 
            file.filePath() != "Z:/" &&  file.filePath() != "D:/"  ){
            drives << file.filePath();
        }
    }
    return drives;
}
This method simply takes a list of drives on the file system and creates a QStringList of drives names that are writable.

Note: On the Symbian platform D:/ and Z:/ are hidden drives that we wouldn’t want the end user to to touch which is why I decided not to add them to my QStringList.

Now we have to expose the QStringList to the QML application which is done in the main.cpp.

QmlApplicationViewer viewer;
QStringList drivesModel = DriveData::getDrives();
viewer.rootContext()->setContextProperty("DrivesModel", 
QVariant::fromValue(drivesModel) );
Now QML can see the new property and you can access it using the quoted name we gave it, in this instance “DrivesModel”

ListView{
     id: pathList
     model: DrivesModel
     delegate: ...
}
And thats it! Simple! To expose other variables to QML that are not going to be used in a Model context is not too different, we can use a similar call, again after the QmlApplicationViewer has been created. I used the following code to expose the version number to the Info dialog in QML:
const QString _VERSION_ = "1.0.0";
viewer.rootContext()->setContextProperty("_VERSION_", _VERSION_);

SymMeme-QML – A QML Based Meme Generator!

Today i finished my first QML based application! Its a reworking of my current Meme Generator which is currently available for free download on the OVI (soon to be Nokia!) Store for Symbian 3 devices!

Obligatory screen shot:

SymMemeQML ListView

Why remake something id only just had published? I love the old meme generator and used it a lot it just wasn’t as fluid or as nice to use as i wanted it. So when Nokia allowed QML applications into the ovi store it was a good opportunity for me to learn this new language and improve my existing app.

SymMemeQML Landscape view

So whats new in the version?

  • Fluid kinetic scrolling thanks to the QML Flickable class which replaces the horrible Qt class i was using before which was really hit and miss!
  • Landscape view! one thing i never really worked out using Qt layouts was how to re-arrange them when switching from portrait to landscape, which is why my apps before were all locked to portrait. This now works fine as can be seen in the screen shot above!
  • Filenames now use the text you’ve written rather than being named “meme-X.jpg” as they were previously which makes finding your memefiles a little easier when navigating via a file browser
  • I learnt how to mix Qt and QML together – nothing great for the end user but awesome from a developer aspect!
  • More characters! Since the last release ive come across more memes and rediscovered old ones which i decided to put in including:
  1. Anti Joke Chicken (Personal favorite atm!)
  2. Clarinet Kid
  3. High Expectations Asian Father
  4. Paedobear
  5. Rasta Science Teacher

SymMeme Portrait View

Whats next for the Meme generator? I’m planning on adding twitter upload to the memes once the images have been saved maybe a meme viewer gallery to quickly see all the meme images you’ve created and obviously adding more characters! If you’ve got any you’d like to see in there let me know!

Awsome no? SymMeme-QML is currently being reviewed by the OVI store team and will surface in the store shortly (i’ll make a short post again when it surfaces!), in the meantime get the old one for free here!

Hello World!

Hello World! Ill try and keep this short and sweet so i can get on with my second, far more interesting post! I’m Talvinder Bansal a 25 year old software developer from the center of the UK! Most of my skills are in web languages predominately  php and sql complimented with xhtml, javascript and css! However most of this blog will be dedicated to my mobile app development which is mostly written in Qt and more recently QtQuick for the Nokia Symbian platform!

People tend to ask me why i haven’t chosen to develop apps for Android or IOS the answer to both being i don’t have a handset to test the apps on (or a MAC to develop for IOS!)  But with the revenue generated from sales of some of my apps i am hoping to buy a windows phone and start developing for that shortly too!!

Anyway welcome and dont forget to to subscribe to my RSS feed and follow me on twitter www.twitter.com/talv.