src/hbinput/inputwidgets/hbinputcandidatelist.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 
       
    26 #include <QLabel>
       
    27 #include <QGraphicsLayout>
       
    28 
       
    29 #if QT_VERSION >= 0x040600
       
    30 #include <QGraphicsDropShadowEffect>
       
    31 #endif
       
    32 
       
    33 #include <hblistwidget.h>
       
    34 #include <hblistwidgetitem.h>
       
    35 #include <hbview.h>
       
    36 #include <hbframeitem.h>
       
    37 #include <hbframedrawer.h>
       
    38 
       
    39 #include <hbdeviceprofile.h>
       
    40 
       
    41 #include <hbinputmethod.h>
       
    42 #include <hbinputsettingproxy.h>
       
    43 #include <hbinputvkbhost.h>
       
    44 
       
    45 #include "hbinputcandidatelist.h"
       
    46 
       
    47 #include "hbdialog_p.h"
       
    48 
       
    49 const int HbCandListDefaultNumRows = 5;
       
    50 const qreal HbCandListMaxWidthMultiplier = 0.8;
       
    51 const qreal HbCandListMinWidth = 30.0;
       
    52 const qreal HbAutoComplPopupSideMargin = 15.0;
       
    53 const qreal HbAutoComplPopupVerticalMargin = 15.0;
       
    54 const qreal HbAutoComplPopupMinAllowedHeight = 25.0;
       
    55 
       
    56 /// @cond
       
    57 
       
    58 class HbCandidateListPrivate : public HbDialogPrivate
       
    59 {
       
    60    Q_DECLARE_PUBLIC(HbCandidateList)
       
    61 
       
    62 public:
       
    63     HbCandidateListPrivate(HbInputMethod* input);
       
    64     ~HbCandidateListPrivate();
       
    65     void calculateAndSetSize(qreal maxWidth);
       
    66     void initFrameIcon();
       
    67 
       
    68 public: 
       
    69     HbListWidget* mList;
       
    70     HbInputMethod* mInput;
       
    71     int numRows;
       
    72     int numCandidates;
       
    73     int longestStringWidth;
       
    74     HbFrameItem *mFrameBackground;
       
    75 };
       
    76 
       
    77 HbCandidateListPrivate::HbCandidateListPrivate(HbInputMethod* input)
       
    78     : mInput(input),
       
    79       numRows(HbCandListDefaultNumRows),
       
    80       numCandidates(0),
       
    81       longestStringWidth(0),
       
    82       mFrameBackground( 0 )
       
    83 {
       
    84     Q_Q(HbCandidateList);
       
    85 
       
    86     mList = new HbListWidget(q);
       
    87 }
       
    88 
       
    89 HbCandidateListPrivate::~HbCandidateListPrivate()
       
    90 {
       
    91 //    delete mBackground;
       
    92 }
       
    93 
       
    94 void HbCandidateListPrivate::initFrameIcon()
       
    95 {
       
    96     Q_Q(HbCandidateList);
       
    97 
       
    98     mFrameBackground = static_cast<HbFrameItem*>( q->primitive( HbStyle::P_Popup_background ));
       
    99 
       
   100     if( mFrameBackground == 0 ) {
       
   101         mFrameBackground = static_cast<HbFrameItem*>( q->style()->createPrimitive(( HbStyle::Primitive )( HbStyle::P_Popup_background ), q ));
       
   102     }
       
   103 }
       
   104 
       
   105 
       
   106 void HbCandidateListPrivate::calculateAndSetSize(qreal maxWidth)
       
   107 {
       
   108     Q_Q(HbCandidateList); 
       
   109 
       
   110     const qreal oneLineHeight = 40.0;  // temporarily as a constant, eventually we'll need to calculate this.
       
   111 
       
   112     QRectF geom = q->geometry();
       
   113     qreal finalWidth = 30 + longestStringWidth * 2;    // Use magic numbers for now until we can calculate this from font.
       
   114 
       
   115     // Font has not been set yet at this point...
       
   116     /*QList<HbAbstractViewItem *>  items = mList->itemPrototypes();
       
   117     mList->adjustSize();
       
   118     HbAbstractViewItem * firstItem = items.at(0);
       
   119 
       
   120     if(firstItem){
       
   121     QFontMetrics fontMetrics(firstItem->fontSpec().font());
       
   122     finalWidth = fontMetrics.boundingRect(longestString).width();	
       
   123     }*/
       
   124 
       
   125     if (finalWidth > maxWidth) {
       
   126         finalWidth = maxWidth;
       
   127     }
       
   128 
       
   129     qreal finalHeight = geom.height();
       
   130     const int numLines = (numCandidates < numRows ? numCandidates : numRows);
       
   131     qreal l = 0, r = 0, t = 0, b = 0;
       
   132     if (q->layout()) {
       
   133         q->layout()->getContentsMargins(&l, &t, &r, &b);
       
   134     }
       
   135 
       
   136     finalWidth = finalWidth + l + r ;
       
   137     finalHeight = (qreal)numLines * oneLineHeight + 5.0 + t + b;
       
   138 
       
   139     if(finalHeight > HbDeviceProfile::current().logicalSize().height() - 30)
       
   140         finalHeight = HbDeviceProfile::current().logicalSize().height() - 30;
       
   141 
       
   142     geom.setHeight(finalHeight);
       
   143     geom.setWidth(finalWidth);
       
   144 
       
   145     q->setGeometry(geom);
       
   146 }
       
   147 
       
   148 /// @endcond
       
   149 
       
   150 /*!
       
   151 @proto
       
   152 @hbinput
       
   153 \class HbCandidateList
       
   154 \brief Hb based candidate list popup.
       
   155 
       
   156 Shows a list of word prediction candidates. Informs the owning
       
   157 input method when a word is selected
       
   158 
       
   159 \sa HbInputVkbWidget
       
   160 */
       
   161 
       
   162 
       
   163 /*!
       
   164 Constructor.
       
   165 @param input The input method that uses this widget.
       
   166 @param parent parent of the widget.
       
   167 */
       
   168 HbCandidateList::HbCandidateList(HbInputMethod* input, QGraphicsItem* parent)
       
   169     : HbDialog(*new HbCandidateListPrivate(input), parent)
       
   170 { 
       
   171     Q_D(HbCandidateList);
       
   172     
       
   173     d->setPriority(HbPopupPrivate::VirtualKeyboard + 1);  // Should be shown on top of virtual keyboard.
       
   174     d->initFrameIcon();
       
   175 
       
   176 #if QT_VERSION >= 0x040600
       
   177     // Make sure the preview pane never steals focus.
       
   178     setFlag(QGraphicsItem::ItemIsPanel, true);
       
   179     setActive(false);
       
   180 
       
   181     // enable drop shadow for the preview pane
       
   182     QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
       
   183     effect->setBlurRadius(8);
       
   184     setGraphicsEffect(effect);
       
   185 #endif
       
   186 
       
   187     setTimeout(NoTimeout);
       
   188     setAttribute(Qt::WA_InputMethodEnabled, false);
       
   189     connect(d->mList, SIGNAL(activated(HbListWidgetItem*)), this, SLOT(itemActivated(HbListWidgetItem*)));
       
   190  
       
   191     setBackgroundFaded(false);        
       
   192 }
       
   193 
       
   194 /*!
       
   195 Destroys the object.
       
   196 */
       
   197 HbCandidateList::~HbCandidateList()
       
   198 {
       
   199 }
       
   200 
       
   201 /*!
       
   202 Populates the candidate list with text strings given as parameter.
       
   203 
       
   204 @param 
       
   205 */
       
   206 void HbCandidateList::populateList(const QStringList& candidates)
       
   207 {
       
   208     Q_D(HbCandidateList);
       
   209 
       
   210     setContentWidget(d->mList);
       
   211 
       
   212     d->setPriority(HbPopupPrivate::VirtualKeyboard + 1);  // Should be shown on top of virtual keyboard.
       
   213     d->mList->clear();
       
   214 
       
   215     int longestwidth = 0;
       
   216     int finalWidth = 250;
       
   217     for (int i = 0; i < candidates.count(); i++) {
       
   218         HbListWidgetItem* item = new HbListWidgetItem();
       
   219         item->setText(candidates[i]);
       
   220         d->mList->addItem(item);
       
   221 
       
   222         // TODO: Font has not been set corretly yet...
       
   223         QFontMetrics fontMetrics(d->mList->fontSpec().font());
       
   224         finalWidth = fontMetrics.width(candidates[i]);
       
   225         if (finalWidth > longestwidth) {
       
   226             longestwidth = finalWidth;
       
   227         }
       
   228     }
       
   229 
       
   230     d->mList->setMinimumWidth(HbCandListMinWidth);
       
   231     d->numCandidates = candidates.count();
       
   232     d->longestStringWidth = longestwidth;
       
   233 
       
   234     //always scroll to first item
       
   235     d->mList->setCurrentRow(0);
       
   236     d->mList->scrollTo(d->mList->currentIndex());
       
   237 
       
   238     d->calculateAndSetSize((qreal)HbDeviceProfile::current().logicalSize().width() * HbCandListMaxWidthMultiplier);
       
   239 }
       
   240 
       
   241 /*!
       
   242 Inherited from HbDialog.
       
   243 */
       
   244 void HbCandidateList::keyPressEvent(QKeyEvent* event)
       
   245 {
       
   246     Q_D(HbCandidateList);
       
   247 
       
   248     if (event->key() == Qt::Key_Space
       
   249         || event->key() == Qt::Key_Enter
       
   250         || event->key() == Qt::Key_Return
       
   251         || event->key() == Qt::Key_Right
       
   252         || event->key() == Qt::Key_Left) {
       
   253         d->mInput->candidatePopupClosed(event->key());
       
   254         hide();
       
   255     }
       
   256 }
       
   257 
       
   258 /*!
       
   259 Inherited from HbDialog.
       
   260 */
       
   261 void HbCandidateList::closeEvent(QCloseEvent* /*event*/)
       
   262 {   
       
   263     hide();
       
   264 	emit candidatePopupCancelled();    
       
   265 }
       
   266 
       
   267 /*!
       
   268 Called when an item on the list is activated. Hides the list and informs the input.
       
   269 */
       
   270 void HbCandidateList::itemActivated(HbListWidgetItem *item)
       
   271 {
       
   272     Q_UNUSED(item);
       
   273     Q_D(HbCandidateList);
       
   274 
       
   275     d->mInput->candidatePopupClosed();    
       
   276     hide();
       
   277 }
       
   278 
       
   279 /*!
       
   280 Returns the currently selected candidate on the list.
       
   281 */
       
   282 QString HbCandidateList::currentCandidate()
       
   283 {
       
   284     Q_D(HbCandidateList);
       
   285     return d->mList->currentItem()->text();
       
   286 }
       
   287 
       
   288 /*!
       
   289 Sets the maximum number of visible candidates.
       
   290 */
       
   291 void HbCandidateList::setNumberOfVisibleLines(int numLines)
       
   292 {
       
   293     Q_D(HbCandidateList);
       
   294 
       
   295     d->numRows = numLines;
       
   296     update();
       
   297 }
       
   298 /*!
       
   299 this event handler is called, for Hide events, is delivered after the widget has been hidden.
       
   300 */
       
   301 void HbCandidateList::hideEvent(QHideEvent * event)
       
   302 {
       
   303     HbDialog::hideEvent(event);
       
   304 }
       
   305 
       
   306 void HbCandidateList::updatePrimitives()
       
   307 {
       
   308     Q_D(HbCandidateList);
       
   309 
       
   310     d->mFrameBackground->frameDrawer().setFrameType(HbFrameDrawer::NinePieces);
       
   311     d->mFrameBackground->frameDrawer().setFrameGraphicsName("qtg_fr_popup_secondary");
       
   312     d->mFrameBackground->setGeometry(boundingRect());
       
   313 }
       
   314 
       
   315 /*!
       
   316 Finds correct size and position for auto-completion popup. It checks if there is enough space to display candidate popup,
       
   317 finds out whether it is display above or below the editor and sets correct width.
       
   318 Returns true if suitable position was found and set.
       
   319 */
       
   320 bool HbCandidateList::setSizeAndPositionForAutoCompletion(HbVkbHost *vkbHost)
       
   321 {
       
   322     Q_D(HbCandidateList);
       
   323 
       
   324     if (vkbHost && d->mInput && d->mInput->focusObject()) {
       
   325         QRectF freeViewRect = vkbHost->applicationArea();
       
   326         QRectF microFocus = d->mInput->focusObject()->microFocus();
       
   327 
       
   328         if (freeViewRect.isValid() &&
       
   329             microFocus.isValid() &&
       
   330             freeViewRect.contains(microFocus)) {
       
   331             QRectF topRect = freeViewRect;
       
   332             topRect.setBottom(microFocus.top());
       
   333             topRect.adjust(HbAutoComplPopupSideMargin, HbAutoComplPopupVerticalMargin, -HbAutoComplPopupSideMargin, -HbAutoComplPopupVerticalMargin);
       
   334 
       
   335             QRectF bottomRect = freeViewRect;
       
   336             bottomRect.setTop(microFocus.bottom());
       
   337             bottomRect.adjust(HbAutoComplPopupSideMargin, HbAutoComplPopupVerticalMargin, -HbAutoComplPopupSideMargin, -HbAutoComplPopupVerticalMargin);
       
   338 
       
   339             if (topRect.height() > bottomRect.height()) {
       
   340                 if (topRect.height() > HbAutoComplPopupMinAllowedHeight) {
       
   341                     qreal finalHeight = (size().height() < topRect.height() ? size().height() : topRect.height());
       
   342                     topRect.setTop(topRect.bottom() - finalHeight);
       
   343                     resize(topRect.width(), topRect.height());
       
   344                     setPos(topRect.topLeft());
       
   345                     return true;
       
   346                 }
       
   347             } else {
       
   348               if (bottomRect.height() > HbAutoComplPopupMinAllowedHeight) {
       
   349                     qreal finalHeight = (size().height() < bottomRect.height() ? size().height() : bottomRect.height());
       
   350                     bottomRect.setHeight(finalHeight);
       
   351                     resize(bottomRect.width(), bottomRect.height());
       
   352                     setPos(bottomRect.topLeft());
       
   353                     return true;
       
   354                 }
       
   355             }
       
   356         }
       
   357     }
       
   358 
       
   359     return false;
       
   360 }
       
   361 
       
   362 // End of file