src/hbplugins/inputmethods/common/hbinputmodehandler.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbplugins/inputmethods/common/hbinputmodehandler.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,429 @@
+/****************************************************************************
+**
+** 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 <QTimer>
+#include <hbinputsettingproxy.h>
+#include <hbinputkeymapfactory.h>
+#include <hbinputkeymap.h>
+#include <hbinpututils.h>
+
+#include "hbinputmodehandler.h"
+#include "hbinputmodehandler_p.h"
+#include "hbinputabstractbase.h"
+
+HbInputModeHandlerPrivate::HbInputModeHandlerPrivate()
+:mKeymap(0),
+mInputMethod(0),
+mTimer(0)
+{
+}
+
+HbInputModeHandlerPrivate::~HbInputModeHandlerPrivate()
+{
+}
+
+void HbInputModeHandlerPrivate::init()
+{
+    Q_Q(HbInputModeHandler);
+    mTimer = new QTimer(q);
+    q->connect(mTimer, SIGNAL(timeout()), q, SLOT(_q_timeout()));
+}
+
+// A virtual timeout function mode handlers should implement this slot.
+void HbInputModeHandlerPrivate::_q_timeout()
+{
+}
+
+QString HbInputModeHandlerPrivate::surroundingText()
+{
+    if (mInputMethod->focusObject()) {
+        return mInputMethod->focusObject()->editorSurroundingText();
+    }
+    return QString();
+}
+
+int HbInputModeHandlerPrivate::cursorPosition()
+{
+    if (mInputMethod->focusObject()) {
+       return mInputMethod->focusObject()->editorCursorPosition();
+    }
+
+    return -1;
+}
+
+void HbInputModeHandlerPrivate::getAndFilterCharactersBoundToKey(QStringList &spellList, Qt::Key key)
+{
+    HbInputFocusObject *focusObject = mInputMethod->focusObject();
+
+    spellList.clear();
+    // Get the functionized character
+    const HbMappedKey* mappedKey = mKeymap->keyForKeycode(mInputMethod->inputState().keyboard(), key);
+    if (!mappedKey) {
+        return;
+    }
+
+    if (!mappedKey->characters(HbModifierFnPressed).isNull() && focusObject && focusObject->characterAllowedInEditor(mappedKey->characters(HbModifierFnPressed).at(0))) {
+        spellList.append(mappedKey->characters(HbModifierFnPressed).at(0));
+    }
+
+    // Get the characters mapped to the key.
+    HbInputState inputState = mInputMethod->inputState();
+    HbTextCase textCase = inputState.textCase();
+    HbModifiers modifiers = HbModifierNone;
+	
+    if (textCase == HbTextCaseUpper || textCase == HbTextCaseAutomatic) {
+        modifiers |= HbModifierShiftPressed;
+    }
+    for (int i=0; i < mappedKey->characters(modifiers).length(); i++) {
+        if (focusObject && focusObject->characterAllowedInEditor(mappedKey->characters(modifiers).at(i))) {
+            spellList.append(mappedKey->characters(modifiers).at(i));
+        }
+    }
+
+    // filter characters.
+  /*  if (key < 0x0ff) {
+    QString charSet = mKeyData->specialCharacterData(mInputMethod->inputState().iKeyboardType);
+    if (charSet.contains(key, Qt::CaseSensitive)) {
+        QString mostUsedCharacters;
+        HbInputSettingProxy::instance()->mostUsedSpecialCharacters(HbMaxSctLineChars, mostUsedCharacters,
+            mInputMethod->focusObject()->editorInterface().filter());
+        spellList.clear();
+        if (!mostUsedCharacters.isNull()) {
+            for (int i=0; i<mostUsedCharacters.count(); i++){
+                QChar char1 = mostUsedCharacters[i];
+                spellList.append(char1);
+            }
+        }
+    }
+    }*/
+    return;
+}
+
+
+void HbInputModeHandlerPrivate::updateTextCase()
+{
+    HbInputState nextState = mInputMethod->inputState();
+    HbTextCase nextCase = HbTextCaseNone;
+
+    switch(nextState.textCase()) {
+        case HbTextCaseLower:
+            // In multiline editor, if enter char is input and then shift is pressed twice,
+            // the case should be reverted to automatic.
+            if (mInputMethod->automaticTextCaseNeeded()) {
+                nextCase = HbTextCaseAutomatic;
+            } else {
+                nextCase = HbTextCaseUpper;
+            }
+            break;
+        case HbTextCaseUpper:
+        case HbTextCaseAutomatic:
+            nextCase = HbTextCaseLower;
+            break;
+        default:
+            break;
+        }
+        nextState.setTextCase(nextCase);
+        mInputMethod->activateState(nextState);
+}
+
+bool HbInputModeHandlerPrivate::isEnterCharacter(QChar character)
+{
+    if (character == 0x21B2 || character == 0x21b3) {
+        return true;
+    }
+    return false;
+}
+HbInputModeHandler::HbInputModeHandler(HbInputModeHandlerPrivate &dd, HbInputAbstractMethod* inputMethod)
+    :d_ptr(&dd)
+{
+    Q_D(HbInputModeHandler);
+    d->q_ptr = this;
+    d->init();
+    d->mInputMethod = inputMethod;
+}
+
+HbInputModeHandler::~HbInputModeHandler()
+{
+    delete d_ptr;
+}
+
+/*!
+ Gateway for all the mode handlers.
+*/
+bool HbInputModeHandler::filterEvent(const QEvent * event)
+{
+    if (event) {
+        if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
+            const QKeyEvent *keyEvent = 0;
+            keyEvent = static_cast<const QKeyEvent *>(event);
+            if (keyEvent) {
+                return filterEvent(keyEvent);
+            }
+        }
+    }
+
+    return false;
+}
+
+/*!
+ This function handles the most common key events.
+*/
+bool HbInputModeHandler::filterEvent(const QKeyEvent * event)
+{
+    Q_UNUSED(event);
+    return false;
+}
+
+/*!
+ Action hanlder. Currently it handles only keymapping loading.
+*/
+bool HbInputModeHandler::actionHandler(HbInputModeAction action)
+{
+    Q_D(HbInputModeHandler);
+    switch (action) {
+    case HbInputModeActionInit:
+        if (d->mKeymap) {
+            break;
+        }
+    case HbInputModeActionPrimaryLanguageChanged: {
+        HbInputLanguage primaryLanguage = HbInputSettingProxy::instance()->globalInputLanguage();
+        d->mKeymap = HbKeymapFactory::instance()->keymap(primaryLanguage);
+        if (!d->mKeymap) {
+            qDebug(" HbInputModeHandler::actionHandler --> Failed to get keymapData!!!");
+            return false;
+        }
+        }
+        break;
+    case HbInputModeActionDeleteAndCommit: {
+        HbInputFocusObject *focusObject = 0;
+        focusObject = d->mInputMethod->focusObject();
+
+        if (focusObject && focusObject->editorCursorPosition()) {
+            QString empty;
+            QList<QInputMethodEvent::Attribute> list;
+            QInputMethodEvent event(QString(), list);
+            event.setCommitString(empty, -1, 1);
+            sendAndUpdate(event);
+        }
+        break;
+        }
+    default :
+        return false;
+    };
+
+    return true;
+}
+
+/*!
+Call-back implementation to indicate that a character was selected from the SCT. With this, the character is committed to the
+editor and editor is again made to focus.
+*/
+void HbInputModeHandler::sctCharacterSelected(QString aChar)
+{
+    commitAndUpdate(aChar);
+}
+
+void HbInputModeHandler::smileySelected(QString smiley)
+{
+    Q_D(HbInputModeHandler);
+    HbInputFocusObject *focusObject = 0;
+    focusObject = d->mInputMethod->focusObject();
+    if (!focusObject) {
+        qDebug("HbInputModeHandler::smileySelected no focusObject ... failed!!");
+        return ;
+    }
+    QStringList patterns = focusObject->editorInterface().smileyTheme().patterns(smiley);
+    foreach( QString string, patterns) {
+        QString filtered;
+        focusObject->filterStringWithEditorFilter(string, filtered);
+        if (filtered == string) {
+            focusObject->commitSmiley(smiley);
+            break;
+        }
+    }
+    d->mInputMethod->updateState();
+}
+
+void HbInputModeHandler::cursorPositionChanged(int oldPos, int newPos)
+{
+    Q_D(HbInputModeHandler);
+    d->mInputMethod->updateState();
+    Q_UNUSED(oldPos);
+    Q_UNUSED(newPos);
+}
+
+/*!
+ this function commits the first number found in the key.
+*/
+void HbInputModeHandler::commitFirstMappedNumber(int key)
+{
+    Q_D(HbInputModeHandler);
+    // This is long key press number shortcut functionality.
+    if (!d->mKeymap) {
+        d->mKeymap = HbKeymapFactory::instance()->keymap(d->mInputMethod->inputState().language());
+    }
+    QChar numChr = HbInputUtils::findFirstNumberCharacterBoundToKey(d->mKeymap->keyForKeycode(d->mInputMethod->inputState().keyboard(), key),
+                                                                    d->mKeymap->language());
+	// when a number is to be entered, it should commit 
+    // the previous string and then append the number to the string
+    if (numChr != 0) {
+        commitAndAppendString(numChr);
+    }
+}
+
+/*!
+Gets the character at index in a key and incriments the index by 1. Returns the Zeroth character if
+this function finds the index to be out of range and incriments index to 1.
+*/
+QChar HbInputModeHandler::getNthCharacterInKey(int &index, int key)
+{
+    Q_D(HbInputModeHandler);
+    HbModifiers modifiers = 0;
+    int textCase = d->mInputMethod->inputState().textCase();
+    if (textCase == HbTextCaseUpper || textCase == HbTextCaseAutomatic) {
+        modifiers |= HbModifierShiftPressed;
+    }
+    if (!d->mKeymap) {
+        d->mKeymap = HbKeymapFactory::instance()->keymap(d->mInputMethod->inputState().language());
+    }
+    const HbMappedKey* mappedKey = d->mKeymap->keyForKeycode(d->mInputMethod->inputState().keyboard(), key);
+    if (!mappedKey) {
+        return 0;
+    }
+    // We need to see which of the characters in keyData are allowed to the editor.
+    // this looks like expensive operation, need to find out a better way/place to do it.
+    QString allowedChars;
+    HbInputFocusObject *focusedObject = d->mInputMethod->focusObject();
+    if(focusedObject) {
+        focusedObject->filterStringWithEditorFilter(mappedKey->characters(modifiers),allowedChars);
+    } else {
+        // we should not come here. Just for saftey.
+         allowedChars =  mappedKey->characters(modifiers);
+    }
+    QChar character = 0;
+    if (!allowedChars.isNull()) {
+        if (index >= allowedChars.length() || index < 0) {
+            index = 0;
+        }
+        character = allowedChars.at(index);
+        index++;
+    }
+    return character;
+}
+
+/*!
+    This function gets all the characters bound to a key and filters those character based on the editor.
+*/
+void HbInputModeHandler::getAndFilterCharactersBoundToKey(QStringList &spellList, Qt::Key key)
+{
+    Q_D(HbInputModeHandler);
+    d->getAndFilterCharactersBoundToKey(spellList, key);
+}
+
+/*!
+    A virtual function, this should be called from plugin when ever there is mouse event.
+*/
+void HbInputModeHandler::mouseHandler(int x, QMouseEvent* mouseEvent)
+{
+    Q_UNUSED(mouseEvent);
+    Q_D(HbInputModeHandler);
+    if(d->cursorPosition() != x) {
+        actionHandler(HbInputModeActionCommit);
+    }
+}
+
+/*!
+    A virtual function, default implementation first commits any inline text by calling actionHandler with
+    HbInputModeActionCommit. Then commits the string.
+*/
+void HbInputModeHandler::commitAndAppendString(const QString& string)
+{
+    // first commit the pre-edit string if any.
+    actionHandler(HbInputModeActionCommit);
+    commitAndUpdate(string);
+}
+
+/*!
+Ignores currently active pre-edit text if any and directly commits the passed string in to the editor. This
+function also updates the inputmethod state.
+*/
+void HbInputModeHandler::commitAndUpdate(const QString& string, int replaceFrom, int replaceLength, bool isAsync)
+{
+    Q_D(HbInputModeHandler);
+    HbInputFocusObject *focusObject = 0;
+    focusObject = d->mInputMethod->focusObject();
+    if (!focusObject) {
+        qDebug("HbInputModeHandler::commitAndUpdate no focusObject ... failed!!");
+        return ;
+    }
+
+    QString filtered;
+    focusObject->filterStringWithEditorFilter(string, filtered);
+
+    // now commit the string which is passed in.
+    QList<QInputMethodEvent::Attribute> list;
+
+    if(isAsync) {
+        QInputMethodEvent *event = new QInputMethodEvent(QString(), list);
+        event->setCommitString(filtered, replaceFrom, replaceLength);
+        focusObject->postEvent(*event);
+    } else {
+        QInputMethodEvent event;
+        event.setCommitString(filtered, replaceFrom, replaceLength);
+        focusObject->sendEvent(event);
+    }
+    d->mInputMethod->updateState();
+}
+
+/*!
+Sends the passed event to the focused object and upates the inputmethod state.
+*/
+void HbInputModeHandler::sendAndUpdate(QEvent& event)
+{
+    Q_D(HbInputModeHandler);
+    HbInputFocusObject *focusObject = 0;
+    focusObject = d->mInputMethod->focusObject();
+    if (!focusObject) {
+        qDebug("HbInputModeHandler::sendAndUpdate no focusObject ... failed!!");
+        return;
+    }
+
+    focusObject->sendEvent(event);
+    d->mInputMethod->updateState();
+}
+
+void HbInputModeHandler::setKeymap(const HbKeymap* keymap)
+{
+    Q_D(HbInputModeHandler);
+    d->mKeymap = keymap;
+}
+
+void HbInputModeHandler::characterPreviewAvailable(bool available)
+{
+    Q_UNUSED(available);
+}
+
+#include "moc_hbinputmodehandler.cpp"
+// EOF