Friday, December 17, 2010

Simple view switching animation with Qt Quick (QML)

Code updated after comment received from "mich", now code looks much better.
---------------------

Now that I have some free time and no work to do, I thought to play with QML and created simple demo that implement views and changes view on swipe event.

As of now I don't have latest QML installed, therefor I am not able to use GestureArea QML element to detect swipe gesture and decided to implement my own swipe detection code in QML.

In demo, view is quite simple just showing colored rectangle and string. My intention for demo was to create reusable view element and to change view from one to another.

My view code is as below, I am calling it as screen in code and named QML file as Screen.qml. Mainly screen element maintain states to hide and show view and animate the transition. In real world it might required lots of other property and function but my implementation have only few.
import Qt 4.7

Item {
    id: screen
    property string color: "red"    
    property string title: "title"
    opacity: 1    

    function hide() {
        screen.state = 'hide';
        screen.x = 0;
    }

    function show(xVal) {        
        screen.x = xVal;        
        screen.state  = 'show';
    }

    Rectangle {
        id: rect
        width: 480
        height: 640
        color:  screen.color
    }

    Text {
        id: title
        text: screen.title;
    }

    states: [
             State {
                 name: "show"
                 PropertyChanges {
                     target: screen
                     x: 0
                     opacity:1
                 }
             },
             State {
                 name: "hide"
                 PropertyChanges {
                     target: screen
                     opacity:0
                 }
             }
         ]

    transitions: [             
             Transition {
                 from:"hide"
                 to:"show"
                 NumberAnimation { properties: "x"; duration:500}                 
                 NumberAnimation { properties: "opacity"; duration: 700 }
             },
             Transition {
                 //from: "show"
                 to: "hide"
                 NumberAnimation { properties: "opacity"; duration: 700 }
             }
         ]
}
In my main.qml entry qml code, I have swipe detection code and view switching code as below.
import Qt 4.7

Rectangle {
    id: container
    width: 480
    height: 640    
    property int currentScreen: 0
    property int previousScreen: 0

    //creating array of screens
    property list<item> screens: [
    Screen {
            parent: container
            id: firstScreen
            title:"First Screen"
            color: "blue"
        },
        Screen {
            parent: container
            id: secondScreen
            title:"Second Screen"
            color: "red"
        },
        Screen {
            parent: container
            id:thirdScreen
            title:"Third Screen"
            color:"green"
        },
        Screen {
            parent: container
            //anchors.fill: parent
            id:fourthScreen
            title:"Fourth Screen"
            color:"orange"
        }
        ]

    Component.onCompleted: {
           console.log("Startup script");
           container.currentScreen = 0;
           container.previousScreen = 0;
           for(var i=0; i < 4; ++i) {
           screens[i].hide();
       }
       screens[0].show(0);
    }

    // function to show particular view 
    function showScreen(screenNo,direction) {
      screens[previousScreen].hide();
       var xVal = direction == -1 ? 400 : -400;
       screens[screenNo].show(xVal);
    }
    
    // function to switch view on swipe
    function onLeftSwipe() {
        previousScreen = currentScreen;
        currentScreen = currentScreen +1;
        if(currentScreen > 3 ) {
            currentScreen = 0;
        }
        showScreen (currentScreen,-1)  ;
    }

    function onRightSwipe() {
        previousScreen = currentScreen;
        currentScreen = currentScreen -1;
        if(currentScreen < 0 ) {
            currentScreen = 3;
        }
        showScreen (currentScreen,1)  ;
    }

    // swipe detection code
    MouseArea {
        id: mouseArea
        anchors.fill: parent;

        property int oldX: 0
        property int oldY: 0

      onPressed: {
        oldX = mouseX;
        oldY = mouseY;
      }

      onReleased: {
          var xDiff = oldX - mouseX;
          var yDiff = oldY - mouseY;
          if( Math.abs(xDiff) > Math.abs(yDiff) ) {
              if( oldX > mouseX) {
                    onLeftSwipe();
              } else {
                    onRightSwipe();
              }
          } else {
              if( oldY > mouseY) {/*up*/ }
              else {/*down*/ }
          }
       }

    }
}

Overall I felt there is lot more to do to create truly reusable view code,but this is all for now.

Friday, December 10, 2010

Creating custom QItemDelegate with QPushButton in Qt

Recently I was working on Audiobook Reader application for maemo. For this application I have created one custom item delegate for QListView which contains two clickable item and generate signal accordingly.

For application I was using some different mechanism to create button inside custom item delegate, but now I found better way to create custom item delegate with QPushButton. So thought to share code.

Following is code for custom item delegate derived from QItemDelegate.

Update: I have uploaded following code to gitorous, Please visit this link if you want a working sample code.

#include <QItemDelegate>
class CustomItemDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    CustomItemDelegate(QObject *parent = 0);
    virtual void paint(QPainter *painter,
                       const QStyleOptionViewItem &option,
                       const QModelIndex &index) const ;

    virtual QSize sizeHint(const QStyleOptionViewItem &option,
                           const QModelIndex &index) const ;

    bool editorEvent(QEvent *event, QAbstractItemModel *model, 
                           const QStyleOptionViewItem &option, 
                           const QModelIndex &index);

signals:
    void buttonClicked(const QModelIndex &index);
private:
    QStyle::State  _state;
};

#include "customitemdelegate.h"
...

CustomItemDelegate::CustomItemDelegate(QObject *parent) :
    QItemDelegate(parent)
{
    _state =  QStyle::State_Enabled;
}

void CustomItemDelegate::paint(QPainter *painter,
                   const QStyleOptionViewItem &option,
                   const QModelIndex &index) const
{
   const QStandardItemModel* model = 
   static_cast<const QStandardItemModel*>(index.model());
   QStandardItem* item = model->item(index.row());

   QString text = item->text();
   QRect rect = option.rect;

    QRect textRect( rect);
    textRect.setHeight( 30);
    painter->drawText(textRect,text);

    QRect buttonRect( rect);
    buttonRect.setY(textRect.y()+ 35);
    buttonRect.setHeight( 30);
    QStyleOptionButton button;
    button.rect = buttonRect;
    button.text = text;
    button.state = _state | QStyle::State_Enabled;

    QApplication::style()->drawControl
        (QStyle::CE_PushButton, &button, painter);
}

QSize CustomItemDelegate::sizeHint(const QStyleOptionViewItem &/*option*/,
                       const QModelIndex &/*index*/) const
{
    //hard coding size for test purpose, 
    //actual size hint can be calculated from option param
    return QSize(800,70);
}

bool CustomItemDelegate::editorEvent(QEvent *event, 
    QAbstractItemModel *model, 
    const QStyleOptionViewItem &option, 
    const QModelIndex &index)
{
    if( event->type() == QEvent::MouseButtonPress ||
        event->type() == QEvent::MouseButtonRelease ) {
    } else {
         //ignoring other mouse event and reseting button's state
         _state = QStyle::State_Raised;
        return true;
    }

    QRect buttonRect( option.rect);
    buttonRect.setY(option.rect.y()+ 35);
    buttonRect.setHeight( 30);

    QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
    if( !buttonRect.contains( mouseEvent->pos()) ) {
        _state = QStyle::State_Raised;
        return true;
    }

    if( event->type() == QEvent::MouseButtonPress) {            
        _state = QStyle::State_Sunken;
    } else if( event->type() == QEvent::MouseButtonRelease) {
        _state = QStyle::State_Raised;
        emit buttonClicked( index);
    }    
    return true;
}
Basically in above code, I am calculating rect where I want to draw my button and drawing QPushButton on list item using QStyleOptionButton class.

And in editor event on mouse press and release event, I am checking if mouse position on click falls into my button's rect or not. If it falls inside my button's rect then I am emitting signal.

I am using item's signal as shown in below code.
CustomList::CustomList(QWidget *parent) :
    QWidget(parent),_view(0)
{
    _view = new QListView();
    _view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    _view->setEditTriggers(QAbstractItemView::NoEditTriggers);

    //creating custom item delegate and setting  it to view
    CustomItemDelegate* itemDelegate = new CustomItemDelegate(_view);
    _view->setItemDelegate( itemDelegate );

    _view->setModel(&_model); 
   
    //connecting delegate's signal to this class's slot
    connect(itemDelegate,SIGNAL(buttonClicked(QModelIndex)),
    this,SLOT(listButtonClicked(QModelIndex)));

    QHBoxLayout* mainLayout = new QHBoxLayout(this);
    mainLayout->addWidget( _view);

    //creating and adding data to model
    QStandardItem* item = new QStandardItem;
    item->setText("testing");

    QStandardItem* item1 = new QStandardItem;
    item1->setText("testing1");

    _model.appendRow(item);
    _model.appendRow(item1);
}

// following slot will be invoked when delegate's button is clicked
void CustomList::listButtonClicked(const QModelIndex &index)
{
    qDebug() << "######### listbutton clicked ######### " << index.row();
}
Following is snap of how custom item delegate looks.

Sunday, December 5, 2010

Audiobook Reader for N900 usign Qt and Phonon

So after long time I found enough time to complete my Audiobook Reader application. This application was in extra-devel repository for long time but there were few problem with it, now finally I worked on those bugs and I am satisfied enough to share information about it.

Now days almost all novels are available in audio format and I am huge fan of those audio book. Previously I was using n900's music player to hear those audio books. But music player dose not preserve last playing position and this create problem when phone restart.

So I created this Audiobook Reader application.Key features are listed below.
  • You can add multiple audiobook.
  • It support both individual audio file which contain whole book, or can add folder which contain books audio file.
  • You can bookmark position in audiobook and can resume from same position.
  • It remember bookmark for all audiobook.This mean you can play multiple audiobook simultaneously.
Following are snaps from  application.


Above snaps is of Book list view. This view list currently added books, 
  • Add Audio button is used to add single audio file which contain whole book content.
  • Add Folder button is used to add folder, which contain multiple audio file for book. Note that you need to select folder which contain audio files, not the individual files.
  • Pokemon icon is used to start playing individual audio book.
  • Cross mark icon is used to remove this book from book list.





In above snaps are from  Reading view.This view list currently played book's title, track name and artist's name.
  • > button is used to play book
  • || button is used to pause book
  • x button is used to stop book, it will put reading position to beginning.
  • <)) button is used to increase/ decrease volume
Currently you can download this application to your n900 from extra-devel repository.

Monday, November 29, 2010

Animating object along with curve in Qt using QPainterPath

Recently I was playing with Qt and found QPainterPath class. While reading documentation, I thought how can I use QPainterPath class and I created following prototype application in result.

QPainterPath can contain many different kind of shapes and we can draw all those shape using drawPath API of QPainter. But I used it to animate an object on curve path instead of just drawing, QPainterPath has some intresting API using which curve animation is quite easy.

In my sample app, I want to animate dot on curve as shown in below pic.


To achieve this, I first created a curved QPainterPath like following,
QPainterPath path;
path.moveTo(100,100);
path.quadTo(100,600,400,400);
Above code will draw curve as shown in above pic.

Now I created a timer and on timeout event, I am updating progress of dot on curve painter path. Like below.
void timeout()
{
    progress += 0.01;
    if( progress > 1 ) {
        progress  = 0;
    }
    update();
}
Now that, I have progress of dot on curve path at certain point in terms of percentage.QPainterPath has API pointAtPercent(), that can be used to get point on curve path at progress value and can draw Dot object at that point like below.
void Testwidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawPath( path );

    painter.setBrush(Qt::SolidPattern);
    painter.drawEllipse(path.pointAtPercent(progress),20,20);
}
Output of above code will look like following.


If you don't like creating animation using QTimer and wants same output using Qt's animation framework then following code shows how that can be done.

In following code, I have created a custom widget named DotWidget and I am animating it on curve path using QPropertyAnimation.

Following code creates a painter path and a widget then applies QPropertyAnimation on it.
createPath();
DotWidget* dotWidget = new DotWidget(this);

QPropertyAnimation* animation = new QPropertyAnimation(dotWidget,
                               "geometry",this);
animation->setDuration(20000);
animation->setEasingCurve(QEasingCurve::Linear);
animation->setLoopCount(-1); //loop forever

//setting value for animation on different position using QPainterPath
for( double i = 0 ; i < 1; i = i+0.1) {
    animation->setKeyValueAt(i,
               QRect(path.pointAtPercent(i).toPoint(),QSize(30,30)));
}
animation->start(); 
Following is code for DotWidget custom widget class. Its very simple widget that draws circle.
#include 
#include 
class DotWidget : public QWidget
{
    Q_OBJECT
public:
    explicit DotWidget(QWidget *parent = 0)
        :QWidget(parent)
    {}

    void paintEvent(QPaintEvent *)
    {
        QPainter painter(this);
        painter.setBrush(Qt::SolidPattern);
        painter.drawEllipse(0,0,25,25);
    }
};
I have created custom widget just to show how it can be done with custom widget, but you can apply same animation of any widget. I have uploaded video that shows output with QPushButton at end of post.

Thats all,following is video for custom animation with timer.



Following is video for animation using QPropertyAnimation with QPushButton

Wednesday, November 24, 2010

Qt Plugin and Signals

If is often required to emit signals from Plug-in created using Qt Plug-in Framework.

In such case most people, connect to signal from loaded plug-in which is derived from QObject and defined plug-in interface.

Like following sample plug-in,

Plug-in interface.
class Worker
{
public:
    virtual ~Worker() {}
    virtual void doWork() = 0;
};
Q_DECLARE_INTERFACE(Worker,"Worker");
Plug-in that implements required interface.
class SampleWorker: public QObject,public Worker
{
Q_OBJECT
public:
    void doWork();
signals:
    void workDone();
};
Plug-in loader code,
QPluginLoader pluginLoader(fileName);
QObject *plugin = pluginLoader.instance();
if (plugin) {
    Worker* worker = qobject_cast<Worker*>(plugin);
    if (worker) {        
        connect(worker,SIGNAL(workDone()),this,SLOT(workDone()));
        worker->doWork();
    }
}
In Plug-in loader code, We are creating plug-in object and if plug-in creation is successfully, we are connecting signal workDone() with some slot. Above code will work fine, because SampleWorker has defined workDone signal.

But problem here is, workDone signal is not part of Worker interface, it is defined in implemented plug-in. If plug-in defines required signal than all works well but we are not forcing plug-in to abide with interface.

Proper solution to this problem could be to create plug-in that return Factory, This factory then creates and returns proper object which is derived from Interface or base class that has defined required method and signals.

like shown in my following sample,
class Worker: public QObject
{
Q_OBJECT
public:
    virtual ~Worker() {}
    virtual void doWork() = 0;

signals:
    void workDone();
};

class WorkerFactory
{
public:
    virtual ~WorkerFactory() {}
    virtual Worker* newWorker() = 0;
};
Q_DECLARE_INTERFACE(WorkerFactory,"WorkerFactory");
Here Worker is actual interface that we need, It defines required method and signals so all subclass will have required method and signals.

Sample plug-in implementation.
class SampleWorker: public Worker
{
Q_OBJECT
public:
// it emits workDone signal, when its done
void doWork();
};

// Plug-in implementation
class SampleWorkerFactory: public QObject, public WorkerFactory
{
Q_OBJECT
Q_INTERFACES(WorkerFactory)
public:
    Worker* newWorker() {
        new SampleWorker();
    }
};
Plug-in loader implementation,
QPluginLoader pluginLoader(fileName);
QObject *plugin = pluginLoader.instance();
if (plugin) {
    WorkerFactory* workerFactory = qobject_cast(plugin);
    if (workerFactory) {
        Worker* worker = workerFactory->newWorker();
        connect(worker,SIGNAL(workDone()),this,SLOT(workDone()));
        worker->doWork();
    }
}
Here plug-in loader code is loading plug-in implementing WorkerFactory interface and asking it to create object that implements Worker interface which define all required method and signals. Now we can connect required signal slots with this worker object.

Sunday, November 21, 2010

Symbian development from Ubuntu machine

Like I have already told in my past few posts that currently I am working on porting my application to Symbian. Another problem while developing for Symbian is, there are different SDK for different version of Symbian and you need to setup all those SDK to support different symbian version and also Symbian SDK are currently supported only on windows platform.

But now, both problems are solved by new Nokia Qt SDK by adding remote compiler feature in its latest release.

Compiling is one part of development, but we also need to test our application on device and as individual developer its quite hard to get hold on different device. This problem is also solved by Forum Nokia from quite some time by Remote Device Access portal.

Remote Device Access allows you to use device remotely for testing purpose. Its has almost all latest device to test with. Thought it might not be possible to test all use case remotely but most use case can be tested remotely.

I am putting some snaps that show how to setup Nokia Qt SDK with remote compiler feature and how to access Remote Device Access portal.

So, you will see welcome screen after starting Nokia Qt SDK installation like below.




After agreeing license agreement, you need to select type of installation. As shown in figure you need to select Custom as type of installation.



After selecting custom for type of installation,select Experimental to enable remote compiler feature.



Now, wait till installation gets completed. After insallation gets completed you need accept Terms of Sevice to enalle Remote Complier in Qt Creator and login using Forum Nokia login id.

Go to Tools -> Options -> Projects to enable Remote Compiler.




Few snaps, how build is performed in remote compiler






After build gets done, it will produce sis file that you can use to test. Now to test this sis file on Remote device access.

Go to http://apu.ndhub.net/devices

You need to login using Forum Nokia login id, its free to all forum nokia member. After successfully login you can choose phone to test application.



Select phone and it will launch Remote Device Access application with interface to intreact with phone.



You can upload your sis file to device to install it.



Now you can test your application on device using Remote Device Access. Following is video from my application using Remote Device Access.

Thursday, November 18, 2010

Storing custom class in QVariant

One of my friend asked me, how we can store custom class or structure in QVariant.

I gave him following sample.Posting same sample in hope it will help others as well.

#include <QCoreApplication>
#include <QPoint>
#include <QVariant>

class MyStruct
{
public:
    QString name;
    QString id;
    QPoint point;
};
Q_DECLARE_METATYPE(MyStruct)

int main(int argc, char *argv[])
{    
    qRegisterMetaType<MyStruct>("MyStruct");

    MyStruct test1;
    test1.name="test";
    test1.id = "testid";
    test1.point=QPoint(100,100);
    QVariant v;
    v.setValue<MyStruct>(test1);

    MyStruct test2 =v.value<MyStructl>();

}

If you need to serialize this variant than you will need to provide serialization method for custom class and also need to register them with metatype system using qRegisterMetaTypeStreamOperators.

Tuesday, November 16, 2010

Mounting LVM Encrypted Volum to recover data

From past two hour I am trying figure out how to recover data from my crashed laptop. Problem was my laptop hard disk was encrypted and by using normal mount command its not possible to get data.

I found this useful link that shows how to recover data in such case. Finally, I booted my laptop using Ubuntu live cd and recovered my data using command provided above link.

Saturday, November 13, 2010

Sprite animation with SVG sprite sheet in Qt Graphics View

Recently I started to port my game to Symbian platform,
In my previous post I showed how to make graphics work with different resolution.But if you are using images in application, you need to use SVG image to make sure that images looks good in all resoltion.

When I started to replace my game images with SVG image, I need to make changes in my sprite class.With normal images I was drawing only certain portion of image from Sprite sheet like code in this post, but I could not make that thing work with SVG. Then to make my sprite class work I made following changes.

In following code, I am using SVG file which contain each frame with unique id and in code on next frame I am rendering SVG element with id for particular frame.

Code for animatedsvgitem.h
#ifndef ANIMATEDSVGITEM_H
#define ANIMATEDSVGITEM_H

#include <QGraphicsSvgItem>
#include <QTimer>

class AnimatedSvgItem : public QGraphicsSvgItem
{
    Q_OBJECT
public:
    AnimatedSvgItem();
    QRectF boundingRect() const;

private slots:
    void nextFrame();

private:
    QTimer *timer;
    QStringList frames;
    int currentFrame;
};
#endif // ANIMATEDSVGITEM_H

Code for animatedsvgitem.cpp
#include "animatedsvgitem.h"

AnimatedSvgItem::AnimatedSvgItem()
    :QGraphicsSvgItem( QString(":/egg.svg") )
{
    //svg element id of frame in svg file
    frames << "egg1" << "egg2" << "egg3" << "egg4" << "egg5" << "egg6" << "egg7" << "egg8";
    currentFrame = 0;
    this->setElementId( frames[currentFrame] );
    timer = new QTimer(this);
    QObject::connect(timer,SIGNAL(timeout()),this,SLOT(nextFrame()));
    timer->start(400);
}

QRectF AnimatedSvgItem::boundingRect() const
{
    return QRectF(0,0,20,20);
}

void AnimatedSvgItem::nextFrame()
{
    currentFrame = ++currentFrame % 8;
    this->setElementId( frames[currentFrame]);
    this->moveBy(5,0);
    update();
}
So this was all, Sprite sheet used for above code is like this but in SVG format.





Here video from sample code.

Thursday, October 28, 2010

Chopper game with Qt Quick (QML)

Today, I created my first Qt Quick (QML) game named Chopper, game is simple and was created just for learning process.

UI Is implemented using QML and logic part is done using JavaScript and tested on Nokia Qt SDK emulator.

If you want to look at code then here is link to my gitorious repository.

Following is snap from game,


And below is video from game.

Saturday, October 23, 2010

Creating Qt game for mobile device with differnt screen size

Till now I have created few Qt games for Maemo 5 (N900) device, and now I wanted to run same games on Symbian device which support Qt.

First problem I encounter doing so is different screen size from N900, in my current game implementation I have hard coded screen size and coordination of game object.

After playing with graphics framework from some time, I created a small prototype application that shows two rectangle one on top left other on bottom right corner and can run on different Symbian device and N900 as well. So first thing I did is to remove all hard coded coordinate and implemented resize event, then scaled all graphics item which are added to graphics scene.

Following is my prototype code.

In below code, I have added QGraphicsView as QMainWindow's central widget and also reimplemented resizeEvent of QMainWindow.
GraphicsWidget::GraphicsWidget(QWidget *parent)
    : QMainWindow(parent)
{    
    _scene = new MyScene();
    _scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    _view = new QGraphicsView(_scene,this);
    _view->setDragMode(QGraphicsView::NoDrag);
    _view->setCacheMode(QGraphicsView::CacheBackground);
    _view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);

    setCentralWidget(_view);

    // Disable scrollbars
    _view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    _view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}

void GraphicsWidget::resizeEvent(QResizeEvent* event)
{
    _scene->setSceneRect(_view->rect());
    QWidget::resizeEvent(event);
}

And then in MyScene class, derived from QGraphicsScene, on sceneRectChanged signal i am scaling all item to scale factor according to my reference screen size, which is of n900 device's screen size.
MyScene::MyScene()
    :QGraphicsScene()
{
    item1 = new MyGraphicsItem();
    addItem( item1 );

    item2 = new MyGraphicsItem();
    addItem( item2 );
    QObject::connect(this,SIGNAL(sceneRectChanged(QRectF)),
                    this,SLOT(resize(QRectF)));
}

void MyScene::resize(const QRectF& newRect)
{
    qreal w = (qreal)newRect.width()/800 ;
    qreal h =  (qreal)newRect.height()/480;

    item1->resetMatrix();
    item1->scale(w,h);
    item1->setPos(newRect.topLeft());

    item2->resetMatrix();
    item2->scale(w,h);
    item2->setPos(newRect.width()-(item2->boundingRect().width()*w),
            newRect.height() - (item2->boundingRect().height()*h));
}
Finally in main function, I am showing QMainWindow in full screen mode.
int main(int argc, char* argv[] )
{
    QApplication app(argc,argv);
    GraphicsWidget widget;
    widget.showFullScreen();
    return app.exec();
}
Following are snaps from prototype running on emulator for different device.



Thursday, October 21, 2010

Using QStateMachine with sprite animation

In 4.6 Qt introduced new State machine framework. Framework looks quite easy to use and extensible for complex use-case.
To explore Qt's State machine framework I thought to use it with sprite animation, as a complex sprite also holds many state and maintaining sprite state and transition from one state to another can become pain if not done properly.

So following is my sample code for prince sprite which use QStateMachine to maintain sprite's state and transition from one state to another. From somewhere in Internet I found sprite sheet for Prince of Persia, to make it easy for sample code I created another simple version of original sprite sheet.
PrinceSprite::PrinceSprite(QGraphicsItem * parent)
    :QGraphicsObject(parent)
{
    mSpriteImage = new QPixmap(":/prince.png");
    changeDir(this);

    //creating different state object , 
    //which are derived from QState and l
    //istening to timer's timeout signal 
    //and also modify frame according to animation
    StandingState* standing = new StandingState(this);
    RunningState* running = new RunningState(this);
    PrepareForAttack* prepareForAttack = 
                        new PrepareForAttack(this);
    Attack* attack = new Attack(this);
    InAttackMode* inAttackMode = new InAttackMode(this);

    //adding transition to state
    //goto running state from stating state at left click
    standing->addTransition(this,SIGNAL(leftClick()),running);
    running->addTransition(this,SIGNAL(leftClick()),standing);
    standing->addTransition(this,SIGNAL(rightClick())
                                    ,prepareForAttack);
    prepareForAttack->addTransition(prepareForAttack,
                        SIGNAL(exited()),inAttackMode);
    inAttackMode->addTransition(this,SIGNAL(leftClick()),attack);
    attack->addTransition(attack,SIGNAL(exited()),inAttackMode);
    inAttackMode->addTransition(this,
                     SIGNAL(rightClick()),standing);

    //adding all state to QStateMachine
    _stateMachine.addState(standing);
    _stateMachine.addState(running);
    _stateMachine.addState(prepareForAttack);
    _stateMachine.addState(attack);
    _stateMachine.addState(inAttackMode);

    //setting initial state and then starting state machine
    _stateMachine.setInitialState( standing);
    _stateMachine.start();
}

In above code I have create different state object for different sprite state, like for StandingState or Attack state.
This state classes are derived from QState class and listen to QTimer's timeout signal to change frame according to animation.

For example following code for Attack state.
#include <QState>

class Attack : public QState
{
    Q_OBJECT
public:
    Attack(PrinceSprite* prince);
    void onEntry ( QEvent * event );
    void onExit ( QEvent * event );

signals:
    void exited();

private slots:
    void nextFrame();
};

#include "attack.h"

Attack::Attack(PrinceSprite* prince)
    :QState()
{}

void Attack::nextFrame()
{    
    _prince->_x += 1;
    _prince->setX(_prince->x() + 7);
    if (_prince->_x >= 4 ) {
        emit exited();
    }
}

void Attack::onEntry ( QEvent * event )
{
    QObject::connect(_prince,SIGNAL(tick()),
                     this,SLOT(nextFrame()));
    _prince->_x = 0;
    _prince->_y = 2;
}

void Attack::onExit ( QEvent * event )
{
    QObject::disconnect(_prince,SIGNAL(tick()),
                        this,SLOT(nextFrame()));
}

So finally, I am not sure if this is correct approach to implement sprite or not, but using Qt's State machine framework is helping a lot to make it simpler.

Follwing is demo of my implementation.

Saturday, October 9, 2010

Crazy chickens on Qt Ambassador Showcase

Finally yesterday my game Crazy Chickens successfully gone through Qt Ambassador Showcase process and now it is show cased in Qt Ambassador Showcase

Coincidently I received my Ambassador T-shirt also on same day. Following is snap of T shirt if you wonder how it looks.

Sunday, October 3, 2010

Detecting Swipe gesture in Qt

In continuation of my previous post of long press gesture in Qt, I created another simple gesture class to detect swipe gesture.

In my implementation, I am storing initial coordinate on mouse press event and comparing initial coordinate with coordinate on mouse release event.In this code I have not considered speed of swipe but we can easily measure speed of swipe by measuring time difference between two event.

myswipegesture.h file
#ifndef MYSWIPEGESTURE_H
#define MYSWIPEGESTURE_H

#include <QObject>
#include <QPoint>

class MySwipeGesture : public QObject
{
    Q_OBJECT
public:
    explicit MySwipeGesture(QObject *parent = 0);
    void handleEvent( QEvent *event);
public:
    enum SwipeDirection {
        Left = 0,
        Right,
        Up,
        Down
    };
signals:
    void handleSwipe( MySwipeGesture::SwipeDirection direction );
private:
    QPoint _startPoint;
    QPoint _endPoint;
};
#endif // MYSWIPEGESTURE_H
myswipegesture.cpp file
#include "myswipegesture.h"
#include <QEvent>
#include <QMouseEvent>

MySwipeGesture::MySwipeGesture(QObject *parent)
    :QObject(parent),_startPoint(0,0),_endPoint(0,0)
{}

void MySwipeGesture::handleEvent( QEvent *event)
{
    if( event->type() == QEvent::MouseButtonPress ) {
    QMouseEvent* mouseEvent = static_cast<QMouseEvent*> (event);
        _startPoint = mouseEvent->pos();
    } else if( event->type() == QEvent::MouseButtonRelease ) {
    QMouseEvent* mouseEvent = static_cast<QMouseEvent*> (event);
        _endPoint = mouseEvent->pos();

        //process distance and direction
        int xDiff = _startPoint.x() - _endPoint.x();
        int yDiff = _startPoint.y() - _endPoint.y();
        if( qAbs(xDiff) > qAbs(yDiff) ) {
            // horizontal swipe detected, now find direction
            if( _startPoint.x() > _endPoint.x() ) {
                emit handleSwipe( Left);
            } else {
                emit handleSwipe( Right);
            }
        } else {
            // vertical swipe detected, now find direction
            if( _startPoint.y() > _endPoint.y() ) {
                emit handleSwipe( Up);
            } else {
                emit handleSwipe( Down);
            }
        }
    } else if( event->type() == QEvent::MouseMove ) {
        //ignore event
    }
}
Some test code.
#include "myswipegesture.h"

TestWidget::TestWidget(QWidget *parent) : QWidget(parent)
{
    _swipeGesture = new MySwipeGesture(this);
    connect(_swipeGesture,SIGNAL(handleSwipe(MySwipeGesture::SwipeDirection)),this,SLOT(swipe(MySwipeGesture::SwipeDirection)));
}

bool TestWidget::event(QEvent *event)
{
    _swipeGesture->handleEvent(event);
    return QWidget::event(event);
}

void TestWidget::swipe(MySwipeGesture::SwipeDirection direction)
{
    qDebug() << "swipe" << direction;
}
Hope this helps.

Sunday, September 26, 2010

Detecting Tap And Hold (Long Press) event in Qt

Recently while working on Qt project I required to recognize Tap and Hold (Long Press) gesture. Qt introduced new gesture handler library in 4.6 but some how it was not working on my machine and I needed to create my own solution. I already have created one custom solution for detecting Tap and Hold for iOS and I tried to port same thing to Qt as well.

Following is my code to detect Tap and Hold for Qt. In code I am starting timer on mouse press event, if timer expire then we have Tap and Hold event. If user release mouse while timer is still active then Tap and Hold is canceled.
#ifndef MYTAPANDHOLDGESTURE_H
#define MYTAPANDHOLDGESTURE_H

#include <QObject>

class QTimer;

class MyTapAndHoldGesture: public QObject
{
    Q_OBJECT
public:
    MyTapAndHoldGesture( QObject *parent = 0 );
    void handleEvent( QEvent *event);

signals:
    void handleTapAndHold();

private slots:
    void timeout();

private:
    QTimer* _timer;
};

#endif // MYTAPANDHOLDGESTURE_H

#include "mytapandholdgesture.h"

#include <QMouseEvent>
#include <QTimer>

MyTapAndHoldGesture::MyTapAndHoldGesture( QObject *parent )
{
    _timer = new QTimer(this);
    connect(_timer,SIGNAL(timeout()),this,SLOT(timeout()));
}

void MyTapAndHoldGesture::handleEvent( QEvent *event)
{
    if( event->type() == QEvent::MouseButtonPress ) {
        _timer->start( 1000 );
    } else if( event->type() == QEvent::MouseButtonRelease ) {
        if( _timer->isActive() ) {
            // tap and hold canceled
            _timer->stop();
        }
    } else if( event->type() == QEvent::MouseMove ) {
        // tap and hold canceled
        _timer->stop();
    }
}

void MyTapAndHoldGesture::timeout()
{
    emit handleTapAndHold();
    _timer->stop();
}

Widget code for testing.
#ifndef TESTWIDGET_H
#define TESTWIDGET_H

#include <QWidget>

class MyTapAndHoldGesture;

class TestWidget : public QWidget
{
    Q_OBJECT
public:
    TestWidget(QWidget *parent = 0);

private:
    bool event(QEvent *event);

private slots:
    void tapAndHold();

private:
    MyTapAndHoldGesture* _gestureHandler;
};

#endif // TESTWIDGET_H

#include "testwidget.h"
#include <QDebug>
#include "mytapandholdgesture.h"

TestWidget::TestWidget(QWidget *parent) :
    QWidget(parent)
{
    _gestureHandler = new MyTapAndHoldGesture(this);
    connect(_gestureHandler,SIGNAL(handleTapAndHold()),
    this,SLOT(tapAndHold()));
}

bool TestWidget::event(QEvent *event)
{
    _gestureHandler->handleEvent( event );
    return QWidget::event(event);
}

void TestWidget::tapAndHold()
{
    qDebug() << "tapAndHold";
}

Wednesday, September 15, 2010

Simple priority queue with Qt

Recently in one of my Qt project I required to use priority queue and found that Qt framework dose not provide such container. Then I decided to write one my self.

Following is simple version of my actual implementation.

In code Queue class implement simple priority queue. Internally I am using QQueue as storage and created one helper structure which holds data and its priority. Actual work is done inside enqueue method, which check priority of item being inserted with other stored items and insert item at appropriate index.
#ifndef QUEUE_H
#define QUEUE_H

#include <QQueue>
#include <QDebug>

enum Priority {
    Normal = 0,
    High = 1
};

template<class T>
class Queue
{
public:

    Queue()
    {}

    void enqueue(Priority priority,T value)
    {
        Item<T> item(priority,value);
        for(int i = 0 ; i < _queue.count() ; ++i ) {
            const Item<T>& otherItem = _queue[i];
            if( priority > otherItem._priority )  {
                _queue.insert(i,item);
                return;
            }
        }
        _queue.append(item);
    }

    T dequeue()
    {
        const Item<T>& item = _queue.dequeue();
        return item._value;
    }

    int count()
    {
        return _queue.count();
    }

private:

    template<class C>
    struct Item
    {
        Priority _priority;
        C _value;

        Item(Priority priority, C value)
        {
            _priority = priority;
            _value = value;
        }
    };

    QQueue< Item<T > > _queue;

};

#endif // QUEUE_H

Some basic test code.
{
    //testing with int as value
    Queue<int> q;
    q.enqueue(High,1);
    q.enqueue(Normal,2);
    q.enqueue(High,3);
    q.enqueue(Normal,5);
    q.enqueue(Normal,6);
    q.enqueue(High,4);

    //output should be 1,3,4,2,5,6
    while( q.count() > 0 )
    {
        qDebug() << q.dequeue();
    }
}

Friday, September 10, 2010

Qt Ambassador program

Today my application for Qt Ambassador was accepted by Qt ambassador program. I had submitted crazy chickens game for Qt ambassador program which is now accepted and soon this game will be showcased in Qt Ambassador showcase.

If you also want to become Qt Ambassador then visit this link for more information.

Sunday, September 5, 2010

My visit to Bannerghatta national park

Recently I visited bannerghatta national park, It was great experience seeing animals in front and not in cage. Follwing are few snaps from national park.


















Wednesday, September 1, 2010

Using Signal/Slot with private implementation pattern in Qt

Sometime when using private implementation pattern in Qt, we might want to connect private class's method to signal.

I have seen some code that in such case create slot in public class that call private class's method and connect slot in public class to actual signal but this approach break primary purpose of hiding implementation details from user and also adds unnecessary code.

But using Q_PRIVATE_SLOT macro, we can easily connect private class method to signal. I created following test code to demonstrate usage of Q_PRIVATE_SLOT. Hope this will helps.

In following code I am trying to connection private class's timeOut slot to timer's timeout signal.
#ifndef TEST_H
#define TEST_H

#include <QObject>

class TestPrivate;
class QTimer;

class Test : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(Test)

public:

   Test();
   void testing();
   void testSignal();

private:
   //this will create slot which is implemented in private class
   Q_PRIVATE_SLOT(d_func(),void timeOut());

signals:
    void signal();

private:
    TestPrivate* d_ptr;
};

#endif // TEST_H

#include <QDebug>
#include <QTimer>

class TestPrivate
{
Q_DECLARE_PUBLIC(Test)

public:

TestPrivate(Test* q)
   :q_ptr(q)
{        
   mTimer = new QTimer(q);
   mTimer->setInterval(1000);
   QObject::connect(mTimer,SIGNAL(timeout()),q,SLOT(timeOut()));
   mTimer->start();
}

private:

void testing()
{
    qDebug() << "TestPrivate::testing()";
}

void timeOut()
{
    qDebug() << "TestPrivate::TimeOut()";
}

void testSignal()
{
    qDebug() << "TestPrivate::testSignal()";
    Q_Q(Test);
    emit q->signal();
}

private:// data

QTimer* mTimer;
Test* q_ptr;

};

Test::Test()
:QObject(0),d_ptr( new TestPrivate(this))
{}

void Test::testing()
{
   Q_D(Test);
   d->testing();
}

void Test::testSignal()
{
   Q_D(Test);
   d->testSignal();
}

//dont forget to add moc file, else code will give errors
#include "moc_test.cpp"
main.cpp to test above code.
#include <QCoreapplication>
#include <QDebug>
#include "test.h"
#include <QtTest/QSignalSpy>

int main(int argc,char* argv[])
{
   QCoreApplication app(argc,argv);

   Test test;
   QSignalSpy spy( &test,SIGNAL(signal()));
   test.testSignal();
   qDebug() << "Signal" << spy.count();
   test.testing();
   app.exec();
}

Sunday, August 29, 2010

Crazy Chickens video on youtube.

I have uploaded video of crazy chickens n900 game on youtube. Here youtube link for video, embedded video is below.

Tuesday, August 24, 2010

Crazy Chickens game for N900 (Maemo) using Qt

Recently I started to learn Qt' graphics view and I decided to put my learning in to some action and as output I created this game called crazy chickens. Its classic egg catcher game.

Goal of game is to catch eggs before they touch the ground. You get four chances if you let egg fall on ground. Speed of game increase as you catch more eggs. To make Motu(the fat boy) catch egg in to basket you need to touch hen which produced the egg. Game dose not take gravity into account so speed of egg remain constant till it fall to ground.

I already uploaded this game to maemo's extra-devel repository, so if you want to try the game enable extra-devel repository. I am also planning to promote this game to extra-testing repository soon so this game should be available in extra-testing repository as well.

Some snaps of this game from my N900.









Sunday, August 22, 2010

Nested function in c++

Recently while working on some code, I required to create nested function. Well in most case you can avoid use of nested function but in my case, in one function I required to use same code repeatedly and that piece of code was not going to be used else where so I wanted to keep that code inside original function only and I also wanted to remove redundant code. So I thought to create nested function.

By standard C++ dose not support use of nested function, some compiler allows it but that depends on compiler being used. So there is one work around by using you can achieve nested function in C++.

By using local class and overloading function operator we can simulate nested function. Following is my sample code to achieve nested function.
void foo() {
    class DoMyWork
    {
    public:
        int operator() (int args) {
            qDebug() << "Parameter passed:" << args;
            return args + 5;
        }
    } doMyWork;//creating instance of DoMyWork
//calling simulated nested function
    int retVal = doMyWork(5);
    qDebug() << "Returned value:" << retVal;
}
So that was all, hope this helps.

Friday, August 20, 2010

Debugging lzo(.lzo) file in maemo

If you are facing segmentation fault in Maemo device than there are some tools available to retrieve core dump files from the device. These tools are in the sp‐rich‐core package. sp‐rich‐core  will produce a core dump file and also additional information about process, most of /proc data, last lines from syslog, df, ifconfig output and much more.  All of such information is added to a
rich core dump package (.rcore) and then, it is compressed in .lzo file.

The core dumps by default are saved on directory /media/mmc1/core‐dumps on device.

To uncompressed core dump you need to use rich-core-extract tool. The package sp‐rich‐core‐postproc provides the rich‐core‐extract utility, which extracts the information from a rich core dump file that GDB can read.

To install this tool type following

apt-get install sp-rich-core sp-rich-core-postproc

Now to uncompress lzo file and to get core dump file use following command.

rich-core-extract core_file.lzo

For more information using gdb in maemo environment visit this post.

Also visit this link for more information on debugging on maemo platform.

Thursday, August 19, 2010

Excellent tutorial about OAuth

I found an excellent article about OAuth protocol thought to share it. It explain concept with example and vary good detail. Have look at it at following link.

http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/

Monday, August 16, 2010

Creating custom graphics item in Qt's graphics view

Now a days I started to learn Qt's Graphics view. Initially I was struggling with it but once I started programming with it I found that its quite easy and powerful. What I like most about it is, while creating custom item we can perform paint opration with items local coordinate and need not worry about scene coordinate.

While creating custom graphics item, Your class needs to be derived from QGraphicsItem or QGraphicsObject. If your object needs to use signal/slot than derive your class from QGraphicsObject else derive it from QGraphicsItem and override paint and boundingRect methods.

For test application I tried to create sprite with custom graphics item that shows rolling ball animation. Following is code for my custom graphics item.
#include <QGraphicsObject>
#include <QPixmap>

class BallGraphicsItem : public QGraphicsObject
{
    Q_OBJECT
public:

    BallGraphicsItem();
    ~BallGraphicsItem();

    void paint ( QPainter * painter, 
const QStyleOptionGraphicsItem * option, 
QWidget * widget = 0 );

    QRectF boundingRect() const;

public slots:
    void move();
    void nextFrame();
private:

    QPixmap mBallImage;    
    int mCurrentRow;
    int mCurrentColumn;    
};

#endif // BALLGRAPHICSITEM_H

#include "ballgraphicsitem.h"
#include <QPainter>
#include <math.h>
#include <QBitmap>


BallGraphicsItem::BallGraphicsItem()
    :QGraphicsObject( ),mBallImage(":sphere.bmp"),
mCurrentRow(0),mCurrentColumn(0)
{
    //masking image to make image transperent
    mBallImage.setMask( 
mBallImage.createMaskFromColor(QColor(255,0,255)));    
}

BallGraphicsItem::~BallGraphicsItem()
{}

QRectF BallGraphicsItem::boundingRect() const
{
    return QRectF(0,0,32,32);
}

void BallGraphicsItem::paint ( QPainter *painter, 
const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/ )
{
    painter->drawPixmap(0,0,mBallImage, 
mCurrentColumn* 32 ,mCurrentRow*32, 32,32);
}

void BallGraphicsItem::nextFrame()
{
    mCurrentColumn = ++mCurrentColumn % 8;
    if( mCurrentColumn == 0 ) {
        mCurrentRow = ++mCurrentRow %4;
    }
}

void BallGraphicsItem::move()
{    
    setPos( x() + 2, y());
    nextFrame();
}

And my main.cpp file looks like following.
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QTimer>
#include "ballgraphicsitem.h"

int main( int argc, char* argv[] )
{
    QApplication app(argc,argv);

    QGraphicsScene scene( 0, 0, 840, 480 );
    QGraphicsView view(&scene);
    view.setRenderHint(QPainter::Antialiasing);
    view.show();

    BallGraphicsItem* ball = new BallGraphicsItem();
    ball->setPos(10,10);
    scene.addItem( ball );

    QTimer *timer = new QTimer(qApp);
    timer->start(1000/30);
    QObject::connect(timer,SIGNAL(timeout()),ball,SLOT(move()));

    return app.exec();
} 
For above code I am using following image, don't know from where I downloaded image.