src/hbservers/hbinputserver/hbinputservermethods.cpp
author hgs
Mon, 18 Oct 2010 18:23:13 +0300
changeset 34 ed14f46c0e55
permissions -rw-r--r--
201041
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
34
hgs
parents:
diff changeset
     1
/****************************************************************************
hgs
parents:
diff changeset
     2
**
hgs
parents:
diff changeset
     3
** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
hgs
parents:
diff changeset
     4
** All rights reserved.
hgs
parents:
diff changeset
     5
** Contact: Nokia Corporation (developer.feedback@nokia.com)
hgs
parents:
diff changeset
     6
**
hgs
parents:
diff changeset
     7
** This file is part of the HbServers module of the UI Extensions for Mobile.
hgs
parents:
diff changeset
     8
**
hgs
parents:
diff changeset
     9
** GNU Lesser General Public License Usage
hgs
parents:
diff changeset
    10
** This file may be used under the terms of the GNU Lesser General Public
hgs
parents:
diff changeset
    11
** License version 2.1 as published by the Free Software Foundation and
hgs
parents:
diff changeset
    12
** appearing in the file LICENSE.LGPL included in the packaging of this file.
hgs
parents:
diff changeset
    13
** Please review the following information to ensure the GNU Lesser General
hgs
parents:
diff changeset
    14
** Public License version 2.1 requirements will be met:
hgs
parents:
diff changeset
    15
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
hgs
parents:
diff changeset
    16
**
hgs
parents:
diff changeset
    17
** In addition, as a special exception, Nokia gives you certain additional
hgs
parents:
diff changeset
    18
** rights.  These rights are described in the Nokia Qt LGPL Exception
hgs
parents:
diff changeset
    19
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
hgs
parents:
diff changeset
    20
**
hgs
parents:
diff changeset
    21
** If you have questions regarding the use of this file, please contact
hgs
parents:
diff changeset
    22
** Nokia at developer.feedback@nokia.com.
hgs
parents:
diff changeset
    23
**
hgs
parents:
diff changeset
    24
****************************************************************************/
hgs
parents:
diff changeset
    25
hgs
parents:
diff changeset
    26
#include "hbinputservermethods_p.h"
hgs
parents:
diff changeset
    27
hgs
parents:
diff changeset
    28
#include <QDateTime>
hgs
parents:
diff changeset
    29
#include <QBuffer>
hgs
parents:
diff changeset
    30
#include <QFileSystemWatcher>
hgs
parents:
diff changeset
    31
#include <QSharedMemory>
hgs
parents:
diff changeset
    32
#include <hbinputsettingproxy.h>
hgs
parents:
diff changeset
    33
#include <hbinputmodecache_p_p.h>
hgs
parents:
diff changeset
    34
hgs
parents:
diff changeset
    35
HbInputServerMethods::HbInputServerMethods(HbInputServer *server)
hgs
parents:
diff changeset
    36
    : mServer(server),
hgs
parents:
diff changeset
    37
      mSharedMethods(0),
hgs
parents:
diff changeset
    38
      mSharedMethodsModTime(0),
hgs
parents:
diff changeset
    39
      mMethods(0),
hgs
parents:
diff changeset
    40
      mMethodsSerialized(new QByteArray()),
hgs
parents:
diff changeset
    41
      mMethodPathWatcher(0)
hgs
parents:
diff changeset
    42
{
hgs
parents:
diff changeset
    43
}
hgs
parents:
diff changeset
    44
hgs
parents:
diff changeset
    45
HbInputServerMethods::~HbInputServerMethods()
hgs
parents:
diff changeset
    46
{
hgs
parents:
diff changeset
    47
    delete mMethodsSerialized;
hgs
parents:
diff changeset
    48
    delete mSharedMethods;
hgs
parents:
diff changeset
    49
    delete mSharedMethodsModTime;
hgs
parents:
diff changeset
    50
    delete mMethods;
hgs
parents:
diff changeset
    51
    delete mMethodPathWatcher;
hgs
parents:
diff changeset
    52
}
hgs
parents:
diff changeset
    53
hgs
parents:
diff changeset
    54
/*
hgs
parents:
diff changeset
    55
Initializes input method sharing.
hgs
parents:
diff changeset
    56
hgs
parents:
diff changeset
    57
Creates shared memories for input method list and its latest modification time.
hgs
parents:
diff changeset
    58
Initializes the list based on available input method plugins and updates the modification time.
hgs
parents:
diff changeset
    59
hgs
parents:
diff changeset
    60
Returns true on success, false if not able to create shared memories.
hgs
parents:
diff changeset
    61
*/
hgs
parents:
diff changeset
    62
bool HbInputServerMethods::initialize()
hgs
parents:
diff changeset
    63
{
hgs
parents:
diff changeset
    64
    mServer->debugPrint("Initializing input mode cache");
hgs
parents:
diff changeset
    65
    // Create shared memory block with last modification time
hgs
parents:
diff changeset
    66
    mSharedMethodsModTime = new QSharedMemory(HbInputMethodListModTimeKey);
hgs
parents:
diff changeset
    67
    if (!mSharedMethodsModTime->create(sizeof(uint))) {
hgs
parents:
diff changeset
    68
        mServer->debugPrint("Unable to create method list mod time shared memory block!");
hgs
parents:
diff changeset
    69
        return false;
hgs
parents:
diff changeset
    70
    }
hgs
parents:
diff changeset
    71
    // Read mode data from disk to local structure
hgs
parents:
diff changeset
    72
    updateLocalInputMethodList();
hgs
parents:
diff changeset
    73
    // Create shared memory object for mode cache
hgs
parents:
diff changeset
    74
    mSharedMethods = new QSharedMemory(HbInputMethodListKey);
hgs
parents:
diff changeset
    75
hgs
parents:
diff changeset
    76
    updateSharedMethodList();
hgs
parents:
diff changeset
    77
hgs
parents:
diff changeset
    78
    startMonitoringMethodListChanges();
hgs
parents:
diff changeset
    79
hgs
parents:
diff changeset
    80
    mServer->debugPrint("Input mode cache initialized");
hgs
parents:
diff changeset
    81
hgs
parents:
diff changeset
    82
    return true;
hgs
parents:
diff changeset
    83
}
hgs
parents:
diff changeset
    84
hgs
parents:
diff changeset
    85
/*
hgs
parents:
diff changeset
    86
Updates shared input methods list based on local list, updates modification time.
hgs
parents:
diff changeset
    87
*/
hgs
parents:
diff changeset
    88
void HbInputServerMethods::updateSharedMethodList()
hgs
parents:
diff changeset
    89
{
hgs
parents:
diff changeset
    90
    mServer->debugPrint("Updating shared memory for input methods");
hgs
parents:
diff changeset
    91
    if (!mSharedMethods->isAttached()) {
hgs
parents:
diff changeset
    92
        // If shared memory block is not attached, it should be created first
hgs
parents:
diff changeset
    93
        mServer->debugPrint("Creating shared memory for input methods");
hgs
parents:
diff changeset
    94
        mSharedMethods->create(mMethodsSerialized->size()+sizeof(int));
hgs
parents:
diff changeset
    95
    } else if (mSharedMethods->size() < static_cast<int>(mMethodsSerialized->size()+sizeof(int))) {
hgs
parents:
diff changeset
    96
        // If the shared memory block is too small, detach from it and recreate it
hgs
parents:
diff changeset
    97
        mServer->debugPrint("Re-creating shared memory for input methods");
hgs
parents:
diff changeset
    98
        mSharedMethods->detach();
hgs
parents:
diff changeset
    99
        bool success = mSharedMethods->create(mMethodsSerialized->size()+sizeof(int));
hgs
parents:
diff changeset
   100
        if (!success) {
hgs
parents:
diff changeset
   101
            mServer->debugPrint("Re-creating shared memory for input methods failed, error: "
hgs
parents:
diff changeset
   102
                                + mSharedMethods->errorString());
hgs
parents:
diff changeset
   103
        }
hgs
parents:
diff changeset
   104
    }
hgs
parents:
diff changeset
   105
hgs
parents:
diff changeset
   106
    // Externalize data from local structure to shared memory
hgs
parents:
diff changeset
   107
    // Data size needs to be saved, since QSharedMemory is reserved in bigger blocks
hgs
parents:
diff changeset
   108
    // and we can't make a block of exactly the required size
hgs
parents:
diff changeset
   109
    mSharedMethods->lock();
hgs
parents:
diff changeset
   110
    *static_cast<int*>(mSharedMethods->data()) = mMethodsSerialized->size();
hgs
parents:
diff changeset
   111
    memcpy(static_cast<char*>(mSharedMethods->data())+sizeof(int), mMethodsSerialized->constData(), mMethodsSerialized->size());
hgs
parents:
diff changeset
   112
    mSharedMethods->unlock();
hgs
parents:
diff changeset
   113
hgs
parents:
diff changeset
   114
    // Update modification time
hgs
parents:
diff changeset
   115
    mSharedMethodsModTime->lock();
hgs
parents:
diff changeset
   116
    *static_cast<uint*>(mSharedMethodsModTime->data()) = QDateTime::currentDateTime().toTime_t();
hgs
parents:
diff changeset
   117
    mSharedMethodsModTime->unlock();
hgs
parents:
diff changeset
   118
    mServer->debugPrint("Shared memory for input methods updated");
hgs
parents:
diff changeset
   119
}
hgs
parents:
diff changeset
   120
hgs
parents:
diff changeset
   121
/*
hgs
parents:
diff changeset
   122
Updates local copy of input methods list based on available input method plugins.
hgs
parents:
diff changeset
   123
If path is given, updates only the methods in that directory.
hgs
parents:
diff changeset
   124
*/
hgs
parents:
diff changeset
   125
void HbInputServerMethods::updateLocalInputMethodList(const QString &path)
hgs
parents:
diff changeset
   126
{
hgs
parents:
diff changeset
   127
    mServer->debugPrint("Updating local copy of methods list");
hgs
parents:
diff changeset
   128
    if (!mMethods) {
hgs
parents:
diff changeset
   129
        mMethods = new QList<HbInputMethodListItem>();
hgs
parents:
diff changeset
   130
    }
hgs
parents:
diff changeset
   131
    if (!path.isEmpty()) {
hgs
parents:
diff changeset
   132
        HbInputModeCachePrivate::readInputMethodDataFromDisk(mMethods, QDir(path));
hgs
parents:
diff changeset
   133
    } else  {
hgs
parents:
diff changeset
   134
        HbInputModeCachePrivate::readInputMethodDataFromDisk(mMethods);
hgs
parents:
diff changeset
   135
    }
hgs
parents:
diff changeset
   136
hgs
parents:
diff changeset
   137
    // Clear deleted items from the list
hgs
parents:
diff changeset
   138
    for (int i = mMethods->size()-1; i >= 0 ; --i) {
hgs
parents:
diff changeset
   139
        if (mMethods->at(i).toBeRemoved) {
hgs
parents:
diff changeset
   140
            mMethods->removeAt(i);
hgs
parents:
diff changeset
   141
        }
hgs
parents:
diff changeset
   142
    }
hgs
parents:
diff changeset
   143
hgs
parents:
diff changeset
   144
    mServer->debugPrint("Number of methods: " + QString::number(mMethods->count()));
hgs
parents:
diff changeset
   145
hgs
parents:
diff changeset
   146
    QBuffer buffer(mMethodsSerialized);
hgs
parents:
diff changeset
   147
    buffer.open(QIODevice::WriteOnly);
hgs
parents:
diff changeset
   148
hgs
parents:
diff changeset
   149
    QDataStream out(&buffer);
hgs
parents:
diff changeset
   150
    out << *mMethods;
hgs
parents:
diff changeset
   151
    mServer->debugPrint("Method list updated, new size: " + QString::number(mMethodsSerialized->size()));
hgs
parents:
diff changeset
   152
}
hgs
parents:
diff changeset
   153
hgs
parents:
diff changeset
   154
/*
hgs
parents:
diff changeset
   155
Sets up directory watchers etc. to monitor changes in input method plugins.
hgs
parents:
diff changeset
   156
*/
hgs
parents:
diff changeset
   157
void HbInputServerMethods::startMonitoringMethodListChanges()
hgs
parents:
diff changeset
   158
{
hgs
parents:
diff changeset
   159
    mServer->debugPrint("Setting up change monitoring for input methods");
hgs
parents:
diff changeset
   160
    if (mMethodPathWatcher) {
hgs
parents:
diff changeset
   161
        mServer->debugPrint("Directory watcher already exists, deleting");
hgs
parents:
diff changeset
   162
        delete mMethodPathWatcher;
hgs
parents:
diff changeset
   163
    }
hgs
parents:
diff changeset
   164
hgs
parents:
diff changeset
   165
    mMethodPathWatcher = new QFileSystemWatcher();
hgs
parents:
diff changeset
   166
hgs
parents:
diff changeset
   167
    // Get the list of plugin paths, remove ROM drive from the paths if it's there
hgs
parents:
diff changeset
   168
    QStringList directoriesToWatch = HbInputSettingProxy::inputMethodPluginPaths();
hgs
parents:
diff changeset
   169
    foreach(const QString& path, directoriesToWatch) {
hgs
parents:
diff changeset
   170
        if (path.length() > 0 && path.at(0) == 'z') {
hgs
parents:
diff changeset
   171
            directoriesToWatch.removeOne(path);
hgs
parents:
diff changeset
   172
        }
hgs
parents:
diff changeset
   173
    }
hgs
parents:
diff changeset
   174
hgs
parents:
diff changeset
   175
    // TODO: Create directories to watch on non-removable drives (c, e on symbian) if they don't exist
hgs
parents:
diff changeset
   176
    mMethodPathWatcher->addPaths(directoriesToWatch);
hgs
parents:
diff changeset
   177
    connect(mMethodPathWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(changeInMethodDirectory(QString)));
hgs
parents:
diff changeset
   178
    mServer->debugPrint("Input method path watcher setup done");
hgs
parents:
diff changeset
   179
hgs
parents:
diff changeset
   180
    // TODO: Set up MMC handling
hgs
parents:
diff changeset
   181
}
hgs
parents:
diff changeset
   182
hgs
parents:
diff changeset
   183
/*
hgs
parents:
diff changeset
   184
Slot directory watchers call when something changes.
hgs
parents:
diff changeset
   185
*/
hgs
parents:
diff changeset
   186
void HbInputServerMethods::changeInMethodDirectory(const QString &path)
hgs
parents:
diff changeset
   187
{
hgs
parents:
diff changeset
   188
    mServer->debugPrint("Change in method path detected, path: " + path);
hgs
parents:
diff changeset
   189
    updateLocalInputMethodList(path);
hgs
parents:
diff changeset
   190
    updateSharedMethodList();
hgs
parents:
diff changeset
   191
}