telutils/dialpad/src/dialpadkeypad.cpp
changeset 46 2fa1fa551b0b
parent 38 bc103bfb69cf
--- a/telutils/dialpad/src/dialpadkeypad.cpp	Mon Aug 23 15:50:31 2010 +0300
+++ b/telutils/dialpad/src/dialpadkeypad.cpp	Fri Sep 03 13:59:20 2010 +0300
@@ -11,61 +11,34 @@
 *
 * Contributors:
 *
-* Description: Dialpad keypad
+* Description: Number grid and dial key.
 *
 */
 
-#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 <hbcolorscheme.h>
 #include <hblineedit.h>
-#include <hbfontspec.h>
 #include <hbevent.h>
+#include <hbmainwindow.h>
 
 #include "dialpadnumericbutton.h"
 #include "dialpadkeypad.h"
 #include "dialpadbutton.h"
 #include "dialpadinputfield.h"
+#include "dialpadnumericbuttongrid.h"
 
-static const int DialpadRowCount = 4;
-static const int DialpadColumnCount = 3;
+static const int DialpadKeypadRowCount = 5;
 static const QLatin1String handsetIcon("qtg_mono_call");
-static const QLatin1String vmbxIcon("qtg_mono_voice_mailbox");
-// layout values in units
-static const qreal DialpadPrimaryTextSize = 5.5;
-static const qreal DialpadSecondaryTextSize = 4.0;
-static const qreal DialpadIconSize = 4.0;
-static const qreal DialpadPrimaryTextLeftMargin  = 1.5;
-static const qreal DialpadPrimarySecondaryMargin  = 0.75;
-
-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),
+    HbWidget(parent),
     mMainWindow(mainWindow),
-    mInputField(inputField),
-    mMaxPrimaryLineWidth(0)
+    mInputField(inputField)
 {
-    setObjectName("keypad");
-
     // create clicked signal mapper
     mKeyClickedSignalMapper = new QSignalMapper(this);
     connect(mKeyClickedSignalMapper,SIGNAL(mapped(int)),
@@ -77,42 +50,11 @@
     mKeyClickedSignalMapper->setMapping(&mInputField.backspaceButton(),
                                         Qt::Key_Backspace);
 
-    // create keypad
-    setGridSize(QSize(DialpadColumnCount, DialpadRowCount));
-    setButtonBorderSize(0);    
-
-    QList<HbInputButton*> buttons;
-
-    for (int i = 0; i < DialpadRowCount * DialpadColumnCount; ++i) {
-        DialpadNumericButton *item = new DialpadNumericButton(
-            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);
+    // create call button
+    mCallButton = new DialpadButton(this);
+    mCallButton->setObjectName("callButton");
     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)),
@@ -120,93 +62,42 @@
     mKeyClickedSignalMapper->setMapping(mCallButton,
                                         Qt::Key_Yes);
 
-    // set button texts
-    setButtonTexts();
-    // set button icons
-    button(0)->setIcon(HbIcon(vmbxIcon));
-
-    // update button texts when input language is changed
-    connect(HbInputSettingProxy::instance(),
-            SIGNAL(globalInputLanguageChanged(HbInputLanguage)),
-            this,SLOT(setButtonTexts()));
-
-    updateColorArray();
-
-    mUnit = HbDeviceProfile::profile(this).unitValue();
+    // create numeric button grid
+    mNumericButtonGrid = new DialpadNumericButtonGrid(mMainWindow,this);
+    QObject::connect(mNumericButtonGrid,
+                     SIGNAL(buttonPressed(const QKeyEvent&)),
+                     this, SLOT(sendKeyPressEvent(const QKeyEvent&)));
+    QObject::connect(mNumericButtonGrid,
+                     SIGNAL(buttonReleased(const QKeyEvent&)),
+                     this, SLOT(sendKeyReleaseEvent(const QKeyEvent&)));
+    QObject::connect(mNumericButtonGrid,
+                     SIGNAL(buttonLongPressed(const QKeyEvent&)),
+                     this, SLOT(sendLongPressEvent(const QKeyEvent&)));
+    QObject::connect(mNumericButtonGrid,
+                     SIGNAL(pressedButtonChanged(const QKeyEvent&,
+                                                 const QKeyEvent&)),
+                     this, SLOT(handleKeyChangeEvent(const QKeyEvent&,
+                                                     const QKeyEvent&)));
 }
 
 DialpadKeypad::~DialpadKeypad()
 {
 }
 
-void DialpadKeypad::setButtonTexts()
+bool DialpadKeypad::isCallButtonEnabled() const
 {
-    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);
-                button(i)->setSecondaryText(QLatin1String("+"));
-                mGeneratedChar.insert(Qt::Key_Asterisk, asterisk);
-                continue;
-            }
-
-            if (keyCode == Qt::Key_NumberSign) {
-                // number sign is not localized
-                QChar numberSign('#');
-                button(i)->setText(numberSign);
-                mGeneratedChar.insert(Qt::Key_NumberSign, numberSign);
-                continue;
-            }
+    return mCallButton->isEnabled();
+}
 
-            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(),
-                        HbInputUtils::inputDigitType(inputLanguage.language()));
-
-                // button text
-                button(i)->setText(numberChar);
-                mGeneratedChar.insert(keyCode,numberChar);
+void DialpadKeypad::setCallButtonEnabled(bool enabled)
+{
+    mCallButton->setEnabled(enabled);
+}
 
-                // 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)->setSecondaryText(characters.left(numberOfCharacters));
-                }
-            }
-        }
-    }
+void DialpadKeypad::resetButtons()
+{
+    mNumericButtonGrid->resetButtons();
+    mCallButton->setDown(false);
 }
 
 void DialpadKeypad::handleKeyClicked(int key)
@@ -226,21 +117,19 @@
 void DialpadKeypad::sendKeyEventToEditor(QEvent::Type type, int key)
 {
     // send key event to editor
-    QKeyEvent keyEvent(type, key, Qt::NoModifier, mGeneratedChar.value(key));
+    QKeyEvent keyEvent(type, key, Qt::NoModifier,
+                       mNumericButtonGrid->inputCharacter(key));
     HbApplication::sendEvent(&mInputField.editor(), &keyEvent);
 }
 
 void DialpadKeypad::sendKeyPressEvent(const QKeyEvent& event)
 {
-    updateButtonLabels();
     mPressedNumericKey = event.key();
     postKeyEvent(QEvent::KeyPress, event.key());
 }
 
 void DialpadKeypad::sendKeyReleaseEvent(const QKeyEvent& event)
 {
-    updateButtonLabels();
-
     if (mPressedNumericKey) {
         // short press, update editor here
         sendKeyEventToEditor(QEvent::KeyPress, event.key());
@@ -262,316 +151,21 @@
     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;
-}
-
-DialpadNumericButton* DialpadKeypad::button(int i) const
-{
-    return static_cast<DialpadNumericButton*>(HbInputButtonGroup::button(i));
-}
-
-void DialpadKeypad::updateButtonLabels()
-{
-    // update numeric buttons according to button state (pressed/released)
-    updateIconColor();
-    updateTextLayouts(rect().size());
-}
-
-void DialpadKeypad::paint(
-    QPainter* painter,
-    const QStyleOptionGraphicsItem* option,
-    QWidget* widget)
-{
-    Q_UNUSED(option);
-    Q_UNUSED(widget);
-
-    // Paints empty buttons
-    HbInputButtonGroup::paint(painter,option,widget);
-
-    qreal cellWidth = boundingRect().width() / gridSize().width();
-    qreal cellHeight = boundingRect().height() / gridSize().height();
-
-    // Draw icons
-    for (int i = 0; i < DialpadRowCount * DialpadColumnCount; i++) {
-        DialpadNumericButton *item = button(i);
-
-        if (!item->icon().isNull()) {
-            // icon is centered to button
-            qreal x = (item->position().x() * cellWidth) + (cellWidth / 2) -
-                      ((DialpadIconSize * mUnit) / 2);
-            qreal y = (item->position().y() * cellHeight) +  (cellHeight / 2) -
-                      ((DialpadIconSize * mUnit) / 2);
-
-            qreal width = DialpadIconSize * mUnit;
-            qreal height = DialpadIconSize * mUnit;
-
-            Qt::Alignment alignment =
-                static_cast<Qt::Alignment>(Qt::AlignVCenter | Qt::AlignHCenter);
-            item->icon().paint(painter,
-                               QRectF(x,y,width,height),
-                               Qt::KeepAspectRatio,
-                               alignment);
-        }                      
-    }
-
-    // Draw texts
-    QPen origPen = painter->pen();
-    for (int i = 0; i < mTextLayouts.count(); ++i) {
-        if (i==SecondaryText) {
-            // dimmed in normal state
-            painter->setPen(mColors.at(Pressed+1));
-        } else {
-            // otherwise normal or pressed color
-            painter->setPen(mColors.at(i/TextTypeCount));
-        }
-        mTextLayouts.at(i)->draw(painter, QPointF(0, 0));
-    }
-    painter->setPen(origPen);
-}
-
-void DialpadKeypad::updateColorArray()
-{
-    mColors.clear();
-
-    QColor normalColor = HbColorScheme::color("qtc_input_button_normal");
-    mColors.insert(Normal, normalColor);
-
-    QColor pressedColor = HbColorScheme::color("qtc_input_button_pressed");
-    mColors.insert(Pressed, pressedColor);
-
-    // this is used for alphabets shown dimmed, use alpha until exact color
-    // is specified
-    QColor disabledColor = HbColorScheme::color("qtc_input_button_normal");
-    disabledColor.setAlpha(128);
-    mColors.insert(Pressed+1, disabledColor);
-}
-
-void DialpadKeypad::updateIconColor()
-{
-    for (int i = 0; i < (DialpadRowCount * DialpadColumnCount); i++) {
-        DialpadNumericButton *item = button(i);
-
-        if (item->state()==HbInputButton::ButtonStatePressed) {
-            item->icon().setColor(mColors.at(Pressed));
-        } else {
-            item->icon().setColor(mColors.at(Normal));
-        }
-    }
-}
-
-void DialpadKeypad::cancelButtonPress()
-{
-    HbInputButtonGroup::cancelButtonPress();
-    updateButtonLabels();
+    mNumericButtonGrid->resetButtons();
 }
 
 void DialpadKeypad::setGeometry(const QRectF &rect)
 {
-    HbInputButtonGroup::setGeometry(rect);
-    updateTextLayouts(rect.size());
-}
-
-void DialpadKeypad::changeEvent(QEvent *event)
-{
-    HbInputButtonGroup::changeEvent(event);
-
-    if (event->type() == HbEvent::ThemeChanged) {
-        updateColorArray();
-        updateIconColor();
-    }
-}
-
-void DialpadKeypad::updateTextLayouts(const QSizeF &size)
-{
-    if (!size.width() && !size.height()) {
-        return;
-    }
-
-    // get normal and pressed state texts
-    QList<QString> textContent;
-    resolveTextContent(textContent);
-
-    // layout the texts
-    createTextLayouts(size, textContent);
-}
-
-void DialpadKeypad::resolveTextContent(QList<QString> &content)
-{
-    QString normalState;
-    QString normalStateSecondary;
-    QString pressedState;
-    QString pressedStateSecondary;
-
-    for (int i = 0; i < (DialpadRowCount*DialpadColumnCount); i++) {
-        DialpadNumericButton *item = button(i);
-        if (item->state()==HbInputButton::ButtonStatePressed) {
-            if (item->text().length()) {
-                pressedState.append(item->text());
-                pressedState.append(QChar(QChar::LineSeparator));
-            }
+    HbWidget::setGeometry(rect);
 
-            if (item->secondaryText().length()) {
-                pressedStateSecondary.append(item->secondaryText());
-                pressedStateSecondary.append(QChar(QChar::LineSeparator));
-            }
-        } else { // ButtonStateNormal
-            if (item->text().length()) {
-                normalState.append(item->text());
-                normalState.append(QChar(QChar::LineSeparator));
-            }
-
-            if (item->secondaryText().length()) {
-                normalStateSecondary.append(item->secondaryText());
-                normalStateSecondary.append(QChar(QChar::LineSeparator));
-            }
-        }
-    }
-
-    content.insert(PrimaryText, normalState);
-    content.insert(SecondaryText, normalStateSecondary);
-    content.insert(TextTypeCount + Pressed, pressedState);
-    content.insert(StateCount + SecondaryText, pressedStateSecondary);
-}
-
-void DialpadKeypad::createTextLayouts(
-    const QSizeF &size, const QList<QString> &content)
-{
-    // clear old layouts
-    qDeleteAll(mTextLayouts);
-    mTextLayouts.clear();
-
-    if (content.count()==2) {
-        // line width is measured only when all buttons are in normal state
-        mMaxPrimaryLineWidth = 0;
-    }
-
-    QFont primaryfFont = HbFontSpec(HbFontSpec::Primary).font();
-    primaryfFont.setPixelSize(DialpadPrimaryTextSize * mUnit);
-
-    QFont secondaryFont = HbFontSpec(HbFontSpec::Secondary).font();
-    secondaryFont.setPixelSize(DialpadSecondaryTextSize * mUnit);
-
-    for (int i=0; i < (StateCount*TextTypeCount); i++ ) {
-        QString text = content.at(i);
-
-        if (!text.isNull()) {
-            QTextLayout* textLayout;
-            int type;
+    // make button heights uniform
+    qreal buttonHeight = rect.height()/DialpadKeypadRowCount;
 
-            if (i%TextTypeCount) {
-                textLayout = new QTextLayout(text,secondaryFont);
-                type = SecondaryText;
-            } else {
-                textLayout = new QTextLayout(text,primaryfFont);
-                type = PrimaryText;
-            }
-
-            mTextLayouts.append(textLayout);
-
-            textLayout->beginLayout();
-
-            int state = (i>=TextTypeCount) ? Pressed : Normal;
-
-            layoutTextLines(size,*textLayout,state,type);
-
-            textLayout->endLayout();
-
-            textLayout->setCacheEnabled(true);
-        }
-    }
-}
-
-void DialpadKeypad::layoutTextLines(
-    const QSizeF &size,
-    QTextLayout &textLayout,
-    int state,
-    int type)
-{
-    QFontMetricsF fontMetrics(textLayout.font());
-    qreal textHeight = fontMetrics.height();
-
-    qreal cellWidth = size.width() / gridSize().width();
-    qreal cellHeight = size.height() / gridSize().height();
-    qreal maxLineWidth = 0;
-
-    for (int j = 0; j < (DialpadRowCount*DialpadColumnCount); j++) {
-        DialpadNumericButton *item = button(j);
-
-        if ((type==PrimaryText && item->text().isNull()) ||
-            (type==SecondaryText && item->secondaryText().isNull())) {
-            continue; // no text for this button -> next button
-        }
-
-        if ( ( state==Normal &&
-               item->state()==HbInputButton::ButtonStateReleased ) ||
-             ( state==Pressed &&
-               item->state()==HbInputButton::ButtonStatePressed ) ) {
-
-            QTextLine line = textLayout.createLine();
+    mNumericButtonGrid->setPos(QPointF(0,0));
+    QSizeF gridSize(rect.size());
+    gridSize.setHeight(gridSize.height()-buttonHeight);
+    mNumericButtonGrid->resize(gridSize);
 
-            qreal textPositionX = 0;
-            qreal textPositionY = 0;
-
-            if (line.isValid()) {
-                line.setNumColumns(item->text().length());
-                // layout text line
-                if (type==SecondaryText) {
-                    if (j==9) {
-                        // + is centered to button
-                        qreal lineWidth = fontMetrics.width(item->text());
-                        textPositionX = (item->position().x() * cellWidth) +
-                                        (cellWidth / 2) -
-                                        (lineWidth / 2);
-                        textPositionY = (item->position().y() +
-                                        (0.5 * item->size().height())) *
-                                        cellHeight - (0.5 * textHeight);
-
-                    } else {
-                        textPositionX = (item->position().x() * cellWidth) +
-                                        (DialpadPrimaryTextLeftMargin * mUnit) +
-                                        mMaxPrimaryLineWidth +
-                                        (DialpadPrimarySecondaryMargin * mUnit)
-                                        + buttonBorderSize();
-                        textPositionY = (item->position().y() +
-                                        (0.5 * item->size().height())) *
-                                        cellHeight - (0.5 * textHeight);
-                    }                    
-                } else {
-                    textPositionX = (item->position().x() * cellWidth) +
-                                    (DialpadPrimaryTextLeftMargin * mUnit)
-                                    + buttonBorderSize();
-                    textPositionY = (item->position().y() +
-                                    (0.5 * item->size().height())) *
-                                    cellHeight - (0.5 * textHeight);
-
-                    // store line width, for drawing secondary text
-                    qreal lineWidth = fontMetrics.width(item->text());
-                    if (mMaxPrimaryLineWidth == 0 && (j>0 && j<10) &&
-                        lineWidth > maxLineWidth) {
-                        maxLineWidth = lineWidth;
-                    }
-                }
-            }
-
-            line.setPosition(QPointF(textPositionX, textPositionY));
-        }
-    }
-
-    mMaxPrimaryLineWidth = maxLineWidth;
+    mCallButton->setPos(QPointF(0,gridSize.height()));
+    mCallButton->resize(rect.width(),buttonHeight);
 }