Saturday, November 26, 2011

Using custom Font with Qt

Recently in one of my application I wanted to use custom font and in little time I figured out that Qt has vary nice support to use custom font with both Qt C++ and QML.

I used following code in my application. Here is output of below code.


Following is code to use custom font with Qt C++.
#include <QPainter>
#include <QFontDatabase>

MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent)
{
    QFontDatabase::addApplicationFont("sandsped.ttf");
}

void MyWidget::paintEvent(QPaintEvent */*event*/) {
    QPainter painter(this);
    painter.drawText(10,20,"Default Font");
    painter.setFont(QFont("Sandoval Speed"));
    painter.drawText(10,50,"Custom Font");
}


Following is code to use custom font with QML.
    FontLoader { id: myFont; source: "sandsped.ttf" }

    Column {
        spacing: 30
        anchors.horizontalCenter: parent.horizontalCenter
        Text {
            text: "Default Font"
        }

        Text {
            font.family: myFont.name
            text: "Custom Font";
        }
    }

Thursday, November 17, 2011

Virtual Joystick with QML

Recently out of curiosity I tried to created virtual joystick, which nowadayx s used quite frequently touch based games.

Well my implementation still required some improvement to provide real feel of joystick but its still quite useful. Here is output.

To test my joystick, I also created a sprite which moves in almost all direction.

Here is my QML code for joystick. I basically used two circle and checking inner circle position with outer circle and deciding direction. I am not describing code, but tried to put necessary comment in code.
import QtQuick 1.0

Item {
    id:joyStick;
    property int offset:30;

    signal dirChanged(string direction);
    signal pressed();
    signal released();

    Rectangle {
        id:totalArea
        color:"gray"
        radius: parent.width/2
        opacity: 0.5
        width:parent.width;height:parent.height
    }

    Rectangle{
        id:stick
        width:totalArea.width/2; height: width
        radius: width/2
        x: totalArea.width/2 - radius;
        y: totalArea.height/2 - radius;        
        color:"black"
    }

    MouseArea{
        id:mouseArea
        anchors.fill: parent

        onPressed: {
            joyStick.pressed();
        }

        onMousePositionChanged: {            
         //(x-center_x)^2 + (y - center_y)^2 < radius^2
         //if stick need to remain inside larger circle
         //var rad = (totalArea.radius - stick.radius);
         //if stick can go outside larger circle
         var rad = totalArea.radius;
         rad =  rad * rad;

         // calculate distance in x direction
         var xDist = mouseX - (totalArea.x + totalArea.radius);
         xDist = xDist * xDist;

         // calculate distance in y direction
         var yDist = mouseY - (totalArea.y + totalArea.radius);
         yDist = yDist * yDist;

         //total distance for inner circle
         var dist = xDist + yDist;            

         //if distance if less then radius then inner circle is inside larger circle
         if( rad < dist) {
             return;
         }

         //center of larger circle
         var oldX = stick.x; var oldY = stick.y;
         stick.x = mouseX - stick.radius;
         stick.y = mouseY - stick.radius;

         //using L R U D LU RU LD RD for describe direction
         var dir="";

         //check if Right or left direction, 
         //by checking if inner circle's y is near center of larger circle
         if( stick.y >= totalArea.radius - stick.radius - joyStick.offset 
 && stick.y+stick.height <= totalArea.radius + stick.radius + joyStick.offset) {
             if( stick.x + stick.radius > totalArea.x + totalArea.radius) {
                 dir = "R";
             } else if( stick.x < totalArea.x + totalArea.radius) {
                 dir = "L";
             }
         }
         //check if Up or Down direction, 
         //by checking if inner circle's x is near center of larger circle
         else if( stick.x >= totalArea.radius - stick.radius - joyStick.offset 
 && stick.x + stick.width <= totalArea.radius + stick.radius + joyStick.offset) {
            if( stick.y + stick.radius > totalArea.y + totalArea.radius) {
                 dir = "D";
            } else if( stick.y < totalArea.y + totalArea.radius) {
                 dir = "U";
            }
         }
         //check if Up Left or Up Right direction,
         //by checking if inner circle is near one of top corner of larger circle
         else if( stick.y < totalArea.radius - stick.radius ) {
            if( stick.x + stick.radius > totalArea.x + totalArea.radius) {
                dir = "R";
            } else if( stick.x < totalArea.x + totalArea.radius) {
                dir = "L";
            }
            dir = dir +"U";
         }
         //check if Down Left or Down Right direction,
         //by checking if inner circle is near one of bottom corner of larger circle
         else if ( stick.y + stick.radius >= totalArea.radius + stick.radius ) {
            if( stick.x + stick.radius > totalArea.x + totalArea.radius) {
               dir = "R";
            } else if( stick.x < totalArea.x + totalArea.radius) {
               dir = "L";
            }
            dir = dir +"D";
         }

         joyStick.dirChanged(dir);
        }

        onReleased: {
            //snap to center
            stick.x = totalArea.width /2 - stick.radius;
            stick.y = totalArea.height/2 - stick.radius;

            joyStick.released();
        }
    }
}

Follwing my code for sprite used in above video.
import QtQuick 1.0

Item {
    id:sprite
    width: 50; height: 50
    clip:true
    property alias running: timer.running;
    property int frameCount: 5
    property int frame:0
    property int row:0

    property int xDir:0;
    property int yDir:0;

    Image{
        id:image
        source:"man.png"
        x:-sprite.width * sprite.frame;
        y:-sprite.height * sprite.row;
    }

    function changeDirection(direction) {
        if( direction === "L") {
            sprite.row=6;
            sprite.xDir = -1;
            sprite.yDir = 0;
        } else if( direction === "R") {
            sprite.row=2;
            sprite.xDir = 1;
            sprite.yDir = 0;
        } else if( direction === "U") {
            sprite.row=4;
            sprite.xDir = 0;
            sprite.yDir = -1;
        } else if( direction === "D") {
            sprite.row=0;
            sprite.xDir = 0;
            sprite.yDir = 1;
        } else if( direction === "RU") {
            sprite.row = 3;
            sprite.xDir = 1;
            sprite.yDir = -1;
        } else if( direction === "LU") {
            sprite.row = 5;
            sprite.xDir = -1;
            sprite.yDir = -1;
        } else if( direction === "RD") {
            sprite.row = 1;
            sprite.xDir = 1;
            sprite.yDir = 1;
        } else if( direction === "LD") {
            sprite.row = 7;
            sprite.xDir = -1;
            sprite.yDir = 1;
        }
    }

    function nextFrame() {
        sprite.frame = ++sprite.frame  % sprite.frameCount
        sprite.x = sprite.x + 5* sprite.xDir;
        sprite.y = sprite.y + 5* sprite.yDir;
    }

    Timer {
       id:timer
       interval: 150; running: false; repeat: true
       onTriggered: {
           nextFrame();
       }
    }
}
Finally, main qml file which include both joystick and sprite.
import QtQuick 1.0

Image {
    width: 854 ;  height:480    
    source:"grass.jpg"
    fillMode: Image.Tile

    Sprite{
        id:man
        x:parent.width/2 ; y: parent.height/2;
    }

    Connections {
        target: joyStick
        onDirChanged:{
            man.changeDirection(direction)
        }

        onPressed:{
            man.running=true;
        }

        onReleased:{
            man.running=false;
        }
    }

    Joystick{
        id:joyStick
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.bottomMargin: 10
        anchors.leftMargin: 10
        width:150;height:150
    }
}


Friday, November 4, 2011

Taking backup of Audiobook Reader on N9/N950

Recently I upgraded my N950 to PR 1.1 and realized that its camera is not working any longer.

After googling a bit I found that issue can be solved by flashing "Linux_OCF_39-5_RM680-RM680-OEM1.bin" image. But that means loosing all data, you can use backup and restore app but unfortunately my Audiobook Reader currently dose not support backup restore.  I need to  implement this feature in next release.

But if you need this support currently like me, then you can try following work around.

Audiobook reader setting file is store at "/home/user/.config/kunal/audiobookreader.conf". You can copy this file to your pc using ssh and then restore it at same place when you need.

I am not sure but same trick can be used for N900 as well.

Hope this helps.