src/hbcore/gui/hbabstractbutton.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbcore/gui/hbabstractbutton.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,1156 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (developer.feedback@nokia.com)
+**
+** This file is part of the HbCore module of the UI Extensions for Mobile.
+**
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at developer.feedback@nokia.com.
+**
+****************************************************************************/
+
+#include "hbabstractbutton.h"
+#include "hbabstractbutton_p.h"
+#include "hbapplication.h"
+#include "hbstyleoption.h"
+#include "hbtooltip.h"
+#include "hbinstance.h"
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsScene>
+#include <QPointer>
+#include <QStyle>
+
+#include <hbwidgetfeedback.h>
+
+namespace {
+    static const int AUTO_REPEAT_DELAY = 300;
+    static const int AUTO_REPEAT_INTERVAL = 100;
+}
+
+/*!
+    @beta
+    @hbcore
+    \class HbAbstractButton
+
+    \brief The HbAbstractButton class is the abstract base class of
+    button widgets, providing functionality common to buttons.
+
+    This class implements an \e abstract button.
+    Subclasses of this class handle user actions, and specify how the button
+    is drawn.
+
+    HbAbstractButton provides support for both push buttons and checkable
+    (toggle) buttons. Checkable buttons are implemented in the HbRadioButton
+    and HbCheckBox classes. Push buttons are implemented in the
+    HbPushButton and HbToolButton classes; these also provide toggle
+    behavior if required.
+
+    Any button can display  text and an icon. setText()
+    sets the text; setIcon() sets the icon. If a button is disabled, its background
+    is changed to give the button a "disabled" appearance.
+
+    All of the buttons provided by Hb (HbPushButton, HbToolButton,
+    HbCheckBox, and HbRadioButton) can display both text and icon.
+    You can also set a tool tip for the button with \qtfunc{QGraphicsItem,setTooltip}.
+
+    HbAbstractButton provides most of the states used for buttons:
+
+    \li isDown() indicates whether the button is \e pressed down.
+
+    \li isChecked() indicates whether the button is \e checked.  Only
+    checkable buttons can be checked and unchecked (see below).
+
+    \li isEnabled() indicates whether the button can be pressed by the
+    user.
+
+    \li setAutoRepeat() sets whether the button will auto-repeat if the
+    user holds it down. \l autoRepeatDelay and \l autoRepeatInterval
+    define how auto-repetition is done.
+
+    \li setCheckable() sets whether the button is a toggle button or not.
+
+    The difference between isDown() and isChecked() is as follows.
+    When the user clicks a toggle button to check it, the button is first
+    \e pressed then released into the \e checked state. When the user
+    clicks it again (to uncheck it), the button moves first to the
+    \e pressed state, then to the \e unchecked state (isChecked() and
+    isDown() are both false).
+
+    HbAbstractButton provides four signals:
+
+    \li pressed() is emitted when the stylus is pressed while
+    the stylus is inside the button.
+
+    \li released() is emitted when the left stylus is released.
+
+    \li clicked() is emitted when the button is first pressed and then
+    released, when the shortcut key is typed, or when click() or
+    animateClick() is called.
+
+    \li toggled() is emitted when the state of a toggle button changes.
+
+    To subclass HbAbstractButton, you must reimplement at least
+    paint() to draw the button's outline and its text or pixmap. It
+    is generally advisable to reimplement sizeHint() as well, and
+    sometimes hitButton() (to determine whether a button press is within
+    the button). For buttons with more than two states (like tri-state
+    buttons), you will also have to reimplement checkStateSet() and
+    nextCheckState().
+*/
+
+/*!
+    \reimp
+    \fn int HbAbstractButton::type() const
+ */
+
+HbAbstractButtonPrivate::HbAbstractButtonPrivate( QSizePolicy::ControlType type )
+    :
+    shortcutId(0),
+    checkable(false), checked(false), autoRepeat(false), autoExclusive(false),
+    down(false), blockRefresh(false),longPress(false),
+    autoRepeatDelay(AUTO_REPEAT_DELAY),
+    autoRepeatInterval(AUTO_REPEAT_INTERVAL),
+    controlType(type), sizeHint(),mSizeHintPolish(false),mRepolishRequested(false)
+{
+}
+
+HbAbstractButtonPrivate::~HbAbstractButtonPrivate()
+{
+}
+
+QList<HbAbstractButton *>HbAbstractButtonPrivate::queryButtonList() const
+{
+    Q_Q( const HbAbstractButton );
+    
+    QList<HbAbstractButton*>candidates;
+    if (q->parentWidget()) {
+        candidates =  qFindChildren<HbAbstractButton *>(q->parentWidget());
+        if (autoExclusive) {
+            for (int i = candidates.count() - 1; i >= 0; --i) {
+                HbAbstractButton *candidate = candidates.at(i);
+                if (!candidate->autoExclusive())
+                    candidates.removeAt(i);
+            }
+        }
+    }
+    return candidates;
+}
+
+HbAbstractButton *HbAbstractButtonPrivate::queryCheckedButton() const
+{
+    QList<HbAbstractButton *> buttonList = queryButtonList();
+    if (!autoExclusive || buttonList.count() == 1) // no group
+        return 0;
+
+    Q_Q( const HbAbstractButton );
+
+    for (int i = 0; i < buttonList.count(); ++i) {
+        HbAbstractButton *b = buttonList.at(i);
+        if (b->isChecked() && b != q)
+            return b;
+    }
+    return checked  ? const_cast<HbAbstractButton *>(q) : 0;
+}
+
+void HbAbstractButtonPrivate::notifyChecked()
+{
+    if (autoExclusive) {
+        if (HbAbstractButton *b = queryCheckedButton())
+            b->setChecked(false);
+    }
+}
+
+void HbAbstractButtonPrivate::moveFocus(int key)
+{
+    Q_Q( HbAbstractButton );
+
+    QList<HbAbstractButton *> buttonList = queryButtonList();;
+    bool exclusive = autoExclusive;
+    QGraphicsItem *focusItem = q->scene()->focusItem();
+    HbAbstractButton *focusButton = 0;
+    if (focusItem && focusItem->isWidget()) {
+        QGraphicsWidget *focusWidget = static_cast<QGraphicsWidget*>(focusItem);
+        focusButton = qobject_cast<HbAbstractButton *>(focusWidget);
+    }
+    if (!focusButton || !buttonList.contains(focusButton))
+        return;
+
+    HbAbstractButton *candidate = 0;
+    int bestScore = -1;
+    QRect target = focusItem->sceneBoundingRect().toRect();
+    QPoint goal = target.center();
+
+    for (int i = 0; i < buttonList.count(); ++i) {
+        HbAbstractButton *button = buttonList.at(i);
+        if (button != focusItem && button->isEnabled() && button->isVisible() &&
+            (autoExclusive || (button->focusPolicy() & Qt::StrongFocus) == Qt::StrongFocus)) {
+            QRect buttonRect = button->sceneBoundingRect().toRect();
+            QPoint p = buttonRect.center();
+
+            //Priority to widgets that overlap on the same coordinate.
+            //In that case, the distance in the direction will be used as significant score,
+            //take also in account orthogonal distance in case two widget are in the same distance.
+            int score;
+            if ((buttonRect.x() < target.right() && target.x() < buttonRect.right())
+                  && (key == Qt::Key_Up || key == Qt::Key_Down)) {
+                //one item's is at the vertical of the other
+                score = (qAbs(p.y() - goal.y()) << 16) + qAbs(p.x() - goal.x());
+            } else if ((buttonRect.y() < target.bottom() && target.y() < buttonRect.bottom())
+                        && (key == Qt::Key_Left || key == Qt::Key_Right) ) {
+                //one item's is at the horizontal of the other
+                score = (qAbs(p.x() - goal.x()) << 16) + qAbs(p.y() - goal.y());
+            } else {
+                score = (1 << 30) + (p.y() - goal.y()) * (p.y() - goal.y()) + (p.x() - goal.x()) * (p.x() - goal.x());
+            }
+
+            if (score > bestScore && candidate)
+                continue;
+
+            switch(key) {
+            case Qt::Key_Up:
+                if (p.y() < goal.y()) {
+                    candidate = button;
+                    bestScore = score;
+                }
+                break;
+            case Qt::Key_Down:
+                if (p.y() > goal.y()) {
+                    candidate = button;
+                    bestScore = score;
+                }
+                break;
+            case Qt::Key_Left:
+                if (p.x() < goal.x()) {
+                    candidate = button;
+                    bestScore = score;
+                }
+                break;
+            case Qt::Key_Right:
+                if (p.x() > goal.x()) {
+                    candidate = button;
+                    bestScore = score;
+                }
+                break;
+            }
+        }
+    }
+
+    if (exclusive
+#ifdef QT_KEYPAD_NAVIGATION
+        && !QApplication::keypadNavigationEnabled()
+#endif
+        && candidate
+        && focusButton->isChecked()
+        && candidate->isCheckable())
+        candidate->click();
+
+    if (candidate) {
+        if (key == Qt::Key_Up || key == Qt::Key_Left)
+            candidate->setFocus(Qt::BacktabFocusReason);
+        else
+            candidate->setFocus(Qt::TabFocusReason);
+    }
+}
+
+void HbAbstractButtonPrivate::fixFocusPolicy()
+{
+    if (!autoExclusive)
+        return;
+
+    Q_Q( HbAbstractButton );
+
+    QList<HbAbstractButton *> buttonList = queryButtonList();
+    for (int i = 0; i < buttonList.count(); ++i) {
+        HbAbstractButton *b = buttonList.at(i);
+        if (!b->isCheckable())
+            continue;
+        b->setFocusPolicy((Qt::FocusPolicy) ((b == q || !q->isCheckable())
+                                         ? (b->focusPolicy() | Qt::TabFocus)
+                                         :  (b->focusPolicy() & ~Qt::TabFocus)));
+    }
+}
+
+void HbAbstractButtonPrivate::init()
+{
+    Q_Q( HbAbstractButton );
+
+	q->setFocusPolicy(Qt::FocusPolicy(qApp->style()->styleHint(QStyle::SH_Button_FocusPolicy)));
+
+    // FIXME: size policy is commented out b/c of a bug in Qt #236689, also in our bugtracker.
+    //q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum, controlType));
+
+    //q->setForegroundRole(QPalette::ButtonText); TODO: check
+    //q->setBackgroundRole(QPalette::Button); TODO: check
+}
+
+void HbAbstractButtonPrivate::refresh()
+{
+    if (blockRefresh)
+        return;
+
+    Q_Q( HbAbstractButton );
+
+    q->updatePrimitives();
+}
+
+void HbAbstractButtonPrivate::click()
+{
+    Q_Q( HbAbstractButton );
+
+    down = false;
+    blockRefresh = true;
+    bool changeState = true;
+    if (checked && queryCheckedButton() == q) {
+        // the checked button of an exclusive or autoexclusive group cannot be unchecked
+        if (autoExclusive)
+            changeState = false;
+    }
+
+    QPointer<HbAbstractButton> guard(q);
+    if (changeState) {
+        q->nextCheckState();
+        if (!guard)
+            return;
+    }
+    blockRefresh = false;
+    refresh();
+    if (guard)
+        emitReleased();
+    if (guard && !longPress)
+        emitClicked();
+    if(guard && longPress)
+        longPress = false;
+}
+
+void HbAbstractButtonPrivate::emitClicked()
+{
+    Q_Q( HbAbstractButton );
+
+    QPointer<HbAbstractButton> guard(q);
+    emit q->clicked(checked);
+}
+
+void HbAbstractButtonPrivate::emitPressed()
+{
+    Q_Q( HbAbstractButton );
+
+    QPointer<HbAbstractButton> guard(q);
+    emit q->pressed();
+}
+
+void HbAbstractButtonPrivate::emitReleased()
+{
+    Q_Q( HbAbstractButton );
+
+    QPointer<HbAbstractButton> guard(q);
+    emit q->released();
+}
+
+
+
+/*!
+    @beta
+    Constructs an abstract button with a \a parent.
+*/
+HbAbstractButton::HbAbstractButton(QGraphicsItem *parent)
+    : HbWidget( *new HbAbstractButtonPrivate, parent)
+{
+    Q_D( HbAbstractButton );
+    d->init();
+}
+
+/*!
+    @beta
+    \internal
+ */
+HbAbstractButton::HbAbstractButton( HbAbstractButtonPrivate &dd, QGraphicsItem * parent ) :
+        HbWidget( dd, parent )
+{
+    Q_D( HbAbstractButton );
+    d->init();
+}
+
+/*!
+    Destroys the button.
+ */
+ HbAbstractButton::~HbAbstractButton()
+{
+}
+
+/*
+\property HbAbstractButton::shortcut
+\brief the mnemonic associated with the button
+
+void HbAbstractButton::setShortcut(const QKeySequence &key)
+{
+    Q_ASSERT(mainWindow());
+    if (d->shortcutId != 0)
+        mainWindow()->releaseShortcut(d->shortcutId);
+    d->shortcut = key;
+    d->shortcutId = mainWindow()->grabShortcut(key);
+}
+
+QKeySequence HbAbstractButton::shortcut() const
+{
+    return d->shortcut;
+}
+*/
+
+/*!
+    @beta
+    Returns whether the button is checkable.
+
+    By default, the button is not checkable.
+
+    \sa setCheckable() checked
+*/
+bool HbAbstractButton::isCheckable() const
+{
+    Q_D( const HbAbstractButton );
+
+    return d->checkable;
+}
+
+/*!
+    @beta
+    Sets whether the button is checkable.
+
+    \sa isCheckable()
+ */
+void HbAbstractButton::setCheckable(bool checkable)
+{
+    Q_D( HbAbstractButton );
+
+    if (d->checkable == checkable)
+        return;
+
+    d->checkable = checkable;
+    d->checked = false;
+}
+
+/*!
+    @beta
+    Returns whether the button is checked.
+
+    Only checkable buttons can be checked. By default, the button is unchecked.
+
+    \sa setChecked() setCheckable()
+*/
+bool HbAbstractButton::isChecked() const
+{
+    Q_D( const HbAbstractButton );
+
+    return d->checked;
+}
+
+/*!
+    @beta
+    Sets whether the button is checked.
+
+    Only checkable buttons can be checked. By default, the button is unchecked.
+
+    \sa isChecked() isCheckable()
+*/
+void HbAbstractButton::setChecked(bool checked)
+{
+    Q_D( HbAbstractButton );
+
+    if (!d->checkable || d->checked == checked) {
+        if (!d->blockRefresh)
+            checkStateSet();
+        return;
+    }
+    if (!checked && d->queryCheckedButton() == this) {
+        // the checked button of an exclusive or autoexclusive group cannot be  unchecked
+        if (d->autoExclusive)
+            return;
+    }
+
+    QPointer<HbAbstractButton> guard(this);
+
+    d->checked = checked;
+    if (!d->blockRefresh)
+        checkStateSet();
+
+    d->refresh();
+
+    if (guard && checked)
+        d->notifyChecked();
+    if (guard)
+        emit toggled(checked);
+}
+
+/*!
+    @beta
+    Returns whether the button is pressed down.
+
+    If this property is \c true, the button is pressed down.
+    The default value is \c false.
+
+    \sa setDown()
+*/
+bool HbAbstractButton::isDown() const
+{
+    Q_D( const HbAbstractButton );
+
+    return d->down;
+}
+
+/*!
+    @beta
+    Sets whether the button is pressed down.
+
+    The signals pressed() and clicked() are not emitted
+    if you set this property to \c true.
+
+    \sa isDown()
+ */
+void HbAbstractButton::setDown(bool down)
+{
+    Q_D( HbAbstractButton );
+
+    if (d->down == down)
+        return;
+    d->down = down;
+    d->refresh();
+    if (d->autoRepeat && d->down)
+        d->repeatTimer.start(d->autoRepeatDelay, this);
+    else
+        d->repeatTimer.stop();
+}
+
+/*!
+    @beta
+    Returns whether autoRepeat is enabled.
+
+    If autoRepeat is enabled, then the pressed(), released(), and clicked() signals are emitted at
+    regular intervals when the button is down. autoRepeat is off by default.
+    The initial delay and the repetition interval are defined in milliseconds by \l
+    autoRepeatDelay and \l autoRepeatInterval.
+
+    Note: If a button is pressed down by a shortcut key, then auto-repeat is enabled and timed by the
+    system and not by this class. The pressed(), released(), and clicked() signals will be emitted
+    like in the normal case.
+*/
+bool HbAbstractButton::autoRepeat() const
+{
+    Q_D( const HbAbstractButton );
+
+    return d->autoRepeat;
+}
+
+/*!
+    @beta
+    Sets whether autoRepeat is enabled.
+ */
+void HbAbstractButton::setAutoRepeat(bool autoRepeat)
+{
+    Q_D( HbAbstractButton );
+
+    if (d->autoRepeat == autoRepeat)
+        return;
+    d->autoRepeat = autoRepeat;
+    if (d->autoRepeat && d->down)
+        d->repeatTimer.start(d->autoRepeatDelay, this);
+    else
+        d->repeatTimer.stop();
+}
+
+/*!
+    @beta
+    Returns the initial delay of auto-repetition in milliseconds.
+
+    If \l autoRepeat is enabled, then autoRepeatDelay defines the initial
+    delay in milliseconds before auto-repetition kicks in.
+
+    \sa autoRepeat, autoRepeatInterval
+*/
+int HbAbstractButton::autoRepeatDelay() const
+{
+    Q_D( const HbAbstractButton );
+
+    return d->autoRepeatDelay;
+}
+
+/*!
+    @beta
+    Sets the initial delay of auto-repetition in milliseconds.
+ */
+void HbAbstractButton::setAutoRepeatDelay(int autoRepeatDelay)
+{
+    Q_D( HbAbstractButton );
+
+    d->autoRepeatDelay = autoRepeatDelay;
+}
+
+/*!
+    @beta
+    Returns the interval of auto-repetition.
+
+    If \l autoRepeat is enabled, then autoRepeatInterval defines the
+    length of the auto-repetition interval in millisecons.
+
+    \sa autoRepeat, autoRepeatDelay
+*/
+int HbAbstractButton::autoRepeatInterval() const
+{
+    Q_D( const HbAbstractButton );
+
+    return d->autoRepeatInterval;
+}
+
+/*!
+    @beta
+    Sets the interval of auto-repetition.
+ */
+void HbAbstractButton::setAutoRepeatInterval(int autoRepeatInterval)
+{
+    Q_D( HbAbstractButton );
+
+    d->autoRepeatInterval = autoRepeatInterval;
+}
+
+/*!
+    @beta
+    Returns whether auto-exclusivity is enabled.
+
+    If auto-exclusivity is enabled, checkable buttons that belong to the
+    same parent widget behave as if they were part of the same
+    exclusive button group. In an exclusive button group, only one button
+    can be checked at any time; checking another button automatically
+    unchecks the previously checked one.
+
+    The property has no effect on buttons that belong to a button
+    group.
+
+    autoExclusive is off by default, except for radio buttons.
+
+    \sa setAutoExclusive()
+*/
+bool HbAbstractButton::autoExclusive() const
+{
+    Q_D( const HbAbstractButton );
+
+    return d->autoExclusive;
+}
+
+/*!
+    @beta
+    Sets whether auto-exclusivity is enabled.
+
+    \sa autoExclusive()
+ */
+void HbAbstractButton::setAutoExclusive(bool autoExclusive)
+{
+    Q_D( HbAbstractButton );
+
+    d->autoExclusive = autoExclusive;
+}
+
+
+
+/*!
+    Performs an animated click: the button is pressed immediately, and
+    released \a msec milliseconds later (the default is 100 ms).
+
+    Calling this function again before the button was released will reset
+    the release timer.
+
+    All signals associated with a click are emitted as appropriate.
+
+    This function does nothing if the button is \link setEnabled()
+    disabled. \endlink
+
+    \sa click()
+*/
+void HbAbstractButton::animateClick(int msec)
+{
+    Q_D( HbAbstractButton );
+
+    if (!isEnabled())
+        return;
+    if (d->checkable && focusPolicy() & Qt::ClickFocus)
+        setFocus();
+    setDown(true);
+    updatePrimitives();
+
+    if (!d->animateTimer.isActive())
+        d->emitPressed();
+    d->animateTimer.start(msec, this);
+}
+
+/*!
+    Performs a click.
+
+    All the usual signals associated with a click are emitted as
+    appropriate. If the button is checkable, the state of the button is
+    toggled.
+
+    This function does nothing if the button is \link setEnabled()
+    disabled. \endlink
+
+    \sa animateClick()
+ */
+void HbAbstractButton::click()
+{
+    Q_D( HbAbstractButton );
+
+    if (!isEnabled())
+        return;
+    QPointer<HbAbstractButton> guard(this);
+    d->down = true;
+    d->emitPressed();
+    if (guard) {
+        d->down = false;
+        nextCheckState();
+        if (guard)
+            d->emitReleased();
+        if (guard && !d->longPress)
+            d->emitClicked();
+    }
+}
+
+/*!
+    \fn void HbAbstractButton::toggle()
+
+    Toggles the state of a checkable button.
+
+     \sa checked
+*/
+void HbAbstractButton::toggle()
+{
+    Q_D( HbAbstractButton );
+
+    setChecked(!d->checked);
+}
+
+/*!
+    This virtual handler is called when setChecked() was called,
+    unless it was called from within nextCheckState(). It allows
+    subclasses to reset their intermediate button states.
+
+    \sa nextCheckState()
+ */
+void HbAbstractButton::checkStateSet()
+{
+}
+
+/*!
+    This virtual handler is called when a button is clicked. The
+    default implementation calls setChecked(!isChecked()) if the button
+    isCheckable().  It allows subclasses to implement intermediate button
+    states.
+
+    \sa checkStateSet()
+*/
+void HbAbstractButton::nextCheckState()
+{
+    if (isCheckable())
+        setChecked(!isChecked());
+}
+
+/*!
+    Returns \c true if \a pos is inside the clickable button rectangle;
+    otherwise returns \c false.
+
+    By default, the clickable area is the entire widget. Subclasses
+    may reimplement this function to provide support for clickable
+    areas of different shapes and sizes.
+*/
+bool HbAbstractButton::hitButton(const QPointF &pos) const
+{
+    return rect().contains(pos);
+}
+
+/*!
+    Initializes \a option with the values from this HbAbstractButton. This method is useful for subclasses when they need a HbStyleOption, but don't want to fill in the pressed state information themselves.
+ */
+void HbAbstractButton::initStyleOption(HbStyleOption *option) const
+{
+    HbWidget::initStyleOption(option);
+    Q_ASSERT(option);
+    option->state |= (isChecked() | isDown() ? QStyle::State_On : QStyle::State_Off);
+}
+
+/*!
+    \reimp
+ */
+bool HbAbstractButton::event(QEvent *event)
+{
+    // as opposed to other widgets, disabled buttons accept mouse
+    // events. This avoids surprising click-through scenarios	
+    Q_D( HbAbstractButton );
+    if (!isEnabled()) {
+        switch(event->type()) {
+        case QEvent::TabletPress:
+        case QEvent::TabletRelease:
+        case QEvent::TabletMove:
+        case QEvent::MouseButtonPress:
+        case QEvent::MouseButtonRelease:
+        case QEvent::MouseButtonDblClick:
+        case QEvent::MouseMove:
+        case QEvent::HoverMove:
+        case QEvent::HoverEnter:
+        case QEvent::HoverLeave:
+        case QEvent::ContextMenu:
+#ifndef QT_NO_WHEELEVENT
+        case QEvent::Wheel:
+#endif
+            return true;
+        default:
+            break;
+        }
+    }
+    if(event->type() ==  QEvent::MouseMove) {
+        return true;
+    }
+
+#ifndef QT_NO_SHORTCUT
+    if (event->type() == QEvent::Shortcut) {
+        QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
+        if (d->shortcutId != se->shortcutId())
+            return false;
+        if (!se->isAmbiguous()) {
+            if (!d->animateTimer.isActive())
+                animateClick();
+        } else {
+            if (focusPolicy() != Qt::NoFocus)
+                setFocus(Qt::ShortcutFocusReason);
+            window()->setAttribute(Qt::WA_KeyboardFocusChange);
+        }
+        return true;
+    }
+#endif
+    return HbWidget::event(event);
+}
+
+/*!
+    \reimp
+ */
+void HbAbstractButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_D( HbAbstractButton );
+
+    if (event->button() != Qt::LeftButton) {
+        event->ignore();
+        return;
+    }
+    if (hitButton(event->pos())) {
+        setDown(true);
+        HbWidgetFeedback::triggered(this, Hb::InstantPressed);
+        updatePrimitives();
+        d->emitPressed();
+        event->accept();
+    } else {
+        event->ignore();
+    }
+}
+
+/*!
+    \reimp
+ */
+void HbAbstractButton::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+    //This check is not required for s60 env
+#ifndef Q_OS_SYMBIAN    
+    if (event->button() != Qt::LeftButton) {
+        event->ignore();
+        return;
+    }
+#endif
+
+    Q_D( HbAbstractButton );
+
+    //TODO: this code will be unnecessary when event filter of HbToolTipLabel will be implemented!!
+    //HbToolTip::hideText();
+
+    if (!d->down) {
+        event->ignore();
+        return;
+    }
+    if (hitButton(event->pos()) && !d->longPress) {
+        HbWidgetFeedback::triggered(this, Hb::InstantClicked);
+    }
+    HbWidgetFeedback::triggered(this, Hb::InstantReleased);
+    if (hitButton(event->pos())) {
+        d->repeatTimer.stop();
+        d->click();
+        event->accept();
+    } else {
+        setDown(false);
+        event->ignore();
+    }
+    d->longPress = false;
+}
+
+/*!
+    \reimp
+ */
+void HbAbstractButton::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+    if (!(event->buttons() & Qt::LeftButton)) {
+        event->ignore();
+        return;
+    }
+
+    Q_D( HbAbstractButton );
+
+    bool hit = hitButton(event->pos());
+    if (!hit) {
+        //TODO: this code will be unnecessary when event filter of HbToolTipLabel will be implemented!!
+        //HbToolTip::hideText();
+    }
+
+    if (hit != d->down) {
+        setDown(!d->down);
+        updatePrimitives();
+        if (d->down) {
+            // this call show tooltip for button,
+            // for the case press, move outside and come back to same button.
+            HbToolTip::showText(toolTip(), this);
+            d->emitPressed();
+            HbWidgetFeedback::triggered(this, Hb::InstantPressed);
+        } else {
+            d->emitReleased();
+            d->longPress = false;
+            HbWidgetFeedback::triggered(this, Hb::InstantReleased);
+        }
+        event->accept();
+    } else if (!hit) {
+        event->ignore();
+    }
+}
+
+/*!
+    \reimp
+ */
+void HbAbstractButton::keyPressEvent(QKeyEvent *event)
+{
+    Q_D( HbAbstractButton );
+
+    bool next = true;
+    switch (event->key()) {
+ 
+    case Qt::Key_Select:
+    case Qt::Key_Enter:
+    case Qt::Key_Return:
+        if (!event->isAutoRepeat()) {
+            setDown(true);
+            updatePrimitives();
+            d->emitPressed();
+        }
+        break;
+    case Qt::Key_Up:
+    case Qt::Key_Left:
+        next = false;
+        // fall through
+    case Qt::Key_Right:
+    case Qt::Key_Down:
+#ifdef QT_KEYPAD_NAVIGATION
+        if (QApplication::keypadNavigationEnabled() && (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right)) {
+            event->ignore();
+            return;
+        }
+#endif
+        if (d->autoExclusive) {
+            // ### Using qobject_cast to check if the parent is a viewport of
+            // QAbstractItemView is a crude hack, and should be revisited and
+            // cleaned up when fixing task 194373. It's here to ensure that we
+            // keep compatibility outside QAbstractItemView.
+            d->moveFocus(event->key());
+            if (hasFocus()) // nothing happend, propagate
+                event->ignore();
+        } else {
+            focusNextPrevChild(next);
+        }
+        break;
+    case Qt::Key_Escape:
+        if (d->down) {
+            setDown(false);
+            updatePrimitives();
+            d->emitReleased();
+            break;
+        }
+        // fall through
+    default:
+        event->ignore();
+    }
+}
+
+/*!
+    \reimp
+ */
+void HbAbstractButton::keyReleaseEvent(QKeyEvent *event)
+{
+    Q_D( HbAbstractButton );
+
+    if (!event->isAutoRepeat())
+        d->repeatTimer.stop();
+
+    switch (event->key()) {
+        case Qt::Key_Select:
+        case Qt::Key_Enter:
+        case Qt::Key_Return: {
+            if (!event->isAutoRepeat() /*&& d->down*/) {
+                if (d->down && !d->longPress) {
+                    HbWidgetFeedback::triggered(this, Hb::InstantClicked);
+                }
+                d->click();
+            }
+	    break;
+        }
+        default:
+            event->ignore();
+    }
+}
+
+/*!
+    \reimp
+ */
+void HbAbstractButton::timerEvent(QTimerEvent *event)
+{
+    Q_D( HbAbstractButton );
+
+    if (event->timerId() == d->repeatTimer.timerId()) {
+        d->repeatTimer.start(d->autoRepeatInterval, this);
+        if (d->down) {
+            QPointer<HbAbstractButton> guard(this);
+            d->emitReleased();
+            if (guard) {
+                d->emitClicked();
+            }
+            if (guard) {
+                d->emitPressed();
+                HbWidgetFeedback::triggered(this, Hb::InstantKeyRepeated);
+            }
+        }
+    } else if (event->timerId() == d->animateTimer.timerId()) {
+        d->animateTimer.stop();
+        d->click();
+    }
+}
+
+
+/*!
+    \reimp
+ */
+void HbAbstractButton::focusInEvent(QFocusEvent *event)
+{
+    Q_D( HbAbstractButton );
+
+#ifdef QT_KEYPAD_NAVIGATION
+    if (!QApplication::keypadNavigationEnabled())
+#endif
+    d->fixFocusPolicy();
+    HbWidget::focusInEvent(event);
+}
+
+/*!
+    \reimp
+ */
+void HbAbstractButton::changeEvent(QEvent *event)
+{
+    Q_D( HbAbstractButton );
+
+    switch (event->type()) {
+    case QEvent::EnabledChange:
+        if (!isEnabled())
+            setDown(false);
+        break;
+    default:
+        d->sizeHint = QSize();
+        break;
+    }
+    HbWidget::changeEvent(event);
+}
+
+/*!
+    \reimp
+*/
+void HbAbstractButton::polish(HbStyleParameters& params)
+{
+        Q_D( HbAbstractButton );
+
+    if (d->mSizeHintPolish) {
+        d->mSizeHintPolish = false;
+        return;
+    }
+    d->mRepolishRequested = false;
+    HbWidget::polish(params);
+}
+
+/*!
+    \reimp
+*/
+QSizeF HbAbstractButton::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+    Q_D(const HbAbstractButton);
+    if (d->mRepolishRequested && isVisible()) {
+        d->mRepolishRequested = false;
+        // force the polish event in order to get the real size
+        QEvent polishEvent(QEvent::Polish);
+        QCoreApplication::sendEvent(const_cast<HbAbstractButton *>(this), &polishEvent);
+        d->mSizeHintPolish = true;
+    }
+    return HbWidget::sizeHint(which, constraint);
+}
+
+/*!
+    \fn void HbAbstractButton::pressed()
+
+    This signal is emitted when the button is pressed down.
+
+    \sa released(), clicked()
+*/
+
+/*!
+    \fn void HbAbstractButton::released()
+
+    This signal is emitted when the button is released.
+
+    \sa pressed(), clicked(), toggled()
+*/
+
+/*!
+    \fn void HbAbstractButton::clicked(bool checked)
+
+    This signal is emitted when the button is activated (i.e. pressed down
+    then released while the stylus is inside the button), when the
+    shortcut key is typed, or when click() or animateClick() is called.
+    Notably, this signal is \e not emitted if you call setDown(),
+    setChecked() or toggle().
+
+    If the button is checkable, \a checked is true if the button is
+    checked, or false if the button is unchecked.
+
+    \sa pressed(), released(), toggled()
+*/
+
+/*!
+    \fn void HbAbstractButton::toggled(bool checked)
+
+    This signal is emitted whenever a checkable button changes its state.
+    \a checked is true if the button is checked, or false if the button is
+    unchecked.
+
+    This may be the result of a user action, click() slot activation,
+    or because setChecked() was called.
+
+    \sa checked, clicked()
+*/
+
+#include "moc_hbabstractbutton.cpp"