Friday, March 1, 2013

Using LocalStorage API from javascipt in QML application

Recently I needed to create database from QML application on which I am working. I wanted to separate database related code from QML and created javascript file to handle database related work. I had to struggle a little to make storage API work from javascript, below are my findings.

As you might already know to use sqllite database in QML you will need to import LocalStorage API.
import QtQuick.LocalStorage 2.0 as Sql
This will work for QML but if you want to use it from javascript then you will need to use following syntax.
.import QtQuick.LocalStorage 2.0 as Sql
Now you should be able to use LocalStorage API in javascript. LocalStorage related API can be accessed by using LocalStorage object and we imported LocalStorage module as Sql, we will need to use access LocalStorage object from Sql scope. Like below.
var db = 
   Sql.LocalStorage.openDatabaseSync("TestDB", "1.0", "Description", 100000);
Now you can use this db object to create table and select values from it just like you do in QML. Following is sample example.
function getDatabase() {
     var db = 
     Sql.LocalStorage.openDatabaseSync("TestDB", "1.0", "Description", 100000);

     //create table
     db.transaction(
        function(tx) {    
var query="CREATE TABLE IF NOT EXISTS TEST(Id INTEGER PRIMARY KEY, Title TEXT)";                   
            tx.executeSql(query);
      });

     return db;
}

function printValues() {

    var db = getDatabase();
    db.transaction( function(tx) {
        var rs = tx.executeSql("SELECT * FROM TEST");
        for(var i = 0; i < rs.rows.length; i++) {
            var dbItem = rs.rows.item(i);
            console.log("ID:"+ dbItem.Id + ", TITLE:"+dbItem.Title);
        }
    });
}

Sunday, February 3, 2013

Audiobook Reader for BlackBerry BB10

For past some time I was working on porting my Audiobook Reader application to BlackBerry BB10 platform.

Application is quite similar to Meego version, though there are few feature missing in BB10 which are available on Meego version. I thought I will work on that once I have some feedback from existing version. So if you have installed and have some feedback kindly provide those.

Application is available both as free version and paid version. Feature wise both version are same, only difference is free version is ad sponsored.

Here is live demo on BB10 dev alpha device.


Here are few snapshot of application for BB10.








Hope you will like the application.






Friday, February 1, 2013

Preventing display dimming in BB10 with Qt

Recently I was creating an application for BB10, where I need to disable display dimming. This same approach also works to avoid auto lock.

There is already API for this if you are using cascades API.

Following should do for Cascades Application
//for C++
Application::mainWindow->screenIdleMode = ScreenIdleMode::KeepAwake;

//for QML, we need to use constant as it seems required enum is not exported properly
Application.mainWindow.screenIdleMode = 1

But my application was pure Qt application. For this I required to use native API. Following is code which i used to achieve desired behavior.
        QScopedPointer view(new QDeclarativeView());
        view->setSource(QUrl("app/native/assets/main.qml"));
        view->showFullScreen();

 int idle_mode = SCREEN_IDLE_MODE_KEEP_AWAKE;
 WId winId = view->winId();
 screen_set_window_property_iv(screen_window_t(winId), SCREEN_PROPERTY_IDLE_MODE,&idle_mode);
You will need to add following headers.
#include <bps/bps.h>
#include <bps/navigator.h>
#include <bps/screen.h>
And need to link screen library.
LIBS += -lscreen

Saturday, January 12, 2013

Signal Slot connection with C++ object and Cascades QML

In this blog post I shown how to achieve signal slot connection with QML and C++ object using Connections QML element.

In BB10 Cascades there are two ways to achieve the same.

First using java script connect method, like blow. Following code is from my previous post of Sprite animation.

This is preferred method as we are using only Cascades API.

Here timer is exported c++ object. By using timer.timeout.connect(renderNextFrame) statement. We are connecting the timeout signal of timer C++ object to renderNextFrame function.

import bb.cascades 1.0
...
        Container {
            id: sprite;
            horizontalAlignment: HorizontalAlignment.Center
            verticalAlignment: VerticalAlignment.Center
            layout: AbsoluteLayout {}  
            
            onCreationCompleted: {
                timer.timeout.connect(renderNextFrame);
                timer.start(200);
            }
                      
            function renderNextFrame() {
                ...
            }
       }
...

Second, Using Connections element like below.
import bb.cascades 1.0
import QtQuick 1.0
...
        Container {
            id: sprite;
            horizontalAlignment: HorizontalAlignment.Center
            verticalAlignment: VerticalAlignment.Center
            
            onCreationCompleted: {
                timer.start(200);
            }
            
            attachedObjects: [
                Connections {
                    target:timer;
                    onTimeout:{
                        sprite.renderNextFrame();
                    }
                }
            ]
            
            function renderNextFrame() {
             ...
            }
        }
...
To use Connections element, we need to import QtQuick components, as Connections element is part of QtQuick.

Once its imported, you will need to declare Connections element as part of attachedObjects. Then you can use it as usual in QML.

And just for reference, I create Timer object like below for above example.
    QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);

    QTimer* timer = new QTimer(app);
    qml->setContextProperty("timer",timer);

Sprite animation from sprite sheet with BB10 Cascades QML

In past I have posted solution for how to achieve sprite animation from sprite sheet with Qt C++ widget framework and with QML framework.

I tried to do the same with BB10 Cascades QML. Final output will look like below.


While it was quite straight forward to achieve this with Qt or QML, with Cascades you will need to tweak few things, like desabling the implicit Cascades animation and enabling cliping.

Following is my code for the dragon sprite.

        Container {
            id: sprite;
            preferredHeight: 100;
            preferredWidth: 100;
            clipContentToBounds: true
            horizontalAlignment: HorizontalAlignment.Center
            verticalAlignment: VerticalAlignment.Center
            layout: AbsoluteLayout {}  
            
            onCreationCompleted: {
                timer.timeout.connect(renderNextFrame);
                timer.start(200);
            }
                        
            function renderNextFrame() {
                dragonSprite.currentFrame = 
                      (dragonSprite.currentFrame + 1) % dragonSprite.frameCount;
                dragonSprite.translationX = 
                     -(dragonSprite.currentFrame * sprite.preferredWidth);
            }
                              
            ImageView{
                id: dragonSprite
                imageSource: "dragon.png"
                scalingMethod: ScalingMethod.AspectFill
                preferredHeight: 100
                preferredWidth: 500 
                property int currentFrame: 0
                property int frameCount: 5
                
                attachedObjects: [
                    ImplicitAnimationController {
                        propertyName: "translationX"
                        enabled: false
                    }
                ]  
            }
        }
First, I am creating parent Container which will hold ImageView with sprite sheet as image source.

We need enable clipping by setting clipContentToBounds to true so only certain portion of image is visible not whole image and also need to set preferredHeight, preferredWidth to indicate clip region.

Then I am attaching the renderNextFrame function with timeout signal. renderNextFrame takes care of which frame to display by changing current frame and translating the image view accordingly.

Second, I am creating ImageView with sprite sheet image as image source. We need to set scalingMethod to ScalingMethod.AspectFill so that unnecessary scaling is not performed. Again we need to set preferredWidth, preferredHeight so that proper frame is displayed.

I am also storing max frame count and current frame number with image.

And finally we need to disable the implicit animation for translationX property. Without this you will not be able to achieve smooth sprite animation. We can use ImplicitAnimationController element to disable implicit animation. However it allows only certain property to be disabled. Here is documentation about ImplicitAnimationController.

Once this is done, you will be able to see smooth animation.