--- a/src/hbplugins/inputmethods/common/hbinputpredictionhandler.cpp Thu Jul 15 14:03:49 2010 +0100
+++ b/src/hbplugins/inputmethods/common/hbinputpredictionhandler.cpp Thu Jul 22 16:36:53 2010 +0100
@@ -39,17 +39,17 @@
#include "hbinputpredictionhandler_p.h"
#include "hbinputabstractbase.h"
-#define HbDeltaHeight 3.0
+static const qreal HbDeltaHeight = 3.0;
HbInputPredictionHandlerPrivate::HbInputPredictionHandlerPrivate()
:mEngine(0),
mCandidates(0),
mBestGuessLocation(0),
mShowTail(true),
- mTailShowing(false),
mAutoAddedSpace(true),
mCanContinuePrediction(true),
- mShowTooltip(true)
+ mShowTooltip(true),
+ mSpellQueryDialog(0)
{
}
@@ -63,13 +63,17 @@
void HbInputPredictionHandlerPrivate::deleteOneCharacter()
{
+ if (!mEngine && !mInputMethod->focusObject()) {
+ return;
+ }
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 ) {
- //Only autocomplition part should be deleted when autocompliton part is enable and user pressed a delete key
- if(false == mTailShowing) {
+ int tailLength = mInputMethod->focusObject()->preEditString().length() - mEngine->inputLength();
+ //Only autocomplition part should be deleted when autocompliton part is shown and user pressed a delete key
+ if(tailLength <= 0) { // no autocompletion part displayed
mEngine->deleteKeyPress( this );
}
//To prevent showing autocompletion part while deleting the characters using backspace key
@@ -112,16 +116,8 @@
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));
- }
+ commitString = getCommitString();
+ mEngine->addUsedWord(commitString);
if (character == QChar(' ') || character == QChar('\n')) {
mAutoAddedSpace = true;
}
@@ -167,14 +163,6 @@
*/
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()
@@ -222,16 +210,21 @@
QBrush brush(col);
QTextCharFormat gray;
gray.setForeground(brush);
- list.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, mEngine->inputLength(), taillength, gray));
+ if((focusedObject->object())->inherits("QGraphicsWebView") || (focusedObject->object())->inherits("QWebView")) {
+ //QGraphicsWebView does not handle partial input length formatting well. Causes crash, a temporary fix provided,
+ //This makes the whole text field grey insted of just the auto-completion part. Anyways, it does not cause crash.
+ //This should be treated as a work around till QGraphicsWebView is fixed.
+ list.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, QInputMethodEvent::TextFormat, gray));
+ } else {
+ 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())) {
@@ -252,7 +245,8 @@
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)) {
+ if(!focusObject || event->key() < 0 ||
+ event->key() == HbInputButton::ButtonKeyCodeCustom) {
return false;
}
@@ -280,59 +274,16 @@
}
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 HbInputButton::ButtonKeyCodeEnter:
case HbInputButton::ButtonKeyCodeSpace:
- 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
@@ -415,18 +366,15 @@
}
//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);
- }
+ if ( cursorPosition < 0 || cursorPosition >= mInputMethod->focusObject()->preEditString().length()) {
+ commit();
} else if (mCandidates->size() > 0) {
if(!mCanContinuePrediction && (*mCandidates)[mBestGuessLocation].endsWith('?')) {
- // mouse has been clicked on the pre-editing string ends with "?"
+ // 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;
+ q->launchSpellQueryDialog();
} else {
//The mouse has been clicked on the pre-editing word, launch candidate list
@@ -437,7 +385,7 @@
void HbInputPredictionHandlerPrivate::init()
{
- mEngine = NULL;
+ mEngine = 0;
HbInputLanguage language = HbInputSettingProxy::instance()->globalInputLanguage();
mEngine = HbPredictionFactory::instance()->predictionEngineForLanguage(language.language());
if (mEngine && !mCandidates) {
@@ -453,24 +401,33 @@
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;
+ QString commitString = getCommitString();
+
+ // need to update the freq information
+ mEngine->commit(commitString);
+ commit(commitString,false);
+ }
+}
+
+QString HbInputPredictionHandlerPrivate::getCommitString()
+{
+ QString commitString;
+ if(mCandidates->count()) {
+ if(!mCanContinuePrediction) {
+ //Remove the "?" mark
+ (*mCandidates)[mBestGuessLocation].chop(1);
+ }
if(mCandidates->count() <= mBestGuessLocation) {
commitString = mCandidates->at(0);
} else if (mShowTail == false) {
@@ -478,10 +435,8 @@
} else {
commitString = mCandidates->at(mBestGuessLocation);
}
- // need to update the freq information
- mEngine->commit(commitString);
- commit(commitString,false);
}
+ return commitString;
}
/*!
@@ -491,12 +446,8 @@
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
+ // Close exact word pop up in qwerty when the word is committed
if(HbInputUtils::isQwertyKeyboard(mInputMethod->inputState().keyboard())) {
mInputMethod->closeExactWordPopup();
}
@@ -505,9 +456,9 @@
if(mEngine) {
if(addToUsedWordDict && !string.isEmpty()) {
- QString separator = " ";
- QStringList stringList = string.split(separator, QString::SkipEmptyParts);
- foreach (QString str, stringList) {
+ QChar spaceChar(' ');
+ QStringList stringList = string.split(spaceChar, QString::SkipEmptyParts);
+ foreach (const QString str, stringList) {
mEngine->addUsedWord(str);
}
}
@@ -516,7 +467,6 @@
//Enable the flag after commit
mCanContinuePrediction = true;
- mTailShowing = false;
}
/*!
@@ -545,8 +495,6 @@
//Enable the flag after commit
mCanContinuePrediction = true;
- mTailShowing = false;
-
}
void HbInputPredictionHandlerPrivate::commitExactWord()
@@ -601,6 +549,21 @@
}
}
+void HbInputPredictionHandlerPrivate::setPreEditTextToEditor(QString string, bool showAutocompletionPart)
+{
+ //update the editor with pre-edit text
+ mEngine->setWord(string);
+ bool used = false;
+ mEngine->updateCandidates(mBestGuessLocation, used);
+ if(showAutocompletionPart) {
+ mShowTail = true;
+ } else {
+ mShowTail = false;
+ }
+ updateEditor();
+
+}
+
HbInputPredictionHandler::HbInputPredictionHandler(HbInputPredictionHandlerPrivate &dd, HbInputAbstractMethod* inputMethod)
:HbInputModeHandler(dd, inputMethod)
{
@@ -631,25 +594,16 @@
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.
+ case HbInputModeActionReset:
+ case HbInputModeActionCommit:
+ case HbInputModeActionFocusLost: {
+ //At the moment we are committing 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();
@@ -694,9 +648,12 @@
case HbInputModeActionHideTail:
d->mShowTail = false;
break;
+ case HbInputModeActionCloseSpellQuery:
+ closeSpellQueryDialog();
+ break;
default:
ret = HbInputModeHandler::actionHandler(action);
- break;
+ break;
}
return ret;
@@ -813,14 +770,106 @@
Q_UNUSED(exactWord);
}
-void HbInputPredictionHandler::processCustomWord(QString customWord)
-{
- Q_UNUSED(customWord);
-}
-
void HbInputPredictionHandler::showExactWordPopupIfNeeded()
{
Q_D(HbInputPredictionHandler);
d->showExactWordPopupIfNeeded();
}
+
+// Launch spell query dialog in responce to launchSpellQueryDialog signal
+void HbInputPredictionHandler::launchSpellQueryDialog()
+{
+ Q_D(HbInputPredictionHandler);
+ HbInputFocusObject *focusedObject = d->mInputMethod->focusObject();
+ if(!focusedObject) {
+ return;
+ }
+
+ // As of now we need to delete and create mSpellQueryDialog every time
+ // we launch it. If we launch the same dialog, keypad does not open sometimes.
+ // Will take sometime to find out the root cause of this, and will fix this.
+ if(d->mSpellQueryDialog) {
+ delete d->mSpellQueryDialog;
+ d->mSpellQueryDialog =0;
+ }
+ if(!d->mSpellQueryDialog) {
+ d->mSpellQueryDialog = new HbInputSpellQuery(d->mInputMethod,this);
+ d->mSpellQueryDialog->setParent(this);
+ }
+
+ QString string;
+ if(d->mCandidates && (*(d->mCandidates)).size() >= d->mBestGuessLocation + 1) {
+ string = (*(d->mCandidates))[d->mBestGuessLocation].left(d->mEngine->inputLength());
+ }
+ d->reset();
+ d->mSpellQueryDialog->launch(string);
+
+}
+
+// To force the spell query dialog to close.
+void HbInputPredictionHandler::closeSpellQueryDialog()
+{
+ Q_D(HbInputPredictionHandler);
+ if (d->mSpellQueryDialog && d->mSpellQueryDialog->isVisible()) {
+ d->mSpellQueryDialog->close();
+ }
+}
+
+//
+void HbInputPredictionHandler::spellQueryDialogClosed(QObject *savedFocusObject
+ ,HbInputSpellQuery::HbSpellCloseReason closeReason,const QString &string)
+{
+ if(!savedFocusObject) {
+ return;
+ }
+
+ Q_D(HbInputPredictionHandler);
+ // set the focus back to the editor which caused the launch of spell dialog.
+ HbInputFocusObject *newFocusObject = new HbInputFocusObject(savedFocusObject);
+ newFocusObject->releaseFocus();
+ newFocusObject->setFocus();
+ HbAbstractEdit *abstractEdit = qobject_cast<HbAbstractEdit*>(savedFocusObject);
+ if(abstractEdit) {
+ abstractEdit->setCursorPosition(abstractEdit->cursorPosition());
+ }
+ d->mInputMethod->setFocusObject(newFocusObject);
+
+ if (closeReason == HbInputSpellQuery::HbOkPressed) {
+ d->commit(string,true);
+ } else if(closeReason == HbInputSpellQuery::HbCancelPressed) {
+ //update the editor with pre-edit text
+ d->setPreEditTextToEditor(string, d->mCanContinuePrediction);
+ // This update is need for below usecase
+ // Editor is empty => enter some data till their is no match => click on word
+ // to launch spell query => now press cancel => testcase of keypad is uppercase,
+ // but it should be lower case
+ d->mInputMethod->updateState();
+ } else if (closeReason == HbInputSpellQuery::HbForceClose) {
+ // Force spell query close happens when oriantation is about to change.
+ // In this case nomal commit() on input method does not seems to work.
+ // So we are directly sending commit even to editor.
+ QList<QInputMethodEvent::Attribute> list;
+ QInputMethodEvent event(QString(), list);
+ event.setCommitString(string);
+ QApplication::sendEvent(savedFocusObject, &event);
+ }
+ // Enable the flag
+ d->mCanContinuePrediction = true;
+}
+
+
+void HbInputPredictionHandler::setAutocompletionStatus(bool status)
+{
+ Q_D(HbInputPredictionHandler);
+ d->mAutocompletionEnabled = status;
+ if(!d->mEngine) {
+ return;
+ }
+ if(!status) {
+ d->mEngine->disableFeature(HbPredFeatureWordCompletion);
+ } else {
+ d->mEngine->enableFeature(HbPredFeatureWordCompletion);
+ }
+
+}
// EOF