src/hbinput/inputwidgets/hbinputcharpreviewpane.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     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 // Qt includes
       
    26 #include <QGraphicsLinearLayout>
       
    27 #include <QSignalMapper>
       
    28 #include <QPainter>
       
    29 #include <QSizePolicy>
       
    30 
       
    31 #if QT_VERSION >= 0x040600
       
    32 #include <QGraphicsDropShadowEffect>
       
    33 #endif
       
    34 
       
    35 #include <hbeffect.h>
       
    36 #include <hbinputsettingproxy.h>
       
    37 #include <hbmainwindow.h>
       
    38 #include <hbcolorscheme.h>
       
    39 #include <hbframedrawer.h>
       
    40 #include <hbframeitem.h>
       
    41 #include <hbdeviceprofile.h>
       
    42 #include <private/hbdialog_p.h>
       
    43 #include <hbtextitem.h>
       
    44 #include <hbmainwindow.h>
       
    45 #include <hbinstance.h>
       
    46 
       
    47 #include "hbinputpreviewlabel.h"
       
    48 #include "hbinputcharpreviewpane.h"
       
    49 
       
    50 const int HbPreviewZoomDelta = 7;
       
    51 const qreal HbPreviewBoundaryDelta = 1.5;
       
    52 const qreal HbBoundaryLabelWidthFactor = 0.75;
       
    53 const qreal HbLabelwidthFactor = 0.50;
       
    54 /// @cond
       
    55 
       
    56 /*
       
    57 Character preview widget for Accented characters.
       
    58 Implements character preview for characters mapped in the preview Pane.
       
    59 */
       
    60 class HbAccentedCharPreviewPane: public HbWidget
       
    61 {
       
    62 public:
       
    63     /*!
       
    64     Constructor.
       
    65     @param parent of the widget.
       
    66     */
       
    67     HbAccentedCharPreviewPane(QGraphicsItem *parent = 0)
       
    68         :HbWidget(parent),
       
    69         mFramePrim(0),
       
    70         mTextItem(0)
       
    71     {
       
    72         mFramePrim = static_cast<HbFrameItem*>(style()->createPrimitive(HbStyle::P_Popup_background, this));
       
    73         mTextItem = static_cast<HbTextItem*>(style()->createPrimitive(HbStyle::P_Label_text, this));
       
    74     }
       
    75     /*!
       
    76     update the text and frame primitives
       
    77     */
       
    78     void updatePrimitives()
       
    79     {
       
    80         if (mFramePrim) {
       
    81             mFramePrim->frameDrawer().setFrameType(HbFrameDrawer::ThreePiecesHorizontal);
       
    82             mFramePrim->frameDrawer().setFrameGraphicsName("qtg_fr_character_preview");
       
    83             mTextItem->setFontSpec(HbFontSpec(HbFontSpec::Primary));
       
    84             mTextItem->setAlignment(Qt::AlignCenter);
       
    85         }
       
    86     }
       
    87     /*!
       
    88     Destroys the object.
       
    89     */
       
    90     ~HbAccentedCharPreviewPane() {
       
    91     }
       
    92 public:
       
    93     HbFrameItem* mFramePrim;
       
    94     HbTextItem* mTextItem;
       
    95 };
       
    96 
       
    97 class HbCharPreviewPanePrivate: public HbDialogPrivate
       
    98 {
       
    99     Q_DECLARE_PUBLIC(HbCharPreviewPane)
       
   100 
       
   101 public:
       
   102     HbCharPreviewPanePrivate();
       
   103     ~HbCharPreviewPanePrivate();
       
   104     void clearCharacters();
       
   105     void updateCharacters();
       
   106     void init();
       
   107 
       
   108 // private slots
       
   109     void _q_showAccentedPreviewPane(QString character, QRectF sceneBoundingRect);
       
   110     void _q_hideAccentedPreviewPane();
       
   111     void _q_hidePreviewPanePopup();
       
   112 public:
       
   113     QStringList mCharacterList;
       
   114     QSignalMapper *mReleaseMapper;
       
   115     QGraphicsLinearLayout* mCandLayout;
       
   116     HbFrameItem* mFramePrim;
       
   117     QSizeF mItemSize;
       
   118     HbAccentedCharPreviewPane* mAccentedPreviewPane;
       
   119 };
       
   120 
       
   121 void HbCharPreviewPanePrivate::init()
       
   122 {
       
   123     Q_Q(HbCharPreviewPane);
       
   124     mFramePrim = static_cast<HbFrameItem*>(q->primitive(HbStyle::P_Popup_background));
       
   125 
       
   126     if (!mFramePrim) {
       
   127         mFramePrim = static_cast<HbFrameItem*>(q->style()->createPrimitive(HbStyle::P_Popup_background, q));
       
   128     }
       
   129 }
       
   130 
       
   131 HbCharPreviewPanePrivate::HbCharPreviewPanePrivate()
       
   132     : mReleaseMapper(0),
       
   133     mCandLayout(0),
       
   134     mFramePrim(0)
       
   135 {
       
   136     mAccentedPreviewPane = new HbAccentedCharPreviewPane();
       
   137 }
       
   138 
       
   139 HbCharPreviewPanePrivate::~HbCharPreviewPanePrivate()
       
   140 {
       
   141     if(mAccentedPreviewPane) {
       
   142         delete mAccentedPreviewPane;
       
   143     }
       
   144     if(mReleaseMapper) {
       
   145         delete mReleaseMapper;
       
   146     }
       
   147 }
       
   148 
       
   149 void HbCharPreviewPanePrivate::clearCharacters()
       
   150 {
       
   151     Q_Q(HbCharPreviewPane);
       
   152     for (int i = mCandLayout->count() - 1; i >= 0; i--) {
       
   153         QGraphicsLayoutItem* layoutitem = mCandLayout->itemAt(i);
       
   154         mCandLayout->removeAt(i);
       
   155         delete layoutitem;
       
   156     }
       
   157     mCandLayout->updateGeometry();
       
   158     q->adjustSize();
       
   159 }
       
   160 
       
   161 void HbCharPreviewPanePrivate::updateCharacters()
       
   162 {
       
   163     Q_Q(HbCharPreviewPane);
       
   164 	// need to set the minimum size to an invalid value here in order to make sure that the size does not become 0
       
   165 	mCandLayout->setMinimumSize(-1,-1);
       
   166     for (int i = 0; i < mCharacterList.count(); i++) {
       
   167         HbPreviewLabel* label = new HbPreviewLabel(mCharacterList[i]);
       
   168         label->setPreferredHeight(mItemSize.height() + HbPreviewZoomDelta);
       
   169         if (mCharacterList.count() > 1 && i != mCharacterList.count()-1) {
       
   170             label->setPreferredWidth(HbBoundaryLabelWidthFactor * mItemSize.width());
       
   171             label->setTextGeometry(mItemSize.width(), mItemSize.height());
       
   172         } else {
       
   173             label->setPreferredWidth(HbLabelwidthFactor * mItemSize.width());
       
   174             label->setTextGeometry(mItemSize.width(), mItemSize.height());
       
   175         }
       
   176 
       
   177         QObject::connect(label, SIGNAL(showAccentedPreview(QString,QRectF)), q, SLOT(_q_showAccentedPreviewPane(QString,QRectF)));
       
   178         QObject::connect(label, SIGNAL(selected()), mReleaseMapper, SLOT(map()));
       
   179         QObject::connect(label, SIGNAL(hideAccentedPreview()), q, SLOT(_q_hideAccentedPreviewPane()));
       
   180         QObject::connect(label, SIGNAL(hidePreview()), q, SLOT(_q_hidePreviewPanePopup()));
       
   181         mReleaseMapper->setMapping(label, mCharacterList[i]);
       
   182         mCandLayout->addItem(label);
       
   183         mCandLayout->setItemSpacing(i, 0.0);
       
   184     }
       
   185 
       
   186     mCandLayout->setContentsMargins(mItemSize.width() / 4, 0, mItemSize.width() / 4, 0);
       
   187     mCandLayout->updateGeometry();
       
   188     q->adjustSize();
       
   189 }
       
   190 /*!
       
   191 Sets the character for preview and shows in it's Pane.
       
   192 @param character The character for preview.
       
   193 @param itemSceneBoundingRect of the QGraphicsItem.
       
   194 */
       
   195 void HbCharPreviewPanePrivate::_q_showAccentedPreviewPane(QString character, QRectF itemSceneBoundingRect)
       
   196 {
       
   197     Q_Q(HbCharPreviewPane);
       
   198     mAccentedPreviewPane->setZValue(q->zValue()+1);
       
   199     q->scene()->addItem(mAccentedPreviewPane);
       
   200     // let's validate.
       
   201     if (!itemSceneBoundingRect.isValid()) {
       
   202         return;
       
   203     }
       
   204 	QColor color = HbColorScheme::color("qtc_editor_normal");
       
   205     // we need to show the accented char preview preview just above the
       
   206     // passed QRectF of the item which is passed.
       
   207     QPointF pos = itemSceneBoundingRect.topLeft();
       
   208     pos.setY(pos.y() - mItemSize.height() +  HbPreviewZoomDelta + HbPreviewBoundaryDelta);
       
   209 
       
   210     // let's adjust x position of the character preview pane so that it
       
   211     // is aligned at the center of the items for which we want to show
       
   212     // the preview.
       
   213     pos.setX(itemSceneBoundingRect.x() - itemSceneBoundingRect.width()/4);
       
   214 
       
   215     // set final position for the character preview pane
       
   216     mAccentedPreviewPane->setPos(pos);
       
   217     mAccentedPreviewPane->mTextItem->setText(character);
       
   218     if (color.isValid()) {
       
   219         mAccentedPreviewPane->mTextItem->setTextColor(color);
       
   220     }
       
   221     mAccentedPreviewPane->updatePrimitives();
       
   222     QSizeF paneSize = itemSceneBoundingRect.size();
       
   223     QRectF rect;
       
   224     rect.setWidth(HbBoundaryLabelWidthFactor * mItemSize.width());
       
   225     rect.setHeight(mItemSize.height());
       
   226     rect.setY(paneSize.height()/2 - mItemSize.height()/2 - HbPreviewZoomDelta - HbPreviewBoundaryDelta);
       
   227     mAccentedPreviewPane->mTextItem->setGeometry(rect);
       
   228 
       
   229     // show it!
       
   230     mAccentedPreviewPane->show();
       
   231 }
       
   232 /*
       
   233 hides the accented single character preview pane whenever user tries to hover on it
       
   234 as the the character is inputed in the editor only when mouse is released from preview pane
       
   235 */
       
   236 void HbCharPreviewPanePrivate::_q_hideAccentedPreviewPane()
       
   237 {
       
   238     mAccentedPreviewPane->hide();
       
   239 }
       
   240 
       
   241 /*
       
   242 hides the accented single character preview pane as well as charcters Preview Pane
       
   243 */
       
   244 void HbCharPreviewPanePrivate::_q_hidePreviewPanePopup()
       
   245 {
       
   246     Q_Q(HbCharPreviewPane);
       
   247     mAccentedPreviewPane->hide();
       
   248     if (q->isVisible()) {
       
   249         q->hide();
       
   250     }
       
   251 }
       
   252 
       
   253 /// @endcond
       
   254 
       
   255 /*!
       
   256 @proto
       
   257 @hbinput
       
   258 \class HbCharPreviewPane
       
   259 \brief Character preview widget for virtual keyboards.
       
   260 
       
   261 
       
   262 Implements character preview for virtual keyboards. Shows a list of clickable
       
   263 characters and maps the clicks to owning keyboard's charFromPreviewSelected slot.
       
   264 For first level of preview popup we have a linear layout, we create a HbPreviewLabel
       
   265 and add the labels to this layout. For second level of preview popup as user clicks
       
   266 on the lebel of preview pane we display preview of the accented character on the preview pane.
       
   267 
       
   268 \sa HbInputVkbWidget
       
   269 \sa HbPreviewLabel
       
   270 */
       
   271 /*!
       
   272 Constructor.
       
   273 @param parent of the widget.
       
   274 */
       
   275 HbCharPreviewPane::HbCharPreviewPane(QGraphicsItem* parent)
       
   276     : HbDialog(*new HbCharPreviewPanePrivate, parent)
       
   277 {
       
   278     Q_D(HbCharPreviewPane);
       
   279 
       
   280     d->q_ptr = this;
       
   281 
       
   282     d->mCandLayout = new QGraphicsLinearLayout(Qt::Horizontal);
       
   283     setLayout(d->mCandLayout);
       
   284 
       
   285     d->setPriority(HbPopupPrivate::VirtualKeyboard + 1);  // Should be visible on top of VKB
       
   286 
       
   287     // set some properties
       
   288     setFocusPolicy(Qt::ClickFocus);
       
   289     setModal(false);
       
   290     setDismissPolicy(HbPopup::TapAnywhere);
       
   291     setBackgroundFaded(false);
       
   292 
       
   293 #if QT_VERSION >= 0x040600
       
   294     // Make sure the preview pane never steals focus.
       
   295     setFlag(QGraphicsItem::ItemIsPanel, true);
       
   296     setActive(false);
       
   297 
       
   298     // enable drop shadow for the preview pane
       
   299     QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
       
   300     effect->setBlurRadius(8);
       
   301     setGraphicsEffect(effect);
       
   302 #endif
       
   303 
       
   304     // signal mapper for getting events
       
   305     d->mReleaseMapper = new QSignalMapper(this);
       
   306 
       
   307     QObject::connect(d->mReleaseMapper, SIGNAL(mapped(QString)), this, SIGNAL(charFromPreviewSelected(QString)));
       
   308     setTimeout(NoTimeout);
       
   309     d->init();
       
   310 
       
   311     // This is important we need to switch off all the effects.
       
   312     // if we dont switch off the effect, and if there is a call to 'show' while a 'hide' animation is
       
   313     // in progress the hide call will be ignored.
       
   314     // this will lead to a problem where we will not able to see all the character
       
   315     // preview in case the user is typing very fast.
       
   316 #ifdef HB_EFFECTS
       
   317     HbEffect::disable(this);
       
   318 #endif // HB_EFFECTS
       
   319 }
       
   320 
       
   321 /*!
       
   322 Destroys the object.
       
   323 */
       
   324 HbCharPreviewPane::~HbCharPreviewPane()
       
   325 {
       
   326 }
       
   327 
       
   328 /*!
       
   329 Sets the list of characters for preview.
       
   330 @param characterList The character preview list.
       
   331 @param itemSceneBoundingRect of the QGraphicsItem.
       
   332 */
       
   333 void HbCharPreviewPane::showCharacters(const QStringList& characterList, const QRectF &itemSceneBoundingRect)
       
   334 {
       
   335     Q_D(HbCharPreviewPane);
       
   336     // let's validate.
       
   337     if (!itemSceneBoundingRect.isValid()) {
       
   338         return;
       
   339     }
       
   340 
       
   341     if (characterList.size() > 1) {
       
   342         setModal(true);
       
   343     } else {
       
   344         setModal(false);
       
   345     }
       
   346 
       
   347     d->mCharacterList = characterList;
       
   348     // let's store items size.
       
   349     d->mItemSize = itemSceneBoundingRect.size();
       
   350 
       
   351     // we need to clear previous character.
       
   352     d->clearCharacters();
       
   353 
       
   354     // update new candidates
       
   355     d->updateCharacters();
       
   356 
       
   357     updateGeometry();
       
   358 
       
   359     // we need to show the preview just above the
       
   360     // passed QRectF of the item which is passed.
       
   361     QPointF pos = itemSceneBoundingRect.topLeft();
       
   362     pos.setY(pos.y() - size().height());
       
   363 
       
   364     // let's adjust x position of the character preview pane so that it
       
   365     // is aligned at the center of the items for which we want to show
       
   366     // the preview.
       
   367     pos.setX(itemSceneBoundingRect.center().x() - size().width()/2);
       
   368 
       
   369     // We need to adjust the character preview pane's postion
       
   370     // such that it is visible in in the current screen.
       
   371     if (pos.x() < 0) {
       
   372         pos.setX(0);
       
   373     } else {
       
   374         const int screenWidth = HbDeviceProfile::profile(this).logicalSize().width();
       
   375         const qreal requiredWidth = pos.x() + (geometry().width());
       
   376         if ( requiredWidth > screenWidth) {
       
   377             pos.setX(screenWidth-(geometry().width()));
       
   378         }
       
   379     }
       
   380 
       
   381     // set final position for the character preview pane
       
   382     setPos(pos);
       
   383 
       
   384     // we need to reset mousePressLocation to None.
       
   385     // We are handling character preview pane a bit differently than a usual popup.
       
   386     // A HbDialog closes the popup on a mouse release. And there is a problem  when we
       
   387     // have long pressed on a button and the preview pane is showing  set of characters,
       
   388     // same time if we do a long press on another button preview will be shown on the next
       
   389     // button but as soon as we release the button HbDialog's internal logic closes the
       
   390     // preview pane. since popup closes on mouse release event. To aviod this situation we
       
   391     // need to reset mousePressLocation. Since this behaviour is very specific to preview pane
       
   392     // we need to fix it here.
       
   393     d->mousePressLocation = HbPopupPrivate::None;
       
   394 
       
   395     // show it!
       
   396     show();
       
   397 }
       
   398 
       
   399 void HbCharPreviewPane::updatePrimitives()
       
   400 {
       
   401     Q_D(HbCharPreviewPane);
       
   402     d->mFramePrim->frameDrawer().setFrameType(HbFrameDrawer::ThreePiecesHorizontal);
       
   403     d->mFramePrim->frameDrawer().setFrameGraphicsName("qtg_fr_character_preview");
       
   404     d->mFramePrim->setGeometry(boundingRect());
       
   405 }
       
   406 
       
   407 #include "moc_hbinputcharpreviewpane.cpp"
       
   408 // End Of File