diff options
Diffstat (limited to 'src/plugins/t9write/plugin/t9writeworker.cpp')
-rw-r--r-- | src/plugins/t9write/plugin/t9writeworker.cpp | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/src/plugins/t9write/plugin/t9writeworker.cpp b/src/plugins/t9write/plugin/t9writeworker.cpp new file mode 100644 index 00000000..be9b4d9e --- /dev/null +++ b/src/plugins/t9write/plugin/t9writeworker.cpp @@ -0,0 +1,404 @@ +/**************************************************************************** +** +** 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 "t9writeworker_p.h" +#include <QLoggingCategory> + +#include <QFile> +#include <QTime> + +QT_BEGIN_NAMESPACE +namespace QtVirtualKeyboard { + +Q_DECLARE_LOGGING_CATEGORY(lcT9Write) + +/*! + \class QtVirtualKeyboard::T9WriteTask + \internal +*/ + +T9WriteTask::T9WriteTask(QObject *parent) : + QObject(parent), + decumaSession(nullptr), + runSema() +{ +} + +void T9WriteTask::wait() +{ + runSema.acquire(); + runSema.release(); +} + +/*! + \class QtVirtualKeyboard::T9WriteDictionaryTask + \internal +*/ + +T9WriteDictionaryTask::T9WriteDictionaryTask(QSharedPointer<T9WriteDictionary> dictionary, + const QString &dictionaryFileName, + bool convertDictionary, + const DECUMA_SRC_DICTIONARY_INFO &dictionaryInfo) : + dictionary(dictionary), + dictionaryFileName(dictionaryFileName), + convertDictionary(convertDictionary), + dictionaryInfo(dictionaryInfo) +{ +} + +void T9WriteDictionaryTask::run() +{ + qCDebug(lcT9Write) << "T9WriteDictionaryTask::run()"; + + QTime perf; + perf.start(); + + bool result = false; + if (dictionary) { + result = dictionary->load(dictionaryFileName); + if (result && convertDictionary) + result = dictionary->convert(dictionaryInfo); + } + + qCDebug(lcT9Write) << "T9WriteDictionaryTask::run(): time:" << perf.elapsed() << "ms"; + + if (result) + emit completed(dictionary); +} + +T9WriteAddArcTask::T9WriteAddArcTask(QVirtualKeyboardTrace *trace) : + trace(trace) +{ +} + +void T9WriteAddArcTask::run() +{ + QTime perf; + perf.start(); + DECUMA_UINT32 arcID = (DECUMA_UINT32)trace->traceId(); + DECUMA_STATUS status = DECUMA_API(StartNewArc)(decumaSession, arcID); + Q_ASSERT(status == decumaNoError); + if (status != decumaNoError) { + qCWarning(lcT9Write) << "T9WriteAddArcTask::run(): Failed to start new arc, status:" << status; + return; + } + + const QVariantList points = trace->points(); + Q_ASSERT(!points.isEmpty()); + + for (const QVariant &p : points) { + const QPoint pt(p.toPointF().toPoint()); + status = DECUMA_API(AddPoint)(decumaSession, (DECUMA_COORD)pt.x(),(DECUMA_COORD)pt.y(), arcID); + if (status != decumaNoError) { + qCWarning(lcT9Write) << "T9WriteAddArcTask::run(): Failed to add point, status:" << status; + DECUMA_API(CancelArc)(decumaSession, arcID); + return; + } + } + + status = DECUMA_API(CommitArc)(decumaSession, arcID); + if (status != decumaNoError) + qCWarning(lcT9Write) << "T9WriteAddArcTask::run(): Failed to commit arc, status:" << status; + else + qCDebug(lcT9Write) << "T9WriteAddArcTask::run(): time:" << perf.elapsed() << "ms"; +} + +/*! + \class QtVirtualKeyboard::T9WriteRecognitionResult + \internal +*/ + +T9WriteRecognitionResult::T9WriteRecognitionResult(int id, int maxResults, int maxCharsPerWord) : + status(decumaNoError), + numResults(0), + instantGesture(0), + id(id), + maxResults(maxResults), + maxCharsPerWord(maxCharsPerWord) +{ + Q_ASSERT(maxResults > 0); + Q_ASSERT(maxCharsPerWord > 0); + results.resize(maxResults); + int bufferLength = (maxCharsPerWord + 1); + _chars.resize(maxResults * bufferLength); + _symbolChars.resize(maxResults * bufferLength); + _symbolStrokes.resize(maxResults * bufferLength); + for (int i = 0; i < maxResults; i++) { + DECUMA_HWR_RESULT &hwrResult = results[i]; + hwrResult.pChars = &_chars[i * bufferLength]; + hwrResult.pSymbolChars = &_symbolChars[i * bufferLength]; + hwrResult.pSymbolStrokes = &_symbolStrokes[i * bufferLength]; + } +} + +/*! + \class QtVirtualKeyboard::T9WriteRecognitionTask + \internal +*/ + +T9WriteRecognitionTask::T9WriteRecognitionTask(QSharedPointer<T9WriteRecognitionResult> result, + const DECUMA_INSTANT_GESTURE_SETTINGS &instantGestureSettings, + BOOST_LEVEL boostLevel, + const QString &stringStart) : + T9WriteTask(), + result(result), + instantGestureSettings(instantGestureSettings), + boostLevel(boostLevel), + stringStart(stringStart), + stateCancelled(false) +{ + qCDebug(lcT9Write) << "T9WriteRecognitionTask():" << "boostLevel:" << boostLevel << "stringStart:" << stringStart; +} + +void T9WriteRecognitionTask::run() +{ + if (!decumaSession) + return; + + { + QMutexLocker stateGuard(&stateLock); + Q_UNUSED(stateGuard); + if (stateCancelled) + return; + } + + //In a normal text composition case boostDictWords and canBeContinued are the preffered settings + DECUMA_RECOGNITION_SETTINGS recSettings; + memset(&recSettings, 0, sizeof(recSettings)); + recSettings.boostLevel = boostLevel; + recSettings.stringCompleteness = canBeContinued; + if (!stringStart.isEmpty()) + recSettings.pStringStart = (DECUMA_UNICODE *)stringStart.utf16(); + + QTime perf; + perf.start(); + +#if SUPPORTS_ABORTRECOGNITION + DECUMA_INTERRUPT_FUNCTIONS interruptFunctions; + interruptFunctions.pShouldAbortRecognize = shouldAbortRecognize; + interruptFunctions.pUserData = (void *)this; + DECUMA_INTERRUPT_FUNCTIONS *pInterruptFunctions = &interruptFunctions; +#else + DECUMA_INTERRUPT_FUNCTIONS *pInterruptFunctions = nullptr; +#endif + result->status = DECUMA_API(Recognize)(decumaSession, result->results.data(), result->results.size(), &result->numResults, result->maxCharsPerWord, &recSettings, pInterruptFunctions); + if (result->status != decumaNoError) + qCWarning(lcT9Write) << "T9WriteRecognitionTask::run(): Recognition failed, status:" << result->status; + + int perfElapsed = perf.elapsed(); + + { + QMutexLocker stateGuard(&stateLock); + Q_UNUSED(stateGuard) + if (stateCancelled) + result.reset(); + qCDebug(lcT9Write) << "T9WriteRecognitionTask::run(): time:" << perfElapsed << "ms" << (stateCancelled ? "(cancelled)" : ""); + } +} + +int T9WriteRecognitionTask::shouldAbortRecognize(void *pUserData) +{ + T9WriteRecognitionTask *pThis = (T9WriteRecognitionTask *)pUserData; + QMutexLocker stateGuard(&pThis->stateLock); + Q_UNUSED(stateGuard) + return pThis->stateCancelled; +} + +bool T9WriteRecognitionTask::cancelRecognition() +{ + QMutexLocker stateGuard(&stateLock); + Q_UNUSED(stateGuard) + stateCancelled = true; + return true; +} + +int T9WriteRecognitionTask::resultId() const +{ + return result != nullptr ? result->id : -1; +} + +/*! + \class QtVirtualKeyboard::T9WriteRecognitionResultsTask + \internal +*/ + +T9WriteRecognitionResultsTask::T9WriteRecognitionResultsTask(QSharedPointer<T9WriteRecognitionResult> result) : + T9WriteTask(), + result(result) +{ +} + +void T9WriteRecognitionResultsTask::run() +{ + if (!result) + return; + + if (result->status != decumaNoError) { + emit recognitionError(result->status); + return; + } + + QVariantList resultList; + for (int i = 0; i < result->numResults; i++) + { + QVariantMap resultMap; + QString resultString; + QString gesture; + const DECUMA_HWR_RESULT &hwrResult = result->results.at(i); + resultString.reserve(hwrResult.nChars); + QVariantList symbolStrokes; + int charPos = 0; + for (int symbolIndex = 0; symbolIndex < hwrResult.nSymbols; symbolIndex++) { + int symbolLength = hwrResult.pSymbolChars[symbolIndex]; + QString symbol(QString::fromUtf16(&hwrResult.pChars[charPos], symbolLength)); + // Do not append gesture symbol to result string + if (hwrResult.bGesture) { + gesture = symbol.right(1); + symbol.chop(1); + } + resultString.append(symbol); + charPos += symbolLength; + if (hwrResult.pSymbolStrokes) + symbolStrokes.append(QVariant((int)hwrResult.pSymbolStrokes[symbolIndex])); + } + + resultMap[QLatin1String("resultId")] = result->id; + resultMap[QLatin1String("chars")] = resultString; + resultMap[QLatin1String("symbolStrokes")] = symbolStrokes; + if (!gesture.isEmpty()) + resultMap[QLatin1String("gesture")] = gesture; + + resultList.append(resultMap); + } + + if (resultList.isEmpty()) + return; + + emit resultsAvailable(resultList); +} + +/*! + \class QtVirtualKeyboard::T9WriteWorker + \internal +*/ + +T9WriteWorker::T9WriteWorker(DECUMA_SESSION *decumaSession, const bool cjk, QObject *parent) : + QThread(parent), + taskSema(), + taskLock(), + decumaSession(decumaSession), + cjk(cjk) +{ + abort = false; +} + +T9WriteWorker::~T9WriteWorker() +{ + abort = true; + taskSema.release(); + wait(); +} + +void T9WriteWorker::addTask(QSharedPointer<T9WriteTask> task) +{ + if (task) { + QMutexLocker guard(&taskLock); + task->moveToThread(this); + taskList.append(task); + taskSema.release(); + } +} + +int T9WriteWorker::removeTask(QSharedPointer<T9WriteTask> task) +{ + int count = 0; + if (task) { + QMutexLocker guard(&taskLock); + count = taskList.removeAll(task); + taskSema.acquire(qMin(count, taskSema.available())); + } + return count; +} + +int T9WriteWorker::removeAllTasks() +{ + QMutexLocker guard(&taskLock); + int count = taskList.count(); + taskList.clear(); + if (taskSema.available()) + taskSema.acquire(taskSema.available()); + return count; +} + +void T9WriteWorker::waitForAllTasks() +{ + while (isRunning()) { + idleSema.acquire(); + QMutexLocker guard(&taskLock); + if (taskList.isEmpty()) { + idleSema.release(); + break; + } + idleSema.release(); + } +} + +int T9WriteWorker::numberOfPendingTasks() +{ + QMutexLocker guard(&taskLock); + return taskList.count() + (!idleSema.available() ? 1 : 0); +} + +void T9WriteWorker::run() +{ + while (!abort) { + idleSema.release(); + taskSema.acquire(); + if (abort) + break; + idleSema.acquire(); + QSharedPointer<T9WriteTask> currentTask; + { + QMutexLocker guard(&taskLock); + if (!taskList.isEmpty()) { + currentTask = taskList.front(); + taskList.pop_front(); + } + } + if (currentTask) { + currentTask->decumaSession = decumaSession; + currentTask->cjk = cjk; + currentTask->run(); + currentTask->runSema.release(); + } + } +} + +} // namespace QtVirtualKeyboard +QT_END_NAMESPACE |