src/hbplugins/inputmethods/touchinput/hbinputpredictionqwertyhandler.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 HbPlugins 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 #include <QTimer>
       
    26 #include <hbinputmethod.h>
       
    27 #include <hbinputkeymapfactory.h>
       
    28 #include <hbinputpredictionengine.h>
       
    29 
       
    30 #include "hbinputpredictionqwertyhandler.h"
       
    31 #include "hbinputpredictionhandler_p.h"
       
    32 #include "hbinputabstractbase.h"
       
    33 
       
    34 class HbInputPredictionQwertyHandlerPrivate: public HbInputPredictionHandlerPrivate
       
    35 {
       
    36     Q_DECLARE_PUBLIC(HbInputPredictionQwertyHandler)
       
    37 public:
       
    38     HbInputPredictionQwertyHandlerPrivate();
       
    39     ~HbInputPredictionQwertyHandlerPrivate();
       
    40     void deleteOneCharacter();
       
    41 
       
    42 public:
       
    43     bool buttonPressed(const QKeyEvent *event);
       
    44     bool buttonReleased(const QKeyEvent *event);
       
    45     void init();
       
    46     void _q_timeout();
       
    47 
       
    48 public:
       
    49     int mButton;    
       
    50     HbFnState mFnState;
       
    51     bool mExactPopupLaunched;
       
    52     bool mPreviewAvailable;
       
    53 };
       
    54 
       
    55 HbInputPredictionQwertyHandlerPrivate::HbInputPredictionQwertyHandlerPrivate()
       
    56 :mButton(0),    
       
    57     mFnState(HbFnOff),
       
    58     mExactPopupLaunched(false),
       
    59     mPreviewAvailable(false)
       
    60 {
       
    61 }
       
    62 
       
    63 HbInputPredictionQwertyHandlerPrivate::~HbInputPredictionQwertyHandlerPrivate()
       
    64 {
       
    65 }
       
    66 
       
    67 void HbInputPredictionQwertyHandlerPrivate::init()
       
    68 {
       
    69 }
       
    70 
       
    71 void HbInputPredictionQwertyHandlerPrivate::_q_timeout()
       
    72 {
       
    73     qDebug("HbInputPredictionQwertyHandler::timeout called");
       
    74     mTimer->stop();
       
    75     QStringList spellList;
       
    76     
       
    77 	//If long key press of shift key is received, just return
       
    78     if (mButton == Qt::Key_Shift) {
       
    79         return;
       
    80     }
       
    81     else if (mButton == Qt::Key_Control) {
       
    82         mInputMethod->selectSpecialCharacterTableMode();
       
    83     }
       
    84 
       
    85     //If long key press of shift key, space key and enter key is received, don't
       
    86     if (mButton) {
       
    87         mInputMethod->launchCharacterPreviewPane(mButton);
       
    88     }
       
    89 }
       
    90 
       
    91 
       
    92 bool HbInputPredictionQwertyHandlerPrivate::buttonReleased(const QKeyEvent *event)
       
    93 {
       
    94     Q_Q(HbInputPredictionQwertyHandler);
       
    95     HbInputFocusObject *focusObject = 0;
       
    96     focusObject = mInputMethod->focusObject();
       
    97     if (!focusObject) {
       
    98         qDebug("HbVirtualQwerty::virtualButtonClicked : no focused editor widget!");
       
    99         return false;
       
   100     }
       
   101 
       
   102     int key = event->key();
       
   103     
       
   104     // If the timer is not active and it is alpha mode, it is a long press
       
   105     // and handled in another function. So just return.
       
   106     if (mTimer->isActive()) {
       
   107         mTimer->stop();
       
   108     } else if (key == Qt::Key_Control) {
       
   109         return true;  
       
   110     } else if (!(key & 0xffff0000) && mPreviewAvailable) {
       
   111         return false;
       
   112     }
       
   113 
       
   114     bool ret = true;
       
   115     switch(key) {    
       
   116     case Qt::Key_Alt:  //Fn
       
   117         if (mFnState == HbFnOff) {
       
   118                 mFnState = HbFnNext;
       
   119             } else if (mFnState == HbFnNext) {
       
   120                 mFnState = HbFnOn;
       
   121             } else {
       
   122                 mFnState = HbFnOff;
       
   123             }
       
   124         break;
       
   125     case Qt::Key_Shift: {
       
   126 			HbTextCase currentTextCase = (HbTextCase)focusObject->editorInterface().textCase();
       
   127 			HbInputLanguage language = mInputMethod->inputState().language();
       
   128 
       
   129 			// Update the Case Information in HbInputState, it internally updates in HbEditorInterface as well
       
   130 			switch(currentTextCase) {
       
   131 			case HbTextCaseLower:
       
   132 				// For Case-insensitive languages, Shift Key is used to switch between character sets (i.e lower case characters and shifted characters)
       
   133 				if(!language.isCaseSensitiveLanguage()){
       
   134 					currentTextCase = HbTextCaseUpper; 
       
   135 				}
       
   136 				else {
       
   137 					currentTextCase = HbTextCaseAutomatic;
       
   138 				}
       
   139 				break;				
       
   140 			case HbTextCaseUpper:	
       
   141 				currentTextCase = HbTextCaseLower;				
       
   142 				break;
       
   143             case HbTextCaseAutomatic:
       
   144 				currentTextCase = HbTextCaseUpper;				                
       
   145                 break;
       
   146             default:
       
   147                 break;
       
   148             }
       
   149 			HbInputState state = mInputMethod->inputState();
       
   150 			state.setTextCase(currentTextCase);			
       
   151 			mInputMethod->activateState(state);
       
   152         }
       
   153         break;
       
   154     case Qt::Key_Control: { // Ctrl/Chr
       
   155             mInputMethod->switchSpecialCharacterTable();
       
   156         }
       
   157         break;
       
   158     default: {
       
   159             HbTextCase currentTextCase = focusObject->editorInterface().textCase();
       
   160             Qt::KeyboardModifiers modifiers = Qt::NoModifier;
       
   161             if (mFnState == HbFnNext) {
       
   162                 modifiers |= Qt::AltModifier;
       
   163                 mFnState = HbFnOff;
       
   164             } else if (mFnState == HbFnOn) {
       
   165                 modifiers |= Qt::AltModifier;
       
   166             }
       
   167             // If shift is pressed, the shifted characters have to be input.
       
   168             if ( HbTextCaseUpper == currentTextCase || HbTextCaseAutomatic == currentTextCase ) {
       
   169                 modifiers |= Qt::ShiftModifier;
       
   170             }
       
   171 
       
   172             // let's pass it to the base class.
       
   173             ret = q->HbInputPredictionHandler::filterEvent(event);
       
   174 
       
   175             mInputMethod->updateState();
       
   176         }
       
   177         break;
       
   178     };
       
   179     return ret;
       
   180 }
       
   181 
       
   182 bool HbInputPredictionQwertyHandlerPrivate::buttonPressed(const QKeyEvent *event)
       
   183 {
       
   184     mButton = event->key();
       
   185     mTimer->start(HbLongPressTimerTimeout);
       
   186     mPreviewAvailable = false;
       
   187     return false;
       
   188 }
       
   189 
       
   190 
       
   191 HbInputPredictionQwertyHandler::HbInputPredictionQwertyHandler(HbInputAbstractMethod *inputMethod)
       
   192     :HbInputPredictionHandler(* new HbInputPredictionQwertyHandlerPrivate, inputMethod)
       
   193 {
       
   194     Q_D(HbInputPredictionQwertyHandler);
       
   195     d->q_ptr = this;
       
   196     d->init();
       
   197 }
       
   198 
       
   199 HbInputPredictionQwertyHandler::~HbInputPredictionQwertyHandler()
       
   200 {
       
   201 }
       
   202 
       
   203 /*!
       
   204 lists different input mode bindings..
       
   205 */
       
   206 void HbInputPredictionQwertyHandler::listInputModes(QVector<HbInputModeProperties>& modes) const
       
   207 {
       
   208     Q_UNUSED(modes); 
       
   209 }
       
   210 
       
   211 /*!
       
   212 Action Handler.
       
   213 */
       
   214 bool HbInputPredictionQwertyHandler::actionHandler(HbInputModeAction action)
       
   215 {
       
   216     Q_D(HbInputPredictionQwertyHandler);
       
   217     bool ret = true;
       
   218     switch (action) {
       
   219         case HbInputModeActionCancelButtonPress:
       
   220         case HbInputModeActionReset:
       
   221             if (d->mTimer->isActive()) {
       
   222                 d->mTimer->stop();
       
   223             }
       
   224             break;
       
   225         case HbInputModeActionFocusRecieved:
       
   226             HbInputPredictionHandler::actionHandler(HbInputModeActionSetCandidateList);
       
   227             HbInputPredictionHandler::actionHandler(HbInputModeActionSetKeypad);
       
   228             d->mTimer->stop();
       
   229             break;
       
   230         case HbInputModeActionFocusLost:
       
   231             HbInputPredictionHandler::actionHandler(HbInputModeActionFocusLost);
       
   232 
       
   233             //TODO
       
   234             /*
       
   235             if (d->mExactPopupLaunched) {
       
   236                 sendCommitString(d->mCandidates->at(1));
       
   237             } else {
       
   238                 sendCommitString(d->mCandidates->at(0));
       
   239             }
       
   240             */
       
   241             // close exactword popup.
       
   242             d->mInputMethod->closeExactWordPopup();
       
   243             break;
       
   244         case HbInputModeActionCommit: {   
       
   245 			d->commit();        
       
   246 		}
       
   247         default: ret = HbInputPredictionHandler::actionHandler(action);
       
   248     }
       
   249     return ret;
       
   250 }
       
   251 
       
   252 /*!
       
   253 filterEvent for key event.
       
   254 */
       
   255 bool HbInputPredictionQwertyHandler::filterEvent(const QKeyEvent * event)
       
   256 {
       
   257     Q_D(HbInputPredictionQwertyHandler);
       
   258 
       
   259     if (event->type() == QEvent::KeyRelease) {
       
   260         return d->buttonReleased(event);
       
   261     } else {
       
   262         return d->buttonPressed(event);
       
   263     }
       
   264 }
       
   265 
       
   266 /*!
       
   267 Commits the word and closes the exact popup if it is visible.
       
   268 */
       
   269 void HbInputPredictionQwertyHandler::commitAndUpdate(const QString& string, int replaceFrom, int replaceLength)
       
   270 {
       
   271     Q_D(HbInputPredictionQwertyHandler);
       
   272     HbInputModeHandler::commitAndUpdate(string, replaceFrom, replaceLength);
       
   273     d->mInputMethod->closeExactWordPopup();
       
   274     d->mExactPopupLaunched = false;  
       
   275 	d->mTailShowing = false;
       
   276 }
       
   277 
       
   278 /*!
       
   279     this function deletes one character and updates the engine and editor.
       
   280 */
       
   281 void HbInputPredictionQwertyHandler::deleteOneCharacter()
       
   282 {
       
   283     Q_D(HbInputPredictionHandler);
       
   284     d->deleteOneCharacter();
       
   285 }
       
   286 
       
   287 /*!
       
   288 this SLOT is called when a character on character previe pane is selected.
       
   289 */
       
   290 void HbInputPredictionQwertyHandler::charFromPreviewSelected(QString character)
       
   291 {
       
   292 	Q_D(HbInputPredictionQwertyHandler);
       
   293     if(character.size() > 0) {
       
   294         appendUnicodeCharacter(character[0]);
       
   295 		d->mInputMethod->updateState();
       
   296     }
       
   297 }
       
   298 
       
   299 /*!
       
   300  this function is called by HbPredictionHandler when HbPredictionHandler encounters a exact word.
       
   301 */
       
   302 void HbInputPredictionQwertyHandler::processExactWord(QString exactWord)
       
   303 {
       
   304     Q_D(HbInputPredictionQwertyHandler);
       
   305     if (exactWord.size()) {
       
   306         d->mInputMethod->launchExactWordPopup(exactWord);
       
   307         d->mExactPopupLaunched = true;
       
   308     } else {
       
   309         d->mInputMethod->closeExactWordPopup();
       
   310         d->mExactPopupLaunched = false;
       
   311     }
       
   312 }
       
   313 
       
   314 /*!
       
   315  this slot should be called when exact word popup is closed.
       
   316 */
       
   317 void HbInputPredictionQwertyHandler::exactWordPopupClosed()
       
   318 {
       
   319     commitExactWord();
       
   320 }
       
   321 
       
   322 void HbInputPredictionQwertyHandler::sctCharacterSelected(QString character)
       
   323 {	
       
   324     HbInputPredictionHandler::sctCharacterSelected(character);
       
   325 }
       
   326 
       
   327 void HbInputPredictionQwertyHandler::smileySelected(QString smiley)
       
   328 {
       
   329     HbInputPredictionHandler::smileySelected(smiley);
       
   330 }
       
   331 void HbInputPredictionQwertyHandler::characterPreviewAvailable(bool available)
       
   332 {
       
   333     Q_D(HbInputPredictionQwertyHandler);
       
   334     d->mPreviewAvailable = available;
       
   335 }
       
   336 
       
   337 /*!
       
   338 Returns true if preidciton engine is available and initialized.
       
   339 */
       
   340 bool HbInputPredictionQwertyHandler::isActive() const
       
   341 { 
       
   342     Q_D(const HbInputPredictionQwertyHandler);
       
   343     return d->mEngine != 0;
       
   344 }
       
   345 
       
   346 void HbInputPredictionQwertyHandlerPrivate::deleteOneCharacter()
       
   347 {
       
   348     mShowTail = true;
       
   349     mShowTooltip = true;
       
   350     // A backspace in predictive means updating the engine for the delete key press
       
   351     // and get the new candidate list from the engine.
       
   352     if ((mEngine->inputLength() >= 1) || selectWord()) {
       
   353         //Only autocomplition part should be deleted when autocompliton part is enable and user pressed a delete key
       
   354         //To prevent showing autocompletion part while deleting the characters using backspace key
       
   355         mShowTail = false;
       
   356         mShowTooltip = false;
       
   357         //The assumption here is that with deletion of a character we always
       
   358         //can go on with prediction. This is because when we delete a key press
       
   359         //we actually reduce ambiguity in the engine and hence we should have
       
   360         //some word getting predicted as a result to that.
       
   361         mCanContinuePrediction = true;
       
   362         if (true == mExactPopupLaunched) {			
       
   363 			QString exactWord = mCandidates->at(0);
       
   364 			mEngine->setWord(exactWord);	
       
   365 			mCandidates->clear();
       
   366 			mCandidates->append(exactWord);
       
   367 			mBestGuessLocation = 0 ;
       
   368 		} 
       
   369 		if(false == mTailShowing && true == mExactPopupLaunched) {
       
   370 				mEngine->deleteKeyPress();				
       
   371 		}
       
   372         //When there is a deletion of key press, no need to update the candidate list
       
   373         //This is because deletion should not cause reprediction.
       
   374 		if(mCandidates->count() && (mCandidates->count()>mBestGuessLocation) && false == mTailShowing && false == mExactPopupLaunched) {
       
   375 		    QString currentWord = mCandidates->at(mBestGuessLocation);
       
   376 			if(currentWord.length() > mEngine->inputLength()) {
       
   377 				//chop off the autocompletion part
       
   378 				currentWord = currentWord.left(mEngine->inputLength());
       
   379 			}
       
   380 		    if(currentWord.length()) {
       
   381                 currentWord.chop(1);
       
   382 		        mEngine->deleteKeyPress();
       
   383 				//We are not supposed to re-construct the candidate list as deletion
       
   384 				//does not cause reprediction. Also, candidate list construction is the
       
   385 				//heaviest operation out of all engine operations.
       
   386 				(*mCandidates)[mBestGuessLocation] = currentWord;
       
   387 		    } else {
       
   388 		        commit(QString(""),false);
       
   389 		    }
       
   390 		        
       
   391 		} else if(!mCandidates->count()) {
       
   392             mCandidates->append(mEngine->currentWord());
       
   393         }
       
   394         // update the editor with the new preedit text.
       
   395         updateEditor();
       
   396         return;
       
   397     }
       
   398 
       
   399     HbInputFocusObject* focusedObject = 0;
       
   400     focusedObject = mInputMethod->focusObject();
       
   401     if (!focusedObject) {
       
   402         return;
       
   403     }
       
   404 
       
   405     if ((focusedObject->inputMethodQuery(Qt::ImCursorPosition).toInt() >= 0) || focusedObject->preEditString().length()) {
       
   406         QList<QInputMethodEvent::Attribute> list;
       
   407         QInputMethodEvent event(QString(), list);
       
   408         event.setCommitString(QString(), -1, 1);
       
   409         commit(event);
       
   410     }
       
   411 }
       
   412 
       
   413 //EOF