--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbplugins/inputmethods/common/hbinputpredictionhandler.cpp Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,896 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (developer.feedback@nokia.com)
+**
+** This file is part of the HbPlugins module of the UI Extensions for Mobile.
+**
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at developer.feedback@nokia.com.
+**
+****************************************************************************/
+#include <QTextCharFormat>
+#include <hbinputpredictionengine.h>
+#include <hbinputsettingproxy.h>
+#include <hbinputpredictionfactory.h>
+#include <hbinputkeymap.h>
+#include <hbinputkeymapfactory.h>
+#include <hbinputdialog.h>
+#include <hbaction.h>
+#include <hbinputvkbhost.h>
+#include <hbcolorscheme.h>
+#include <hbinpututils.h>
+#include "../touchinput/virtualqwerty.h"
+
+#include "hbinputpredictionhandler_p.h"
+#include "hbinputabstractbase.h"
+
+#define HbDeltaHeight 3.0
+
+HbInputPredictionHandlerPrivate::HbInputPredictionHandlerPrivate()
+ :mEngine(0),
+ mCandidates(0),
+ mBestGuessLocation(0),
+ mShowTail(true),
+ mTailShowing(false),
+ mAutoAddedSpace(true),
+ mCanContinuePrediction(true),
+ mShowTooltip(true)
+{
+}
+
+HbInputPredictionHandlerPrivate::~HbInputPredictionHandlerPrivate()
+{
+ if (mCandidates) {
+ delete mCandidates;
+ mCandidates = 0;
+ }
+}
+
+void HbInputPredictionHandlerPrivate::deleteOneCharacter()
+{
+ mShowTail = true;
+ mShowTooltip = true;
+ // A backspace in predictive means updating the engine for the delete key press
+ // and get the new candidate list from the engine.
+ if ((mEngine->inputLength() >= 1) || selectWord()) {
+ //Only autocomplition part should be deleted when autocompliton part is enable and user pressed a delete key
+ if(false == mTailShowing) {
+ mEngine->deleteKeyPress( this );
+ }
+ //To prevent showing autocompletion part while deleting the characters using backspace key
+ mShowTail = false;
+ mShowTooltip = false;
+ if (mEngine->inputLength() > 0) {
+ bool unused = false;
+ mEngine->updateCandidates(mBestGuessLocation, unused);
+ if (!mCandidates->count()) {
+ mCandidates->append(mEngine->currentWord());
+ }
+ }
+ mCanContinuePrediction = true;
+ // update the editor with the new preedit text.
+ updateEditor();
+ return;
+ }
+
+ HbInputFocusObject* focusedObject = 0;
+ focusedObject = mInputMethod->focusObject();
+ if (!focusedObject) {
+ return;
+ }
+
+ if ((focusedObject->inputMethodQuery(Qt::ImCursorPosition).toInt() >= 0) || focusedObject->preEditString().length()) {
+ QList<QInputMethodEvent::Attribute> list;
+ QInputMethodEvent event(QString(), list);
+ event.setCommitString(QString(), -1, 1);
+ commit(event);
+ }
+}
+
+void HbInputPredictionHandlerPrivate::commitAndAppendCharacter(QChar character)
+{
+ if (!mEngine) {
+ return;
+ }
+
+ HbInputFocusObject* focusedObject = 0;
+ focusedObject = mInputMethod->focusObject();
+ if (!focusedObject) {
+ return;
+ }
+
+ QString commitString;
+ if (mEngine->inputLength() > 0 && mCandidates->count() > 0) {
+ if(mCandidates->count() <= mBestGuessLocation) {
+ commitString = mCandidates->at(0);
+ mEngine->addUsedWord(mCandidates->at(0));
+ } else if (mShowTail == false) {
+ commitString = mCandidates->at(mBestGuessLocation).left(mEngine->inputLength());
+ mEngine->addUsedWord(mCandidates->at(mBestGuessLocation).left(mEngine->inputLength()));
+ } else {
+ commitString = mCandidates->at(mBestGuessLocation);
+ mEngine->addUsedWord(mCandidates->at(mBestGuessLocation));
+ }
+ if (character == QChar(' ') || character == QChar('\n')) {
+ mAutoAddedSpace = true;
+ }
+ commit(commitString);
+ } else {
+ mAutoAddedSpace = false;
+ }
+ commitString = character;
+ commit(commitString);
+}
+
+/*!
+Commits the candidate upon closing of the candidate list. Now can the closing key be anything other than
+just selection. Need to evaluate this. When the candidate list is visible, the current implementation of the
+candidate list does not allow the virtual keypad to be clicked.
+*/
+void HbInputPredictionHandlerPrivate::candidatePopupClosed(int closingKey, const QString& activatedText)
+{
+ if (!mEngine) {
+ return;
+ }
+
+ HbInputFocusObject* focusedObject = 0;
+ focusedObject = mInputMethod->focusObject();
+ if (!focusedObject) {
+ return;
+ }
+
+ QString commitString = activatedText;
+ if (closingKey == Qt::Key_0 || closingKey == Qt::Key_Space) {
+ commitString = activatedText+' ';
+ } else if (closingKey == Qt::Key_Enter || closingKey == Qt::Key_Return) {
+ commitString = activatedText;
+ commit(commitString);
+ commitString = '\n';
+ }
+
+ commit(commitString,true);
+}
+
+/*!
+This function shows the exact popup if needed.
+*/
+void HbInputPredictionHandlerPrivate::showExactWordPopupIfNeeded()
+{
+ Q_Q(HbInputPredictionHandler);
+ if (mShowTooltip && mBestGuessLocation > 0 && mCandidates->at(0).mid(0, mEngine->inputLength()) \
+ != mCandidates->at(mBestGuessLocation).mid(0, mEngine->inputLength())) {
+ q->processExactWord(mCandidates->at(0));
+ } else {
+ QString empty;
+ q->processExactWord(empty);
+ }
+}
+
+QList<HbKeyPressProbability> HbInputPredictionHandlerPrivate::probableKeypresses()
+{
+ if(HbInputUtils::isQwertyKeyboard(mInputMethod->inputState().keyboard())) {
+ //Useof the concrete input method implementations make the modehandlersin flexible.
+ //Later an intermediate abstract class needsto be introduced.
+ HbVirtualQwerty * qwertyInputMethod = qobject_cast<HbVirtualQwerty*>(mInputMethod);
+ if(qwertyInputMethod) {
+ return qwertyInputMethod->probableKeypresses();
+ }
+ }
+ return QList<HbKeyPressProbability>();
+}
+
+/*!
+This sets the selected candidate from the candidate list as the editor text.
+*/
+bool HbInputPredictionHandlerPrivate::selectWord(bool selectFromLeft)
+{
+ if (!mEngine) {
+ return false;
+ }
+ mShowTail = false;
+
+ HbInputFocusObject* focusedObject = 0;
+ focusedObject = mInputMethod->focusObject();
+ if(!focusedObject) {
+ return false;
+ }
+ // No word selected, if we move next to a word on left side, select it
+ int cursorPos = focusedObject->inputMethodQuery(Qt::ImCursorPosition).toInt();
+
+ QString text = focusedObject->inputMethodQuery(Qt::ImSurroundingText).toString();
+ if ((cursorPos > 0 && selectFromLeft) || (cursorPos < text.length() && !selectFromLeft)) {
+ int start;
+ int end;
+ if (selectFromLeft && cursorPos>=1 &&!text.at(cursorPos-1).isSpace()) {
+ // selecting word from left side of cursor
+ end = cursorPos;
+ for(start = end; start > 0; start--) {
+ if (text.at(start-1).isSpace()) {
+ break;
+ }
+ }
+ } else if (!selectFromLeft && !text.at(cursorPos).isSpace()) {
+ // selecting word from right side of cursor
+ start = cursorPos;
+ for(end = start; end < text.length(); ++end) {
+ if (text.at(end).isSpace()) {
+ break;
+ }
+ }
+ } else {
+ // no word in the direction where cursor is moving
+ return false;
+ }
+ int length = end-start;
+ // update internal state and editor
+ if(length > 0){
+ mEngine->setWord(text.mid(start, length), this);
+ }
+ bool unused = false;
+ mEngine->updateCandidates(mBestGuessLocation, unused);
+ //With selection we can always continue predicting, even when the selection
+ //is not a well predicted word.
+ if (!mCandidates->count()) {
+ //Here we are making sure that even if the engine does not return any candidate
+ //for given input sequence, the candidate list is non-empty. In such a scenario
+ //the candidate list will contain the actual selection or the exact word.
+ mCandidates->append(mEngine->currentWord());
+ }
+ //
+ QTextCharFormat underlined;
+ QList<QInputMethodEvent::Attribute> list;
+ underlined.setFontUnderline(true);
+ QInputMethodEvent::Attribute textstyle(QInputMethodEvent::TextFormat, 0, mEngine->inputLength(), underlined);
+ list.append(textstyle);
+ QInputMethodEvent event(mCandidates->at(0), list);
+ event.setCommitString(QString(), (selectFromLeft ? -length : 0), length);
+ focusedObject->sendEvent(event);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*!
+This method updates the editor contents based on the candidates available in the candidate list.
+*/
+void HbInputPredictionHandlerPrivate::updateEditor()
+{
+ Q_Q(HbInputPredictionHandler);
+ if (!mEngine) {
+ return;
+ }
+
+ QList<QInputMethodEvent::Attribute> list;
+ QTextCharFormat underlined;
+ HbInputFocusObject *focusedObject = 0;
+ underlined.setFontUnderline(true);
+ QInputMethodEvent::Attribute textstyle(QInputMethodEvent::TextFormat, 0, mEngine->inputLength(), underlined);
+ list.append(textstyle);
+
+ focusedObject = mInputMethod->focusObject();
+ Q_ASSERT(focusedObject);
+
+ if (mEngine->inputLength() == 0) {
+ QInputMethodEvent event(QString(), list);
+ q->sendAndUpdate(event);
+ } else {
+ if (mCandidates->count() > mBestGuessLocation) {
+ int taillength = mCandidates->at(mBestGuessLocation).length() - mEngine->inputLength();
+ if (taillength > 0 && mShowTail) {
+ // TODO: Color from skin should be used
+ QColor col = HbColorScheme::color("qtc_editor_hint_normal");
+ QBrush brush(col);
+ QTextCharFormat gray;
+ gray.setForeground(brush);
+ list.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, mEngine->inputLength(), taillength, gray));
+ list.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, mEngine->inputLength(), 0, 0));
+ QInputMethodEvent event(mCandidates->at(mBestGuessLocation), list);
+ focusedObject->sendEvent(event);
+ mTailShowing = true;
+ } else {
+ list.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, mCandidates->at(mBestGuessLocation).length(), 0, 0));
+ QInputMethodEvent event(mCandidates->at(mBestGuessLocation).left(mEngine->inputLength()), list);
+ focusedObject->sendEvent(event);
+ mTailShowing = false;
+ }
+ if (mShowTooltip && mBestGuessLocation > 0 && mCandidates->at(0).mid(0, mEngine->inputLength()) \
+ != mCandidates->at(mBestGuessLocation).mid(0, mEngine->inputLength())) {
+ q->processExactWord(mCandidates->at(0));
+ } else {
+ QString empty;
+ q->processExactWord(empty);
+ }
+ } else {
+ QInputMethodEvent event(QString(""), list);
+ focusedObject->sendEvent(event);
+ }
+ }
+}
+
+bool HbInputPredictionHandlerPrivate::filterEvent(const QKeyEvent * event)
+{
+ HbInputFocusObject* focusObject = 0;
+ focusObject = mInputMethod->focusObject();
+ //If the focused object is NULL or the key event is improper, can not continue
+ if(!focusObject || (event->key()<0)) {
+ return false;
+ }
+
+ Q_Q(HbInputPredictionHandler);
+ if (!mEngine) {
+ return false;
+ }
+
+ bool ret = false;
+ mModifiers = Qt::NoModifier;
+ mCanContinuePrediction = true;
+ switch (event->key()) {
+ case Qt::Key_Backspace:
+ case Qt::Key_Delete:
+ {
+ QString currentSelection = focusObject->inputMethodQuery(Qt::ImCurrentSelection).toString();
+ if(currentSelection.length()) {
+ QKeyEvent event = QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
+ q->sendAndUpdate(event);
+ event = QKeyEvent(QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier);
+ q->sendAndUpdate(event);
+ } else {
+ deleteOneCharacter();
+ }
+ }
+ ret = true;
+ break;
+ case Qt::Key_Period: // TODO: better handling for punctuation
+ case Qt::Key_Comma: { // Need to take fn, shift etc. in account
+ HbModifier modifier = HbModifierNone;
+ int currentTextCase = focusObject->editorInterface().textCase();
+ if ( HbTextCaseUpper == currentTextCase || HbTextCaseAutomatic == currentTextCase ) {
+ modifier = HbModifierShiftPressed;
+ }
+ QString qc;
+ const HbMappedKey* mappedKey = mKeymap->keyForKeycode(mInputMethod->inputState().keyboard(), event->key());
+
+ if (mappedKey) {
+ if (modifier == HbModifierNone) {
+ qc = mappedKey->characters(HbModifierNone).left(1);
+ } else if (modifier == HbModifierShiftPressed) {
+ qc = mappedKey->characters(HbModifierShiftPressed).left(1);
+ }
+ }
+
+ if (mEngine->inputLength() == 0) {
+ QList<QInputMethodEvent::Attribute> list;
+ QInputMethodEvent event(QString(), list);
+ if (mAutoAddedSpace) {
+ int cursorPos = mInputMethod->focusObject()->inputMethodQuery(Qt::ImCursorPosition).toInt();
+ QString text = mInputMethod->focusObject()->inputMethodQuery(Qt::ImSurroundingText).toString();
+ if (cursorPos > 0 && text.at(cursorPos-1).isSpace()) {
+ event.setCommitString(qc, -1, 1);
+ } else {
+ event.setCommitString(qc);
+ }
+ } else {
+ event.setCommitString(qc);
+ }
+ mAutoAddedSpace = false;
+ q->sendAndUpdate(event);
+ } else {
+ // Fix for input stopping after ,. keys in qwerty predictive
+ commitAndAppendCharacter(qc.at(0));
+ QString empty;
+ q->processExactWord(empty);
+ }
+ ret = true;
+ }
+ break;
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ case Qt::Key_Space:
+ case Qt::Key_0: {//Space
+ // A space means we have to commit the candidates when we are in predictive mode.
+ QChar qc(event->key());
+ if (qc == Qt::Key_Enter) {
+ qc = QChar('\n'); // Editor expects normal line feed.
+ } else if (qc == Qt::Key_0) {
+ qc = QChar(' ');
+ }
+ commitAndAppendCharacter(qc);
+ // if exact word popup functionality is on then we should inform exact word popup
+ // about the space.//++TODO
+ QString empty;
+ q->processExactWord(empty);
+ ret = true;
+ }
+ break;
+ default: {
+ mShowTail = true;
+ mShowTooltip = true;
+ mAutoAddedSpace = false;
+ if (q->HbInputModeHandler::filterEvent(event)) {
+ return true;
+ }
+ if (mEngine) {
+ int currentTextCase = focusObject->editorInterface().textCase();
+ if ( HbTextCaseUpper == currentTextCase || HbTextCaseAutomatic == currentTextCase ) {
+ mModifiers |= Qt::ShiftModifier;
+ }
+ mEngine->appendKeyPress(event->key(), mModifiers, mInputMethod->inputState().textCase(), this);
+ bool isCustomWord = false;
+ mEngine->updateCandidates(mBestGuessLocation, isCustomWord);
+ //The engine can not predict the word, it is a custom word. Now engine returns a
+ //single candidate entry which is actually the previous properly predicted character.
+ //TODO: In such a scenario, the prediction should stop and there needs to be some way for
+ //the user to tell the correct word which he wants (Some query editor). But, such a thing is
+ //not in place and hence the current implementation just appends a "?" and displays the
+ //previous word itself.
+ if (isCustomWord && mCandidates->count()) {
+ QString replacementText = mCandidates->at(0);//+"?";
+ mCandidates->clear();
+ mCandidates->append(replacementText);
+ //Since there is only one candidate, that's the best prediction.
+ mBestGuessLocation = 0;
+ }
+ //We need to check and carry out necessary steps if the engine fails to predict any candidate,
+ //for the give input sequence.
+ handleEmptyCandidateList();
+ updateEditor();
+ mInputMethod->updateState();
+ ret = true;
+ }
+ }
+ }
+
+ return ret;
+}
+
+void HbInputPredictionHandlerPrivate::keyHandlerUnicode(const QChar& character)
+{
+ if (!mEngine) {
+ return;
+ }
+ mEngine->appendCharacter(character, mInputMethod->inputState().textCase(), this);
+ bool unused = false;
+ mEngine->updateCandidates(mBestGuessLocation, unused);
+ //Check if the candidate list is empty and take necessary steps if so.
+ handleEmptyCandidateList();
+ updateEditor();
+}
+
+
+
+void HbInputPredictionHandlerPrivate::mouseHandler(int cursorPosition, QMouseEvent* mouseEvent)
+{
+ Q_Q(HbInputPredictionHandler);
+ // we are missing something we must get out.
+ if (!mEngine && !mInputMethod->focusObject()) {
+ return;
+ }
+
+ // mouse move / hover events needs to be ignored.
+ if (mouseEvent->type() != QEvent::MouseButtonPress) {
+ return;
+ }
+
+ //The mouse has been clicked outside of the pre-editing word and hence need to commit the word.
+ if ( cursorPosition < 0 || (mCandidates->size()>0 && cursorPosition >= mCandidates->at(mBestGuessLocation).length())) {
+ if (mEngine->inputLength() > 0 && mCandidates->count() > 0 && mBestGuessLocation < mCandidates->count()) {
+ commit(mCandidates->at(mBestGuessLocation),true);
+ }
+ } else if (mCandidates->size() > 0) {
+ if(!mCanContinuePrediction && (*mCandidates)[mBestGuessLocation].endsWith('?')) {
+ // mouse has been clicked on the pre-editing string ends with "?"
+ //Remove the "?" mark
+ (*mCandidates)[mBestGuessLocation].chop(1);
+ updateEditor();
+ q->processCustomWord((*mCandidates)[mBestGuessLocation]);
+ mCanContinuePrediction = true;
+ } else {
+
+ //The mouse has been clicked on the pre-editing word, launch candidate list
+ mInputMethod->launchCandidatePopup(*mCandidates);
+ }
+ }
+}
+
+void HbInputPredictionHandlerPrivate::init()
+{
+ HbInputLanguage language = HbInputSettingProxy::instance()->globalInputLanguage();
+ mEngine = HbPredictionFactory::instance()->predictionEngineForLanguage(language.language());
+ if (mEngine) {
+ mCandidates = new QStringList();
+ }
+}
+
+void HbInputPredictionHandlerPrivate::reset()
+{
+ if (mEngine) {
+ mEngine->clear();
+ }
+ if (mCandidates) {
+ mCandidates->clear();
+ }
+
+ mTailShowing = false;
+}
+
+void HbInputPredictionHandlerPrivate::commit()
+{
+ if (mEngine && mEngine->inputLength() > 0 && mCandidates->count() > 0) {
+ if(!mCanContinuePrediction) {
+ //Remove the "?" mark
+ (*mCandidates)[mBestGuessLocation].chop(1);
+ }
+
+ // Close exact word pop up in qwerty when the word is committed
+ if(HbInputUtils::isQwertyKeyboard(mInputMethod->inputState().keyboard())) {
+ mInputMethod->closeExactWordPopup();
+ }
+
+ QString commitString;
+ if(mCandidates->count() <= mBestGuessLocation) {
+ commitString = mCandidates->at(0);
+ } else if (mShowTail == false) {
+ commitString = mCandidates->at(mBestGuessLocation).left(mEngine->inputLength());
+ } else {
+ commitString = mCandidates->at(mBestGuessLocation);
+ }
+ // need to update the freq information
+ mEngine->commit(commitString);
+ commit(commitString,false);
+ }
+}
+
+/*!
+This function accepts a Qstring and commits the string to editor. This also clears all the key presses and
+candidates from prediction engine
+*/
+void HbInputPredictionHandlerPrivate::commit(const QString& string, bool addToUsedWordDict, bool isAsync)
+{
+ Q_Q(HbInputPredictionHandler);
+ if(!mCanContinuePrediction) {
+ //Remove the "?" mark
+ (*mCandidates)[mBestGuessLocation].chop(1);
+ }
+
+ // Close exact word pop up in qwerty when the word is committed
+ if(HbInputUtils::isQwertyKeyboard(mInputMethod->inputState().keyboard())) {
+ mInputMethod->closeExactWordPopup();
+ }
+
+ q->commitAndUpdate(string, 0, 0, isAsync);
+
+ if(mEngine) {
+ if(addToUsedWordDict && !string.isEmpty()) {
+ QString separator = " ";
+ QStringList stringList = string.split(separator, QString::SkipEmptyParts);
+ foreach (QString str, stringList) {
+ mEngine->addUsedWord(str);
+ }
+ }
+ mEngine->clear();
+ }
+
+ //Enable the flag after commit
+ mCanContinuePrediction = true;
+ mTailShowing = false;
+}
+
+/*!
+This function accepts a QInputMethodEvent and commits the event to editor. This also clears all the key presses and
+candidates from prediction engine
+Warning: Use this only when you want to commit some string to editor. If you want to send some formating information
+to editor, use sendAndUpdate(QInputMethodEvent & event); The reason is that, this commit function cleans prediction
+engine state also.
+*/
+void HbInputPredictionHandlerPrivate::commit(QInputMethodEvent & event,bool addToUsedWordDict)
+{
+ Q_Q(HbInputPredictionHandler);
+
+ // Close exact word pop up in qwerty when the word is committed
+ if(HbInputUtils::isQwertyKeyboard(mInputMethod->inputState().keyboard())) {
+ mInputMethod->closeExactWordPopup();
+ }
+
+ q->sendAndUpdate(event);
+
+ if(mEngine) {
+ if(addToUsedWordDict && !event.commitString().isEmpty())
+ mEngine->addUsedWord(event.commitString());
+ mEngine->clear();
+ }
+
+ //Enable the flag after commit
+ mCanContinuePrediction = true;
+ mTailShowing = false;
+
+}
+
+void HbInputPredictionHandlerPrivate::commitExactWord()
+{
+ if (mEngine && mEngine->inputLength() /*> 0 && mCandidates->count() > 0*/) {
+ commit(mCandidates->at(0), true);
+ }
+}
+
+/*!
+This function checks if the constructed candidate list is empty and if so, then
+appends a "?" mark to the best guessed candidate with put the current key input.
+*/
+void HbInputPredictionHandlerPrivate::handleEmptyCandidateList()
+{
+ if (!mCandidates->count()) {
+ QString existingWord(mEngine->currentWord());
+ int lastKeyCode = 0;
+ int lastCharacterCode = 0;
+ bool isCustomWord = false;
+ if(existingWord.length()) {
+ lastCharacterCode = existingWord[existingWord.length()-1].unicode();
+ }
+ const HbKeymap* keymap = HbKeymapFactory::instance()->keymap(HbInputSettingProxy::instance()->globalInputLanguage());
+ if(keymap) {
+ const HbMappedKey* lastKey = keymap->keyForKeycode(mInputMethod->inputState().keyboard(), lastCharacterCode);
+ if (lastKey) {
+ lastKeyCode = lastKey->keycode.unicode();
+ }
+ }
+ //Temporarily delete the key press
+ mEngine->deleteKeyPress();
+ mEngine->updateCandidates(mBestGuessLocation, isCustomWord);
+ if (mCandidates->count()){
+ (*mCandidates)[mBestGuessLocation].append("?");
+ } else {
+ //Should the mBestGuessLocation not be zero.
+ mBestGuessLocation = 0;
+ mCandidates->append(mEngine->currentWord());
+ (*mCandidates)[mBestGuessLocation].append("?");
+ }
+ //Now again append the same key press
+ if (lastKeyCode) {
+ mEngine->appendKeyPress(lastKeyCode, mModifiers, mInputMethod->inputState().textCase(), this);
+ } else {
+ mEngine->appendKeyPress(lastCharacterCode, mModifiers, mInputMethod->inputState().textCase(), this);
+ }
+ mCanContinuePrediction = false;
+ } else {
+ mCanContinuePrediction = true;
+ }
+}
+
+HbInputPredictionHandler::HbInputPredictionHandler(HbInputPredictionHandlerPrivate &dd, HbInputAbstractMethod* inputMethod)
+:HbInputModeHandler(dd, inputMethod)
+{
+ Q_D(HbInputPredictionHandler);
+ d->q_ptr = this;
+ d->init();
+}
+
+
+HbInputPredictionHandler::~HbInputPredictionHandler()
+{
+}
+
+/*!
+ Mouse handler
+*/
+void HbInputPredictionHandler::mouseHandler(int cursorPosition, QMouseEvent* mouseEvent)
+{
+ Q_D(HbInputPredictionHandler);
+ d->mouseHandler(cursorPosition, mouseEvent);
+}
+
+/*!
+ Action Handler
+*/
+bool HbInputPredictionHandler::actionHandler(HbInputModeAction action)
+{
+ Q_D(HbInputPredictionHandler);
+ bool ret = true;
+ switch (action) {
+ case HbInputModeActionReset: {
+ //At the moment we are commiting the text with the autocompletion part as it needs to be committed on clicking outside the editor.
+ //TO DO : When We back to the application by pressing Application key the inline word should not commit and remain in the inline editing
+ //d->mShowTail = false;
+ d->commit();
+ d->reset();
+ }
+ break;
+ case HbInputModeActionFocusLost: {
+ // if focus lost happens and before that if toolitip is available then typing line word should be committed in the editor
+ // if tooltip and autocompletion part is available then typing line word should be committed in the editor along with the autocompletion part
+ // Focus change should commit the auto-completed part as well.
+ d->commit();
+ }
+ break;
+ case HbInputModeActionCommit: {
+ d->commit();
+ }
+ break;
+ case HbInputModeActionDeleteAndCommit: {
+ deleteOneCharacter();
+ d->commit();
+ }
+ break;
+ case HbInputModeActionSetCandidateList: {
+ if (d->mEngine) {
+ d->mEngine->setCandidateList(d->mCandidates);
+ } else {
+ ret = false;
+ }
+ }
+ break;
+ case HbInputModeActionSetKeypad: {
+ if (d->mEngine) {
+ d->mEngine->setKeyboard(d->mInputMethod->inputState().keyboard());
+ } else {
+ ret = false;;
+ }
+ }
+ break;
+ case HbInputModeActionLaunchCandidatePopup:
+ if (d->mEngine && d->mCandidates->size()) {
+ d->mInputMethod->launchCandidatePopup(*d->mCandidates);
+ } else {
+ ret = false;
+ }
+ break;
+ case HbInputModeActionSecondaryLanguageChanged:
+ if (d->mEngine) {
+ d->mEngine->setSecondaryLanguage(HbInputSettingProxy::instance()->globalSecondaryInputLanguage());
+ }
+ break;
+ case HbInputModeActionPrimaryLanguageChanged:
+ if(!d->mEngine) {
+ d->init();
+ }
+ if (d->mEngine) {
+ d->mEngine->setLanguage(HbInputSettingProxy::instance()->globalInputLanguage());
+ }
+ break;
+ case HbInputModeActionHideTail:
+ d->mShowTail = false;
+ break;
+ default:
+ ret = HbInputModeHandler::actionHandler(action);
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ returs the true if we have something in in-line editing.
+*/
+bool HbInputPredictionHandler::isComposing()
+{
+ Q_D(HbInputPredictionHandler);
+ if (d->mEngine && d->mEngine->inputLength()>0) {
+ return true;
+ }
+ return false;
+}
+
+/*!
+ SLOT to receive input candidate popup close events.
+*/
+void HbInputPredictionHandler::candidatePopupClosed(QString activatedText, int closingKey)
+{
+ Q_D(HbInputPredictionHandler);
+ d->candidatePopupClosed(closingKey, activatedText);
+}
+
+/*!
+ SLOT to receive input qwery dialog box events.
+*/
+void HbInputPredictionHandler::inputQueryPopupClosed(QString activatedWord, int closingKey)
+{
+ Q_UNUSED(activatedWord);
+ Q_UNUSED(closingKey);
+}
+
+/*!
+ Appends a unicode character and updates the candidates and editor.
+*/
+void HbInputPredictionHandler::appendUnicodeCharacter(QChar character)
+{
+ Q_D(HbInputPredictionHandler);
+ d->keyHandlerUnicode(character);
+}
+
+/*!
+ returns supported languages in current engine.
+*/
+QList<HbInputLanguage> HbInputPredictionHandler::supportedLanguages() const
+{
+ Q_D(const HbInputPredictionHandler);
+ if (d->mEngine) {
+ return d->mEngine->languages();
+ }
+
+ return QList<HbInputLanguage>();
+}
+
+/*!
+ filterEvent function to handler key events.
+*/
+bool HbInputPredictionHandler::filterEvent(const QKeyEvent * event)
+{
+ Q_D(HbInputPredictionHandler);
+ return d->filterEvent(event);
+}
+
+/*!
+ this SLOT is called when a character in sct is selected.
+*/
+void HbInputPredictionHandler::sctCharacterSelected(QString character)
+{
+ Q_D(HbInputPredictionHandler);
+ //d->mShowTail = false;
+ d->commit();
+ HbInputModeHandler::sctCharacterSelected(character);
+}
+
+void HbInputPredictionHandler::smileySelected(QString smiley)
+{
+ Q_D(HbInputPredictionHandler);
+ d->commit();
+ HbInputModeHandler::smileySelected(smiley);
+}
+/*!
+ this function commits current pre-edit and adds a character at the end.
+*/
+void HbInputPredictionHandler::commitAndAppendCharacter(QChar character)
+{
+ Q_D(HbInputPredictionHandler);
+ d->commitAndAppendCharacter(character);
+}
+
+/*!
+ this function deletes one character and updates the engine and editor.
+*/
+void HbInputPredictionHandler::deleteOneCharacter()
+{
+ Q_D(HbInputPredictionHandler);
+ d->deleteOneCharacter();
+}
+
+void HbInputPredictionHandler::commitExactWord()
+{
+ Q_D(HbInputPredictionHandler);
+ d->commitExactWord();
+}
+
+/*!
+ * A virtual function called by the HbInputPredictionHandler when there is a exact word found
+ * and needs to to handled. Called with an empty string when there is no exact word found.
+ */
+void HbInputPredictionHandler::processExactWord(QString exactWord)
+{
+ Q_UNUSED(exactWord);
+}
+
+void HbInputPredictionHandler::processCustomWord(QString customWord)
+{
+ Q_UNUSED(customWord);
+}
+
+void HbInputPredictionHandler::showExactWordPopupIfNeeded()
+{
+ Q_D(HbInputPredictionHandler);
+ d->showExactWordPopupIfNeeded();
+}
+// EOF