src/hbplugins/inputmethods/common/hbinputmodehandler.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 <QTextCharFormat>
       
    26 #include <QTimer>
       
    27 #include <hbinputsettingproxy.h>
       
    28 #include <hbinputkeymapfactory.h>
       
    29 #include <hbinputkeymap.h>
       
    30 #include <hbinpututils.h>
       
    31 
       
    32 #include "hbinputmodehandler.h"
       
    33 #include "hbinputmodehandler_p.h"
       
    34 #include "hbinputabstractbase.h"
       
    35 
       
    36 HbInputModeHandlerPrivate::HbInputModeHandlerPrivate()
       
    37 :mKeymap(0),
       
    38 mInputMethod(0),
       
    39 mTimer(0)
       
    40 {
       
    41 }
       
    42 
       
    43 HbInputModeHandlerPrivate::~HbInputModeHandlerPrivate()
       
    44 {
       
    45 }
       
    46 
       
    47 void HbInputModeHandlerPrivate::init()
       
    48 {
       
    49     Q_Q(HbInputModeHandler);
       
    50     mTimer = new QTimer(q);
       
    51     q->connect(mTimer, SIGNAL(timeout()), q, SLOT(_q_timeout()));
       
    52 }
       
    53 
       
    54 // A virtual timeout function mode handlers should implement this slot.
       
    55 void HbInputModeHandlerPrivate::_q_timeout()
       
    56 {
       
    57 }
       
    58 
       
    59 QString HbInputModeHandlerPrivate::surroundingText()
       
    60 {
       
    61     if (mInputMethod->focusObject()) {
       
    62         return mInputMethod->focusObject()->editorSurroundingText();
       
    63     }
       
    64     return QString();
       
    65 }
       
    66 
       
    67 int HbInputModeHandlerPrivate::cursorPosition()
       
    68 {
       
    69     if (mInputMethod->focusObject()) {
       
    70        return mInputMethod->focusObject()->editorCursorPosition();
       
    71     }
       
    72 
       
    73     return -1;
       
    74 }
       
    75 
       
    76 void HbInputModeHandlerPrivate::getAndFilterCharactersBoundToKey(QStringList &spellList, Qt::Key key)
       
    77 {
       
    78     HbInputFocusObject *focusObject = mInputMethod->focusObject();
       
    79 
       
    80     spellList.clear();
       
    81     // Get the functionized character
       
    82     const HbMappedKey* mappedKey = mKeymap->keyForKeycode(mInputMethod->inputState().keyboard(), key);
       
    83     if (!mappedKey) {
       
    84         return;
       
    85     }
       
    86 
       
    87     if (!mappedKey->characters(HbModifierFnPressed).isNull() && focusObject && focusObject->characterAllowedInEditor(mappedKey->characters(HbModifierFnPressed).at(0))) {
       
    88         spellList.append(mappedKey->characters(HbModifierFnPressed).at(0));
       
    89     }
       
    90 
       
    91     // Get the characters mapped to the key.
       
    92     HbInputState inputState = mInputMethod->inputState();
       
    93     HbTextCase textCase = inputState.textCase();
       
    94     HbModifiers modifiers = HbModifierNone;
       
    95 	
       
    96     if (textCase == HbTextCaseUpper || textCase == HbTextCaseAutomatic) {
       
    97         modifiers |= HbModifierShiftPressed;
       
    98     }
       
    99     for (int i=0; i < mappedKey->characters(modifiers).length(); i++) {
       
   100         if (focusObject && focusObject->characterAllowedInEditor(mappedKey->characters(modifiers).at(i))) {
       
   101             spellList.append(mappedKey->characters(modifiers).at(i));
       
   102         }
       
   103     }
       
   104 
       
   105     // filter characters.
       
   106   /*  if (key < 0x0ff) {
       
   107     QString charSet = mKeyData->specialCharacterData(mInputMethod->inputState().iKeyboardType);
       
   108     if (charSet.contains(key, Qt::CaseSensitive)) {
       
   109         QString mostUsedCharacters;
       
   110         HbInputSettingProxy::instance()->mostUsedSpecialCharacters(HbMaxSctLineChars, mostUsedCharacters,
       
   111             mInputMethod->focusObject()->editorInterface().filter());
       
   112         spellList.clear();
       
   113         if (!mostUsedCharacters.isNull()) {
       
   114             for (int i=0; i<mostUsedCharacters.count(); i++){
       
   115                 QChar char1 = mostUsedCharacters[i];
       
   116                 spellList.append(char1);
       
   117             }
       
   118         }
       
   119     }
       
   120     }*/
       
   121     return;
       
   122 }
       
   123 
       
   124 
       
   125 void HbInputModeHandlerPrivate::updateTextCase()
       
   126 {
       
   127     HbInputState nextState = mInputMethod->inputState();
       
   128     HbTextCase nextCase = HbTextCaseNone;
       
   129 
       
   130     switch(nextState.textCase()) {
       
   131         case HbTextCaseLower:
       
   132             // In multiline editor, if enter char is input and then shift is pressed twice,
       
   133             // the case should be reverted to automatic.
       
   134             if (mInputMethod->automaticTextCaseNeeded()) {
       
   135                 nextCase = HbTextCaseAutomatic;
       
   136             } else {
       
   137                 nextCase = HbTextCaseUpper;
       
   138             }
       
   139             break;
       
   140         case HbTextCaseUpper:
       
   141         case HbTextCaseAutomatic:
       
   142             nextCase = HbTextCaseLower;
       
   143             break;
       
   144         default:
       
   145             break;
       
   146         }
       
   147         nextState.setTextCase(nextCase);
       
   148         mInputMethod->activateState(nextState);
       
   149 }
       
   150 
       
   151 bool HbInputModeHandlerPrivate::isEnterCharacter(QChar character)
       
   152 {
       
   153     if (character == 0x21B2 || character == 0x21b3) {
       
   154         return true;
       
   155     }
       
   156     return false;
       
   157 }
       
   158 HbInputModeHandler::HbInputModeHandler(HbInputModeHandlerPrivate &dd, HbInputAbstractMethod* inputMethod)
       
   159     :d_ptr(&dd)
       
   160 {
       
   161     Q_D(HbInputModeHandler);
       
   162     d->q_ptr = this;
       
   163     d->init();
       
   164     d->mInputMethod = inputMethod;
       
   165 }
       
   166 
       
   167 HbInputModeHandler::~HbInputModeHandler()
       
   168 {
       
   169     delete d_ptr;
       
   170 }
       
   171 
       
   172 /*!
       
   173  Gateway for all the mode handlers.
       
   174 */
       
   175 bool HbInputModeHandler::filterEvent(const QEvent * event)
       
   176 {
       
   177     if (event) {
       
   178         if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
       
   179             const QKeyEvent *keyEvent = 0;
       
   180             keyEvent = static_cast<const QKeyEvent *>(event);
       
   181             if (keyEvent) {
       
   182                 return filterEvent(keyEvent);
       
   183             }
       
   184         }
       
   185     }
       
   186 
       
   187     return false;
       
   188 }
       
   189 
       
   190 /*!
       
   191  This function handles the most common key events.
       
   192 */
       
   193 bool HbInputModeHandler::filterEvent(const QKeyEvent * event)
       
   194 {
       
   195     Q_UNUSED(event);
       
   196     return false;
       
   197 }
       
   198 
       
   199 /*!
       
   200  Action hanlder. Currently it handles only keymapping loading.
       
   201 */
       
   202 bool HbInputModeHandler::actionHandler(HbInputModeAction action)
       
   203 {
       
   204     Q_D(HbInputModeHandler);
       
   205     switch (action) {
       
   206     case HbInputModeActionInit:
       
   207         if (d->mKeymap) {
       
   208             break;
       
   209         }
       
   210     case HbInputModeActionPrimaryLanguageChanged: {
       
   211         HbInputLanguage primaryLanguage = HbInputSettingProxy::instance()->globalInputLanguage();
       
   212         d->mKeymap = HbKeymapFactory::instance()->keymap(primaryLanguage);
       
   213         if (!d->mKeymap) {
       
   214             qDebug(" HbInputModeHandler::actionHandler --> Failed to get keymapData!!!");
       
   215             return false;
       
   216         }
       
   217         }
       
   218         break;
       
   219     case HbInputModeActionDeleteAndCommit: {
       
   220         HbInputFocusObject *focusObject = 0;
       
   221         focusObject = d->mInputMethod->focusObject();
       
   222 
       
   223         if (focusObject && focusObject->editorCursorPosition()) {
       
   224             QString empty;
       
   225             QList<QInputMethodEvent::Attribute> list;
       
   226             QInputMethodEvent event(QString(), list);
       
   227             event.setCommitString(empty, -1, 1);
       
   228             sendAndUpdate(event);
       
   229         }
       
   230         break;
       
   231         }
       
   232     default :
       
   233         return false;
       
   234     };
       
   235 
       
   236     return true;
       
   237 }
       
   238 
       
   239 /*!
       
   240 Call-back implementation to indicate that a character was selected from the SCT. With this, the character is committed to the
       
   241 editor and editor is again made to focus.
       
   242 */
       
   243 void HbInputModeHandler::sctCharacterSelected(QString aChar)
       
   244 {
       
   245     commitAndUpdate(aChar);
       
   246 }
       
   247 
       
   248 void HbInputModeHandler::smileySelected(QString smiley)
       
   249 {
       
   250     Q_D(HbInputModeHandler);
       
   251     HbInputFocusObject *focusObject = 0;
       
   252     focusObject = d->mInputMethod->focusObject();
       
   253     if (!focusObject) {
       
   254         qDebug("HbInputModeHandler::smileySelected no focusObject ... failed!!");
       
   255         return ;
       
   256     }
       
   257     QStringList patterns = focusObject->editorInterface().smileyTheme().patterns(smiley);
       
   258     foreach( QString string, patterns) {
       
   259         QString filtered;
       
   260         focusObject->filterStringWithEditorFilter(string, filtered);
       
   261         if (filtered == string) {
       
   262             focusObject->commitSmiley(smiley);
       
   263             break;
       
   264         }
       
   265     }
       
   266     d->mInputMethod->updateState();
       
   267 }
       
   268 
       
   269 void HbInputModeHandler::cursorPositionChanged(int oldPos, int newPos)
       
   270 {
       
   271     Q_D(HbInputModeHandler);
       
   272     d->mInputMethod->updateState();
       
   273     Q_UNUSED(oldPos);
       
   274     Q_UNUSED(newPos);
       
   275 }
       
   276 
       
   277 /*!
       
   278  this function commits the first number found in the key.
       
   279 */
       
   280 void HbInputModeHandler::commitFirstMappedNumber(int key)
       
   281 {
       
   282     Q_D(HbInputModeHandler);
       
   283     // This is long key press number shortcut functionality.
       
   284     if (!d->mKeymap) {
       
   285         d->mKeymap = HbKeymapFactory::instance()->keymap(d->mInputMethod->inputState().language());
       
   286     }
       
   287     QChar numChr = HbInputUtils::findFirstNumberCharacterBoundToKey(d->mKeymap->keyForKeycode(d->mInputMethod->inputState().keyboard(), key),
       
   288                                                                     d->mKeymap->language());
       
   289 	// when a number is to be entered, it should commit 
       
   290     // the previous string and then append the number to the string
       
   291     if (numChr != 0) {
       
   292         commitAndAppendString(numChr);
       
   293     }
       
   294 }
       
   295 
       
   296 /*!
       
   297 Gets the character at index in a key and incriments the index by 1. Returns the Zeroth character if
       
   298 this function finds the index to be out of range and incriments index to 1.
       
   299 */
       
   300 QChar HbInputModeHandler::getNthCharacterInKey(int &index, int key)
       
   301 {
       
   302     Q_D(HbInputModeHandler);
       
   303     HbModifiers modifiers = 0;
       
   304     int textCase = d->mInputMethod->inputState().textCase();
       
   305     if (textCase == HbTextCaseUpper || textCase == HbTextCaseAutomatic) {
       
   306         modifiers |= HbModifierShiftPressed;
       
   307     }
       
   308     if (!d->mKeymap) {
       
   309         d->mKeymap = HbKeymapFactory::instance()->keymap(d->mInputMethod->inputState().language());
       
   310     }
       
   311     const HbMappedKey* mappedKey = d->mKeymap->keyForKeycode(d->mInputMethod->inputState().keyboard(), key);
       
   312     if (!mappedKey) {
       
   313         return 0;
       
   314     }
       
   315     // We need to see which of the characters in keyData are allowed to the editor.
       
   316     // this looks like expensive operation, need to find out a better way/place to do it.
       
   317     QString allowedChars;
       
   318     HbInputFocusObject *focusedObject = d->mInputMethod->focusObject();
       
   319     if(focusedObject) {
       
   320         focusedObject->filterStringWithEditorFilter(mappedKey->characters(modifiers),allowedChars);
       
   321     } else {
       
   322         // we should not come here. Just for saftey.
       
   323          allowedChars =  mappedKey->characters(modifiers);
       
   324     }
       
   325     QChar character = 0;
       
   326     if (!allowedChars.isNull()) {
       
   327         if (index >= allowedChars.length() || index < 0) {
       
   328             index = 0;
       
   329         }
       
   330         character = allowedChars.at(index);
       
   331         index++;
       
   332     }
       
   333     return character;
       
   334 }
       
   335 
       
   336 /*!
       
   337     This function gets all the characters bound to a key and filters those character based on the editor.
       
   338 */
       
   339 void HbInputModeHandler::getAndFilterCharactersBoundToKey(QStringList &spellList, Qt::Key key)
       
   340 {
       
   341     Q_D(HbInputModeHandler);
       
   342     d->getAndFilterCharactersBoundToKey(spellList, key);
       
   343 }
       
   344 
       
   345 /*!
       
   346     A virtual function, this should be called from plugin when ever there is mouse event.
       
   347 */
       
   348 void HbInputModeHandler::mouseHandler(int x, QMouseEvent* mouseEvent)
       
   349 {
       
   350     Q_UNUSED(mouseEvent);
       
   351     Q_D(HbInputModeHandler);
       
   352     if(d->cursorPosition() != x) {
       
   353         actionHandler(HbInputModeActionCommit);
       
   354     }
       
   355 }
       
   356 
       
   357 /*!
       
   358     A virtual function, default implementation first commits any inline text by calling actionHandler with
       
   359     HbInputModeActionCommit. Then commits the string.
       
   360 */
       
   361 void HbInputModeHandler::commitAndAppendString(const QString& string)
       
   362 {
       
   363     // first commit the pre-edit string if any.
       
   364     actionHandler(HbInputModeActionCommit);
       
   365     commitAndUpdate(string);
       
   366 }
       
   367 
       
   368 /*!
       
   369 Ignores currently active pre-edit text if any and directly commits the passed string in to the editor. This
       
   370 function also updates the inputmethod state.
       
   371 */
       
   372 void HbInputModeHandler::commitAndUpdate(const QString& string, int replaceFrom, int replaceLength, bool isAsync)
       
   373 {
       
   374     Q_D(HbInputModeHandler);
       
   375     HbInputFocusObject *focusObject = 0;
       
   376     focusObject = d->mInputMethod->focusObject();
       
   377     if (!focusObject) {
       
   378         qDebug("HbInputModeHandler::commitAndUpdate no focusObject ... failed!!");
       
   379         return ;
       
   380     }
       
   381 
       
   382     QString filtered;
       
   383     focusObject->filterStringWithEditorFilter(string, filtered);
       
   384 
       
   385     // now commit the string which is passed in.
       
   386     QList<QInputMethodEvent::Attribute> list;
       
   387 
       
   388     if(isAsync) {
       
   389         QInputMethodEvent *event = new QInputMethodEvent(QString(), list);
       
   390         event->setCommitString(filtered, replaceFrom, replaceLength);
       
   391         focusObject->postEvent(*event);
       
   392     } else {
       
   393         QInputMethodEvent event;
       
   394         event.setCommitString(filtered, replaceFrom, replaceLength);
       
   395         focusObject->sendEvent(event);
       
   396     }
       
   397     d->mInputMethod->updateState();
       
   398 }
       
   399 
       
   400 /*!
       
   401 Sends the passed event to the focused object and upates the inputmethod state.
       
   402 */
       
   403 void HbInputModeHandler::sendAndUpdate(QEvent& event)
       
   404 {
       
   405     Q_D(HbInputModeHandler);
       
   406     HbInputFocusObject *focusObject = 0;
       
   407     focusObject = d->mInputMethod->focusObject();
       
   408     if (!focusObject) {
       
   409         qDebug("HbInputModeHandler::sendAndUpdate no focusObject ... failed!!");
       
   410         return;
       
   411     }
       
   412 
       
   413     focusObject->sendEvent(event);
       
   414     d->mInputMethod->updateState();
       
   415 }
       
   416 
       
   417 void HbInputModeHandler::setKeymap(const HbKeymap* keymap)
       
   418 {
       
   419     Q_D(HbInputModeHandler);
       
   420     d->mKeymap = keymap;
       
   421 }
       
   422 
       
   423 void HbInputModeHandler::characterPreviewAvailable(bool available)
       
   424 {
       
   425     Q_UNUSED(available);
       
   426 }
       
   427 
       
   428 #include "moc_hbinputmodehandler.cpp"
       
   429 // EOF