src/hbinput/inputwidgets/hbinputvkbwidget.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbinput/inputwidgets/hbinputvkbwidget.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,1174 @@
+/****************************************************************************
+**
+** 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 HbInput 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 <QPixmap>
+#include <QBitmap>
+#include <QPainter>
+#include <QGraphicsItemAnimation>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsProxyWidget>
+#include <QTimeLine>
+#include <QGraphicsGridLayout>
+#include <QGraphicsScene>
+#include <QGraphicsLinearLayout>
+
+#include <hbapplication.h>
+#include <hbmainwindow.h>
+#include <hbaction.h>
+#include <hbview.h>
+#include <hbwidget.h>
+#include <hbpushbutton.h>
+#include <hbinputsettingproxy.h>
+#include <hbdialog.h>
+#include <hbeffect.h>
+#include <hbstackedwidget.h>
+#include <hbframedrawer.h>
+#include <hbevent.h>
+
+#include <hbinputmethod.h>
+#include <hbinputsettingproxy.h>
+#include <hbinpututils.h>
+#include <hbinputdef.h>
+#include <hbinputvkbhost.h>
+#include <hbinputsettingdialog.h>
+#include <hbinputcommondialogs.h>
+#include <hbinputkeymap.h>
+#include <hbinputkeymapfactory.h>
+#include <hbwidgetfeedback.h>
+#include <hbsmileyengine.h>
+#include <hbinputpredictionfactory.h>
+
+#include "hbinputvirtualrocker.h"
+#include "hbinputvkbwidget.h"
+#include "hbinputvkbwidget_p.h"
+#include "hbinputtouchkeypadbutton.h"
+#include "hbinputsettinglist.h"
+#include "hbinputmodeindicator.h"
+#include <hbfeedbackmanager.h>
+#include "hbinputsmileypicker.h"
+#include "hbinputscreenshotwidget.h"
+const qreal HbMouseDragDelta = 0.4;
+const qreal HbRockerWidth = 50.0;
+
+const int MaxSweepTime = 500;
+const int SweepLength = 150;
+
+
+/*!
+@proto
+@hbinput
+\class HbInputVkbWidget
+\brief A base class for touch keypads.
+
+This class implements default mechanisms for opening and closing touch keypads.
+It know how to operate in landscape and in portait modes and it know how
+implement split view -mechasnism for S60 QT UI's Hb library. It also implements
+closing mechansim, where used is able to close the touch keypad by sliding it downwards
+with a finger. This class also implements background drawing for touch keypads.
+*/
+
+/// @cond
+
+inline HbWidget* hbwidget_cast(QGraphicsItem *item)
+{
+    if( item->isWidget() && static_cast<QGraphicsWidget*>(item)->inherits("HbWidget") ) {
+        return static_cast<HbWidget*>(item);
+    }
+    return 0;
+}
+
+HbInputVkbWidgetPrivate::HbInputVkbWidgetPrivate()
+: mOwner(0),
+mMode(EModeAbc),
+mKeymap(0),
+mModifiers(0),
+mInputModeIndicator(0),
+mApplicationButton(0),
+mSettingsButton(0),
+mSettingList(0),
+mButtonLayout(0),
+mRocker(0),
+mBackgroundDrawer(0),
+mIconDrawer(0),
+mMainWinConnected(false),
+mShowRocker(false),
+mLayout(0),
+mCurrentHost(0),
+mDrawbackground(true),
+mMouseButtonPressedDown(false),
+mFlickDirection(HbInputVkbWidget::HbFlickDirectionNone),
+mSmileyPicker(0),
+mScreenshotWidget(0),
+mScreenshotTimeLine(250),
+mMostRecentlyAccessedButton(0),
+mMostRecentlyClickedLocation(0.0,0.0),
+mFocusedObject(0),
+mFlickAnimation(false),
+mSettingsListOpen(false),
+mAnimateWhenDialogCloses(false),
+mKeyboardSize(HbQwerty4x10),
+mCloseHandleHeight(0),
+mCloseHandle(NULL),
+mKeyboardDimmed(false)
+{
+}
+
+
+HbInputVkbWidgetPrivate::~HbInputVkbWidgetPrivate()
+{
+    delete mSettingList;
+    delete mBackgroundDrawer;
+    delete mIconDrawer;
+    delete mSmileyPicker;
+    delete mScreenshotWidget;
+}
+
+void HbInputVkbWidgetPrivate::init()
+{
+    Q_Q(HbInputVkbWidget);
+
+    mRocker = new HbInputVirtualRocker(q);
+    mRocker->setObjectName("VirtualRocker");
+    QSizeF rockerSize(HbRockerWidth, HbRockerWidth);
+    mRocker->resize(rockerSize);
+    mRocker->setMinimumSize(HbRockerWidth, HbRockerWidth);
+    mRocker->setMaximumSize(HbRockerWidth*20, HbRockerWidth*20);
+
+    QObject::connect(mRocker, SIGNAL(rockerDirection(int, HbInputVirtualRocker::RockerSelectionMode)),
+        q, SIGNAL(rockerDirection(int, HbInputVirtualRocker::RockerSelectionMode)));
+
+    mRocker->setVisible(false);
+
+    mBackgroundDrawer = new HbFrameDrawer();
+    mBackgroundDrawer->setFrameGraphicsName(backgroundGraphics);
+    mBackgroundDrawer->setFrameType(HbFrameDrawer::ThreePiecesVertical);
+    mBackgroundDrawer->setFillWholeRect(true);
+    mBackgroundDrawer->setBorderWidths(0.0, HbCloseHandleHeight, 0.0, HbCloseHandleHeight);
+
+    mIconDrawer = new HbFrameDrawer();
+    mIconDrawer->setFrameType(HbFrameDrawer::OnePiece);
+    mIconDrawer->setFrameGraphicsName(HbInputVkbHandleIcon);
+
+    mReleaseMapper = new QSignalMapper(q);
+    mPressMapper = new QSignalMapper(q);
+    mActionMapper = new QSignalMapper(q);
+}
+
+// re-implemented by inherited keyboards
+int HbInputVkbWidgetPrivate::keyCode(int buttonId)
+{
+    Q_UNUSED(buttonId);
+    return -1;
+}
+
+// re-implemented by inherited keyboards
+int HbInputVkbWidgetPrivate::keyCode(HbTouchKeypadButton *button)
+{
+    Q_UNUSED(button);
+    return -1;
+}
+
+void HbInputVkbWidgetPrivate::handleStandardButtonPress(int buttonid)
+{
+    int keycode = buttonid;
+    if (buttonid >= 0) {
+        keycode = keyCode(buttonid);
+    }
+
+    QKeyEvent event(QEvent::KeyPress, keycode, Qt::NoModifier);
+    if (mOwner) {
+        mOwner->filterEvent(&event);
+    }
+}
+
+void HbInputVkbWidgetPrivate::handleStandardButtonRelease(int buttonid)
+{
+    int keycode = buttonid;
+    if (buttonid >= 0) {
+        keycode = keyCode(buttonid);
+    }
+
+    QKeyEvent event(QEvent::KeyRelease, keycode, Qt::NoModifier);
+    if (mOwner) {
+        mOwner->filterEvent(&event);
+    }
+}
+
+void HbInputVkbWidgetPrivate::addCustomButtonToLayout( HbTouchKeypadButton* button,
+                                                       int index)
+{
+    Q_UNUSED(button);
+    Q_UNUSED(index);
+}
+
+void HbInputVkbWidgetPrivate::redirectMousePressEvent(QGraphicsSceneMouseEvent *aEvent)
+{
+    q_ptr->mousePressEvent(aEvent);
+}
+
+void HbInputVkbWidgetPrivate::redirectMouseReleaseEvent(QGraphicsSceneMouseEvent *aEvent)
+{
+    q_ptr->mouseReleaseEvent(aEvent);
+}
+
+void HbInputVkbWidgetPrivate::applyEditorConstraints() {
+    // no default implementaiton as of now.
+}
+
+void HbInputVkbWidgetPrivate::setRockerPosition()
+{
+    Q_Q(HbInputVkbWidget);
+
+    // Set rocker position.
+    QSizeF padArea = q->keypadButtonAreaSize();
+    QPointF point((padArea.width() * 0.5) - (mRocker->size().width() * 0.5),
+        (padArea.height() * 0.5) - (mRocker->size().height() * 0.5));
+    point.setY(point.y() + mCloseHandleHeight);
+
+    if (q->keypadLayout() && q->keypadLayout()->geometry().height()) {
+        point.setX(((padArea.width() * 0.5) - (mRocker->size().width() * 0.5)));
+        point.setY(((q->keypadLayout()->geometry().height() * 0.5) - (mRocker->size().height() * 0.5) + mCloseHandleHeight));
+    }
+    mRocker->setPos(point);
+}
+
+void HbInputVkbWidgetPrivate::captureScreenshot()
+{
+    Q_Q(HbInputVkbWidget);
+
+    if (!mScreenshotWidget) {
+        mScreenshotWidget = new HbInputScreenshotWidget();
+        mScreenshotWidget->setGeometry(q->geometry());
+        q->mainWindow()->scene()->addItem(mScreenshotWidget);
+    }
+
+    QPointF position = q->pos();
+    QRectF rect = QRectF(position.x(), position.y()+ mCloseHandleHeight, q->boundingRect().width(), q->boundingRect().height()- mCloseHandleHeight);
+    QTransform rotateTrans;
+    rotateTrans = q->mainWindow()->viewportTransform();
+    QRectF transRect = rotateTrans.mapRect(rect);
+    QPixmap pixmap;
+    pixmap = QPixmap::grabWidget(q->mainWindow(), (int)transRect.x(), (int)transRect.y(), (int)transRect.width(), (int)transRect.height());
+    pixmap = pixmap.transformed(rotateTrans.inverted());
+    mScreenshotWidget->setScreenshot(pixmap);
+}
+
+
+void HbInputVkbWidgetPrivate::updateMouseHitItem(HbTouchKeypadButton *button, QPointF position)
+{
+    mMostRecentlyAccessedButton = button;
+    mMostRecentlyClickedLocation = position;
+}
+
+void HbInputVkbWidgetPrivate::normalizeProbabilities(QList<HbKeyPressProbability> &allProbableKeys)
+{
+    qreal sum = 0.0;
+    foreach (HbKeyPressProbability key, allProbableKeys) {
+        sum += key.probability;
+    }
+
+    for (int count=0;count<allProbableKeys.size();count++) {
+        allProbableKeys[count].probability = allProbableKeys[count].probability / sum;
+    }
+}
+
+bool HbInputVkbWidgetPrivate::isKeyboardDimmed()
+{
+    return mKeyboardDimmed;
+}
+
+bool HbInputVkbWidgetPrivate::isSmileysEnabled()
+{
+    bool ret = false;
+    if (!mOwner || !mOwner->focusObject()) {
+        return ret;
+    }
+    if (mOwner->focusObject()->editorInterface().editor()->inherits("HbAbstractEdit")) {
+        if (!mOwner->focusObject()->editorInterface().smileyTheme().isNull()) {
+            ret = true;
+        }		
+    }	else {
+        HbSmileyEngine smileyEngine;
+        if (!smileyEngine.defaultTheme().isNull()) {
+            ret = true;
+        }	
+    }	
+    return ret;	
+}
+/// @endcond
+
+/*!
+Costructs the object.
+*/
+HbInputVkbWidget::HbInputVkbWidget(QGraphicsItem* parent)
+    : HbWidget(*new HbInputVkbWidgetPrivate, parent)
+{
+    Q_D(HbInputVkbWidget);
+    d->q_ptr = this;
+    d->init();
+
+    setFocusPolicy(Qt::ClickFocus);
+    setPos(QPointF(0,0));
+
+#ifdef HB_EFFECTS
+    HbEffect::disable(this);
+#endif // HB_EFFECTS
+
+#if QT_VERSION >= 0x040600
+    // Make sure the keypad never steals focus.
+    setFlag(QGraphicsItem::ItemIsPanel, true);
+    setActive(false);
+#endif
+}
+
+/*!
+Constructs the object.
+*/
+HbInputVkbWidget::HbInputVkbWidget(HbInputVkbWidgetPrivate& dd, QGraphicsItem* parent)
+  : HbWidget(dd, parent)
+{
+    Q_D(HbInputVkbWidget);
+    d->q_ptr = this;
+    d->init();
+
+    setFocusPolicy(Qt::ClickFocus);
+    setPos(QPointF(0,0));
+
+#ifdef HB_EFFECTS
+    HbEffect::disable(this);
+#endif // HB_EFFECTS
+
+#if QT_VERSION >= 0x040600
+    // Make sure the keypad never steals focus.
+    setFlag(QGraphicsItem::ItemIsPanel, true);
+    setActive(false);
+#endif
+}
+
+/*!
+Destructs the object.
+*/
+HbInputVkbWidget::~HbInputVkbWidget()
+{
+}
+
+/*!
+Vkb host calls this handler when the keypad open animation finishes.
+*/
+void HbInputVkbWidget::keyboardOpened(HbVkbHost *host)
+{
+    Q_D(HbInputVkbWidget);
+
+    d->mCurrentHost = host;
+    d->mRocker->setVisible(d->mShowRocker);
+    d->setRockerPosition();
+}
+
+/*!
+Vkb host calls this handler when the keyboard close animation has finished.
+
+\sa HbVkbHost
+*/
+void HbInputVkbWidget::keyboardClosed(HbVkbHost *host)
+{
+    Q_UNUSED(host);
+    Q_D(HbInputVkbWidget);
+
+    d->mRocker->setVisible(false);
+}
+
+/*!
+Vkb host calls this handler when the keyboard minimize animation has finished.
+
+\sa HbVkbHost
+*/
+void HbInputVkbWidget::keyboardMinimized(HbVkbHost *host)
+{
+    Q_UNUSED(host);
+}
+
+/*!
+handles mouse press event.
+*/
+void HbInputVkbWidget::mousePressEvent(QGraphicsSceneMouseEvent* event)
+{
+    Q_D(HbInputVkbWidget);
+    Q_UNUSED(event);
+    if (!d->mMouseButtonPressedDown) {
+        d->mMouseButtonPressedDown = true;
+        d->mMousePressTime.start();
+    }
+}
+
+/*!
+Handles mouse release event.
+*/
+void HbInputVkbWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+{
+    Q_D(HbInputVkbWidget);
+    d->mFlickDirection = HbFlickDirectionNone;
+    d->mMouseButtonPressedDown = false;
+
+    QPointF mouseDownpoint = event->buttonDownScenePos(Qt::LeftButton);
+
+    if (d->mCurrentHost && d->mCurrentHost->keypadStatus() != HbVkbHost::HbVkbStatusOpened &&
+        d->mCurrentHost->activeKeypad() && d->mOwner) {
+        HbWidgetFeedback::triggered(this, Hb::InstantFlicked);
+        d->mCurrentHost->openKeypad(d->mCurrentHost->activeKeypad(), d->mOwner);
+    } else if (d->mMousePressTime.elapsed() < MaxSweepTime || mouseDownpoint.y() <= scenePos().y() + d->mCloseHandleHeight) {
+        QPointF delta = event->scenePos() - mouseDownpoint;
+
+        qreal height;
+        if (HbInputSettingProxy::instance()->screenOrientation() == Qt::Horizontal) {
+            height = geometry().height() * 0.5;
+        } else {
+            // For ITU-T, 40% of the scene height is considered.
+            height = 0.4 * geometry().height();
+        }
+        // If the user drags the mouse on keypad and the
+        // delta is greater than 10% of the height, keypad is closed
+        height = HbMouseDragDelta * height;
+
+        if (delta.y() > height) {
+            HbWidgetFeedback::triggered(this, Hb::InstantFlicked);
+            d->mFlickDirection = HbFlickDirectionDown;
+            emit keypadCloseEventDetected(HbVkbCloseMethodButtonDrag);
+        }
+
+        if (qAbs(delta.x()) > SweepLength) {
+
+            d->mFlickDirection = delta.x()>0 ? HbFlickDirectionRight : HbFlickDirectionLeft;
+
+            if (d->mFlickAnimation){
+                HbWidgetFeedback::triggered(this, Hb::InstantFlicked);
+                animKeyboardChange();
+            }
+            emit flickEvent(d->mFlickDirection);
+        }
+    }
+}
+
+/*!
+Handles virtual key press
+*/
+void HbInputVkbWidget::mappedKeyPress(int buttonid)
+{
+    Q_D(HbInputVkbWidget);
+    d->handleStandardButtonPress(buttonid);
+}
+
+/*!
+Handles virtual key release
+*/
+void HbInputVkbWidget::mappedKeyRelease(int buttonid)
+{
+    Q_D(HbInputVkbWidget);
+    d->handleStandardButtonRelease(buttonid);
+}
+
+
+/*!
+The paint method. Draws the widget.
+*/
+void HbInputVkbWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
+{
+    Q_UNUSED(option);
+    Q_UNUSED(widget);
+
+    Q_D(HbInputVkbWidget);
+
+    QRectF rect = boundingRect();
+    if (d->mDrawbackground) {
+        d->mBackgroundDrawer->paint(painter, rect);
+    }
+
+    rect.setLeft(rect.width()/2 - d->mCloseHandleHeight*3);
+    rect.setWidth(d->mCloseHandleHeight*6);
+    rect.setHeight(d->mCloseHandleHeight);
+    d->mIconDrawer->paint(painter, rect);
+}
+
+/*!
+Sets virtual rocker visibility.
+*/
+void HbInputVkbWidget::setRockerVisible(bool visible)
+{
+    Q_D(HbInputVkbWidget);
+    d->mShowRocker = visible;
+}
+
+/*!
+Returns true if virtual rocker is allowed to be visible.
+*/
+bool HbInputVkbWidget::isRockerVisible() const
+{
+    Q_D(const HbInputVkbWidget);
+    if (d->mShowRocker) {
+        return d->mRocker->isVisible();
+    } else {
+        return false;
+    }
+}
+
+/*!
+Returns active keypad mode. Possible values are EModeAbc, EModeNumeric and EModeSct.
+*/
+HbKeypadMode HbInputVkbWidget::mode() const
+{
+    Q_D(const HbInputVkbWidget);
+    return d->mMode;
+}
+
+/*!
+Returns active keypad modifiers.
+*/
+HbModifiers HbInputVkbWidget::modifiers() const
+{
+    Q_D(const HbInputVkbWidget);
+    return d->mModifiers;
+}
+
+/*!
+Sets the keypad to given mode. Possible values are EModeAbc, EModeNumeric and EModeSct.
+*/
+void HbInputVkbWidget::setMode(HbKeypadMode mode, HbModifiers modifiers)
+{
+    Q_D(HbInputVkbWidget);
+    d->mModifiers = modifiers;
+    d->mMode = mode;
+}
+
+/*!
+Sets key map data object. Given key map data will be used as a source for button titles.
+Usually the key map data for active input language is used.
+*/
+void HbInputVkbWidget::setKeymap(const HbKeymap* keymap)
+{
+    Q_D(HbInputVkbWidget);
+    if (keymap) {
+        d->mKeymap = keymap;
+    }
+}
+
+/*!
+This is called right before the keypad is about to open. This gives inheriting classes opportunity
+to do whatever initialization they need to do at this point.
+*/
+void HbInputVkbWidget::aboutToOpen(HbVkbHost *host)
+{
+    Q_D(HbInputVkbWidget);
+
+    d->mCurrentHost = host;
+
+    if (!d->mLayout) {
+        // get preferred size from vkbhost and set it to vkb.
+        // Keypad buttons will flicker while vkb opening (when we open keypad for first time )
+        // if we dont set size to vkb before seting layout to vkb.
+        resize(preferredKeyboardSize());
+        d->mLayout = new QGraphicsLinearLayout(Qt::Vertical);
+        d->mLayout->setContentsMargins(0.0, 0.0, 0.0, 0.0);
+        d->mLayout->setSpacing(0.0);
+
+        setLayout(d->mLayout);
+
+        d->mCloseHandle = new QGraphicsWidget();
+        d->mCloseHandle->setObjectName("vkbHandle");
+        d->mCloseHandleHeight = HbCloseHandleHeight;
+        d->mCloseHandle->setMinimumHeight(d->mCloseHandleHeight);
+        d->mCloseHandle->setMaximumHeight(d->mCloseHandleHeight);
+
+        d->mLayout->addItem(d->mCloseHandle);
+        d->mLayout->addItem(keypadLayout());
+    }
+
+
+    if (d->mOwner && d->mOwner->focusObject()) {
+        qreal vkbZValue = d->mOwner->focusObject()->findVkbZValue();
+        setZValue(vkbZValue);
+        d->mRocker->setZValue(vkbZValue+0.5);
+    }
+
+    show();
+}
+
+/*!
+This is called right before the keypad is about to close.
+*/
+void HbInputVkbWidget::aboutToClose(HbVkbHost *host)
+{
+    Q_D(HbInputVkbWidget);
+
+    d->mCurrentHost = host;
+
+    d->mRocker->setVisible(false);
+    if (d->mSettingList) {
+        d->mSettingList->close();
+    }
+}
+
+/*!
+Enables or disabled all buttons in the keyboard that have not been disabled directly.
+*/
+void HbInputVkbWidget::setKeyboardDimmed(bool dimmed)
+{
+    Q_D(HbInputVkbWidget);
+    d->mKeyboardDimmed = dimmed;
+    if (keypadLayout()) {
+        int itemCount = keypadLayout()->count();
+        for (int i=0; i<itemCount; i++) {
+            HbTouchKeypadButton* button = static_cast<HbTouchKeypadButton*>(keypadLayout()->itemAt(i));
+            button->setFade(dimmed);
+        }
+    }
+    if (!dimmed) {
+        // when we undimmed the keyboard, all the buttons will be enabled by default.
+        // we need to call applyEditorConstraints on the keyboard to apply constraints
+        d->applyEditorConstraints();
+    }
+
+}
+
+/*!
+Shows settings list
+*/
+void HbInputVkbWidget::showSettingList()
+{
+    Q_D(HbInputVkbWidget);
+    HbPredictionFactory *predFactory = HbPredictionFactory::instance();
+
+    d->mSettingsListOpen = true;
+    d->captureScreenshot();
+
+    if (!d->mSettingList) {
+        d->mSettingList = new HbInputSettingList();
+        connect(d->mSettingList, SIGNAL(aboutToClose()), this, SLOT(settingsClosed()));
+        connect(d->mSettingList, SIGNAL(inputSettingsButtonClicked()), this, SLOT(executeSettingsDialog()));
+        connect(d->mSettingList, SIGNAL(inputMethodsButtonClicked()), this, SLOT(executeMethodDialog()));
+    }
+
+#if QT_VERSION >= 0x040600
+    HbInputFocusObject *focusObject = d->mOwner->focusObject();
+    if (focusObject &&
+        focusObject->editorInterface().isPredictionAllowed() &&
+        !focusObject->editorInterface().isNumericEditor() &&
+        predFactory->predictionEngineForLanguage(HbInputSettingProxy::instance()->globalInputLanguage())) {
+        d->mSettingList->setPredictionSelectionEnabled(true);
+    } else {
+        d->mSettingList->setPredictionSelectionEnabled(false);
+    }
+#endif
+
+    d->mSettingsButton->setBackgroundAttributes(HbTouchKeypadButton::HbTouchButtonLatched);
+    qreal x = d->mSettingsButton->scenePos().x() + d->mSettingsButton->rect().width();
+    qreal y = d->mSettingsButton->scenePos().y();
+    d->mSettingList->setPreferredPos(QPointF(x, y), HbPopup::BottomRightCorner);
+    d->mSettingList->showSettingList();
+    d->mSettingsListOpen = false;
+    if ( d->mAnimateWhenDialogCloses ) {
+        animKeyboardChange();
+        d->mAnimateWhenDialogCloses = false;
+    } else if(d->mScreenshotTimeLine.state() != QTimeLine::Running) {
+        keypadLanguageChangeFinished();
+    }
+}
+
+/*!
+Slot to connect aboutToClose of settings list to update keyboard graphics.
+*/
+void HbInputVkbWidget::settingsClosed()
+{
+    Q_D(HbInputVkbWidget);
+    d->mSettingsButton->setBackgroundAttributes(HbTouchKeypadButton::HbTouchButtonReleased);
+}
+
+/*!
+Closes settings list
+*/
+void HbInputVkbWidget::closeSettingList()
+{
+    Q_D(HbInputVkbWidget);
+    d->mSettingList->close();
+    d->mSettingsButton->setBackgroundAttributes(HbTouchKeypadButton::HbTouchButtonReleased);
+}
+
+/*!
+Toggles prediction status.
+*/
+void HbInputVkbWidget::togglePredictionStatus()
+{
+    closeSettingList();
+    bool predictionStatus = HbInputSettingProxy::instance()->predictiveInputStatus();
+    HbInputSettingProxy::instance()->setPredictiveInputStatus(!predictionStatus);
+    update();
+}
+
+/*!
+Executes settingsDialog
+*/
+void HbInputVkbWidget::executeSettingsDialog()
+{
+    Q_D(HbInputVkbWidget);
+
+    closeSettingList();
+    HbInputSettingDialog::HbSettingItems items = HbInputSettingDialog::HbSettingItemAll;
+    if (d->mOwner->focusObject()->editorInterface().isNumericEditor()) {
+        items &=  (~HbInputSettingDialog::HbSettingItemPrediction);
+    }
+    HbInputSettingDialog* settings = new HbInputSettingDialog(items);
+    d->mSettingsListOpen = true;
+    settings->exec();
+    delete settings;
+    d->mSettingsListOpen = false;
+    if ( d->mAnimateWhenDialogCloses ) {
+        animKeyboardChange();
+        d->mAnimateWhenDialogCloses = false;
+    } else {
+        keypadLanguageChangeFinished();
+    }
+}
+
+/*!
+Executes input method selection dialog
+*/
+void HbInputVkbWidget::executeMethodDialog()
+{
+    Q_D(HbInputVkbWidget);
+
+    closeSettingList();
+    HbInputMethodDescriptor method
+        = HbInputCommonDialogs::showCustomInputMethodSelectionDialog(HbInputSettingProxy::instance()->globalInputLanguage());
+    if (!method.isEmpty() && d->mOwner) {
+        d->mOwner->activateInputMethod(method);
+    }
+}
+
+/*!
+Virtual function, each derived keypads should calculate and provide the
+layout information through this functions. This layout information is used
+by HbInputVkbWidget for layouting different components of vkb.
+*/
+QGraphicsLayout *HbInputVkbWidget::keypadLayout()
+{
+    Q_D(HbInputVkbWidget);
+    return d->mButtonLayout;
+}
+
+/*!
+Returns the keypad in QWidget form.
+*/
+QWidget* HbInputVkbWidget::asWidget()
+{
+    return HbInputUtils::createWrapperWidget(this);
+}
+
+/*!
+Returns the keypad in QGraphicsWidget form.
+*/
+QGraphicsWidget* HbInputVkbWidget::asGraphicsWidget()
+{
+    return this;
+}
+
+/*!
+Returns preferred keyboard size. HbVkbHost uses this information when it opens the keyboard.
+*/
+QSizeF HbInputVkbWidget::preferredKeyboardSize()
+{
+    Q_D(HbInputVkbWidget);
+
+    if (d->mCurrentHost) {
+        // Just rely on the host and return what it suggests.
+        QSizeF rect = d->mCurrentHost->keyboardArea();
+        return rect;
+    }
+
+    return QSizeF(0.0, 0.0);
+}
+
+/*!
+This method is called every time vkb host draws an opening animation frame.
+*/
+void HbInputVkbWidget::keyboardAnimationFrame(HbVkbAnimationType type, qreal x)
+{
+    Q_UNUSED(type);
+    Q_UNUSED(x);
+
+    Q_D(HbInputVkbWidget);
+    d->setRockerPosition();
+}
+
+/*!
+Returns the size of the keypad button area.
+*/
+QSizeF HbInputVkbWidget::keypadButtonAreaSize()
+{
+    Q_D(HbInputVkbWidget);
+    QSizeF ret = preferredKeyboardSize();
+    if (ret.height() >  d->mCloseHandleHeight) {
+        ret.setHeight(ret.height() - d->mCloseHandleHeight);
+	}
+
+    return ret;
+}
+
+/*!
+Sets the status of the background drawing. This method can be used to
+optimize vkb widget drawing. If it is known that the widget will cover whole
+vkb area and there are no places where the background shows through, then the background
+drawing can be turned off to speed up paint method.
+*/
+void HbInputVkbWidget::setBackgroundDrawing(bool backgroundEnabled)
+{
+    Q_D(HbInputVkbWidget);
+    d->mDrawbackground = backgroundEnabled;
+}
+
+
+/*!
+Returns all possible keys those the user could have intended to press
+for the last registered touch along with their corresponding probability.
+One issue of thecurrent API implementation is that it does not always
+sum up the probabilities to 1.0, but sometimes it returns.999999899 etc.
+Need to be careful about it!
+*/
+QList<HbKeyPressProbability> HbInputVkbWidget::probableKeypresses()
+{
+    Q_D(HbInputVkbWidget);
+
+    QList<HbKeyPressProbability> probableKeys;
+    int totalItems = d->mButtonLayout->count();
+    QRectF buttonRect = d->mMostRecentlyAccessedButton->geometry();
+    //The overlaying rectangle is the test rectangle that is used for finding
+    //intersactions with other buttons.
+    QRectF overlayingRect(d->mMostRecentlyClickedLocation.x()-buttonRect.width()/2,d->mMostRecentlyClickedLocation.y()-buttonRect.height()/2, buttonRect.width(), buttonRect.height());
+    QPainterPath path(overlayingRect.topLeft());
+    path.addRect(overlayingRect);
+    for(int count=0; count < totalItems; count++) {
+        QGraphicsItem *item = d->mButtonLayout->itemAt(count)->graphicsItem();
+        QPainterPath testPath = item->mapFromScene(path);
+        HbTouchKeypadButton *buttonItem = 0;
+        if(item->isWidget()){
+            buttonItem =  qobject_cast<HbTouchKeypadButton *>(static_cast<QGraphicsWidget *>(item));
+        }
+        if(!buttonItem) {
+            continue;
+        }
+
+        //Checkif the button collides with the path, if yes,it means that the colliding
+        //key also could have been clicked by the user. The probability of the button being
+        //clickedin that case willdependon the area of the intersaction rectangle.
+        if(buttonItem->collidesWithPath(testPath)) {
+            //Initiallylet the intersaction be same as the overlaying rectangle,later we will
+            //shrink the rectangle and find the actual intersected rectangle.
+            QRectF intersactionRect = overlayingRect;
+            //The overlaying rectangle is in scene coordinates, map it to the item coordinates.
+            intersactionRect.moveTopLeft(buttonItem->mapFromScene(overlayingRect.topLeft()));
+            int width = (int)intersactionRect.width();
+            int height = (int)intersactionRect.height();
+            qreal probability = 0.0;
+            //Shrink based on the size of the intersaction
+            if (intersactionRect.topLeft().x() > 0) {
+                width -= (int)intersactionRect.topLeft().x();
+            } else {
+                width += (int)intersactionRect.topLeft().x();
+            }
+            if (intersactionRect.topLeft().y() > 0) {
+                height -= (int)intersactionRect.topLeft().y();
+            } else {
+                height += (int)intersactionRect.topLeft().y();
+            }
+            //The probabilty of the key is based on the intersaction area.
+            probability = (height * width) / (intersactionRect.width()* intersactionRect.height());
+            HbKeyPressProbability probablekey;
+            probablekey.keycode = d->keyCode(buttonItem);
+            probablekey.probability = probability;
+
+            if(probablekey.keycode && (probablekey.probability>0)) {
+                probableKeys.append(probablekey);
+            }
+        }
+    }
+    //Normalize makes sure that all probability summation is 1.0.
+    d->normalizeProbabilities(probableKeys);
+    return probableKeys;
+}
+
+/*!
+Sets up the common buttons in the tool cluster (settings and application buttons).
+*/
+void HbInputVkbWidget::setupToolCluster()
+{
+    Q_D(HbInputVkbWidget);
+    if(!d->mOwner || !d->mOwner->focusObject()) {
+        return;
+    }
+
+    // Create settings button if it does not exist
+    if (!d->mSettingsButton) {
+        d->mSettingsButton = new HbTouchKeypadButton(this, QString(""));
+        d->mInputModeIndicator = new HbInputModeIndicator(*d->mSettingsButton, this);
+        d->mSettingsButton->setButtonType(HbTouchKeypadButton::HbTouchButtonFunction);
+        d->mSettingsButton->setBackgroundAttributes(HbTouchKeypadButton::HbTouchButtonReleased);
+
+        connect(d->mSettingsButton, SIGNAL(clicked()), this, SLOT(showSettingList()));
+
+        connect(d->mSettingsButton, SIGNAL(pressed()), d->mPressMapper, SLOT(map()));
+        connect(d->mSettingsButton, SIGNAL(released()), d->mReleaseMapper, SLOT(map()));
+        d->mPressMapper->setMapping(d->mSettingsButton, -1);
+        d->mReleaseMapper->setMapping(d->mSettingsButton, -1);
+    } else {
+        d->mInputModeIndicator->updateIndicator();
+    }
+
+    // If there's a application specific button defined, create new button with the properties
+    // or update the existing one. Otherwise create an empty button or clean the properties of an existing one.
+    if (!d->mOwner->focusObject()->editorInterface().actions().isEmpty()) {
+        QList<HbAction*> actions = d->mOwner->focusObject()->editorInterface().actions();
+        if (d->mApplicationButtonAction != actions.first()) {
+            if (d->mApplicationButton) {
+                d->mApplicationButton->setText(actions.first()->text());
+                d->mApplicationButton->setIcon(actions.first()->icon());
+                d->mApplicationButton->disconnect(SIGNAL(clicked()));
+                d->mApplicationButton->disconnect(SIGNAL(pressed()));
+                d->mApplicationButton->disconnect(SIGNAL(released()));
+
+                // disconnects old signal
+                disconnect(d->mApplicationButtonAction, SIGNAL(changed()), this, SLOT(refreshApplicationButton()));
+                disconnect(d->mApplicationButton, SIGNAL(clicked()), d->mApplicationButtonAction, SLOT(trigger()));
+            } else {
+                d->mApplicationButton = new HbTouchKeypadButton(this, actions.first()->icon(), actions.first()->text());
+            }
+            d->mApplicationButtonAction = actions.first();
+            // Connect to enabling signal and check its value
+            connect(actions.first(), SIGNAL(changed()), this, SLOT(refreshApplicationButton()));
+
+            if (actions.first()->isEnabled()) {
+                // action is enabled
+                connect(d->mApplicationButton, SIGNAL(clicked()), d->mApplicationButtonAction, SLOT(trigger()));
+
+                connect(d->mApplicationButton, SIGNAL(pressed()), d->mPressMapper, SLOT(map()));
+                connect(d->mApplicationButton, SIGNAL(released()), d->mReleaseMapper, SLOT(map()));
+                d->mPressMapper->setMapping(d->mApplicationButton, -1);
+                d->mReleaseMapper->setMapping(d->mApplicationButton, -1);
+
+                d->mApplicationButton->setToolTip(actions.first()->toolTip());
+                d->mApplicationButton->setButtonType(HbTouchKeypadButton::HbTouchButtonFunction);
+                d->mApplicationButton->setBackgroundAttributes(HbTouchKeypadButton::HbTouchButtonReleased);
+            } else {
+                // action is disabled
+                d->mApplicationButton->setButtonType(HbTouchKeypadButton::HbTouchButtonFnInActive);
+                d->mApplicationButton->setBackgroundAttributes(HbTouchKeypadButton::HbTouchButtonPressed);
+            }
+            d->mApplicationButton->setToolTip(actions.first()->toolTip());
+        }
+    } else {
+        if (d->mApplicationButton) {
+            if (d->mApplicationButtonAction) {
+                disconnect(d->mApplicationButtonAction, SIGNAL(changed()), this, SLOT(refreshApplicationButton()));
+            }
+            d->mApplicationButton->disconnect(SIGNAL(clicked()));
+            d->mApplicationButton->disconnect(SIGNAL(pressed()));
+            d->mApplicationButton->disconnect(SIGNAL(released()));
+            d->mApplicationButton->setText(QString());
+            d->mApplicationButton->setIcon(HbIcon());
+            d->mApplicationButton->setToolTip(QString());
+			d->mApplicationButtonAction = 0;
+        } else {
+            d->mApplicationButton = new HbTouchKeypadButton(this, QString());
+            d->mApplicationButton->setButtonType(HbTouchKeypadButton::HbTouchButtonFunction);
+            d->mApplicationButton->setBackgroundAttributes(HbTouchKeypadButton::HbTouchButtonReleased);
+        }
+        d->mApplicationButtonAction = NULL;
+    }
+}
+
+/*!
+shape function actually refines the bounding rect. This function is used for collision detection
+and hit test.
+*/
+QPainterPath HbInputVkbWidget::shape() const
+{
+    QRectF rect = boundingRect();
+    QPainterPath path;
+    path.addRect(rect);
+    return path;
+}
+
+QSizeF HbInputVkbWidget::minimizedKeyboardSize()
+{
+    Q_D(HbInputVkbWidget);
+    return QSizeF(0.0, d->mCloseHandleHeight);
+}
+
+void HbInputVkbWidget::showSmileyPicker(int rows, int columns)
+{
+    Q_D(HbInputVkbWidget);
+    if (!d->mOwner || !d->mOwner->focusObject()) {
+        return;
+    }
+    // check whether the smiley recognition is enabled 	in the currently focused editor.
+    if (!d->isSmileysEnabled()) {
+        return;
+    }
+    HbInputFocusObject *focusObject = d->mOwner->focusObject();
+	
+    if (!d->mSmileyPicker || d->mFocusedObject != focusObject) {
+        d->mFocusedObject = focusObject;
+        if (d->mSmileyPicker) {
+            delete d->mSmileyPicker;
+        }
+        // get the smiley list from editor interface smiley theme.
+        QStringList smileys = focusObject->editorInterface().smileyTheme().smileys();
+        // if the smiley list is empty and the editor is not a Hb editor, 
+        // then get the default smiley list from smiley engine.
+        if (smileys.isEmpty() && !focusObject->editorInterface().editor()->inherits("HbAbstractEdit")) {
+            HbSmileyEngine smileyEngine;
+            smileys = smileyEngine.defaultTheme().smileys();
+        }
+
+        if (!smileys.isEmpty()) {
+            d->mSmileyPicker = new HbInputSmileyPicker(rows, columns, 0, smileys);
+            d->mSmileyPicker->setObjectName("vkbwidget_smiley_picker");
+            connect(d->mSmileyPicker, SIGNAL(selected(QString)), this, SIGNAL(smileySelected(QString)));
+        }			
+    }
+
+    if (d->mSmileyPicker) {
+        d->mSmileyPicker->setGeometry(QRectF(0, pos().y(), geometry().width(),
+            geometry().height()));
+        d->mSmileyPicker->show();
+    }		
+}
+
+HbInputVkbWidget::HbFlickDirection HbInputVkbWidget::flickDirection()
+{
+    Q_D(HbInputVkbWidget);
+    return d->mFlickDirection;
+}
+
+/*!
+    Intended for internal use only
+*/
+void HbInputVkbWidget::refreshApplicationButton()
+{
+    Q_D(HbInputVkbWidget);
+
+    d->mApplicationButton->setText(d->mApplicationButtonAction->text());
+    d->mApplicationButton->setIcon(d->mApplicationButtonAction->icon());
+
+    if (d->mApplicationButton->getButtonType() == HbTouchKeypadButton::HbTouchButtonFnInActive
+        && d->mApplicationButtonAction->isEnabled()) {
+        // action has been enabled
+        connect(d->mApplicationButton, SIGNAL(clicked()), d->mApplicationButtonAction, SLOT(trigger()));
+        d->mApplicationButton->setToolTip(d->mApplicationButtonAction->toolTip());
+        d->mApplicationButton->setFade(false);
+    } else if (d->mApplicationButton->getButtonType() == HbTouchKeypadButton::HbTouchButtonFunction
+        && !d->mApplicationButtonAction->isEnabled()) {
+        // action has been disabled
+        d->mApplicationButton->disconnect(SIGNAL(clicked()));
+        d->mApplicationButton->setFade(true);
+    }
+}
+
+void HbInputVkbWidget::keypadLanguageChangeAnimationUpdate(qreal aValue)
+{
+    Q_D(HbInputVkbWidget);
+
+    int direction = 1;
+    if (flickDirection() == HbFlickDirectionLeft) {
+        direction = -1;
+    }
+
+    QRectF rect = boundingRect();
+    QPointF position = pos();
+    position.setX(direction * (-rect.width() + rect.width() * aValue));
+    if (d->mScreenshotWidget) {
+       d->mScreenshotWidget->setPos(position.x() + direction * rect.width(), position.y());
+       setPos(position);
+    }
+}
+
+void HbInputVkbWidget::keypadLanguageChangeFinished()
+{
+    Q_D(HbInputVkbWidget);
+    delete d->mScreenshotWidget;
+    d->mScreenshotWidget = NULL;
+}
+
+void HbInputVkbWidget::animKeyboardChange()
+{
+    Q_D(HbInputVkbWidget);
+    if (mainWindow()) {
+        if (d->mSettingsListOpen){
+            d->mAnimateWhenDialogCloses = true;
+        } else {
+            if (!d->mAnimateWhenDialogCloses) {
+                d->captureScreenshot();
+            }
+            connect(&d->mScreenshotTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(keypadLanguageChangeAnimationUpdate(qreal)));
+            connect(&d->mScreenshotTimeLine, SIGNAL(finished()), this, SLOT(keypadLanguageChangeFinished()));
+            d->mScreenshotTimeLine.start();
+        }
+    }
+}
+
+QSizeF HbInputVkbWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+    Q_UNUSED(constraint);
+    Q_D(const HbInputVkbWidget);
+
+    QSizeF sh;
+    switch (which) {
+        case Qt::MinimumSize:
+            sh = QSizeF(0, 0);
+            break;
+        case Qt::PreferredSize:
+            if (d->mCurrentHost) {
+                sh = d->mCurrentHost->keyboardArea();
+            }
+            break;
+        case Qt::MaximumSize:
+            sh = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+            break;
+        default:
+            qWarning("HbInputVkbWidget::sizeHint(): Don't know how to handle the value of 'which'");
+            break;
+    }
+    return sh;
+}
+
+/*!
+    \reimp
+ */
+void HbInputVkbWidget::changeEvent(QEvent *event)
+{
+    Q_D(HbInputVkbWidget);
+    if (event->type() == HbEvent::ThemeChanged) {
+        d->mBackgroundDrawer->themeChanged();
+        d->mIconDrawer->themeChanged();
+    }
+    HbWidget::changeEvent(event);
+}
+
+// End of file