src/hbplugins/inputmethods/common/hbinputpredictionhandler.cpp
branchGCC_SURGE
changeset 15 f378acbc9cfb
parent 7 923ff622b8b9
child 21 4633027730f5
child 34 ed14f46c0e55
--- 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