src/hbinput/inputwidgets/hbinputbuttongroup.cpp
changeset 2 06ff229162e9
child 3 11d3954df52a
equal deleted inserted replaced
1:f7ac710697a9 2:06ff229162e9
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbInput module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include <QPainter>
       
    27 #include <QTextLayout>
       
    28 #include <QGraphicsSceneMouseEvent>
       
    29 #include <QTouchEvent>
       
    30 #include <QTimer>
       
    31 #include <QGraphicsDropShadowEffect>
       
    32 
       
    33 #include <hbmainwindow.h>
       
    34 #include <hbaction.h>
       
    35 #include <hbevent.h>
       
    36 #include <hbcolorscheme.h>
       
    37 #include <hbdialog.h>
       
    38 #include <hbframeitem.h>
       
    39 #include <hbwidgetfeedback.h>
       
    40 #include <hbdeviceprofile.h>
       
    41 #include "hbframedrawerpool_p.h"
       
    42 
       
    43 #include "hbinputbuttongroup.h"
       
    44 #include "hbinputbuttongroup_p.h"
       
    45 #include "hbinputbutton.h"
       
    46 
       
    47 /// @cond
       
    48 
       
    49 const QString HbNormalBackground("qtg_fr_input_btn_keypad_normal");
       
    50 const QString HbNormalPressedBackground("qtg_fr_input_btn_keypad_pressed");
       
    51 const QString HbNormalInActiveBackground("qtg_fr_input_btn_keypad_disabled");
       
    52 const QString HbNormalLatchedBackground("qtg_fr_input_btn_keypad_latched");
       
    53 
       
    54 const QString HbFunctionBackground("qtg_fr_input_btn_function_normal");
       
    55 const QString HbFunctionPressedBackground("qtg_fr_input_btn_function_pressed");
       
    56 const QString HbFunctionInActiveBackground("qtg_fr_input_btn_function_disabled");
       
    57 const QString HbFunctionLatchedBackground("qtg_fr_input_btn_function_latched");
       
    58 
       
    59 const QString HbPreviewBackground("qtg_fr_character_preview");
       
    60 
       
    61 const QString HbNormalColor("qtc_input_button_normal");
       
    62 const QString HbNormalColorPressed("qtc_input_button_pressed");
       
    63 const QString HbNormalColorInActive("qtc_input_button_disabled");
       
    64 const QString HbNormalColorLatched("qtc_input_button_latched");
       
    65 
       
    66 const QString HbFunctionColor("qtc_input_function_normal");
       
    67 const QString HbFunctionColorPressed("qtc_input_function_pressed");
       
    68 const QString HbFunctionColorInActive("qtc_input_function_disabled");
       
    69 const QString HbFunctionColorLatched("qtc_input_function_latched");
       
    70 
       
    71 const QString HbButtonPreviewColor("qtc_input_preview_normal");
       
    72 const QString HbCharacterSelectionPreviewColor("qtc_input_button_accented_normal");
       
    73 
       
    74 const int HbLongPressTimeout = 600;
       
    75 const int HbAutoRepeatTimeout = 100;
       
    76 
       
    77 const int HbTextTypeCount = HbInputButton::ButtonTypeCount * HbInputButton::ButtonStateCount;
       
    78 const int HbTextLayoutCount = HbTextTypeCount * 3;
       
    79 
       
    80 const qreal HbTextSizeInUnits = 5.75;
       
    81 const qreal HbPrimaryTextSizeInUnits = 5.37;
       
    82 const qreal HbSecondaryTextSizeInUnits = 3.36;
       
    83 const qreal HbLabelTextSizeInUnits = 9;
       
    84 const qreal HbPrimaryIconSizeInUnits = 5;
       
    85 const qreal HbSecondaryIconSizeInUnits = 3.36;
       
    86 const qreal HbHorizontalMarginInUnits = 0.75;
       
    87 const qreal HbVerticalMarginInUnits = 1.14;
       
    88 const qreal HbPreviewWidthInUnits = 10;
       
    89 const qreal HbPreviewHeightInUnits = 16;
       
    90 const qreal HbPreviewMarginInUnits = 3;
       
    91 
       
    92 const qreal HbTouchAreaSizeInUnits = 8;
       
    93 
       
    94 HbInputButtonGroupPrivate::HbInputButtonGroupPrivate()
       
    95  : mUnitValue(0), mGridSize(1, 1), mButtonBorderSize(1.0), mEnabled(true),
       
    96    mButtonPreviewEnabled(false), mCharacterSelectionPreviewEnabled(false),
       
    97    mMultiTouchEnabled(true), mCharacterSelectionPreview(0), mBackground(0)
       
    98 {
       
    99     for (int i = 0; i < HbTextLayoutCount; ++i) {
       
   100         mTextLayouts.append(0);
       
   101     }
       
   102 
       
   103     updateColorArray();
       
   104 }
       
   105 
       
   106 HbInputButtonGroupPrivate::~HbInputButtonGroupPrivate()
       
   107 {
       
   108     foreach(HbFrameDrawer *drawer, mButtonDrawers) {
       
   109         HbFrameDrawerPool::release(drawer);
       
   110     }
       
   111 
       
   112     foreach (HbInputButton *button, mButtonData) {
       
   113         delete button;
       
   114     }
       
   115     mButtonData.clear();
       
   116 
       
   117     foreach (QTextLayout *layout, mTextLayouts) {
       
   118         delete layout;
       
   119     }
       
   120 
       
   121     foreach (QTimer *timer, mLongPressTimers) {
       
   122         delete timer;
       
   123     }
       
   124 
       
   125     delete mCharacterSelectionPreview;
       
   126 
       
   127     HbFrameDrawerPool::release(mBackground);
       
   128 }
       
   129 
       
   130 void HbInputButtonGroupPrivate::updateGraphics(const QSizeF &size)
       
   131 {
       
   132     if (!size.width() && !size.height()) {
       
   133         return;
       
   134     }
       
   135 
       
   136     qreal cellWidth = size.width() / mGridSize.width();
       
   137     qreal cellHeight = size.height() / mGridSize.height();
       
   138 
       
   139     for (int i = 0; i < mButtonData.count(); ++i) {
       
   140         HbInputButton *item = mButtonData.at(i);
       
   141 
       
   142         qreal width = cellWidth * item->size().width() - 2 * mButtonBorderSize;
       
   143         qreal height = cellHeight * item->size().height() - 2 * mButtonBorderSize;
       
   144         QSizeF frameSize = QSizeF(width, height);
       
   145         HbFrameDrawer *drawer = 0;
       
   146         QColor color;
       
   147         if (mEnabled) {
       
   148             drawer = HbFrameDrawerPool::get(buttonGraphics(item->type(), item->state()), HbFrameDrawer::NinePieces, frameSize);
       
   149             color = mColors.at(item->type() * HbInputButton::ButtonStateCount + item->state());
       
   150         } else {
       
   151             drawer = HbFrameDrawerPool::get(buttonGraphics(item->type(), HbInputButton::ButtonStateDisabled), HbFrameDrawer::NinePieces, frameSize);
       
   152             color = mColors.at(item->type() * HbInputButton::ButtonStateCount + HbInputButton::ButtonStateDisabled);
       
   153         }
       
   154 
       
   155         if (i < mButtonDrawers.count()) {
       
   156             if (drawer != mButtonDrawers.at(i)) {
       
   157                 HbFrameDrawerPool::release(mButtonDrawers.at(i));
       
   158                 mButtonDrawers.replace(i, drawer);
       
   159             }
       
   160         } else {
       
   161             mButtonDrawers.append(drawer);
       
   162         }
       
   163 
       
   164         QList<HbIcon> icons = item->icons();
       
   165         for (int i = 0; i < icons.count(); ++i) {
       
   166             if (!icons.at(i).isNull()) {
       
   167                 icons[i].setColor(color);
       
   168             }
       
   169         }
       
   170         item->setIcons(icons);
       
   171     }
       
   172 
       
   173     for (int i = mButtonDrawers.count() - 1; i >= mButtonData.count(); --i) {
       
   174         HbFrameDrawerPool::release(mButtonDrawers.at(i));
       
   175         mButtonDrawers.removeAt(i);
       
   176     }
       
   177 }
       
   178 
       
   179 void HbInputButtonGroupPrivate::updateTextLayouts(const QSizeF &size)
       
   180 {
       
   181     if (!size.width() && !size.height()) {
       
   182         return;
       
   183     }
       
   184 
       
   185     QHash<int, QString> textContent;
       
   186     for (int i = 0; i < HbTextLayoutCount; ++i) {
       
   187         delete mTextLayouts[i];
       
   188         mTextLayouts[i] = 0;
       
   189     }
       
   190 
       
   191     // Sort different button texts to correct text content based on the
       
   192     // button type and state
       
   193     for (int i = 0; i < mButtonData.count(); ++i) {
       
   194         HbInputButton *item = mButtonData.at(i);
       
   195 
       
   196         int index = item->type() * HbInputButton::ButtonStateCount + item->state();
       
   197         if (!mEnabled) {
       
   198             index = item->type() * HbInputButton::ButtonStateCount + HbInputButton::ButtonStateDisabled;
       
   199         }
       
   200 
       
   201         if (!item->text(HbInputButton::ButtonTextIndexPrimary).isEmpty() &&
       
   202             item->icon(HbInputButton::ButtonIconIndexPrimary).isNull()) {
       
   203             int primaryIndex = index;
       
   204             if (item->text(HbInputButton::ButtonTextIndexSecondaryFirstRow).isEmpty() &&
       
   205                 item->icon(HbInputButton::ButtonIconIndexSecondaryFirstRow).isNull() &&
       
   206                 item->text(HbInputButton::ButtonTextIndexSecondarySecondRow).isEmpty() &&
       
   207                 item->icon(HbInputButton::ButtonIconIndexSecondarySecondRow).isNull()) {
       
   208                 primaryIndex += HbTextTypeCount;
       
   209             }
       
   210             textContent[primaryIndex] += item->text(HbInputButton::ButtonTextIndexPrimary);
       
   211             textContent[primaryIndex] += QChar(QChar::LineSeparator);
       
   212         }
       
   213 
       
   214         index += HbTextTypeCount * 2;
       
   215 
       
   216         if (!item->text(HbInputButton::ButtonTextIndexSecondaryFirstRow).isEmpty() &&
       
   217             item->icon(HbInputButton::ButtonIconIndexSecondaryFirstRow).isNull()) {
       
   218             textContent[index] += item->text(HbInputButton::ButtonTextIndexSecondaryFirstRow);
       
   219             textContent[index] += QChar(QChar::LineSeparator);
       
   220         }
       
   221 
       
   222         if (!item->text(HbInputButton::ButtonTextIndexSecondarySecondRow).isEmpty() &&
       
   223             item->icon(HbInputButton::ButtonIconIndexSecondarySecondRow).isNull()) {
       
   224             textContent[index] += item->text(HbInputButton::ButtonTextIndexSecondarySecondRow);
       
   225             textContent[index] += QChar(QChar::LineSeparator);
       
   226         }
       
   227     }
       
   228 
       
   229     // Create text layouts for each text content
       
   230     for (int index = 0; index < HbTextLayoutCount; ++index) {
       
   231         if (textContent.contains(index)) {
       
   232             int textIndex = index / HbTextTypeCount;
       
   233             if (textIndex == 0) {
       
   234                 createPrimaryTextLayout(index, textContent, size);
       
   235             } else if (textIndex == 1) {
       
   236                 createPrimarySingleTextLayout(index, textContent, size);
       
   237             } else {
       
   238                 createSecondaryTextLayout(index, textContent, size);
       
   239             }
       
   240         }
       
   241     }
       
   242 }
       
   243 
       
   244 void HbInputButtonGroupPrivate::updateCustomActions()
       
   245 {
       
   246     for (int i = 0; i < mUsedCustomButtons.count(); ++i) {
       
   247         if (i < mButtonData.count()) {
       
   248             HbInputButton *item = mButtonData.at(mUsedCustomButtons.at(i));
       
   249 
       
   250             item->setIcon(HbIcon(), HbInputButton::ButtonIconIndexPrimary);
       
   251             item->setText(QString(), HbInputButton::ButtonTextIndexPrimary);
       
   252             item->setText(QString(), HbInputButton::ButtonTextIndexSecondaryFirstRow);
       
   253             item->setText(QString(), HbInputButton::ButtonTextIndexSecondarySecondRow);
       
   254             item->setState(HbInputButton::ButtonStateReleased);
       
   255         }
       
   256     }
       
   257     mUsedCustomButtons.clear();
       
   258 
       
   259     for (int i = 0; i < mButtonData.count(); ++i) {
       
   260         HbInputButton *item = mButtonData.at(i);
       
   261 
       
   262         int actionIndex = item->keyCode() - HbInputButton::ButtonKeyCodeCustom;
       
   263 
       
   264         if (actionIndex >= 0 && actionIndex < mCustomActions.count()) {
       
   265             item->setIcon(mCustomActions.at(actionIndex)->icon(), HbInputButton::ButtonIconIndexPrimary);
       
   266             if (!mCustomActions.at(actionIndex)->isEnabled()) {
       
   267                 item->setState(HbInputButton::ButtonStateDisabled);
       
   268             }
       
   269             mUsedCustomButtons.append(i);
       
   270         }
       
   271     }
       
   272 }
       
   273 
       
   274 void HbInputButtonGroupPrivate::updateButtonGrid(const QSizeF &size)
       
   275 {
       
   276     mButtonGridPositions.clear();
       
   277 
       
   278     if (!size.width() && !size.height()) {
       
   279         return;
       
   280     }
       
   281 
       
   282     qreal cellWidth = size.width() / mGridSize.width();
       
   283     qreal cellHeight = size.height() / mGridSize.height();
       
   284 
       
   285     for (int i = 0; i < mButtonData.count(); ++i) {
       
   286         HbInputButton *item = mButtonData.at(i);
       
   287 
       
   288         for (int y = 0; y < item->size().height(); ++y) {
       
   289             for (int x = 0; x < item->size().width(); ++x) {
       
   290                 QPair<int, int> position = QPair<int, int>(item->position().x() + x, item->position().y() + y);
       
   291                 mButtonGridPositions.insert(position, i);
       
   292             }
       
   293         }
       
   294         QRectF rect = QRectF(item->position().x() * cellWidth, item->position().y() * cellHeight,
       
   295                              item->size().width() * cellWidth, item->size().height() * cellHeight);
       
   296         item->setBoundingRect(rect);
       
   297     }
       
   298 }
       
   299 
       
   300 void HbInputButtonGroupPrivate::updateColorArray()
       
   301 {
       
   302     mColors.clear();
       
   303     for (int i = 0; i < HbTextTypeCount; ++i) {
       
   304         HbInputButton::HbInputButtonType type = static_cast<HbInputButton::HbInputButtonType>(i / HbInputButton::ButtonStateCount);
       
   305         HbInputButton::HbInputButtonState state = static_cast<HbInputButton::HbInputButtonState>(i % HbInputButton::ButtonStateCount);
       
   306         mColors.append(HbColorScheme::color(buttonColor(type, state)));
       
   307     }
       
   308 }
       
   309 
       
   310 void HbInputButtonGroupPrivate::showButtonPreview(HbInputButton * const item)
       
   311 {
       
   312     Q_Q(HbInputButtonGroup);
       
   313 
       
   314     int index = mButtonData.indexOf(item);
       
   315     if (mButtonPreviewEnabled && item->type() != HbInputButton::ButtonTypeFunction &&
       
   316         !mButtonPreview.contains(index)) {
       
   317         HbInputButtonGroup *group = new HbInputButtonGroup(QSize(1, 1), q);
       
   318         mButtonPreview.insert(index, group);
       
   319 
       
   320         QList<HbInputButton*> buttons;
       
   321         HbInputButton *previewItem = new HbInputButton(item->text(HbInputButton::ButtonTextIndexPrimary).at(0).unicode(), QPoint(0, 0));
       
   322         previewItem->setType(HbInputButton::ButtonTypeLabel);
       
   323         previewItem->setText(item->text(HbInputButton::ButtonTextIndexPrimary), HbInputButton::ButtonTextIndexPrimary);
       
   324         buttons.append(previewItem);
       
   325         group->setButtons(buttons);
       
   326 
       
   327         qreal cellWidth = q->boundingRect().width() / mGridSize.width();
       
   328         qreal cellHeight = q->boundingRect().height() / mGridSize.height();
       
   329 
       
   330         QFont font = HbFontSpec(HbFontSpec::Primary).font();
       
   331         font.setPixelSize(fontSize(ButtonTextTypeLabel));
       
   332         QFontMetricsF fontMetrics(font);
       
   333         qreal textWidth = fontMetrics.width(item->text(HbInputButton::ButtonTextIndexPrimary));
       
   334 
       
   335         qreal width = textWidth + HbPreviewMarginInUnits * mUnitValue;
       
   336         if (width < HbPreviewWidthInUnits * mUnitValue) {
       
   337             width = HbPreviewWidthInUnits * mUnitValue;
       
   338         }
       
   339         qreal height = HbPreviewHeightInUnits * mUnitValue;
       
   340         qreal x = (item->position().x() + 0.5 * item->size().width()) * cellWidth - 0.5 * width;
       
   341         if (x < 0) {
       
   342             x = 0;
       
   343         } else if (x + width > q->boundingRect().width()) {
       
   344             x = q->boundingRect().width() - width;
       
   345         }
       
   346         qreal y = item->position().y() * cellHeight - height;
       
   347         group->setGeometry(QRectF(x, y, width, height));
       
   348         if (q->parentItem()) {
       
   349             group->setZValue(q->parentItem()->zValue() + 1);
       
   350         }
       
   351         
       
   352         QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
       
   353         effect->setBlurRadius(8);
       
   354         group->setGraphicsEffect(effect);
       
   355 
       
   356         group->setButtonBorderSize(0);
       
   357         HbFrameDrawer *drawer = HbFrameDrawerPool::get(HbPreviewBackground, HbFrameDrawer::ThreePiecesHorizontal, QSizeF(width, height));
       
   358         drawer->setFillWholeRect(true);
       
   359         group->setBackground(drawer);
       
   360         q->mainWindow()->scene()->addItem(group);
       
   361     }
       
   362 }
       
   363 
       
   364 void HbInputButtonGroupPrivate::hideButtonPreview(HbInputButton * const item)
       
   365 {
       
   366     int index = mButtonData.indexOf(item);
       
   367     if (mButtonPreview.contains(index)) {
       
   368         delete mButtonPreview.take(index);
       
   369     }
       
   370 }
       
   371 
       
   372 void HbInputButtonGroupPrivate::showCharacterSelectionPreview(HbInputButton * const item)
       
   373 {
       
   374     Q_Q(HbInputButtonGroup);
       
   375 
       
   376     if (mCharacterSelectionPreviewEnabled && item->type() != HbInputButton::ButtonTypeFunction &&
       
   377         item->mappedCharacters().count() > 1) {
       
   378         
       
   379         mProbabilities.clear();
       
   380         q->cancelButtonPress();
       
   381         
       
   382         if (!mCharacterSelectionPreview) {
       
   383             mCharacterSelectionPreview = new HbDialog();
       
   384             mCharacterSelectionPreview->setModal(true);
       
   385             mCharacterSelectionPreview->setBackgroundFaded(false);
       
   386             mCharacterSelectionPreview->setTimeout(HbPopup::NoTimeout);
       
   387             mCharacterSelectionPreview->setDismissPolicy(HbPopup::TapAnywhere);
       
   388             mCharacterSelectionPreview->setFlag(QGraphicsItem::ItemIsPanel, true);
       
   389             mCharacterSelectionPreview->setActive(false);
       
   390             qreal margin = HbPreviewMarginInUnits * mUnitValue * 0.5;
       
   391             mCharacterSelectionPreview->setContentsMargins(margin, 0, margin, 0);
       
   392             QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
       
   393             effect->setBlurRadius(8);
       
   394             mCharacterSelectionPreview->setGraphicsEffect(effect);
       
   395         }
       
   396 
       
   397         HbInputButtonGroup *group = new HbInputButtonGroup(QSize(item->mappedCharacters().count(), 1));
       
   398         QObject::connect(group, SIGNAL(buttonPressed(const QKeyEvent&)), q, SLOT(emitButtonPressed(const QKeyEvent&)));
       
   399         QObject::connect(group, SIGNAL(buttonDoublePressed(const QKeyEvent&)), q, SLOT(emitButtonDoublePressed(const QKeyEvent&)));
       
   400         QObject::connect(group, SIGNAL(buttonReleased(const QKeyEvent&)), q, SLOT(emitButtonReleased(const QKeyEvent&)));
       
   401         QObject::connect(group, SIGNAL(buttonLongPressed(const QKeyEvent&)), q, SLOT(emitButtonLongPressed(const QKeyEvent&)));
       
   402         QObject::connect(group, SIGNAL(pressedButtonChanged(const QKeyEvent&, const QKeyEvent&)), q, SLOT(emitPressedButtonChanged(const QKeyEvent&, const QKeyEvent&)));
       
   403         
       
   404         qreal cellWidth = q->boundingRect().width() / mGridSize.width();
       
   405         qreal cellHeight = q->boundingRect().height() / mGridSize.height();
       
   406 
       
   407         QFont font = HbFontSpec(HbFontSpec::Primary).font();
       
   408         font.setPixelSize(fontSize(ButtonTextTypeLabel));
       
   409         QFontMetricsF fontMetrics(font);
       
   410         qreal textWidth = fontMetrics.width(item->mappedCharacters());
       
   411 
       
   412         qreal width = textWidth + HbPreviewMarginInUnits * mUnitValue * item->mappedCharacters().count();
       
   413         qreal height = HbPreviewHeightInUnits * mUnitValue;
       
   414         qreal x = q->scenePos().x() + (item->position().x() + 0.5 * item->size().width()) * cellWidth;
       
   415         qreal y = q->scenePos().y() + item->position().y() * cellHeight;
       
   416 
       
   417         QList<HbInputButton*> buttons;
       
   418         for (int i = 0; i < item->mappedCharacters().count(); ++i) {
       
   419             HbInputButton *previewItem = new HbInputButton(item->keyCode(), QPoint(i, 0));
       
   420             previewItem->setType(HbInputButton::ButtonTypeLabel);
       
   421             previewItem->setText(item->mappedCharacters().at(i), HbInputButton::ButtonTextIndexPrimary);
       
   422             buttons.append(previewItem);
       
   423         }
       
   424         group->setButtons(buttons);
       
   425         group->setButtonBorderSize(0);
       
   426 
       
   427         mCharacterSelectionPreview->setPreferredSize(QSizeF(width, height));
       
   428         mCharacterSelectionPreview->setPreferredPos(QPointF(x, y), HbPopup::BottomEdgeCenter);
       
   429         mCharacterSelectionPreview->setContentWidget(group);
       
   430 
       
   431         HbFrameDrawer *drawer = HbFrameDrawerPool::get(HbPreviewBackground, HbFrameDrawer::ThreePiecesHorizontal, QSizeF(width, height));
       
   432         drawer->setFillWholeRect(true);
       
   433         mCharacterSelectionPreview->setBackgroundItem(new HbFrameItem(drawer));
       
   434 
       
   435         mCharacterSelectionPreview->show();
       
   436     }
       
   437 }
       
   438 
       
   439 void HbInputButtonGroupPrivate::pressEvent(const QPointF &position, bool emitSignal)
       
   440 {
       
   441     Q_Q(HbInputButtonGroup);
       
   442 
       
   443     if (!(position.x() >= 0 && position.x() < q->boundingRect().width() &&
       
   444         position.y() >= 0 && position.y() < q->boundingRect().height())) {
       
   445         return;
       
   446     }
       
   447 
       
   448     int column = static_cast<int>(position.x() / (q->boundingRect().width() / mGridSize.width()));
       
   449     int row = static_cast<int>(position.y() / (q->boundingRect().height() / mGridSize.height()));
       
   450 
       
   451     int index = mButtonGridPositions.value(QPair<int, int>(column, row));
       
   452 
       
   453     if (index >= 0 && index < mButtonData.count()) {
       
   454         HbInputButton *item = mButtonData.at(index);
       
   455 
       
   456         if ((item->state() != HbInputButton::ButtonStateReleased && 
       
   457             item->state() != HbInputButton::ButtonStateLatched) ||
       
   458             (mCharacterSelectionPreview && mCharacterSelectionPreview->isVisible())) {
       
   459             if (item->state() == HbInputButton::ButtonStateDisabled) {
       
   460                 startLongPress(index);
       
   461             }
       
   462             return;
       
   463         }
       
   464 
       
   465         HbWidgetFeedback::triggered(q, Hb::InstantPressed);
       
   466 
       
   467         item->setState(HbInputButton::ButtonStatePressed);
       
   468         updateGraphics(QSizeF(q->boundingRect().width(), q->boundingRect().height()));
       
   469         updateTextLayouts(QSizeF(q->boundingRect().width(), q->boundingRect().height()));
       
   470         q->update();
       
   471 
       
   472         showButtonPreview(item);
       
   473 
       
   474         startLongPress(index);
       
   475 
       
   476         if (!mUsedCustomButtons.contains(index)) {
       
   477             if (emitSignal) {
       
   478                 QString text;
       
   479                 if (item->type() == HbInputButton::ButtonTypeLabel) {
       
   480                     text = item->text(HbInputButton::ButtonTextIndexPrimary);
       
   481                 }
       
   482                 QKeyEvent event(QEvent::KeyPress, item->keyCode(), Qt::NoModifier, text);
       
   483                 q->emitButtonPressed(event);
       
   484             }
       
   485         }
       
   486     }
       
   487 }
       
   488 
       
   489 void HbInputButtonGroupPrivate::doublePressEvent(const QPointF &position, bool emitSignal)
       
   490 {
       
   491     Q_Q(HbInputButtonGroup);
       
   492 
       
   493     if (!(position.x() >= 0 && position.x() < q->boundingRect().width() &&
       
   494         position.y() >= 0 && position.y() < q->boundingRect().height())) {
       
   495         return;
       
   496     }
       
   497 
       
   498     int column = static_cast<int>(position.x() / (q->boundingRect().width() / mGridSize.width()));
       
   499     int row = static_cast<int>(position.y() / (q->boundingRect().height() / mGridSize.height()));
       
   500 
       
   501     int index = mButtonGridPositions.value(QPair<int, int>(column, row));
       
   502 
       
   503     if (index >= 0 && index < mButtonData.count()) {
       
   504         HbInputButton *item = mButtonData.at(index);
       
   505 
       
   506         if ((item->state() != HbInputButton::ButtonStateReleased && 
       
   507             item->state() != HbInputButton::ButtonStateLatched) ||
       
   508             (mCharacterSelectionPreview && mCharacterSelectionPreview->isVisible())) {
       
   509             if (item->state() == HbInputButton::ButtonStateDisabled) {
       
   510                 startLongPress(index);
       
   511             }
       
   512             return;
       
   513         }
       
   514 
       
   515         HbWidgetFeedback::triggered(q, Hb::InstantPressed);
       
   516 
       
   517         item->setState(HbInputButton::ButtonStatePressed);
       
   518         updateGraphics(QSizeF(q->boundingRect().width(), q->boundingRect().height()));
       
   519         updateTextLayouts(QSizeF(q->boundingRect().width(), q->boundingRect().height()));
       
   520         q->update();
       
   521 
       
   522         showButtonPreview(item);
       
   523 
       
   524         startLongPress(index);
       
   525 
       
   526         if (!mUsedCustomButtons.contains(index)) {
       
   527             if (emitSignal) {
       
   528                 QString text;
       
   529                 if (item->type() == HbInputButton::ButtonTypeLabel) {
       
   530                     text = item->text(HbInputButton::ButtonTextIndexPrimary);
       
   531                 }
       
   532                 QKeyEvent event(QEvent::KeyPress, item->keyCode(), Qt::NoModifier, text);
       
   533                 q->emitButtonDoublePressed(event);
       
   534             }
       
   535         }
       
   536     }
       
   537 }
       
   538 
       
   539 void HbInputButtonGroupPrivate::moveEvent(const QPointF &oldPosition, const QPointF &newPosition)
       
   540 {
       
   541     Q_Q(HbInputButtonGroup);
       
   542 
       
   543     int oldColumn = static_cast<int>(oldPosition.x() / (q->boundingRect().width() / mGridSize.width()));
       
   544     int oldRow = static_cast<int>(oldPosition.y() / (q->boundingRect().height() / mGridSize.height()));
       
   545     int newColumn = static_cast<int>(newPosition.x() / (q->boundingRect().width() / mGridSize.width()));
       
   546     int newRow = static_cast<int>(newPosition.y() / (q->boundingRect().height() / mGridSize.height()));
       
   547 
       
   548     int oldIndex = mButtonGridPositions.value(QPair<int, int>(oldColumn, oldRow));
       
   549     int newIndex = mButtonGridPositions.value(QPair<int, int>(newColumn, newRow));
       
   550 
       
   551     if (newPosition.x() >= 0 && newPosition.x() < q->boundingRect().width() &&
       
   552         newPosition.y() >= 0 && newPosition.y() < q->boundingRect().height() &&
       
   553         oldPosition.x() >= 0 && oldPosition.x() < q->boundingRect().width() &&
       
   554         oldPosition.y() >= 0 && oldPosition.y() < q->boundingRect().height()) {
       
   555         
       
   556         if (oldIndex != newIndex) {
       
   557             releaseEvent(oldPosition, false);
       
   558             pressEvent(newPosition, false);
       
   559 
       
   560             QString text;
       
   561             HbInputButton *oldItem = mButtonData.at(oldIndex);
       
   562             if (oldItem->type() == HbInputButton::ButtonTypeLabel) {
       
   563                 text = oldItem->text(HbInputButton::ButtonTextIndexPrimary);
       
   564             }
       
   565             QKeyEvent releaseEvent(QEvent::KeyRelease, oldItem->keyCode(), Qt::NoModifier, text);
       
   566 
       
   567             HbInputButton *newItem = mButtonData.at(newIndex);
       
   568             if (newItem->type() == HbInputButton::ButtonTypeLabel) {
       
   569                 text = newItem->text(HbInputButton::ButtonTextIndexPrimary);
       
   570             }
       
   571             QKeyEvent pressEvent(QEvent::KeyPress, newItem->keyCode(), Qt::NoModifier, text);
       
   572 
       
   573             q->emitPressedButtonChanged(releaseEvent, pressEvent);
       
   574         }
       
   575     } else {
       
   576         releaseEvent(oldPosition, false);
       
   577         pressEvent(newPosition);
       
   578     }
       
   579 }
       
   580 
       
   581 void HbInputButtonGroupPrivate::releaseEvent(const QPointF &position, bool emitSignal)
       
   582 {
       
   583     Q_Q(HbInputButtonGroup);
       
   584 
       
   585     if (!(position.x() >= 0 && position.x() < q->boundingRect().width() &&
       
   586         position.y() >= 0 && position.y() < q->boundingRect().height())) {
       
   587         return;
       
   588     }
       
   589 
       
   590     int column = static_cast<int>(position.x() / (q->boundingRect().width() / mGridSize.width()));
       
   591     int row = static_cast<int>(position.y() / (q->boundingRect().height() / mGridSize.height()));
       
   592 
       
   593     int index = mButtonGridPositions.value(QPair<int, int>(column, row));
       
   594 
       
   595     if (index >= 0 && index < mButtonData.count()) {
       
   596         HbInputButton *item = mButtonData.at(index);
       
   597 
       
   598         cancelLongPress(index);
       
   599 
       
   600         if (item->state() != HbInputButton::ButtonStatePressed) {
       
   601             return;
       
   602         }
       
   603 
       
   604         HbWidgetFeedback::triggered(q, Hb::InstantReleased);
       
   605 
       
   606         item->setState(HbInputButton::ButtonStateReleased);
       
   607         updateGraphics(QSizeF(q->boundingRect().width(), q->boundingRect().height()));
       
   608         updateTextLayouts(QSizeF(q->boundingRect().width(), q->boundingRect().height()));
       
   609         q->update();
       
   610 
       
   611         if (mCharacterSelectionPreview && mCharacterSelectionPreview->isVisible()) {
       
   612             return;
       
   613         }
       
   614 
       
   615         hideButtonPreview(item);
       
   616 
       
   617         if (emitSignal) {
       
   618             HbWidgetFeedback::triggered(q, Hb::InstantClicked);
       
   619             int actionIndex = item->keyCode() - HbInputButton::ButtonKeyCodeCustom;
       
   620             if (actionIndex >= 0 && actionIndex < mCustomActions.count()) {
       
   621                 mCustomActions.at(actionIndex)->activate(QAction::Trigger);
       
   622             } else {
       
   623                 calculateButtonProbabilities(position);
       
   624 
       
   625                 QString text;
       
   626                 if (item->type() == HbInputButton::ButtonTypeLabel) {
       
   627                     text = item->text(HbInputButton::ButtonTextIndexPrimary);
       
   628                 }
       
   629                 QKeyEvent event(QEvent::KeyRelease, item->keyCode(), Qt::NoModifier, text);
       
   630                 q->emitButtonReleased(event);
       
   631             }
       
   632         }
       
   633     }
       
   634 }
       
   635 
       
   636 void HbInputButtonGroupPrivate::longPressEvent()
       
   637 {
       
   638     Q_Q(HbInputButtonGroup);
       
   639 
       
   640     int index = mLongPressButtons.at(0);
       
   641     mLongPressButtons.removeAt(0);
       
   642     QTimer *timer = mLongPressTimers.at(0);
       
   643     mLongPressTimers.removeAt(0);
       
   644 
       
   645     if (index >= 0 && index < mButtonData.count()) {
       
   646         HbInputButton *item = mButtonData.at(index);
       
   647 
       
   648         if (item->autoRepeat() &&
       
   649             (item->state() == HbInputButton::ButtonStatePressed ||
       
   650             item->state() == HbInputButton::ButtonStateLatched)) {
       
   651             mLongPressButtons.append(index);
       
   652             mLongPressTimers.append(timer);
       
   653             timer->start(HbAutoRepeatTimeout);
       
   654 
       
   655             HbWidgetFeedback::triggered(q, Hb::InstantKeyRepeated);
       
   656 
       
   657             QString text;
       
   658             if (item->type() == HbInputButton::ButtonTypeLabel) {
       
   659                 text = item->text(HbInputButton::ButtonTextIndexPrimary);
       
   660             }
       
   661             QKeyEvent releaeEvent(QEvent::KeyRelease, item->keyCode(), Qt::NoModifier, text, true);
       
   662             q->emitButtonReleased(releaeEvent);
       
   663             QKeyEvent pressEvent(QEvent::KeyPress, item->keyCode(), Qt::NoModifier, text, true);
       
   664             q->emitButtonPressed(pressEvent);
       
   665         } else {
       
   666             if (mCharacterSelectionPreviewEnabled) {
       
   667                 showCharacterSelectionPreview(item);
       
   668             }
       
   669 
       
   670             HbWidgetFeedback::triggered(q, Hb::InstantLongPressed);
       
   671 
       
   672             delete timer;
       
   673 
       
   674             QString text;
       
   675             if (item->type() == HbInputButton::ButtonTypeLabel) {
       
   676                 text = item->text(HbInputButton::ButtonTextIndexPrimary);
       
   677             }
       
   678             QKeyEvent event(QEvent::KeyPress, item->keyCode(), Qt::NoModifier, text, true);
       
   679             q->emitButtonLongPressed(event);
       
   680         }
       
   681     }
       
   682 }
       
   683 
       
   684 void HbInputButtonGroupPrivate::calculateButtonProbabilities(const QPointF &position)
       
   685 {
       
   686     Q_Q(HbInputButtonGroup);
       
   687 
       
   688     mProbabilities.clear();
       
   689 
       
   690     qreal cellWidth = q->boundingRect().width() / mGridSize.width();
       
   691     qreal cellHeight = q->boundingRect().height() / mGridSize.height();
       
   692 
       
   693     QRectF touchArea = QRectF(position.x() - 0.5 * cellWidth, position.y() - 0.5 * cellHeight,
       
   694                               HbTouchAreaSizeInUnits * mUnitValue, HbTouchAreaSizeInUnits * mUnitValue);
       
   695 
       
   696     qreal probabilities = 0;
       
   697     foreach (HbInputButton *button, mButtonData) {
       
   698         QRectF intersection = button->boundingRect().intersected(touchArea);
       
   699 
       
   700         if (intersection.isValid()) {
       
   701             qreal probability = intersection.width() * intersection.height() / (touchArea.width() * touchArea.height());
       
   702             probabilities += probability;
       
   703 
       
   704             HbKeyPressProbability probableKey;
       
   705             probableKey.keycode = button->keyCode();
       
   706             probableKey.probability = probability;
       
   707             mProbabilities.append(probableKey);
       
   708         }
       
   709     }
       
   710 
       
   711     // Normalize
       
   712     for (int i = 0; i < mProbabilities.count(); ++i) {
       
   713         mProbabilities[i].probability /= probabilities;
       
   714     }
       
   715 }
       
   716 
       
   717 void HbInputButtonGroupPrivate::createPrimarySingleTextLayout(int index, const QHash<int, QString> &textContent, const QSizeF &size)
       
   718 {
       
   719     qreal cellWidth = size.width() / mGridSize.width();
       
   720     qreal cellHeight = size.height() / mGridSize.height();
       
   721 
       
   722     QFont font = HbFontSpec(HbFontSpec::Primary).font();
       
   723 
       
   724     int typeIndex = index % HbTextTypeCount / HbInputButton::ButtonStateCount;
       
   725     if (typeIndex == HbInputButton::ButtonTypeLabel) {
       
   726         font.setPixelSize(fontSize(ButtonTextTypeLabel));
       
   727     } else {
       
   728         font.setPixelSize(fontSize(ButtonTextTypeSingle));
       
   729     }
       
   730 
       
   731     mTextLayouts[index] = new QTextLayout(textContent.value(index), font);
       
   732     QFontMetricsF fontMetrics(font);
       
   733 
       
   734     // Create text line for each button with primary text and correct type and state. Layout it
       
   735     // to correct position
       
   736     mTextLayouts.at(index)->beginLayout();
       
   737     foreach (HbInputButton *item, mButtonData) {
       
   738         int layoutIndex = item->type() * HbInputButton::ButtonStateCount + item->state() + HbTextTypeCount;
       
   739         if (!mEnabled) {
       
   740             layoutIndex = item->type() * HbInputButton::ButtonStateCount + HbInputButton::ButtonStateDisabled + HbTextTypeCount;
       
   741         }
       
   742         if (index == layoutIndex && !item->text(HbInputButton::ButtonTextIndexPrimary).isEmpty() &&
       
   743             item->icon(HbInputButton::ButtonIconIndexPrimary).isNull() &&
       
   744             item->text(HbInputButton::ButtonTextIndexSecondaryFirstRow).isEmpty() &&
       
   745             item->icon(HbInputButton::ButtonIconIndexSecondaryFirstRow).isNull() &&
       
   746             item->text(HbInputButton::ButtonTextIndexSecondarySecondRow).isEmpty() &&
       
   747             item->icon(HbInputButton::ButtonIconIndexSecondarySecondRow).isNull()) {
       
   748             qreal textWidth = fontMetrics.width(item->text(HbInputButton::ButtonTextIndexPrimary));
       
   749             qreal textHeight = fontMetrics.height();
       
   750             
       
   751             QTextLine line = mTextLayouts.at(index)->createLine();
       
   752             line.setNumColumns(1);
       
   753 
       
   754             if (typeIndex == HbInputButton::ButtonTypeLabel) {
       
   755                 layoutTextLine(ButtonTextTypeLabel, item, QSizeF(cellWidth, cellHeight), line, QSizeF(textWidth, textHeight));
       
   756             } else {
       
   757                 layoutTextLine(ButtonTextTypeSingle, item, QSizeF(cellWidth, cellHeight), line, QSizeF(textWidth, textHeight));
       
   758             }
       
   759         }
       
   760     }
       
   761     mTextLayouts.at(index)->endLayout();
       
   762     mTextLayouts.at(index)->setCacheEnabled(true);
       
   763 }
       
   764 
       
   765 void HbInputButtonGroupPrivate::createPrimaryTextLayout(int index, const QHash<int, QString> &textContent, const QSizeF &size)
       
   766 {
       
   767     qreal cellWidth = size.width() / mGridSize.width();
       
   768     qreal cellHeight = size.height() / mGridSize.height();
       
   769 
       
   770     QFont font = HbFontSpec(HbFontSpec::Primary).font();
       
   771     font.setPixelSize(fontSize(ButtonTextTypePrimary));
       
   772 
       
   773     mTextLayouts[index] = new QTextLayout(textContent.value(index), font);
       
   774     QFontMetricsF fontMetrics(font);
       
   775 
       
   776     // Create text line for each button with primary text and correct type and state. Layout it
       
   777     // to correct position
       
   778     mTextLayouts.at(index)->beginLayout();
       
   779     foreach (HbInputButton *item, mButtonData) {
       
   780         int layoutIndex = item->type() * HbInputButton::ButtonStateCount + item->state();
       
   781         if (!mEnabled) {
       
   782             layoutIndex = item->type() * HbInputButton::ButtonStateCount + HbInputButton::ButtonStateDisabled;
       
   783         }
       
   784         if (index == layoutIndex && !item->text(HbInputButton::ButtonTextIndexPrimary).isEmpty() &&
       
   785             item->icon(HbInputButton::ButtonIconIndexPrimary).isNull() &&
       
   786             !(item->text(HbInputButton::ButtonTextIndexSecondaryFirstRow).isEmpty() &&
       
   787             item->icon(HbInputButton::ButtonIconIndexSecondaryFirstRow).isNull() &&
       
   788             item->text(HbInputButton::ButtonTextIndexSecondarySecondRow).isEmpty() &&
       
   789             item->icon(HbInputButton::ButtonIconIndexSecondarySecondRow).isNull())) {
       
   790             qreal textWidth = fontMetrics.width(item->text(HbInputButton::ButtonTextIndexPrimary));
       
   791             qreal textHeight = fontMetrics.height();
       
   792 
       
   793             QTextLine line = mTextLayouts.at(index)->createLine();
       
   794             line.setNumColumns(1);
       
   795 
       
   796             layoutTextLine(ButtonTextTypePrimary, item, QSizeF(cellWidth, cellHeight), line, QSizeF(textWidth, textHeight));
       
   797         }
       
   798     }
       
   799     mTextLayouts.at(index)->endLayout();
       
   800     mTextLayouts.at(index)->setCacheEnabled(true);
       
   801 }
       
   802 
       
   803 void HbInputButtonGroupPrivate::createSecondaryTextLayout(int index, const QHash<int, QString> &textContent, const QSizeF &size)
       
   804 {
       
   805     qreal cellWidth = size.width() / mGridSize.width();
       
   806     qreal cellHeight = size.height() / mGridSize.height();
       
   807 
       
   808     QFont font = HbFontSpec(HbFontSpec::Primary).font();
       
   809     font.setPixelSize(fontSize(ButtonTextTypeSecondaryFirstRow));
       
   810 
       
   811     mTextLayouts[index] = new QTextLayout(textContent.value(index), font);
       
   812     QFontMetricsF fontMetrics(font);
       
   813 
       
   814     // Create text line for each button with secondary first row or second row text and correct type and state.
       
   815     // Layout it to correct position
       
   816     mTextLayouts.at(index)->beginLayout();
       
   817     foreach (HbInputButton *item, mButtonData) {
       
   818         int layoutIndex = item->type() * HbInputButton::ButtonStateCount + item->state() + HbTextTypeCount * 2;
       
   819         if (!mEnabled) {
       
   820             layoutIndex = item->type() * HbInputButton::ButtonStateCount + HbInputButton::ButtonStateDisabled + HbTextTypeCount * 2;
       
   821         }
       
   822         if (index == layoutIndex) {
       
   823             if (!item->text(HbInputButton::ButtonTextIndexSecondaryFirstRow).isEmpty() && 
       
   824                 item->icon(HbInputButton::ButtonIconIndexSecondaryFirstRow).isNull()) {
       
   825                 qreal textWidth = fontMetrics.width(item->text(HbInputButton::ButtonTextIndexSecondaryFirstRow));
       
   826                 qreal textHeight = fontMetrics.height();
       
   827 
       
   828                 QTextLine line = mTextLayouts.at(index)->createLine();
       
   829                 line.setNumColumns(1);
       
   830 
       
   831                 layoutTextLine(ButtonTextTypeSecondaryFirstRow, item, QSizeF(cellWidth, cellHeight), line, QSizeF(textWidth, textHeight));
       
   832             }
       
   833 
       
   834             if (!item->text(HbInputButton::ButtonTextIndexSecondarySecondRow).isEmpty() && 
       
   835                 item->icon(HbInputButton::ButtonIconIndexSecondarySecondRow).isNull()) {
       
   836                 qreal textWidth = fontMetrics.width(item->text(HbInputButton::ButtonTextIndexSecondarySecondRow));
       
   837                 qreal textHeight = fontMetrics.height();
       
   838 
       
   839                 QTextLine line = mTextLayouts.at(index)->createLine();
       
   840                 line.setNumColumns(1);
       
   841 
       
   842                 layoutTextLine(ButtonTextTypeSecondarySecondRow, item, QSizeF(cellWidth, cellHeight), line, QSizeF(textWidth, textHeight));
       
   843             }
       
   844         }
       
   845     }
       
   846     mTextLayouts.at(index)->endLayout();
       
   847     mTextLayouts.at(index)->setCacheEnabled(true);
       
   848 }
       
   849 
       
   850 void HbInputButtonGroupPrivate::layoutTextLine(HbInputButtonTextType textType, const HbInputButton *button, const QSizeF &cellSize,
       
   851                                                QTextLine &textLine, const QSizeF &textSize)
       
   852 {
       
   853     qreal textPositionX = 0.0;
       
   854     qreal textPositionY = 0.0;
       
   855     if (textType == ButtonTextTypeSingle ||
       
   856         textType == ButtonTextTypeLabel) {
       
   857         textPositionX = (button->position().x() + 0.5 * button->size().width()) * cellSize.width() - 0.5 * textSize.width();
       
   858         textPositionY = (button->position().y() + 0.5 * button->size().height()) * cellSize.height() - 0.5 * textSize.height();
       
   859     } else if (textType == ButtonTextTypePrimary) {
       
   860         textPositionX = button->position().x() * cellSize.width() + HbHorizontalMarginInUnits * mUnitValue + mButtonBorderSize;
       
   861         textPositionY = (button->position().y() + 0.5 * button->size().height()) * cellSize.height() - 0.5 * textSize.height();
       
   862     } else if (textType == ButtonTextTypeSecondaryFirstRow) {
       
   863         textPositionX = (button->position().x() + button->size().width()) * cellSize.width() -
       
   864             textSize.width() - HbHorizontalMarginInUnits * mUnitValue - mButtonBorderSize;
       
   865         textPositionY = (button->position().y() + button->size().height()) * cellSize.height() -
       
   866             textSize.height() - HbVerticalMarginInUnits * mUnitValue - mButtonBorderSize;
       
   867     } else if (textType == ButtonTextTypeSecondarySecondRow) {
       
   868         textPositionX = (button->position().x() + button->size().width()) * cellSize.width() -
       
   869             textSize.width() - HbHorizontalMarginInUnits * mUnitValue - mButtonBorderSize;
       
   870         textPositionY = button->position().y() * cellSize.height() + HbVerticalMarginInUnits * mUnitValue + mButtonBorderSize;
       
   871     }
       
   872     textLine.setPosition(QPointF(textPositionX, textPositionY));
       
   873 }
       
   874 
       
   875 QString HbInputButtonGroupPrivate::buttonGraphics(HbInputButton::HbInputButtonType type, HbInputButton::HbInputButtonState state)
       
   876 {
       
   877     if (type == HbInputButton::ButtonTypeNormal) {
       
   878         if (state == HbInputButton::ButtonStateReleased) {
       
   879             return HbNormalBackground;
       
   880         } else if (state == HbInputButton::ButtonStatePressed) {
       
   881             return HbNormalPressedBackground;
       
   882         } else if (state == HbInputButton::ButtonStateLatched) {
       
   883             return HbNormalLatchedBackground;
       
   884         } else if (state == HbInputButton::ButtonStateDisabled) {
       
   885             return HbNormalInActiveBackground;
       
   886         }
       
   887     } else if (type == HbInputButton::ButtonTypeFunction) {
       
   888         if (state == HbInputButton::ButtonStateReleased) {
       
   889             return HbFunctionBackground;
       
   890         } else if (state == HbInputButton::ButtonStatePressed) {
       
   891             return HbFunctionPressedBackground;
       
   892         } else if (state == HbInputButton::ButtonStateLatched) {
       
   893             return HbFunctionLatchedBackground;
       
   894         } else if (state == HbInputButton::ButtonStateDisabled) {
       
   895             return HbFunctionInActiveBackground;
       
   896         }
       
   897     }
       
   898     return QString("");
       
   899 }
       
   900 
       
   901 QString HbInputButtonGroupPrivate::buttonColor(HbInputButton::HbInputButtonType type, HbInputButton::HbInputButtonState state)
       
   902 {
       
   903     if (type == HbInputButton::ButtonTypeNormal) {
       
   904         if (state == HbInputButton::ButtonStateReleased) {
       
   905             return HbNormalColor;
       
   906         } else if (state == HbInputButton::ButtonStatePressed) {
       
   907             return HbNormalColorPressed;
       
   908         } else if (state == HbInputButton::ButtonStateLatched) {
       
   909             return HbNormalColorLatched;
       
   910         } else if (state == HbInputButton::ButtonStateDisabled) {
       
   911             return HbNormalColorInActive;
       
   912         }
       
   913     } else if (type == HbInputButton::ButtonTypeFunction) {
       
   914         if (state == HbInputButton::ButtonStateReleased) {
       
   915             return HbFunctionColor;
       
   916         } else if (state == HbInputButton::ButtonStatePressed) {
       
   917             return HbFunctionColorPressed;
       
   918         } else if (state == HbInputButton::ButtonStateLatched) {
       
   919             return HbFunctionColorLatched;
       
   920         } else if (state == HbInputButton::ButtonStateDisabled) {
       
   921             return HbFunctionColorInActive;
       
   922         }
       
   923     } else if (type == HbInputButton::ButtonTypeLabel) {
       
   924         if (mButtonData.count() == 1) {
       
   925             return HbButtonPreviewColor;
       
   926         } else {
       
   927             return HbCharacterSelectionPreviewColor;
       
   928         }
       
   929     }
       
   930     return QString("");
       
   931 }
       
   932 
       
   933 qreal HbInputButtonGroupPrivate::fontSize(HbInputButtonTextType textType)
       
   934 {
       
   935     if (textType == ButtonTextTypeSingle) {
       
   936         return HbTextSizeInUnits * mUnitValue;
       
   937     } else if (textType == ButtonTextTypePrimary) {
       
   938         return HbPrimaryTextSizeInUnits * mUnitValue;
       
   939     } else if (textType == ButtonTextTypeSecondaryFirstRow ||
       
   940         textType == ButtonTextTypeSecondarySecondRow) {
       
   941         return HbSecondaryTextSizeInUnits * mUnitValue;
       
   942     } else if (textType == ButtonTextTypeLabel) {
       
   943         return HbLabelTextSizeInUnits * mUnitValue;
       
   944     }
       
   945     return 0;
       
   946 }
       
   947 
       
   948 void HbInputButtonGroupPrivate::startLongPress(int index)
       
   949 {
       
   950     Q_Q(HbInputButtonGroup);
       
   951     if (!mUsedCustomButtons.contains(index)) {
       
   952         mLongPressButtons.append(index);
       
   953         mLongPressTimers.append(new QTimer());
       
   954         mLongPressTimers.back()->setSingleShot(true);
       
   955         QObject::connect(mLongPressTimers.back(), SIGNAL(timeout()), q, SLOT(longPressEvent()));
       
   956         mLongPressTimers.back()->start(HbLongPressTimeout);
       
   957     }
       
   958 }
       
   959 
       
   960 void HbInputButtonGroupPrivate::cancelLongPress(int index)
       
   961 {
       
   962     if (mLongPressButtons.contains(index)) {
       
   963         int listIndex = mLongPressButtons.indexOf(index);
       
   964         delete mLongPressTimers.at(listIndex);
       
   965         mLongPressTimers.removeAt(listIndex);
       
   966         mLongPressButtons.removeAt(listIndex);
       
   967     }
       
   968 }
       
   969 
       
   970 /// @endcond
       
   971 
       
   972 /*!
       
   973 Constructor
       
   974 */
       
   975 HbInputButtonGroup::HbInputButtonGroup(QGraphicsItem *parent)
       
   976  : HbWidget(*new HbInputButtonGroupPrivate, parent)
       
   977 {
       
   978     Q_D(HbInputButtonGroup);
       
   979 
       
   980     d->mUnitValue = HbDeviceProfile::profile(mainWindow()).unitValue();
       
   981 
       
   982     setAcceptedMouseButtons(Qt::LeftButton);
       
   983 }
       
   984 
       
   985 /*!
       
   986 Constructor
       
   987 */
       
   988 HbInputButtonGroup::HbInputButtonGroup(HbInputButtonGroupPrivate &dd, QGraphicsItem *parent)
       
   989  : HbWidget(dd, parent)
       
   990 {
       
   991     Q_D(HbInputButtonGroup);
       
   992 
       
   993     d->mUnitValue = HbDeviceProfile::profile(mainWindow()).unitValue();
       
   994 
       
   995     setAcceptedMouseButtons(Qt::LeftButton);
       
   996 }
       
   997 
       
   998 /*!
       
   999 Constructor
       
  1000 */
       
  1001 HbInputButtonGroup::HbInputButtonGroup(const QSize &size, QGraphicsItem *parent)
       
  1002  : HbWidget(*new HbInputButtonGroupPrivate, parent)
       
  1003 {
       
  1004     Q_D(HbInputButtonGroup);
       
  1005 
       
  1006     d->mUnitValue = HbDeviceProfile::profile(mainWindow()).unitValue();
       
  1007 
       
  1008     setAcceptedMouseButtons(Qt::LeftButton);
       
  1009     
       
  1010     setGridSize(size);
       
  1011 }
       
  1012 
       
  1013 /*!
       
  1014 Constructor
       
  1015 */
       
  1016 HbInputButtonGroup::HbInputButtonGroup(HbInputButtonGroupPrivate &dd, const QSize &size, QGraphicsItem *parent)
       
  1017  : HbWidget(dd, parent)
       
  1018 {
       
  1019     Q_D(HbInputButtonGroup);
       
  1020 
       
  1021     d->mUnitValue = HbDeviceProfile::profile(mainWindow()).unitValue();
       
  1022 
       
  1023     setAcceptedMouseButtons(Qt::LeftButton);
       
  1024     
       
  1025     setGridSize(size);
       
  1026 }
       
  1027 
       
  1028 /*!
       
  1029 Destructor
       
  1030 */
       
  1031 HbInputButtonGroup::~HbInputButtonGroup()
       
  1032 {
       
  1033 }
       
  1034 
       
  1035 /*!
       
  1036 Sets new grid size and updates button group content based on the new grid size.
       
  1037 
       
  1038 \sa gridSize
       
  1039 */
       
  1040 void HbInputButtonGroup::setGridSize(const QSize &size)
       
  1041 {
       
  1042     Q_D(HbInputButtonGroup);
       
  1043 
       
  1044     d->mGridSize = size;
       
  1045     if (d->mGridSize.width() < 1) {
       
  1046         d->mGridSize.setWidth(1);
       
  1047     }
       
  1048     if (d->mGridSize.height() < 1) {
       
  1049         d->mGridSize.setHeight(1);
       
  1050     }
       
  1051 
       
  1052     setButtonBorderSize(d->mButtonBorderSize);
       
  1053     d->updateButtonGrid(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1054     d->updateGraphics(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1055     d->updateTextLayouts(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1056     update();
       
  1057 }
       
  1058 
       
  1059 /*!
       
  1060 Returns current grid size.
       
  1061 
       
  1062 \sa setGridSize
       
  1063 */
       
  1064 QSize HbInputButtonGroup::gridSize() const
       
  1065 {
       
  1066     Q_D(const HbInputButtonGroup);
       
  1067 
       
  1068     return d->mGridSize;
       
  1069 }
       
  1070 
       
  1071 /*!
       
  1072 Sets the button data and updates button group based on the new data.
       
  1073 Takes ownership of the button items. Button items that are not in the new list 
       
  1074 will be destroyed.
       
  1075 
       
  1076 \sa buttons
       
  1077 \sa button
       
  1078 */
       
  1079 void HbInputButtonGroup::setButtons(const QList<HbInputButton*> &data)
       
  1080 {
       
  1081     Q_D(HbInputButtonGroup);
       
  1082 
       
  1083     foreach (HbInputButton *button, d->mButtonData) {
       
  1084         if (!data.contains(button)) {
       
  1085             delete button;
       
  1086         }
       
  1087     }
       
  1088     d->mButtonData = data;
       
  1089 
       
  1090     d->updateButtonGrid(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1091     d->updateCustomActions();
       
  1092     d->updateColorArray();
       
  1093     d->updateGraphics(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1094     d->updateTextLayouts(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1095     update();
       
  1096 }
       
  1097 
       
  1098 /*!
       
  1099 Sets the button item and updates button group based on the new data.
       
  1100 Takes ownership of the button item. Old button item in the given index will be destroyed.
       
  1101 If null item is passed then the item from the given index will be removed.
       
  1102 If index is out of bounds then the item is inserted to the end of button list.
       
  1103 
       
  1104 \sa buttons
       
  1105 \sa button
       
  1106 */
       
  1107 void HbInputButtonGroup::setButton(HbInputButton *data, int index)
       
  1108 {
       
  1109     Q_D(HbInputButtonGroup);
       
  1110 
       
  1111     if (index >= 0 && index < d->mButtonData.count()) {
       
  1112         if (data != d->mButtonData.at(index)) {
       
  1113             delete d->mButtonData.at(index);
       
  1114         }
       
  1115         if (data) {
       
  1116             d->mButtonData.replace(index, data);
       
  1117         } else {
       
  1118             d->mButtonData.removeAt(index);
       
  1119         }
       
  1120     } else {
       
  1121         d->mButtonData.append(data);
       
  1122     }
       
  1123     setButtons(d->mButtonData);
       
  1124 }
       
  1125 
       
  1126 /*!
       
  1127 Sets the button item and updates button group based on the new data.
       
  1128 Takes ownership of the button item. Old button item in the given position will be destroyed.
       
  1129 If null item is passed then the item from the given position will be removed.
       
  1130 If the given position doesn't contain a button then the item is inserted to the end of button list.
       
  1131 
       
  1132 \sa buttons
       
  1133 \sa button
       
  1134 */
       
  1135 void HbInputButtonGroup::setButton(HbInputButton *data, int column, int row)
       
  1136 {
       
  1137     Q_D(HbInputButtonGroup);
       
  1138 
       
  1139     int index = d->mButtonGridPositions.value(QPair<int, int>(column, row));
       
  1140     setButton(data, index);
       
  1141 }
       
  1142 
       
  1143 /*!
       
  1144 Sets the button item and updates button group based on the new data.
       
  1145 Takes ownership of the button item. Old button item with given key code will be destroyed.
       
  1146 If null item is passed then the item with given key code will be removed.
       
  1147 If group contains multiple buttons with same key code then the first one will be replaced.
       
  1148 If there isn't any button with given key code then the button will be added to the end of button list.
       
  1149 
       
  1150 \sa buttons
       
  1151 \sa button
       
  1152 */
       
  1153 void HbInputButtonGroup::setButton(HbInputButton *data, HbInputButton::HbInputButtonKeyCode keyCode)
       
  1154 {
       
  1155     Q_D(HbInputButtonGroup);
       
  1156 
       
  1157     int index = 0;
       
  1158     for (; index < d->mButtonData.count(); ++index) {
       
  1159         HbInputButton *item = d->mButtonData.at(index);
       
  1160         if (item->keyCode() == keyCode) {
       
  1161             break;
       
  1162         }
       
  1163     }
       
  1164     
       
  1165     setButton(data, index);
       
  1166 }
       
  1167 
       
  1168 /*!
       
  1169 Returns button data.
       
  1170 Ownership of the returned button items is not transferred.
       
  1171 
       
  1172 \sa setButtons
       
  1173 \sa setButton
       
  1174 */
       
  1175 QList<HbInputButton*> HbInputButtonGroup::buttons() const
       
  1176 {
       
  1177     Q_D(const HbInputButtonGroup);
       
  1178 
       
  1179     return d->mButtonData;
       
  1180 }
       
  1181 
       
  1182 /*!
       
  1183 Returns button item.
       
  1184 Ownership of the returned button item is not transferred.
       
  1185 
       
  1186 \sa setButtons
       
  1187 \sa setButton
       
  1188 */
       
  1189 HbInputButton *HbInputButtonGroup::button(int index) const
       
  1190 {
       
  1191     Q_D(const HbInputButtonGroup);
       
  1192 
       
  1193     if (index >= 0 && index < d->mButtonData.count()) {
       
  1194         return d->mButtonData.at(index);
       
  1195     }
       
  1196     return 0;
       
  1197 }
       
  1198 
       
  1199 /*!
       
  1200 Returns button data.
       
  1201 Ownership of the button items is not transferred.
       
  1202 
       
  1203 \sa setButtons
       
  1204 \sa setButton
       
  1205 */
       
  1206 HbInputButton *HbInputButtonGroup::button(int column, int row) const
       
  1207 {
       
  1208     Q_D(const HbInputButtonGroup);
       
  1209     
       
  1210     int index = d->mButtonGridPositions.value(QPair<int, int>(column, row));
       
  1211     return button(index);
       
  1212 }
       
  1213 
       
  1214 /*!
       
  1215 Returns button data.
       
  1216 Ownership of the button items is not transferred.
       
  1217 
       
  1218 \sa setButtons
       
  1219 \sa setButton
       
  1220 */
       
  1221 HbInputButton *HbInputButtonGroup::button(HbInputButton::HbInputButtonKeyCode keyCode) const
       
  1222 {
       
  1223     Q_D(const HbInputButtonGroup);
       
  1224 
       
  1225     foreach (HbInputButton *button, d->mButtonData) {
       
  1226         if (button->keyCode() == keyCode) {
       
  1227             return button;
       
  1228         }
       
  1229     }
       
  1230     return 0;
       
  1231 }
       
  1232 
       
  1233 /*!
       
  1234 Sets custom actions and updates button group based on the new data. Custom actions
       
  1235 are mapped to buttons which keycode is equal or bigger than HbInputButtonKeyCustom.
       
  1236 Ownership of the actions is not transferred.
       
  1237 
       
  1238 \sa customButtonActions
       
  1239 */
       
  1240 void HbInputButtonGroup::setCustomButtonActions(const QList<HbAction*> &actions)
       
  1241 {
       
  1242     Q_D(HbInputButtonGroup);
       
  1243 
       
  1244     disconnect(this, SLOT(updateCustomButtons()));
       
  1245 
       
  1246     d->mCustomActions = actions;
       
  1247 
       
  1248     foreach (HbAction *action, d->mCustomActions) {
       
  1249         connect(action, SIGNAL(changed()), this, SLOT(updateCustomButtons()));
       
  1250     }
       
  1251 
       
  1252     d->updateCustomActions();
       
  1253     d->updateGraphics(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1254     d->updateTextLayouts(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1255     update();
       
  1256 }
       
  1257 
       
  1258 /*!
       
  1259 Returns current custom actions.
       
  1260 Ownership of the actions is not transferred.
       
  1261 
       
  1262 \sa setCustomButtonActions
       
  1263 */
       
  1264 QList<HbAction*> HbInputButtonGroup::customButtonActions() const
       
  1265 {
       
  1266     Q_D(const HbInputButtonGroup);
       
  1267 
       
  1268     return d->mCustomActions;
       
  1269 }
       
  1270 
       
  1271 /*!
       
  1272 Sets the border size for the buttons and updates button group based on the new value.
       
  1273 Size must be in a range between 0 to half of button size.
       
  1274 
       
  1275 \sa buttonBorderSize
       
  1276 */
       
  1277 void HbInputButtonGroup::setButtonBorderSize(qreal borderSize)
       
  1278 {
       
  1279     Q_D(HbInputButtonGroup);
       
  1280 
       
  1281     if (borderSize < 0.0) {
       
  1282         borderSize = 0.0;
       
  1283     } else if (boundingRect().width() != 0.0 && boundingRect().height() != 0.0) {
       
  1284         qreal maxSize = boundingRect().width() / d->mGridSize.width() * 0.5;
       
  1285         if (boundingRect().width() > boundingRect().height()) {
       
  1286             maxSize = boundingRect().height() / d->mGridSize.height() * 0.5;
       
  1287         }
       
  1288         if (borderSize > maxSize) {
       
  1289             borderSize = maxSize;
       
  1290         }
       
  1291     }
       
  1292     d->mButtonBorderSize = borderSize;
       
  1293 
       
  1294     d->updateGraphics(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1295     update();
       
  1296 }
       
  1297 
       
  1298 /*!
       
  1299 Returns the border size.
       
  1300 
       
  1301 \sa setButtonBorderSize
       
  1302 */
       
  1303 qreal HbInputButtonGroup::buttonBorderSize() const
       
  1304 {
       
  1305     Q_D(const HbInputButtonGroup);
       
  1306 
       
  1307     return d->mButtonBorderSize;
       
  1308 }
       
  1309 
       
  1310 /*!
       
  1311 Sets button preview state.
       
  1312 
       
  1313 \sa isButtonPreviewEnabled
       
  1314 */
       
  1315 void HbInputButtonGroup::setButtonPreviewEnabled(bool enabled)
       
  1316 {
       
  1317     Q_D(HbInputButtonGroup);
       
  1318 
       
  1319     d->mButtonPreviewEnabled = enabled;
       
  1320 }
       
  1321 
       
  1322 /*!
       
  1323 Returns preview state.
       
  1324 
       
  1325 \sa setButtonPreviewEnabled
       
  1326 */
       
  1327 bool HbInputButtonGroup::isButtonPreviewEnabled() const
       
  1328 {
       
  1329     Q_D(const HbInputButtonGroup);
       
  1330 
       
  1331     return d->mButtonPreviewEnabled;
       
  1332 }
       
  1333 
       
  1334 /*!
       
  1335 Sets button specific character selection preview state.
       
  1336 
       
  1337 \sa isCharacterSelectionPreviewEnabled
       
  1338 */
       
  1339 void HbInputButtonGroup::setCharacterSelectionPreviewEnabled(bool enabled)
       
  1340 {
       
  1341     Q_D(HbInputButtonGroup);
       
  1342 
       
  1343     d->mCharacterSelectionPreviewEnabled = enabled;
       
  1344 }
       
  1345 
       
  1346 /*!
       
  1347 Returns button specific character selection preview state.
       
  1348 
       
  1349 \sa setCharacterSelectionPreviewEnabled
       
  1350 */
       
  1351 bool HbInputButtonGroup::isCharacterSelectionPreviewEnabled() const
       
  1352 {
       
  1353     Q_D(const HbInputButtonGroup);
       
  1354 
       
  1355     return d->mCharacterSelectionPreviewEnabled;
       
  1356 }
       
  1357 
       
  1358 
       
  1359 /*!
       
  1360 Sets multi touch enabled or disabled.
       
  1361 
       
  1362 \sa isMultiTouchEnabled
       
  1363 */
       
  1364 void HbInputButtonGroup::setMultiTouchEnabled(bool enabled)
       
  1365 {
       
  1366     Q_D(HbInputButtonGroup);
       
  1367 
       
  1368     d->mMultiTouchEnabled = enabled;
       
  1369     setAcceptTouchEvents(enabled);
       
  1370 }
       
  1371 
       
  1372 /*!
       
  1373 Returns multi touch state.
       
  1374 
       
  1375 \sa setMultiTouchEnabled
       
  1376 */
       
  1377 bool HbInputButtonGroup::isMultiTouchEnabled() const
       
  1378 {
       
  1379     Q_D(const HbInputButtonGroup);
       
  1380     
       
  1381     return d->mMultiTouchEnabled;
       
  1382 }
       
  1383 
       
  1384 /*!
       
  1385 Sets button group background graphics.
       
  1386 Takes ownership of the background object.
       
  1387 */
       
  1388 void HbInputButtonGroup::setBackground(HbFrameDrawer *background)
       
  1389 {
       
  1390     Q_D(HbInputButtonGroup);
       
  1391 
       
  1392     HbFrameDrawerPool::release(d->mBackground);
       
  1393     d->mBackground = background;
       
  1394 }
       
  1395 
       
  1396 /*!
       
  1397 Returns all possible buttons the user could have intended to press
       
  1398 for the last registered touch along with their corresponding probabilities.
       
  1399 */
       
  1400 QList<HbKeyPressProbability> HbInputButtonGroup::buttonProbabilities() const
       
  1401 {
       
  1402     Q_D(const HbInputButtonGroup);
       
  1403 
       
  1404     return d->mProbabilities;
       
  1405 }
       
  1406 
       
  1407 /*!
       
  1408 Sets the button group enabled or disabled.
       
  1409 
       
  1410 \sa isEnabled
       
  1411 */
       
  1412 void HbInputButtonGroup::setEnabled(bool enabled)
       
  1413 {
       
  1414     Q_D(HbInputButtonGroup);
       
  1415 
       
  1416     d->mEnabled = enabled;
       
  1417     d->updateGraphics(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1418     d->updateTextLayouts(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1419     update();
       
  1420 }
       
  1421 
       
  1422 /*!
       
  1423 Returns the button group state.
       
  1424 
       
  1425 \sa setEnabled
       
  1426 */
       
  1427 bool HbInputButtonGroup::isEnabled() const
       
  1428 {
       
  1429     Q_D(const HbInputButtonGroup);
       
  1430 
       
  1431     return d->mEnabled;
       
  1432 }
       
  1433 
       
  1434 /*!
       
  1435 Draws the button group.
       
  1436 */
       
  1437 void HbInputButtonGroup::paint(QPainter* painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
       
  1438 {
       
  1439     Q_UNUSED(option);
       
  1440     Q_UNUSED(widget);
       
  1441 
       
  1442     Q_D(HbInputButtonGroup);
       
  1443 
       
  1444     if (d->mBackground) {
       
  1445         d->mBackground->paint(painter, QRectF(0, 0, boundingRect().width(), boundingRect().height()));
       
  1446     }
       
  1447 
       
  1448     qreal cellWidth = boundingRect().width() / d->mGridSize.width();
       
  1449     qreal cellHeight = boundingRect().height() / d->mGridSize.height();
       
  1450 
       
  1451     for (int i = 0; i < d->mButtonData.count(); ++i) {
       
  1452         HbInputButton *item = d->mButtonData.at(i);
       
  1453 
       
  1454         if (d->mButtonDrawers.at(i)) {
       
  1455             qreal x = item->position().x() * cellWidth + d->mButtonBorderSize;
       
  1456             qreal y = item->position().y() * cellHeight + d->mButtonBorderSize;
       
  1457             qreal width = item->size().width() * cellWidth - 2 * d->mButtonBorderSize;
       
  1458             qreal height = item->size().height() * cellHeight - 2 * d->mButtonBorderSize;
       
  1459 
       
  1460             painter->save();
       
  1461             painter->translate(x, y);
       
  1462             d->mButtonDrawers.at(i)->paint(painter, QRectF(0, 0, width, height));        
       
  1463             painter->restore();
       
  1464         }
       
  1465 
       
  1466         if (!item->icon(HbInputButton::ButtonIconIndexPrimary).isNull()) {
       
  1467             qreal x = item->position().x() * cellWidth;
       
  1468             qreal y = item->position().y() * cellHeight;
       
  1469             qreal width = item->size().width() * cellWidth;
       
  1470             qreal height = item->size().height() * cellHeight;
       
  1471 
       
  1472             if (!item->text(HbInputButton::ButtonTextIndexSecondaryFirstRow).isEmpty() ||
       
  1473                 !item->text(HbInputButton::ButtonTextIndexSecondarySecondRow).isEmpty() ||
       
  1474                 !item->icon(HbInputButton::ButtonIconIndexSecondaryFirstRow).isNull() ||
       
  1475                 !item->icon(HbInputButton::ButtonIconIndexSecondarySecondRow).isNull()) {
       
  1476                 x += HbHorizontalMarginInUnits * d->mUnitValue + d->mButtonBorderSize;
       
  1477                 y += 0.5 * (item->size().height() * cellHeight - HbPrimaryIconSizeInUnits * d->mUnitValue);
       
  1478                 width = HbPrimaryIconSizeInUnits * d->mUnitValue;
       
  1479                 height = HbPrimaryIconSizeInUnits * d->mUnitValue;
       
  1480             }
       
  1481             item->icon(HbInputButton::ButtonIconIndexPrimary).paint(painter, QRectF(x, y, width, height));
       
  1482         }
       
  1483 
       
  1484         if (!item->icon(HbInputButton::ButtonIconIndexSecondaryFirstRow).isNull()) {
       
  1485             qreal x = (item->position().x() + item->size().width()) * cellWidth -
       
  1486                 HbSecondaryIconSizeInUnits * d->mUnitValue - HbHorizontalMarginInUnits * d->mUnitValue - d->mButtonBorderSize;
       
  1487             qreal y = (item->position().y() + item->size().height()) * cellHeight -
       
  1488                 HbSecondaryIconSizeInUnits * d->mUnitValue - HbVerticalMarginInUnits * d->mUnitValue - d->mButtonBorderSize;
       
  1489             qreal width = HbSecondaryIconSizeInUnits * d->mUnitValue;
       
  1490             qreal height = HbSecondaryIconSizeInUnits * d->mUnitValue;
       
  1491 
       
  1492             Qt::Alignment alignment = static_cast<Qt::Alignment>(Qt::AlignVCenter | Qt::AlignRight);
       
  1493             item->icon(HbInputButton::ButtonIconIndexSecondaryFirstRow).paint(painter, QRectF(x, y, width, height), Qt::KeepAspectRatio, alignment);
       
  1494         }
       
  1495 
       
  1496         if (!item->icon(HbInputButton::ButtonIconIndexSecondarySecondRow).isNull()) {
       
  1497             qreal x = (item->position().x() + item->size().width()) * cellWidth -
       
  1498                 HbSecondaryIconSizeInUnits * d->mUnitValue - HbHorizontalMarginInUnits * d->mUnitValue - d->mButtonBorderSize;
       
  1499             qreal y = item->position().y() * cellHeight + HbVerticalMarginInUnits * d->mUnitValue + d->mButtonBorderSize;
       
  1500             qreal width = HbSecondaryIconSizeInUnits * d->mUnitValue;
       
  1501             qreal height = HbSecondaryIconSizeInUnits * d->mUnitValue;
       
  1502 
       
  1503             Qt::Alignment alignment = static_cast<Qt::Alignment>(Qt::AlignVCenter | Qt::AlignRight);
       
  1504             item->icon(HbInputButton::ButtonIconIndexSecondaryFirstRow).paint(painter, QRectF(x, y, width, height), Qt::KeepAspectRatio, alignment);
       
  1505         }
       
  1506 
       
  1507     }
       
  1508 
       
  1509     for (int i = 0; i < HbTextLayoutCount; ++i) {
       
  1510         painter->save();
       
  1511         painter->setPen(d->mColors.at(i % HbTextTypeCount));
       
  1512 
       
  1513         if (d->mTextLayouts.at(i)) {
       
  1514             d->mTextLayouts.at(i)->draw(painter, QPointF(0, 0));
       
  1515         }
       
  1516         painter->restore();
       
  1517     }
       
  1518 }
       
  1519 
       
  1520 /*!
       
  1521 \reimp
       
  1522 
       
  1523 Handles touch events.
       
  1524 */
       
  1525 bool HbInputButtonGroup::sceneEvent(QEvent *event)
       
  1526 {
       
  1527     Q_D(HbInputButtonGroup);
       
  1528 
       
  1529     if (!d->mEnabled) {
       
  1530         event->ignore();
       
  1531         return false;
       
  1532     }
       
  1533 
       
  1534     if (event->type() == QEvent::TouchBegin) {
       
  1535         QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
       
  1536         foreach (QTouchEvent::TouchPoint point, touchEvent->touchPoints()) {
       
  1537             if (!point.isPrimary() && d->mMultiTouchEnabled) {         
       
  1538                 d->pressEvent(point.pos());
       
  1539             }
       
  1540         }
       
  1541     } else if (event->type() == QEvent::TouchUpdate) {
       
  1542         QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
       
  1543         foreach (QTouchEvent::TouchPoint point, touchEvent->touchPoints()) {
       
  1544             if (!point.isPrimary() && d->mMultiTouchEnabled) {
       
  1545                 if (point.state() & Qt::TouchPointPressed) {
       
  1546                     d->pressEvent(point.pos());
       
  1547                 } else if (point.state() & Qt::TouchPointMoved) {
       
  1548                     d->moveEvent(point.lastPos(), point.pos());
       
  1549                 } else if (point.state() & Qt::TouchPointReleased) {
       
  1550                     d->releaseEvent(point.pos());
       
  1551                 }
       
  1552             }
       
  1553         }
       
  1554     } else if (event->type() == QEvent::TouchEnd) {
       
  1555         QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
       
  1556         foreach (QTouchEvent::TouchPoint point, touchEvent->touchPoints()) {
       
  1557             if (!point.isPrimary() && d->mMultiTouchEnabled) {  
       
  1558                 d->releaseEvent(point.pos());
       
  1559             }
       
  1560         }
       
  1561     } else if (event->type() == QEvent::GraphicsSceneMousePress) {
       
  1562         QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
       
  1563         d->pressEvent(mouseEvent->pos());
       
  1564     } else if (event->type() == QEvent::GraphicsSceneMouseDoubleClick) {
       
  1565         QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
       
  1566         d->doublePressEvent(mouseEvent->pos());
       
  1567     } else if (event->type() == QEvent::GraphicsSceneMouseMove) {
       
  1568         QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
       
  1569         d->moveEvent(mouseEvent->lastPos(), mouseEvent->pos());
       
  1570     } else if (event->type() == QEvent::GraphicsSceneMouseRelease) {
       
  1571         QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
       
  1572         d->releaseEvent(mouseEvent->pos());
       
  1573     } else {
       
  1574         return HbWidget::event(event);
       
  1575     }
       
  1576     return true;
       
  1577 }
       
  1578 
       
  1579 /*!
       
  1580 \reimp
       
  1581 
       
  1582 Updates button group geometry.
       
  1583 */
       
  1584 void HbInputButtonGroup::setGeometry(const QRectF &rect)
       
  1585 {
       
  1586     Q_D(HbInputButtonGroup);
       
  1587 
       
  1588     HbWidget::setGeometry(rect);
       
  1589 
       
  1590     setButtonBorderSize(d->mButtonBorderSize);
       
  1591     d->updateButtonGrid(QSizeF(rect.width(), rect.height()));
       
  1592     d->updateGraphics(QSizeF(rect.width(), rect.height()));
       
  1593     d->updateTextLayouts(QSizeF(rect.width(), rect.height()));
       
  1594 }
       
  1595 
       
  1596 /*!
       
  1597 \reimp
       
  1598 
       
  1599 Updates theme graphics
       
  1600  */
       
  1601 void HbInputButtonGroup::changeEvent(QEvent *event)
       
  1602 {
       
  1603     Q_D(HbInputButtonGroup);
       
  1604    
       
  1605     if (event->type() == HbEvent::ThemeChanged) {
       
  1606         if (d->mBackground) {
       
  1607             d->mBackground->themeChanged();
       
  1608         }
       
  1609 
       
  1610         foreach (HbFrameDrawer *drawer, d->mButtonDrawers) {
       
  1611             drawer->themeChanged();
       
  1612         }
       
  1613 
       
  1614         d->updateColorArray();
       
  1615 
       
  1616         for (int i = 0; i < d->mButtonData.count(); ++i) {
       
  1617             HbInputButton *item = d->mButtonData.at(i);
       
  1618 
       
  1619             QColor color;
       
  1620             if (d->mEnabled) {
       
  1621                 color = d->mColors.at(item->type() * HbInputButton::ButtonStateCount + item->state());
       
  1622             } else {
       
  1623                 color = d->mColors.at(item->type() * HbInputButton::ButtonStateCount + HbInputButton::ButtonStateDisabled);
       
  1624             }
       
  1625 
       
  1626             if (!item->icon(HbInputButton::ButtonIconIndexPrimary).isNull()) {
       
  1627                 HbIcon icon = item->icon(HbInputButton::ButtonIconIndexPrimary);
       
  1628                 icon.setColor(color);
       
  1629                 item->setIcon(icon, HbInputButton::ButtonIconIndexPrimary);
       
  1630             }
       
  1631         }
       
  1632     }
       
  1633     HbWidget::changeEvent(event);
       
  1634 }
       
  1635 
       
  1636 /*!
       
  1637 \reimp
       
  1638 
       
  1639 Enables touch events if multi touch is enabled.
       
  1640 */
       
  1641 void HbInputButtonGroup::showEvent(QShowEvent *event)
       
  1642 {
       
  1643     Q_D(HbInputButtonGroup);
       
  1644 
       
  1645     setAcceptTouchEvents(d->mMultiTouchEnabled);
       
  1646 
       
  1647     HbWidget::showEvent(event);
       
  1648 }
       
  1649 
       
  1650 /*!
       
  1651 \reimp
       
  1652 
       
  1653 Releases all pressed buttons when hidden.
       
  1654 */
       
  1655 void HbInputButtonGroup::hideEvent(QHideEvent *event)
       
  1656 {
       
  1657     cancelButtonPress();
       
  1658 
       
  1659     HbWidget::hideEvent(event);
       
  1660 }
       
  1661 
       
  1662 /*!
       
  1663 Emits buttonPressed signal.
       
  1664 */
       
  1665 void HbInputButtonGroup::emitButtonPressed(const QKeyEvent &event)
       
  1666 {
       
  1667     emit buttonPressed(event);
       
  1668 }
       
  1669 
       
  1670 /*!
       
  1671 Emits buttonDoublePressed signal.
       
  1672 */
       
  1673 void HbInputButtonGroup::emitButtonDoublePressed(const QKeyEvent &event)
       
  1674 {
       
  1675     emit buttonDoublePressed(event);
       
  1676 }
       
  1677 
       
  1678 /*!
       
  1679 Emits buttonReleased signal.
       
  1680 */
       
  1681 void HbInputButtonGroup::emitButtonReleased(const QKeyEvent &event)
       
  1682 {
       
  1683     Q_D(HbInputButtonGroup);
       
  1684 
       
  1685     if (d->mCharacterSelectionPreview) {
       
  1686         d->mCharacterSelectionPreview->hide();
       
  1687     }
       
  1688 
       
  1689     emit buttonReleased(event);
       
  1690 }
       
  1691 
       
  1692 /*!
       
  1693 Emits buttonLongPressed signal.
       
  1694 */
       
  1695 void HbInputButtonGroup::emitButtonLongPressed(const QKeyEvent &event)
       
  1696 {
       
  1697     emit buttonLongPressed(event);
       
  1698 }
       
  1699 
       
  1700 /*!
       
  1701 Emits pressedButtonChanged signal.
       
  1702 */
       
  1703 void HbInputButtonGroup::emitPressedButtonChanged(const QKeyEvent &releaseEvent, const QKeyEvent &pressEvent)
       
  1704 {
       
  1705     emit pressedButtonChanged(releaseEvent, pressEvent);
       
  1706 }
       
  1707 
       
  1708 /*!
       
  1709 Cancels current button press and releases all buttons.
       
  1710 */
       
  1711 void HbInputButtonGroup::cancelButtonPress()
       
  1712 {
       
  1713     Q_D(HbInputButtonGroup);
       
  1714 
       
  1715     ungrabMouse();
       
  1716 
       
  1717     for (int i = 0; i < d->mButtonData.count(); ++i) {
       
  1718         if (d->mButtonData.at(i)->state() == HbInputButton::ButtonStatePressed) {
       
  1719             d->mButtonData.at(i)->setState(HbInputButton::ButtonStateReleased);
       
  1720         }
       
  1721         d->hideButtonPreview(d->mButtonData.at(i));
       
  1722 
       
  1723         if (d->mLongPressButtons.contains(i)) {
       
  1724             int listIndex = d->mLongPressButtons.indexOf(i);
       
  1725             delete d->mLongPressTimers.at(listIndex);
       
  1726             d->mLongPressTimers.removeAt(listIndex);
       
  1727             d->mLongPressButtons.removeAt(listIndex);
       
  1728         }
       
  1729     }
       
  1730     if (d->mCharacterSelectionPreview) {
       
  1731         d->mCharacterSelectionPreview->hide();
       
  1732     }
       
  1733 
       
  1734     d->updateGraphics(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1735     d->updateTextLayouts(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1736     update();
       
  1737 }
       
  1738 
       
  1739 /*!
       
  1740 Called when long press occurs.
       
  1741 */
       
  1742 void HbInputButtonGroup::longPressEvent()
       
  1743 {
       
  1744     Q_D(HbInputButtonGroup);
       
  1745 
       
  1746     d->longPressEvent();
       
  1747 }
       
  1748 
       
  1749 /*!
       
  1750 Updates custom buttons with custom actions.
       
  1751 
       
  1752 \sa setCustomButtonActions
       
  1753 */
       
  1754 void HbInputButtonGroup::updateCustomButtons()
       
  1755 {
       
  1756     Q_D(HbInputButtonGroup);
       
  1757 
       
  1758     d->updateCustomActions();
       
  1759     d->updateGraphics(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1760     d->updateTextLayouts(QSizeF(boundingRect().width(), boundingRect().height()));
       
  1761     update();
       
  1762 }
       
  1763 
       
  1764 // End of file