src/hbcore/inputfw/hbinputmodecache.cpp
changeset 6 c3690ec91ef8
parent 5 627c4a0fd0e7
child 7 923ff622b8b9
equal deleted inserted replaced
5:627c4a0fd0e7 6:c3690ec91ef8
    20 **
    20 **
    21 ** If you have questions regarding the use of this file, please contact
    21 ** If you have questions regarding the use of this file, please contact
    22 ** Nokia at developer.feedback@nokia.com.
    22 ** Nokia at developer.feedback@nokia.com.
    23 **
    23 **
    24 ****************************************************************************/
    24 ****************************************************************************/
       
    25 #include "hbinputmodecache_p.h"
       
    26 
    25 #include <QInputContextPlugin>
    27 #include <QInputContextPlugin>
    26 #include <QLocale>
    28 #include <QLocale>
    27 #include <QFileSystemWatcher>
    29 #include <QFileSystemWatcher>
    28 #include <QLibrary>
    30 #include <QLibrary>
    29 #include <QPluginLoader>
    31 #include <QPluginLoader>
    30 #include <QDir>
    32 #include <QDir>
    31 
    33 
    32 #include "hbinputmodecache_p.h"
       
    33 #include "hbinpututils.h"
    34 #include "hbinpututils.h"
    34 #include "hbinputmethod.h"
    35 #include "hbinputmethod.h"
    35 #include "hbinputsettingproxy.h"
    36 #include "hbinputsettingproxy.h"
    36 #include "hbinputmodeproperties.h"
    37 #include "hbinputmodeproperties.h"
    37 #include "hbinputkeymapfactory.h"
    38 #include "hbinputkeymapfactory.h"
    67 {
    68 {
    68 public:
    69 public:
    69     HbInputModeCachePrivate() : mWatcher(new QFileSystemWatcher()), mShuttingDown(false) {}
    70     HbInputModeCachePrivate() : mWatcher(new QFileSystemWatcher()), mShuttingDown(false) {}
    70     ~HbInputModeCachePrivate() {}
    71     ~HbInputModeCachePrivate() {}
    71     void refresh(const QString &directory = QString());
    72     void refresh(const QString &directory = QString());
    72     QInputContextPlugin *pluginInstance(const QString& pluginFileName) const;
    73     QInputContextPlugin *pluginInstance(const QString &pluginFileName) const;
    73     HbInputMethod *methodInstance(const QString &pluginFileName, const QString &key) const;
    74     HbInputMethod *methodInstance(const QString &pluginFileName, const QString &key) const;
    74     HbInputModeProperties propertiesFromString(const QString &entry) const;
    75     HbInputModeProperties propertiesFromString(const QString &entry) const;
    75     HbInputModeProperties propertiesFromState(const HbInputState &state) const;
    76     HbInputModeProperties propertiesFromState(const HbInputState &state) const;
    76     HbInputMethod *cachedMethod(HbInputMethodListItem &item);
    77     HbInputMethod *cachedMethod(HbInputMethodListItem &item);
    77     void updateMonitoredPaths();
    78     void updateMonitoredPaths();
    81     QFileSystemWatcher *mWatcher;
    82     QFileSystemWatcher *mWatcher;
    82     QList<HbInputMethodListItem> mMethods;
    83     QList<HbInputMethodListItem> mMethods;
    83     bool mShuttingDown;
    84     bool mShuttingDown;
    84 };
    85 };
    85 
    86 
    86 QInputContextPlugin* HbInputModeCachePrivate::pluginInstance(const QString& pluginFileName) const
    87 QInputContextPlugin *HbInputModeCachePrivate::pluginInstance(const QString &pluginFileName) const
    87 {
    88 {
    88     if (QLibrary::isLibrary(pluginFileName)) {
    89     if (QLibrary::isLibrary(pluginFileName)) {
    89         QPluginLoader loader(pluginFileName);
    90         QPluginLoader loader(pluginFileName);
    90         QObject* plugin = loader.instance();
    91         QObject *plugin = loader.instance();
    91         if (plugin) {
    92         if (plugin) {
    92             return qobject_cast<QInputContextPlugin*>(plugin);
    93             return qobject_cast<QInputContextPlugin *>(plugin);
    93         }
    94         }
    94     }
    95     }
    95 
    96 
    96     return 0;
    97     return 0;
    97 }
    98 }
    99 HbInputMethod *HbInputModeCachePrivate::methodInstance(const QString &pluginFileName, const QString &key) const
   100 HbInputMethod *HbInputModeCachePrivate::methodInstance(const QString &pluginFileName, const QString &key) const
   100 {
   101 {
   101     QInputContextPlugin *plugin = pluginInstance(pluginFileName);
   102     QInputContextPlugin *plugin = pluginInstance(pluginFileName);
   102     if (plugin) {
   103     if (plugin) {
   103         QInputContext *instance = plugin->create(key);
   104         QInputContext *instance = plugin->create(key);
   104         HbInputMethod *result = qobject_cast<HbInputMethod*>(instance);
   105         HbInputMethod *result = qobject_cast<HbInputMethod *>(instance);
   105         if (result) {
   106         if (result) {
   106             QStringList languages = plugin->languages(key);
   107             QStringList languages = plugin->languages(key);
   107             QList<HbInputModeProperties> modeList;
   108             QList<HbInputModeProperties> modeList;
   108             foreach (QString language, languages) {
   109             foreach(const QString &language, languages) {
   109                   modeList.append(propertiesFromString(language));
   110                 modeList.append(propertiesFromString(language));
   110             }
   111             }
   111             result->d_ptr->mInputModes = modeList;
   112             result->d_ptr->mInputModes = modeList;
   112         }
   113         }
   113         return result;
   114         return result;
   114     }
   115     }
   128         mMethods[k].toBeRemoved = true;
   129         mMethods[k].toBeRemoved = true;
   129     }
   130     }
   130 
   131 
   131     // Query plugin paths and scan the folders.
   132     // Query plugin paths and scan the folders.
   132     QStringList folders = HbInputSettingProxy::instance()->inputMethodPluginPaths();
   133     QStringList folders = HbInputSettingProxy::instance()->inputMethodPluginPaths();
   133     foreach (QString folder, folders) {
   134     foreach(const QString &folder, folders) {
   134         QDir dir(folder);
   135         QDir dir(folder);
   135         for (unsigned int i = 0; i < dir.count(); i++) {
   136         for (unsigned int i = 0; i < dir.count(); i++) {
   136             QString path = QString(dir.absolutePath());
   137             QString path = QString(dir.absolutePath());
   137             if (path.right(1) != "\\" && path.right(1) != "/") {
   138             if (path.right(1) != "\\" && path.right(1) != "/") {
   138                 path += QDir::separator();
   139                 path += QDir::separator();
   139             }
   140             }
   140             path += dir[i];
   141             path += dir[i];
   141             QInputContextPlugin* inputContextPlugin = pluginInstance(path);
   142             QInputContextPlugin *inputContextPlugin = pluginInstance(path);
   142             if (inputContextPlugin) {
   143             if (inputContextPlugin) {
   143                 HbInputMethodListItem listItem;
   144                 HbInputMethodListItem listItem;
   144                 listItem.descriptor.setPluginNameAndPath(dir.absolutePath() + QDir::separator() + dir[i]);
   145                 listItem.descriptor.setPluginNameAndPath(dir.absolutePath() + QDir::separator() + dir[i]);
   145 
   146 
   146                 // For each found plugin, check if there is already a list item for it.
   147                 // For each found plugin, check if there is already a list item for it.
   147                 // If not, then add one.
   148                 // If not, then add one.
   148                 QStringList contextKeys = inputContextPlugin->keys();
   149                 QStringList contextKeys = inputContextPlugin->keys();
   149                 foreach (QString key, contextKeys) {
   150                 foreach(const QString &key, contextKeys) {
   150                     listItem.descriptor.setKey(key);
   151                     listItem.descriptor.setKey(key);
   151                     listItem.descriptor.setDisplayName(inputContextPlugin->displayName(key));
   152                     listItem.descriptor.setDisplayName(inputContextPlugin->displayName(key));
   152 
   153 
   153                     int index = mMethods.indexOf(listItem);
   154                     int index = mMethods.indexOf(listItem);
   154                     if (index >= 0) {
   155                     if (index >= 0) {
   182                 }
   183                 }
   183 
   184 
   184                 // Replace it with null input context.
   185                 // Replace it with null input context.
   185                 HbInputMethod *master = HbInputMethodNull::Instance();
   186                 HbInputMethod *master = HbInputMethodNull::Instance();
   186                 master->d_ptr->mIsActive = true;
   187                 master->d_ptr->mIsActive = true;
   187                 QInputContext* proxy = master->d_ptr->proxy();
   188                 QInputContext *proxy = master->d_ptr->proxy();
   188                 if (proxy != qApp->inputContext())
   189                 if (proxy != qApp->inputContext()) {
   189                     qApp->setInputContext(proxy);
   190                     qApp->setInputContext(proxy);
       
   191                 }
   190             }
   192             }
   191             delete mMethods[i].cached;
   193             delete mMethods[i].cached;
   192             mMethods.removeAt(i);
   194             mMethods.removeAt(i);
   193             i--;
   195             i--;
   194         }
   196         }
   197 
   199 
   198 HbInputModeProperties HbInputModeCachePrivate::propertiesFromString(const QString &entry) const
   200 HbInputModeProperties HbInputModeCachePrivate::propertiesFromString(const QString &entry) const
   199 {
   201 {
   200     HbInputModeProperties result;
   202     HbInputModeProperties result;
   201 
   203 
   202     QStringList parts = entry.split(" ");
   204     QStringList parts = entry.split(' ');
   203     if (parts.count() == 4) {
   205     if (parts.count() == 4) {
   204         // See HbInputModeProperties::toString() for details,
   206         // See HbInputModeProperties::toString() for details,
   205         QString languageStr = parts[0] + QString(" ") + parts[1];
   207         QString languageStr = parts[0] + QString(" ") + parts[1];
   206         HbInputLanguage language;
   208         HbInputLanguage language;
   207         language.fromString(languageStr);
   209         language.fromString(languageStr);
   239     if (!watchedDirs.isEmpty()) {
   241     if (!watchedDirs.isEmpty()) {
   240         mWatcher->removePaths(watchedDirs);
   242         mWatcher->removePaths(watchedDirs);
   241     }
   243     }
   242 
   244 
   243     QStringList paths = HbInputSettingProxy::instance()->inputMethodPluginPaths();
   245     QStringList paths = HbInputSettingProxy::instance()->inputMethodPluginPaths();
   244     foreach (QString path, paths) {
   246     foreach(const QString &path, paths) {
   245         QDir dir(path);
   247         QDir dir(path);
   246         if (!dir.exists() && path.left(1) == "f") {
   248         if (!dir.exists() && path.left(1) == "f") {
   247             mWatcher->addPath(QString("f:") + QDir::separator());
   249             mWatcher->addPath(QString("f:") + QDir::separator());
   248         } else {
   250         } else {
   249             mWatcher->addPath(path);
   251             mWatcher->addPath(path);
   253 
   255 
   254 bool HbInputModeCachePrivate::isMappedLanguage(const HbInputLanguage &language) const
   256 bool HbInputModeCachePrivate::isMappedLanguage(const HbInputLanguage &language) const
   255 {
   257 {
   256     if (language.defined()) {
   258     if (language.defined()) {
   257         QList<HbInputLanguage> languages = HbKeymapFactory::instance()->availableLanguages();
   259         QList<HbInputLanguage> languages = HbKeymapFactory::instance()->availableLanguages();
   258         foreach (const HbInputLanguage mappedLanguage, languages) {
   260         foreach(const HbInputLanguage &mappedLanguage, languages) {
   259             if (mappedLanguage == language) {
   261             if (mappedLanguage == language) {
   260                 return true;
   262                 return true;
   261             }
   263             }
   262         }
   264         }
   263     }
   265     }
   269 
   271 
   270 /*!
   272 /*!
   271 \internal
   273 \internal
   272 Returns the singleton instance.
   274 Returns the singleton instance.
   273 */
   275 */
   274 HbInputModeCache* HbInputModeCache::instance()
   276 HbInputModeCache *HbInputModeCache::instance()
   275 {
   277 {
   276     static HbInputModeCache theCache;
   278     static HbInputModeCache theCache;
   277     return &theCache;
   279     return &theCache;
   278 }
   280 }
   279 
   281 
   327 void HbInputModeCache::shutdown()
   329 void HbInputModeCache::shutdown()
   328 {
   330 {
   329     Q_D(HbInputModeCache);
   331     Q_D(HbInputModeCache);
   330     d->mShuttingDown = true;
   332     d->mShuttingDown = true;
   331 
   333 
   332     foreach (HbInputMethodListItem method, d->mMethods) {
   334     foreach(HbInputMethodListItem method, d->mMethods) {
   333         delete method.cached;
   335         delete method.cached;
   334         method.cached = 0;
   336         method.cached = 0;
   335     }
   337     }
   336     d->mMethods.clear();
   338     d->mMethods.clear();
   337     delete d->mWatcher;
   339     delete d->mWatcher;
   340 
   342 
   341 /*!
   343 /*!
   342 \internal
   344 \internal
   343 Loads given input method and caches it.
   345 Loads given input method and caches it.
   344 */
   346 */
   345 HbInputMethod* HbInputModeCache::loadInputMethod(const HbInputMethodDescriptor &inputMethod)
   347 HbInputMethod *HbInputModeCache::loadInputMethod(const HbInputMethodDescriptor &inputMethod)
   346 {
   348 {
   347     Q_D(HbInputModeCache);
   349     Q_D(HbInputModeCache);
   348 
   350 
   349     for (int i = 0; i < d->mMethods.count(); i++) {
   351     for (int i = 0; i < d->mMethods.count(); i++) {
   350         if (d->mMethods[i].descriptor.pluginNameAndPath() == inputMethod.pluginNameAndPath() &&
   352         if (d->mMethods[i].descriptor.pluginNameAndPath() == inputMethod.pluginNameAndPath() &&
   368 {
   370 {
   369     Q_D(HbInputModeCache);
   371     Q_D(HbInputModeCache);
   370 
   372 
   371     QList<HbInputMethodDescriptor> result;
   373     QList<HbInputMethodDescriptor> result;
   372 
   374 
   373     foreach (HbInputMethodListItem item, d->mMethods) {
   375     foreach(const HbInputMethodListItem &item, d->mMethods) {
   374         foreach (QString language, item.languages) {
   376         foreach(const QString &language, item.languages) {
   375             HbInputModeProperties properties = d->propertiesFromString(language);
   377             HbInputModeProperties properties = d->propertiesFromString(language);
   376             if (properties.inputMode() == HbInputModeCustom) {
   378             if (properties.inputMode() == HbInputModeCustom) {
   377                 result.append(item.descriptor);
   379                 result.append(item.descriptor);
   378                 break;
   380                 break;
   379             }
   381             }
   385 
   387 
   386 /*!
   388 /*!
   387 \internal
   389 \internal
   388 Find correct handler for given input state.
   390 Find correct handler for given input state.
   389 */
   391 */
   390 HbInputMethod* HbInputModeCache::findStateHandler(const HbInputState& state)
   392 HbInputMethod *HbInputModeCache::findStateHandler(const HbInputState &state)
   391 {
   393 {
   392     Q_D(HbInputModeCache);
   394     Q_D(HbInputModeCache);
   393 
   395 
   394     HbInputModeProperties stateProperties = d->propertiesFromState(state);
   396     HbInputModeProperties stateProperties = d->propertiesFromState(state);
   395     int languageRangeIndex = -1;    
   397     int languageRangeIndex = -1;
   396 
   398 
   397     // First check if there is a method that matches excatly (ie. also specifies
   399     // First check if there is a method that matches excatly (ie. also specifies
   398     // the language).
   400     // the language).
   399     for (int i = 0; i < d->mMethods.count(); i++) {
   401     for (int i = 0; i < d->mMethods.count(); i++) {
   400         foreach (QString language, d->mMethods[i].languages) {
   402         foreach(const QString &language, d->mMethods[i].languages) {
   401             HbInputModeProperties properties = d->propertiesFromString(language);
   403             HbInputModeProperties properties = d->propertiesFromString(language);
   402             if (properties.language().undefined() &&
   404             if (properties.language().undefined() &&
   403                 properties.keyboard() == stateProperties.keyboard() &&
   405                 properties.keyboard() == stateProperties.keyboard() &&
   404                 properties.inputMode() == stateProperties.inputMode()) {
   406                 properties.inputMode() == stateProperties.inputMode()) {
   405                 // Remember the index, we'll need this in the next phase if no exact
   407                 // Remember the index, we'll need this in the next phase if no exact
   419     // range, meaning that the language is left unspecified in which case we'll
   421     // range, meaning that the language is left unspecified in which case we'll
   420     // use key mapping factory for matching.
   422     // use key mapping factory for matching.
   421     if (languageRangeIndex >= 0) {
   423     if (languageRangeIndex >= 0) {
   422         QList<HbInputLanguage> languages = HbKeymapFactory::instance()->availableLanguages();
   424         QList<HbInputLanguage> languages = HbKeymapFactory::instance()->availableLanguages();
   423 
   425 
   424         foreach(HbInputLanguage language, languages) {
   426         foreach(const HbInputLanguage &language, languages) {
   425             // exact match is returned If the country variant is specified in state language,
   427             // exact match is returned If the country variant is specified in state language,
   426             // otherwise a method that matches to only language range is returned.
   428             // otherwise a method that matches to only language range is returned.
   427             bool exactMatchFound = (stateProperties.language().variant() != QLocale::AnyCountry) ?
   429             bool exactMatchFound = (stateProperties.language().variant() != QLocale::AnyCountry) ?
   428                 (language == stateProperties.language()) :
   430                                    (language == stateProperties.language()) :
   429                 (language.language() == stateProperties.language().language());
   431                                    (language.language() == stateProperties.language().language());
   430             if (exactMatchFound) {
   432             if (exactMatchFound) {
   431                 return d->cachedMethod(d->mMethods[languageRangeIndex]);
   433                 return d->cachedMethod(d->mMethods[languageRangeIndex]);
   432             }
   434             }
   433         }
   435         }
   434     }
   436     }
   440 \internal
   442 \internal
   441 Returns the active input method.
   443 Returns the active input method.
   442 
   444 
   443 \sa HbInputMethod
   445 \sa HbInputMethod
   444 */
   446 */
   445 HbInputMethod* HbInputModeCache::activeMethod() const
   447 HbInputMethod *HbInputModeCache::activeMethod() const
   446 {
   448 {
   447     Q_D(const HbInputModeCache);
   449     Q_D(const HbInputModeCache);
   448 
   450 
   449     foreach (HbInputMethodListItem item, d->mMethods) {
   451     foreach(const HbInputMethodListItem &item, d->mMethods) {
   450         if (item.cached && item.cached->isActiveMethod()) {
   452         if (item.cached && item.cached->isActiveMethod()) {
   451             return item.cached;
   453             return item.cached;
   452         }
   454         }
   453     }
   455     }
   454 
   456 
   463 {
   465 {
   464     Q_D(const HbInputModeCache);
   466     Q_D(const HbInputModeCache);
   465 
   467 
   466     QList<HbInputLanguage> result;
   468     QList<HbInputLanguage> result;
   467 
   469 
   468     foreach (HbInputMethodListItem item, d->mMethods) {
   470     foreach(const HbInputMethodListItem &item, d->mMethods) {
   469         foreach (QString language, item.languages) {
   471         foreach(const QString &language, item.languages) {
   470             HbInputModeProperties mode = d->propertiesFromString(language);
   472             HbInputModeProperties mode = d->propertiesFromString(language);
   471             if (mode.inputMode() != HbInputModeCustom) {
   473             if (mode.inputMode() != HbInputModeCustom) {
   472                 if (mode.language().undefined()) {
   474                 if (mode.language().undefined()) {
   473                     // This is language range. Let's add everything
   475                     // This is language range. Let's add everything
   474                     // we have key mappings for.
   476                     // we have key mappings for.
   475                     QList<HbInputLanguage> languages = HbKeymapFactory::instance()->availableLanguages();
   477                     QList<HbInputLanguage> languages = HbKeymapFactory::instance()->availableLanguages();
   476                     foreach (HbInputLanguage mappedLanguage, languages) {
   478                     foreach(const HbInputLanguage &mappedLanguage, languages) {
   477                         if (!result.contains(mappedLanguage)) {
   479                         if (!result.contains(mappedLanguage)) {
   478                             result.append(mappedLanguage);
   480                             result.append(mappedLanguage);
   479                         }
   481                         }
   480                     }
   482                     }
   481                 } else {
   483                 } else {
   496 */
   498 */
   497 bool HbInputModeCache::acceptsState(const HbInputMethod *inputMethod, const HbInputState &state) const
   499 bool HbInputModeCache::acceptsState(const HbInputMethod *inputMethod, const HbInputState &state) const
   498 {
   500 {
   499     Q_D(const HbInputModeCache);
   501     Q_D(const HbInputModeCache);
   500 
   502 
   501     foreach (const HbInputMethodListItem item, d->mMethods) {
   503     foreach(const HbInputMethodListItem &item, d->mMethods) {
   502         if (item.cached == inputMethod) {           
   504         if (item.cached == inputMethod) {
   503             foreach (const QString language, item.languages) {
   505             foreach(const QString &language, item.languages) {
   504                 HbInputModeProperties mode = d->propertiesFromString(language);
   506                 HbInputModeProperties mode = d->propertiesFromString(language);
   505                 // Check if keyboard type matches.
   507                 // Check if keyboard type matches.
   506                 if (mode.keyboard() == state.keyboard()) {
   508                 if (mode.keyboard() == state.keyboard()) {
   507                     // Check if input mode matches or it is a custom input method but
   509                     // Check if input mode matches or it is a custom input method but
   508                     // state's mode is not numeric.
   510                     // state's mode is not numeric.
   531 */
   533 */
   532 HbInputMethodDescriptor HbInputModeCache::descriptor(const HbInputMethod *inputMethod) const
   534 HbInputMethodDescriptor HbInputModeCache::descriptor(const HbInputMethod *inputMethod) const
   533 {
   535 {
   534     Q_D(const HbInputModeCache);
   536     Q_D(const HbInputModeCache);
   535 
   537 
   536     foreach (HbInputMethodListItem item, d->mMethods) {
   538     foreach(const HbInputMethodListItem &item, d->mMethods) {
   537         if (item.cached == inputMethod) {
   539         if (item.cached == inputMethod) {
   538             return item.descriptor;
   540             return item.descriptor;
   539         }
   541         }
   540     }
   542     }
   541 
   543