aboutsummaryrefslogtreecommitdiffstats
path: root/src/virtualkeyboard/lipiinputmethod.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/virtualkeyboard/lipiinputmethod.cpp')
-rw-r--r--src/virtualkeyboard/lipiinputmethod.cpp624
1 files changed, 0 insertions, 624 deletions
diff --git a/src/virtualkeyboard/lipiinputmethod.cpp b/src/virtualkeyboard/lipiinputmethod.cpp
deleted file mode 100644
index 5bb1d46c..00000000
--- a/src/virtualkeyboard/lipiinputmethod.cpp
+++ /dev/null
@@ -1,624 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "lipiinputmethod.h"
-#include "lipisharedrecognizer.h"
-#include "inputengine.h"
-#include "inputcontext.h"
-#include "shifthandler.h"
-#include "virtualkeyboarddebug.h"
-#include "trace.h"
-#include "handwritinggesturerecognizer.h"
-
-#ifdef HAVE_HUNSPELL
-#include "hunspellinputmethod_p.h"
-#endif
-
-#include "LTKCaptureDevice.h"
-#include "LTKScreenContext.h"
-#include "LTKTraceGroup.h"
-#include "LTKChannel.h"
-#include "LTKTraceFormat.h"
-#include "LTKTrace.h"
-#include "LTKShapeRecoResult.h"
-
-#include <QCryptographicHash>
-
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
-#include "unipentrace.h"
-#include <QStandardPaths>
-#endif
-
-#ifdef HAVE_HUNSPELL
-#define LipiInputMethodPrivateBase HunspellInputMethodPrivate
-#else
-#define LipiInputMethodPrivateBase AbstractInputMethodPrivate
-#endif
-
-namespace QtVirtualKeyboard {
-
-class LipiInputMethodPrivate : public LipiInputMethodPrivateBase
-{
- Q_DECLARE_PUBLIC(LipiInputMethod)
-public:
- LipiInputMethodPrivate(LipiInputMethod *q_ptr) :
-#ifdef HAVE_HUNSPELL
- LipiInputMethodPrivateBase(static_cast<HunspellInputMethod *>(q_ptr)),
-#else
- LipiInputMethodPrivateBase(),
-#endif
- q_ptr(q_ptr),
- recognizeTimer(0),
- textCase(InputEngine::Lower)
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
- , unipenTrace(0)
-#endif
- {
- }
-
- ~LipiInputMethodPrivate()
- {
- cancelRecognition();
- }
-
- QByteArray getContext(InputEngine::PatternRecognitionMode patternRecognitionMode,
- const QVariantMap &traceCaptureDeviceInfo,
- const QVariantMap &traceScreenInfo) const
- {
- QCryptographicHash hash(QCryptographicHash::Md5);
-
- hash.addData((const char *)&patternRecognitionMode, sizeof(patternRecognitionMode));
-
- QByteArray mapData;
- QDataStream ds(&mapData, QIODevice::WriteOnly);
- ds << traceCaptureDeviceInfo;
- ds << traceScreenInfo;
- hash.addData(mapData);
-
- return hash.result();
- }
-
- void setContext(InputEngine::PatternRecognitionMode patternRecognitionMode,
- const QVariantMap &traceCaptureDeviceInfo,
- const QVariantMap &traceScreenInfo)
- {
- QByteArray context = getContext(patternRecognitionMode, traceCaptureDeviceInfo, traceScreenInfo);
- if (context == currentContext)
- return;
-
- VIRTUALKEYBOARD_DEBUG() << "LipiInputMethodPrivate::setContext():" << QString(context.toHex());
-
- clearTraces();
-
- deviceInfo.reset(new LTKCaptureDevice());
- deviceInfo->setSamplingRate(traceCaptureDeviceInfo.value("sampleRate", 60).toInt());
- deviceInfo->setXDPI(traceCaptureDeviceInfo.value("dpi", 96).toInt());
- deviceInfo->setYDPI(deviceInfo->getXDPI());
- deviceInfo->setLatency(traceCaptureDeviceInfo.value("latency", 0.0).toFloat());
- deviceInfo->setUniformSampling(traceCaptureDeviceInfo.value("uniform", false).toBool());
-
- screenContext.reset(new LTKScreenContext());
- QRectF boundingBox(traceScreenInfo.value("boundingBox").toRectF());
- if (!boundingBox.isEmpty()) {
- screenContext->setBboxLeft(boundingBox.left());
- screenContext->setBboxTop(boundingBox.top());
- screenContext->setBboxRight(boundingBox.right());
- screenContext->setBboxBottom(boundingBox.bottom());
- }
-
- QVariantList horizontalRulers(traceScreenInfo.value("horizontalRulers", QVariantList()).toList());
- if (!horizontalRulers.isEmpty()) {
- for (QVariantList::ConstIterator i = horizontalRulers.constBegin();
- i != horizontalRulers.constEnd(); i++) {
- screenContext->addHLine(i->toFloat());
- }
- }
-
- QVariantList verticalRulers(traceScreenInfo.value("verticalRulers", QVariantList()).toList());
- if (!horizontalRulers.isEmpty()) {
- for (QVariantList::ConstIterator i = verticalRulers.constBegin();
- i != verticalRulers.constEnd(); i++) {
- screenContext->addVLine(i->toFloat());
- }
- }
-
- gestureRecognizer.setDpi(deviceInfo->getXDPI());
-
- currentContext = context;
- }
-
- Trace *traceBegin(int traceId, InputEngine::PatternRecognitionMode patternRecognitionMode,
- const QVariantMap &traceCaptureDeviceInfo, const QVariantMap &traceScreenInfo)
- {
- Q_UNUSED(traceId)
-
- stopRecognizeTimer();
-
- setContext(patternRecognitionMode, traceCaptureDeviceInfo, traceScreenInfo);
-
- if (recognitionTask) {
- recognizer.cancelRecognitionTask(recognitionTask);
- recognitionTask.reset();
- delayedResult.clear();
- }
-
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
- if (!unipenTrace) {
- Q_Q(LipiInputMethod);
- unipenTrace = new UnipenTrace(traceCaptureDeviceInfo, traceScreenInfo, q);
- }
-#endif
-
- Trace *trace = new Trace();
- trace->setChannels(QStringList("t"));
- traceList.append(trace);
-
- return trace;
- }
-
- void traceEnd(Trace *trace)
- {
- if (trace->isCanceled()) {
- VIRTUALKEYBOARD_DEBUG() << "LipiInputMethodPrivate::traceEnd(): discarded" << trace;
- traceList.removeOne(trace);
- delete trace;
- } else {
- addPointsToTraceGroup(trace);
- }
- handleGesture();
- if (!traceList.isEmpty() && countActiveTraces() == 0)
- restartRecognition();
- }
-
- int countActiveTraces() const
- {
- int count = 0;
- for (Trace *trace : qAsConst(traceList)) {
- if (!trace->isFinal())
- count++;
- }
- return count;
- }
-
- void handleGesture()
- {
- if (countActiveTraces() > 0)
- return;
-
- QVariantMap gesture = gestureRecognizer.recognize(traceList);
- if (gesture.isEmpty())
- return;
-
- VIRTUALKEYBOARD_DEBUG() << "LipiInputMethodPrivate::handleGesture():" << gesture;
-
- if (gesture[QLatin1String("type")].toString() == QLatin1String("swipe")) {
-
- static const int SWIPE_MIN_LENGTH = 25; // mm
- static const int SWIPE_ANGLE_THRESHOLD = 15; // degrees +-
-
- qreal swipeLength = gesture[QLatin1String("length_mm")].toReal();
- if (swipeLength >= SWIPE_MIN_LENGTH) {
-
- Q_Q(LipiInputMethod);
- InputContext *ic = q->inputContext();
- if (!ic)
- return;
-
- qreal swipeAngle = gesture[QLatin1String("angle_degrees")].toReal();
- int swipeTouchCount = gesture[QLatin1String("touch_count")].toInt();
-
- // Swipe left
- if (swipeAngle <= 180 + SWIPE_ANGLE_THRESHOLD && swipeAngle >= 180 - SWIPE_ANGLE_THRESHOLD) {
- if (swipeTouchCount == 1) {
- // Single swipe: backspace
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
- dumpTraces();
- saveTraces(Qt::Key_Backspace, 100);
-#endif
- cancelRecognition();
- ic->inputEngine()->virtualKeyClick(Qt::Key_Backspace, QString(), Qt::NoModifier);
- } else if (swipeTouchCount == 2) {
- // Double swipe: reset word, or backspace
- cancelRecognition();
- if (!ic->preeditText().isEmpty()) {
- q->reset();
- ic->setPreeditText(QString());
- } else {
- ic->inputEngine()->virtualKeyClick(Qt::Key_Backspace, QString(), Qt::NoModifier);
- }
- }
- return;
- }
-
- // Swipe right
- if (swipeAngle <= SWIPE_ANGLE_THRESHOLD || swipeAngle >= 360 - SWIPE_ANGLE_THRESHOLD) {
- if (swipeTouchCount == 1) {
- // Single swipe: space
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
- dumpTraces();
- saveTraces(Qt::Key_Space, 100);
-#endif
- cancelRecognition();
- ic->inputEngine()->virtualKeyClick(Qt::Key_Space, QString(" "), Qt::NoModifier);
- } else if (swipeTouchCount == 2) {
- // Double swipe: commit word, or insert space
- cancelRecognition();
-#ifdef HAVE_HUNSPELL
- if (activeWordIndex != -1) {
- q->selectionListItemSelected(SelectionListModel::WordCandidateList, activeWordIndex);
- return;
- }
-#endif
- ic->inputEngine()->virtualKeyClick(Qt::Key_Space, QString(" "), Qt::NoModifier);
- }
- return;
- }
-
- // Swipe up
- if (swipeAngle <= 270 + SWIPE_ANGLE_THRESHOLD && swipeAngle >= 270 - SWIPE_ANGLE_THRESHOLD) {
- if (swipeTouchCount == 1) {
- // Single swipe: toggle input mode
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
- dumpTraces();
- saveTraces(Qt::Key_Mode_switch, 100);
-#endif
- cancelRecognition();
- if (!(ic->inputMethodHints() & (Qt::ImhDialableCharactersOnly | Qt::ImhFormattedNumbersOnly | Qt::ImhDigitsOnly))) {
- InputEngine::InputMode inputMode = ic->inputEngine()->inputMode();
- inputMode = inputMode == InputEngine::Latin ?
- InputEngine::Numeric : InputEngine::Latin;
- ic->inputEngine()->setInputMode(inputMode);
- }
- } else if (swipeTouchCount == 2) {
- // Double swipe: toggle text case
- cancelRecognition();
- ic->shiftHandler()->toggleShift();
- }
- return;
- }
- }
- }
- }
-
- void clearTraces()
- {
- qDeleteAll(traceList);
- traceList.clear();
- traceGroup.emptyAllTraces();
- }
-
- void addPointsToTraceGroup(Trace *trace)
- {
- vector<LTKChannel> channels;
- channels.push_back(LTKChannel("X", DT_INT, true));
- channels.push_back(LTKChannel("Y", DT_INT, true));
- bool hasTime = trace->channels().contains("t");
- if (hasTime)
- channels.push_back(LTKChannel("T", DT_FLOAT, true));
- LTKTraceFormat traceFormat(channels);
- LTKTrace ltktrace(traceFormat);
-
- const QVariantList points = trace->points();
- const QVariantList timeData = hasTime ? trace->channelData("t") : QVariantList();
- QVariantList::ConstIterator t = timeData.constBegin();
- for (const QVariant &p : points) {
- const QPointF pt(p.toPointF());
- vector<float> point;
- point.push_back(pt.x());
- point.push_back(pt.y());
- if (hasTime) {
- point.push_back(t->toFloat());
- t++;
- }
- ltktrace.addPoint(point);
- }
- traceGroup.addTrace(ltktrace);
- }
-
- void finishRecognition()
- {
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
- dumpTraces();
-#endif
- stopRecognizeTimer();
- clearTraces();
- if (recognitionTask && !delayedResult.isEmpty() && recognitionTask->resultId() == delayedResult["resultId"].toInt())
- processResult(delayedResult);
- delayedResult.clear();
- recognitionTask.reset();
- }
-
- void restartRecognition()
- {
- recognitionTask = recognizer.newRecognition(*deviceInfo, *screenContext, subsetOfClasses, 0.0f, 4);
- if (recognitionTask) {
- Q_Q(LipiInputMethod);
-
- recognitionTask->traceGroup = traceGroup;
-
- QSharedPointer<LipiRecognitionResultsTask> resultsTask = recognizer.startRecognition(recognitionTask);
- q->connect(resultsTask.data(), SIGNAL(resultsAvailable(const QVariantList &)), SLOT(resultsAvailable(const QVariantList &)));
-
- resetRecognizeTimer();
- } else {
- stopRecognizeTimer();
- }
- }
-
- bool cancelRecognition()
- {
- stopRecognizeTimer();
- clearTraces();
- delayedResult.clear();
- bool result = !recognitionTask.isNull();
- recognitionTask.reset();
- return recognizer.cancelRecognition() || result;
- }
-
- void resetRecognizeTimer()
- {
- Q_Q(LipiInputMethod);
- stopRecognizeTimer();
- recognizeTimer = q->startTimer(300);
- }
-
- void stopRecognizeTimer()
- {
- if (recognizeTimer) {
- Q_Q(LipiInputMethod);
- q->killTimer(recognizeTimer);
- recognizeTimer = 0;
- }
- }
-
- void resultsAvailable(const QVariantList &resultList)
- {
- if (!resultList.isEmpty()) {
- const QVariantMap result = resultList.at(0).toMap();
- if (recognitionTask && recognitionTask->resultId() == result["resultId"].toInt())
- delayedResult = result;
- else
- processResult(result);
- }
- }
-
- void processResult(const QVariantMap &result)
- {
- const QChar ch = result["unicode"].toChar();
- const QChar chUpper = ch.toUpper();
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
- // In recording mode, the text case must match with the current text case
- if (unipenTrace) {
- if (!ch.isLetter() || (ch.isUpper() == (textCase == InputEngine::Upper)))
- saveTraces(ch.unicode(), qRound(result["confidence"].toDouble() * 100));
- delete unipenTrace;
- unipenTrace = 0;
- }
-#endif
- Q_Q(LipiInputMethod);
- q->inputContext()->inputEngine()->virtualKeyClick((Qt::Key)chUpper.unicode(),
- textCase == InputEngine::Lower ? QString(ch.toLower()) : QString(chUpper),
- Qt::NoModifier);
- }
-
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
- void dumpTraces()
- {
- if (unipenTrace)
- unipenTrace->record(traceList);
- }
-
- void saveTraces(uint unicode, uint confidence)
- {
- if (!unipenTrace)
- return;
-
- QStringList homeLocations = QStandardPaths::standardLocations(QStandardPaths::HomeLocation);
- if (!homeLocations.isEmpty()) {
- QString filePath = QStringLiteral("%1/%2").arg(homeLocations.at(0)).arg("VIRTUAL_KEYBOARD_TRACES");
- unipenTrace->setDirectory(filePath);
- unipenTrace->save(unicode, confidence);
- }
- }
-#endif
-
- LipiInputMethod *q_ptr;
- LipiSharedRecognizer recognizer;
- QByteArray currentContext;
- QScopedPointer<LTKCaptureDevice> deviceInfo;
- QScopedPointer<LTKScreenContext> screenContext;
- QSharedPointer<LipiRecognitionTask> recognitionTask;
- LTKTraceGroup traceGroup;
- QList<Trace *> traceList;
- int recognizeTimer;
- InputEngine::TextCase textCase;
- vector<int> subsetOfClasses;
- QVariantMap delayedResult;
- HandwritingGestureRecognizer gestureRecognizer;
-#ifdef QT_VIRTUALKEYBOARD_RECORD_TRACE_INPUT
- UnipenTrace *unipenTrace;
-#endif
-};
-
-/*!
- \class QtVirtualKeyboard::LipiInputMethod
- \internal
-*/
-
-LipiInputMethod::LipiInputMethod(QObject *parent) :
- LipiInputMethodBase(*new LipiInputMethodPrivate(this), parent)
-{
-}
-
-LipiInputMethod::~LipiInputMethod()
-{
-}
-
-QList<InputEngine::InputMode> LipiInputMethod::inputModes(const QString &locale)
-{
- Q_UNUSED(locale)
- QList<InputEngine::InputMode> availableInputModes;
- const Qt::InputMethodHints inputMethodHints(inputContext()->inputMethodHints());
-
- if (inputMethodHints.testFlag(Qt::ImhDialableCharactersOnly) || inputMethodHints.testFlag(Qt::ImhDigitsOnly)) {
- availableInputModes.append(InputEngine::Dialable);
- } else if (inputMethodHints.testFlag(Qt::ImhFormattedNumbersOnly)) {
- availableInputModes.append(InputEngine::Numeric);
- } else {
- availableInputModes.append(InputEngine::Latin);
- availableInputModes.append(InputEngine::Numeric);
- }
-
- return availableInputModes;
-}
-
-bool LipiInputMethod::setInputMode(const QString &locale, InputEngine::InputMode inputMode)
-{
- Q_D(LipiInputMethod);
-#ifdef HAVE_HUNSPELL
- HunspellInputMethod::setInputMode(locale, inputMode);
-#else
- Q_UNUSED(locale)
-#endif
- bool result = d->recognizer.setModel(QStringLiteral("SHAPEREC_ALPHANUM"));
- if (!result)
- return false;
- d->subsetOfClasses.clear();
- switch (inputMode) {
- case InputEngine::Latin:
- d->recognizer.subsetOfClasses(QStringLiteral("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz?,.@"), d->subsetOfClasses);
- break;
- case InputEngine::Numeric:
- case InputEngine::Dialable:
- d->recognizer.subsetOfClasses(QStringLiteral("1234567890,.+"), d->subsetOfClasses);
- break;
- default:
- break;
- }
- return true;
-}
-
-bool LipiInputMethod::setTextCase(InputEngine::TextCase textCase)
-{
- Q_D(LipiInputMethod);
- d->textCase = textCase;
-#ifdef HAVE_HUNSPELL
- HunspellInputMethod::setTextCase(textCase);
-#endif
- return true;
-}
-
-bool LipiInputMethod::keyEvent(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers)
-{
-#ifdef HAVE_HUNSPELL
- Q_D(LipiInputMethod);
- switch (key) {
- case Qt::Key_Enter:
- case Qt::Key_Return:
- d->cancelRecognition();
- break;
- case Qt::Key_Backspace:
- if (d->cancelRecognition())
- return true;
- break;
- default:
- break;
- }
- return HunspellInputMethod::keyEvent(key, text, modifiers);
-#else
- Q_UNUSED(key)
- Q_UNUSED(text)
- Q_UNUSED(modifiers)
- return false;
-#endif
-}
-
-void LipiInputMethod::reset()
-{
- LipiInputMethodBase::reset();
- Q_D(LipiInputMethod);
- d->cancelRecognition();
-}
-
-void LipiInputMethod::update()
-{
- LipiInputMethodBase::update();
-}
-
-void LipiInputMethod::selectionListItemSelected(SelectionListModel::Type type, int index)
-{
- LipiInputMethodBase::selectionListItemSelected(type, index);
- Q_D(LipiInputMethod);
- d->cancelRecognition();
-}
-
-QList<InputEngine::PatternRecognitionMode> LipiInputMethod::patternRecognitionModes() const
-{
- return QList<InputEngine::PatternRecognitionMode>()
- << InputEngine::HandwritingRecoginition;
-}
-
-Trace *LipiInputMethod::traceBegin(int traceId, InputEngine::PatternRecognitionMode patternRecognitionMode,
- const QVariantMap &traceCaptureDeviceInfo, const QVariantMap &traceScreenInfo)
-{
- Q_D(LipiInputMethod);
- return d->traceBegin(traceId, patternRecognitionMode, traceCaptureDeviceInfo, traceScreenInfo);
-}
-
-bool LipiInputMethod::traceEnd(Trace *trace)
-{
- Q_D(LipiInputMethod);
- d->traceEnd(trace);
- return true;
-}
-
-void LipiInputMethod::timerEvent(QTimerEvent *timerEvent)
-{
- Q_D(LipiInputMethod);
- if (timerEvent->timerId() == d->recognizeTimer) {
- d->finishRecognition();
- }
-}
-
-void LipiInputMethod::resultsAvailable(const QVariantList &resultList)
-{
-#ifdef QT_VIRTUALKEYBOARD_DEBUG
- {
- VIRTUALKEYBOARD_DEBUG() << "LipiInputMethod::resultsAvailable():";
- for (int i = 0; i < resultList.size(); i++) {
- QVariantMap result = resultList.at(i).toMap();
- VIRTUALKEYBOARD_DEBUG() << QString("%1: %2 (%3)").arg(i + 1).arg(result["unicode"].toChar()).arg(result["confidence"].toFloat()).toUtf8().constData();
- }
- }
-#endif
- Q_D(LipiInputMethod);
- d->resultsAvailable(resultList);
-}
-
-} // namespace QtVirtualKeyboard