telutils/dialpad/src/dialpadkeypad.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 23 Jun 2010 18:49:32 +0300
changeset 31 a2467631ae02
parent 27 7eb70891911c
child 32 1f002146abb4
permissions -rw-r--r--
Revision: 201023 Kit: 2010125

/*!
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Dialpad keypad
*
*/

#include <QLocale>
#include <QSignalMapper>

#include <hbinstance.h>
#include <hbinputkeymapfactory.h>
#include <hbinputkeymap.h>
#include <hbinpututils.h>
#include <hbinputsettingproxy.h>
#include <hbinputlanguage.h>
#include <hbapplication.h>
#include <hblineedit.h>
#include <hbinputbutton.h>

#include "dialpadkeypad.h"
#include "dialpadbutton.h"
#include "dialpadinputfield.h"

static const int DialpadRowCount = 4;
static const int DialpadColumnCount = 3;
static const QString handsetIcon("qtg_mono_call");
static const QString vmbxIcon("qtg_mono_voice_mailbox");
static const qreal DialpadKeypadBorderWidth = 0.25;

static const int DialpadKeyCodeTable[DialpadRowCount*DialpadColumnCount] =
{
    Qt::Key_1,        Qt::Key_2,      Qt::Key_3,
    Qt::Key_4,        Qt::Key_5,      Qt::Key_6,
    Qt::Key_7,        Qt::Key_8,      Qt::Key_9,
    Qt::Key_Asterisk, Qt::Key_0,      Qt::Key_NumberSign
    // Qt::Key_Yes and Qt::Key_BackSpace are handled separately
};

DialpadKeypad::DialpadKeypad(
    const HbMainWindow& mainWindow,
    DialpadInputField& inputField,
    QGraphicsItem* parent) :
    HbInputButtonGroup(parent),
    mMainWindow(mainWindow),
    mInputField(inputField)
{
    setObjectName("keypad");

    // create clicked signal mapper
    mKeyClickedSignalMapper = new QSignalMapper(this);
    connect(mKeyClickedSignalMapper,SIGNAL(mapped(int)),
            SLOT(handleKeyClicked(int)));

    // connect backspace signals
    connect(&mInputField.backspaceButton(),SIGNAL(clicked()),
            mKeyClickedSignalMapper,SLOT(map()));
    mKeyClickedSignalMapper->setMapping(&mInputField.backspaceButton(),
                                        Qt::Key_Backspace);

    // create keypad
    setGridSize(QSize(DialpadColumnCount, DialpadRowCount));
    setButtonBorderSize(DialpadKeypadBorderWidth);

    QList<HbInputButton*> buttons;

    for (int i = 0; i < DialpadRowCount * DialpadColumnCount; ++i) {
        HbInputButton *item = new HbInputButton(
            DialpadKeyCodeTable[i],
            QPoint(i % DialpadColumnCount, i / DialpadColumnCount));
        buttons.append(item);

        item->setType(HbInputButton::ButtonTypeNormal);
    }

    setButtons(buttons);

    // connect keypad signals
    QObject::connect(this, SIGNAL(buttonPressed(const QKeyEvent&)),
                     this, SLOT(sendKeyPressEvent(const QKeyEvent&)));
    QObject::connect(this, SIGNAL(buttonReleased(const QKeyEvent&)),
                     this, SLOT(sendKeyReleaseEvent(const QKeyEvent&)));
    QObject::connect(this, SIGNAL(buttonLongPressed(const QKeyEvent&)),
                     this, SLOT(sendLongPressEvent(const QKeyEvent&)));
    QObject::connect(this, SIGNAL(pressedButtonChanged(const QKeyEvent&,
                                                       const QKeyEvent&)),
                     this, SLOT(handleKeyChangeEvent(const QKeyEvent&,
                                                     const QKeyEvent&)));

    // create call button (parent layouts this)
    mCallButton = new DialpadButton(parent);
    mCallButton->setButtonType(DialpadButton::CallButton);
    mCallButton->setIcon(HbIcon(handsetIcon));
    QString buttonName;
    buttonName.setNum(Qt::Key_Yes);
    mCallButton->setObjectName(buttonName);
    connect(mCallButton,SIGNAL(clicked()),
            mKeyClickedSignalMapper,SLOT(map()));
    connect(mCallButton,SIGNAL(longPress(QPointF)),
            mKeyClickedSignalMapper,SLOT(map()));
    mKeyClickedSignalMapper->setMapping(mCallButton,
                                        Qt::Key_Yes);

    // set button texts
    setButtonTexts();
    // set button icons
    button(0)->setIcon(HbIcon(vmbxIcon),
        HbInputButton::ButtonIconIndexSecondaryFirstRow);

    // update button texts when input language is changed
    connect(HbInputSettingProxy::instance(),
            SIGNAL(globalInputLanguageChanged(HbInputLanguage)),
            this,SLOT(setButtonTexts()));
}

DialpadKeypad::~DialpadKeypad()
{
}

void DialpadKeypad::setButtonTexts()
{
    HbInputLanguage inputLanguage =
        HbInputSettingProxy::instance()->globalInputLanguage();
    const HbKeymap *keymap =
        HbKeymapFactory::instance()->keymap(inputLanguage.language());

    mGeneratedChar.clear();

    if (keymap) {
        int buttonCount = (DialpadRowCount*DialpadColumnCount);
        for (int i = 0; i < buttonCount; i++) {
            int keyCode = DialpadKeyCodeTable[i];

            if (keyCode == Qt::Key_Asterisk) {
                // asterisk is not localized
                QChar asterisk('*');
                button(i)->setText(asterisk,
                    HbInputButton::ButtonTextIndexPrimary);
                button(i)->setText("+",
                    HbInputButton::ButtonTextIndexSecondaryFirstRow);
                mGeneratedChar.insert(Qt::Key_Asterisk, asterisk);
                continue;
            }

            if (keyCode == Qt::Key_NumberSign) {
                // number sign is not localized
                QChar numberSign('#');
                button(i)->setText(numberSign,
                    HbInputButton::ButtonTextIndexPrimary);
                button(i)->setText(" ",
                    HbInputButton::ButtonTextIndexSecondaryFirstRow);
                mGeneratedChar.insert(Qt::Key_NumberSign, numberSign);
                continue;
            }

            int index = i;
            if (keyCode==Qt::Key_0) {
                index = i-1;
            }

            const HbMappedKey *key =
                keymap->keyForIndex(HbKeyboardVirtual12Key, index);

            if (key) {
                QChar numberChar =
                    HbInputUtils::findFirstNumberCharacterBoundToKey(
                        key,
                        inputLanguage.language());

                // button text
                button(i)->setText(numberChar,
                    HbInputButton::ButtonTextIndexPrimary);
                mGeneratedChar.insert(keyCode,numberChar);

                // additional text (letters)
                int numberOfCharacters;
                if (keyCode==Qt::Key_7 || keyCode == Qt::Key_9) {
                    numberOfCharacters = 4;
                } else if (keyCode==Qt::Key_0||keyCode==Qt::Key_1) {
                    numberOfCharacters = 0;
                } else {
                    numberOfCharacters = 3;
                }

                QString characters = key->characters(HbModifierNone);

                if (numberOfCharacters==0 && keyCode!=Qt::Key_1) {
                    button(i)->setText(" ",
                        HbInputButton::ButtonTextIndexSecondaryFirstRow);
                } else {
                    button(i)->setText(characters.left(numberOfCharacters),
                        HbInputButton::ButtonTextIndexSecondaryFirstRow);
                }
            }
        }
    }
}

void DialpadKeypad::handleKeyClicked(int key)
{
    // concerns only yes and backspace keys
    postKeyEvent(QEvent::KeyPress, key);
    postKeyEvent(QEvent::KeyRelease, key);
}

void DialpadKeypad::postKeyEvent(QEvent::Type type, int key)
{
    // send simulated key to application
    QKeyEvent *keyEvent = new QKeyEvent(type, key, Qt::NoModifier);
    HbApplication::postEvent(const_cast<HbMainWindow*>(&mMainWindow),keyEvent);
}

void DialpadKeypad::sendKeyEventToEditor(QEvent::Type type, int key)
{
    // send key event to editor
    QKeyEvent keyEvent(type, key, Qt::NoModifier, mGeneratedChar.value(key));
    HbApplication::sendEvent(&mInputField.editor(), &keyEvent);
}

void DialpadKeypad::sendKeyPressEvent(const QKeyEvent& event)
{
    mPressedNumericKey = event.key();
    postKeyEvent(QEvent::KeyPress, event.key());
}

void DialpadKeypad::sendKeyReleaseEvent(const QKeyEvent& event)
{
    if (mPressedNumericKey) {
        // short press, update editor here
        sendKeyEventToEditor(QEvent::KeyPress, event.key());
    }

    postKeyEvent(QEvent::KeyRelease, event.key());    
}

void DialpadKeypad::sendLongPressEvent(const QKeyEvent& event)
{
    sendKeyEventToEditor(QEvent::KeyPress, event.key());
    mPressedNumericKey = 0;
}

void DialpadKeypad::handleKeyChangeEvent(
    const QKeyEvent& releaseEvent,
    const QKeyEvent& pressEvent)
{
    Q_UNUSED(pressEvent)

    postKeyEvent(QEvent::KeyRelease, releaseEvent.key());
    cancelButtonPress();
}

void DialpadKeypad::setCallButtonEnabled(bool enabled)
{
    mCallButton->setEnabled(enabled);
}

void DialpadKeypad::resetButtons()
{
    cancelButtonPress();
    mCallButton->setDown(false);
}

DialpadButton& DialpadKeypad::callButton() const
{
    return *mCallButton;
}