/**************************************************************************** ** ** 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$ ** ****************************************************************************/ import QtTest 1.0 import QtQuick 2.0 import QtQuick.VirtualKeyboard 2.3 import QtQuick.VirtualKeyboard.Settings 2.2 import "handwriting.js" as Handwriting import "utils.js" as Utils InputPanel { id: inputPanel z: 99 anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom visible: active property var testcase property var virtualKeyPressPoint: null readonly property int cursorPosition: InputContext.cursorPosition readonly property string preeditText: InputContext.preeditText readonly property string surroundingText: InputContext.surroundingText readonly property bool autoCapitalizationEnabled: InputContext.priv.shiftHandler.autoCapitalizationEnabled readonly property bool toggleShiftEnabled: InputContext.priv.shiftHandler.toggleShiftEnabled readonly property string locale: keyboard.locale readonly property string defaultLocale: VirtualKeyboardSettings.locale readonly property var availableLocales: VirtualKeyboardSettings.availableLocales readonly property var activeLocales: VirtualKeyboardSettings.activeLocales readonly property int inputMode: InputContext.inputEngine.inputMode readonly property var inputMethod: InputContext.inputEngine.inputMethod readonly property var keyboard: Utils.findChildByProperty(inputPanel, "objectName", "keyboard", null) readonly property bool handwritingMode: keyboard.handwritingMode readonly property var keyboardLayoutLoader: Utils.findChildByProperty(keyboard, "objectName", "keyboardLayoutLoader", null) readonly property var keyboardInputArea: Utils.findChildByProperty(keyboard, "objectName", "keyboardInputArea", null) readonly property var characterPreviewBubble: Utils.findChildByProperty(keyboard, "objectName", "characterPreviewBubble", null) readonly property var alternativeKeys: Utils.findChildByProperty(keyboard, "objectName", "alternativeKeys", null) readonly property var naviationHighlight: Utils.findChildByProperty(keyboard, "objectName", "naviationHighlight", null) readonly property bool naviationHighlightAnimating: naviationHighlight.xAnimation.running || naviationHighlight.yAnimation.running || naviationHighlight.widthAnimation.running || naviationHighlight.heightAnimation.running readonly property var wordCandidateView: Utils.findChildByProperty(keyboard, "objectName", "wordCandidateView", null) readonly property var wordCandidateContextMenu: Utils.findChildByProperty(keyboard, "objectName", "wordCandidateContextMenu", null) readonly property var shadowInputControl: Utils.findChildByProperty(keyboard, "objectName", "shadowInputControl", null) readonly property var shadowInput: Utils.findChildByProperty(keyboard, "objectName", "shadowInput", null) readonly property var selectionControl: Utils.findChildByProperty(inputPanel, "objectName", "selectionControl", null) readonly property var anchorHandle: selectionControl.children[0] readonly property var cursorHandle: selectionControl.children[1] readonly property var fullScreenModeSelectionControl: Utils.findChildByProperty(inputPanel, "objectName", "fullScreenModeSelectionControl", null) readonly property var fullScreenModeAnchorHandle: fullScreenModeSelectionControl.children[0] readonly property var fullScreenModeCursorHandle: fullScreenModeSelectionControl.children[1] readonly property bool wordCandidateListVisibleHint: InputContext.inputEngine.wordCandidateListVisibleHint readonly property bool keyboardLayoutsAvailable: keyboard.availableLocaleIndices.length > 0 && keyboard.availableLocaleIndices.indexOf(-1) === -1 property alias keyboardLayoutsAvailableSpy: keyboardLayoutsAvailableSpy property alias keyboardLayoutLoaderItemSpy: keyboardLayoutLoaderItemSpy property alias characterPreviewBubbleSpy: characterPreviewBubbleSpy property alias alternativeKeysSpy: alternativeKeysSpy property alias activeKeyChangedSpy: activeKeyChangedSpy property alias virtualKeyClickedSpy: virtualKeyClickedSpy property alias dragSymbolModeSpy: dragSymbolModeSpy property alias styleSpy: styleSpy property alias soundEffectSpy: soundEffectSpy property alias inputMethodResultSpy: inputMethodResultSpy property alias wordCandidateListChangedSpy: wordCandidateListChangedSpy property alias inputMethodSelectionListChangedSpy: inputMethodSelectionListChangedSpy property alias wordCandidateListVisibleSpy: wordCandidateListVisibleSpy property alias shiftStateSpy: shiftStateSpy property alias shadowInputControlVisibleSpy: shadowInputControlVisibleSpy property alias externalLanguageSwitchSpy: externalLanguageSwitchSpy signal inputMethodResult(var text) LayoutMirroring.childrenInherit: true Connections { target: InputContext function onPreeditTextChanged() { if (InputContext.preeditText.length > 0) inputMethodResult(InputContext.preeditText) } } Connections { target: InputContext.inputEngine function onVirtualKeyClicked(key, text, modifiers, isAutoRepeat) { inputMethodResult(text) } } SignalSpy { id: keyboardLayoutsAvailableSpy target: inputPanel signalName: "onKeyboardLayoutsAvailableChanged" } SignalSpy { id: keyboardLayoutLoaderItemSpy target: keyboardLayoutLoader signalName: "onItemChanged" } SignalSpy { id: characterPreviewBubbleSpy target: characterPreviewBubble signalName: "onVisibleChanged" } SignalSpy { id: alternativeKeysSpy target: alternativeKeys signalName: "onVisibleChanged" } SignalSpy { id: activeKeyChangedSpy target: InputContext.inputEngine signalName: "activeKeyChanged" } SignalSpy { id: virtualKeyClickedSpy target: InputContext.inputEngine signalName: "virtualKeyClicked" } SignalSpy { id: dragSymbolModeSpy target: keyboardInputArea signalName: "onDragSymbolModeChanged" } SignalSpy { id: styleSpy target: keyboard signalName: "onStyleChanged" } SignalSpy { id: soundEffectSpy target: keyboard.soundEffect signalName: "onPlayingChanged" } SignalSpy { id: inputMethodResultSpy target: inputPanel signalName: "inputMethodResult" } SignalSpy { id: wordCandidateListChangedSpy target: wordCandidateView.model signalName: "dataChanged" } SignalSpy { id: inputMethodSelectionListChangedSpy target: InputContext.inputEngine.inputMethod signalName: "selectionListChanged" } SignalSpy { id: wordCandidateListVisibleSpy target: wordCandidateView signalName: "onVisibleConditionChanged" } SignalSpy { id: wordCandidateContextMenuActiveSpy target: wordCandidateContextMenu signalName: "onActiveChanged" } SignalSpy { id: shiftStateSpy target: InputContext signalName: "onShiftActiveChanged" } SignalSpy { id: shadowInputControlVisibleSpy target: shadowInputControl signalName: "onVisibleChanged" } SignalSpy { id: externalLanguageSwitchSpy target: inputPanel signalName: "onExternalLanguageSwitch" } function findChildByProperty(parent, propertyName, propertyValue, compareCb) { var obj = null if (parent === null) return null var children = parent.children for (var i = 0; i < children.length; i++) { obj = children[i] if (obj.hasOwnProperty(propertyName)) { if (compareCb !== null) { if (compareCb(obj[propertyName], propertyValue)) break } else if (obj[propertyName] === propertyValue) { break } } obj = findChildByProperty(obj, propertyName, propertyValue, compareCb) if (obj) break } return obj } function isLocaleSupported(inputLocale) { var localeIndex = VirtualKeyboardSettings.availableLocales.indexOf(inputLocale) return localeIndex !== -1 } function setLocale(inputLocale) { VirtualKeyboardSettings.locale = inputLocale if (["ar", "fa"].indexOf(inputLocale.substring(0, 2)) !== -1) return inputPanel.keyboard.locale.substring(0, 2) === inputLocale.substring(0, 2) return inputPanel.keyboard.locale === inputLocale } function setActiveLocales(activeLocales) { VirtualKeyboardSettings.activeLocales = activeLocales } function setWclAutoHideDelay(wclAutoHideDelay) { VirtualKeyboardSettings.wordCandidateList.autoHideDelay = wclAutoHideDelay } function setWclAlwaysVisible(wclAlwaysVisible) { VirtualKeyboardSettings.wordCandidateList.alwaysVisible = wclAlwaysVisible } function setWclAutoCommitWord(wclAutoCommitWord) { VirtualKeyboardSettings.wordCandidateList.autoCommitWord = wclAutoCommitWord } function setFullScreenMode(fullScreenMode) { VirtualKeyboardSettings.fullScreenMode = fullScreenMode } function mapInputMode(inputModeName) { if (inputModeName === "Latin") return InputEngine.InputMode.Latin else if (inputModeName === "Numeric") return InputEngine.InputMode.Numeric else if (inputModeName === "Dialable") return InputEngine.InputMode.Dialable else if (inputModeName === "Pinyin") return InputEngine.InputMode.Pinyin else if (inputModeName === "Cangjie") return InputEngine.InputMode.Cangjie else if (inputModeName === "Zhuyin") return InputEngine.InputMode.Zhuyin else if (inputModeName === "Hangul") return InputEngine.InputMode.Hangul else if (inputModeName === "Hiragana") return InputEngine.InputMode.Hiragana else if (inputModeName === "Katakana") return InputEngine.InputMode.Katakana else if (inputModeName === "FullwidthLatin") return InputEngine.InputMode.FullwidthLatin else if (inputModeName === "Greek") return InputEngine.InputMode.Greek else if (inputModeName === "Cyrillic") return InputEngine.InputMode.Cyrillic else if (inputModeName === "Arabic") return InputEngine.InputMode.Arabic else if (inputModeName === "Hebrew") return InputEngine.InputMode.Hebrew else if (inputModeName === "ChineseHandwriting") return InputEngine.InputMode.ChineseHandwriting else if (inputModeName === "JapaneseHandwriting") return InputEngine.InputMode.JapaneseHandwriting else if (inputModeName === "KoreanHandwriting") return InputEngine.InputMode.KoreanHandwriting else if (inputModeName === "Thai") return InputEngine.InputMode.Thai else return -1 } function isInputModeSupported(inputMode) { return InputContext.inputEngine.inputModes.indexOf(inputMode) !== -1 } function setInputMode(inputMode) { if (!isInputModeSupported(inputMode)) return false if (InputContext.inputEngine.inputMode !== inputMode) InputContext.inputEngine.inputMode = inputMode return true } function testPublicEnums() { // Scoped testcase.verify(InputEngine.TextCase.Lower !== undefined) testcase.verify(InputEngine.TextCase.Upper !== undefined) testcase.verify(InputEngine.InputMode.Latin !== undefined) testcase.verify(InputEngine.InputMode.Numeric !== undefined) testcase.verify(InputEngine.InputMode.Dialable !== undefined) testcase.verify(InputEngine.InputMode.Pinyin !== undefined) testcase.verify(InputEngine.InputMode.Cangjie !== undefined) testcase.verify(InputEngine.InputMode.Zhuyin !== undefined) testcase.verify(InputEngine.InputMode.Hangul !== undefined) testcase.verify(InputEngine.InputMode.Hiragana !== undefined) testcase.verify(InputEngine.InputMode.Katakana !== undefined) testcase.verify(InputEngine.InputMode.FullwidthLatin !== undefined) testcase.verify(InputEngine.InputMode.Greek !== undefined) testcase.verify(InputEngine.InputMode.Cyrillic !== undefined) testcase.verify(InputEngine.InputMode.Arabic !== undefined) testcase.verify(InputEngine.InputMode.Hebrew !== undefined) testcase.verify(InputEngine.InputMode.ChineseHandwriting !== undefined) testcase.verify(InputEngine.InputMode.JapaneseHandwriting !== undefined) testcase.verify(InputEngine.InputMode.KoreanHandwriting !== undefined) testcase.verify(InputEngine.InputMode.Thai !== undefined) testcase.verify(InputEngine.PatternRecognitionMode.None !== undefined) testcase.verify(InputEngine.PatternRecognitionMode.PatternRecognitionDisabled !== undefined) testcase.verify(InputEngine.PatternRecognitionMode.Handwriting !== undefined) testcase.verify(InputEngine.PatternRecognitionMode.HandwritingRecoginition !== undefined) testcase.verify(InputEngine.ReselectFlag.WordBeforeCursor !== undefined) testcase.verify(InputEngine.ReselectFlag.WordAfterCursor !== undefined) testcase.verify(InputEngine.ReselectFlag.WordAtCursor !== undefined) testcase.verify(SelectionListModel.Type.WordCandidateList !== undefined) testcase.verify(SelectionListModel.Role.Display !== undefined) testcase.verify(SelectionListModel.Role.WordCompletionLength !== undefined) testcase.verify(SelectionListModel.Role.Dictionary !== undefined) testcase.verify(SelectionListModel.DictionaryType.Default !== undefined) testcase.verify(SelectionListModel.DictionaryType.User !== undefined) // Unscoped testcase.verify(InputEngine.Lower !== undefined) testcase.verify(InputEngine.Upper !== undefined) testcase.verify(InputEngine.Latin !== undefined) testcase.verify(InputEngine.Numeric !== undefined) testcase.verify(InputEngine.Dialable !== undefined) testcase.verify(InputEngine.Pinyin !== undefined) testcase.verify(InputEngine.Cangjie !== undefined) testcase.verify(InputEngine.Zhuyin !== undefined) testcase.verify(InputEngine.Hangul !== undefined) testcase.verify(InputEngine.Hiragana !== undefined) testcase.verify(InputEngine.Katakana !== undefined) testcase.verify(InputEngine.FullwidthLatin !== undefined) testcase.verify(InputEngine.Greek !== undefined) testcase.verify(InputEngine.Cyrillic !== undefined) testcase.verify(InputEngine.Arabic !== undefined) testcase.verify(InputEngine.Hebrew !== undefined) testcase.verify(InputEngine.ChineseHandwriting !== undefined) testcase.verify(InputEngine.JapaneseHandwriting !== undefined) testcase.verify(InputEngine.KoreanHandwriting !== undefined) testcase.verify(InputEngine.Thai !== undefined) testcase.verify(InputEngine.None !== undefined) testcase.verify(InputEngine.PatternRecognitionDisabled !== undefined) testcase.verify(InputEngine.Handwriting !== undefined) testcase.verify(InputEngine.HandwritingRecoginition !== undefined) testcase.verify(InputEngine.WordBeforeCursor !== undefined) testcase.verify(InputEngine.WordAfterCursor !== undefined) testcase.verify(InputEngine.WordAtCursor !== undefined) testcase.verify(SelectionListModel.WordCandidateList !== undefined) testcase.verify(SelectionListModel.DisplayRole !== undefined) testcase.verify(SelectionListModel.WordCompletionLengthRole !== undefined) testcase.verify(SelectionListModel.DictionaryType !== undefined) testcase.verify(SelectionListModel.Default !== undefined) testcase.verify(SelectionListModel.User !== undefined) } function setExternalLanguageSwitchEnabled(enabled) { externalLanguageSwitchEnabled = enabled } function setLayoutMirroring(enabled) { LayoutMirroring.enabled = enabled } function findVirtualKey(key) { return Utils.findChild(keyboardLayoutLoader, key, function(obj, param) { if (!obj.hasOwnProperty("key") || !obj.hasOwnProperty("text")) return false return (typeof param == "number") ? obj.key === param : obj.text.toUpperCase() === param.toUpperCase() }) } function findVirtualKeyAlternative(key) { if (typeof key != "string") return null return Utils.findChildByProperty(keyboardLayoutLoader, "effectiveAlternativeKeys", key.toUpperCase(), function(propertyValue, key) { if (typeof propertyValue == "string") return propertyValue.toUpperCase().indexOf(key) !== -1 return propertyValue.filter(function(value) { return key === value.toUpperCase() }).length > 0 }) } function findObjectByName(objectName) { return Utils.findChildByProperty(keyboard, "objectName", objectName, null) } function virtualKeyPressOnCurrentLayout(key) { var keyObj = typeof key == "object" && key.hasOwnProperty("key") ? key : findVirtualKey(key) var alternativeKey = false if (!keyObj && typeof key == "string") { keyObj = findVirtualKeyAlternative(key) alternativeKey = keyObj !== null if (alternativeKey) alternativeKeysSpy.clear() } if (keyObj) { virtualKeyPressPoint = inputPanel.mapFromItem(keyObj, keyObj.width / 2, keyObj.height / 2) testcase.mousePress(inputPanel, virtualKeyPressPoint.x, virtualKeyPressPoint.y) testcase.wait(20) if (alternativeKey) { alternativeKeysSpy.wait() var keyIndex = keyObj.effectiveAlternativeKeys.indexOf(key.toLowerCase()) var itemX = keyIndex * keyboard.style.alternateKeysListItemWidth + keyboard.style.alternateKeysListItemWidth / 2 virtualKeyPressPoint.x = inputPanel.mapFromItem(alternativeKeys.listView, itemX, 0).x testcase.mouseMove(inputPanel, virtualKeyPressPoint.x, virtualKeyPressPoint.y) testcase.waitForRendering(inputPanel) } return true } return false } function multiLayoutKeyActionHelper(key, keyActionOnCurrentLayoutCb) { if (!keyboardLayoutLoader.item) { console.warn("Key not found \\u%1 (keyboard layout not loaded)".arg(key.charCodeAt(0).toString(16))) return false } var success = keyActionOnCurrentLayoutCb(key) for (var c = 0; !success && c < 2; c++) { // Check if the current layout contains multiple layouts if (keyboardLayoutLoader.item.hasOwnProperty("item")) { if (keyboardLayoutLoader.item.hasOwnProperty("secondPage")) { keyboardLayoutLoader.item.secondPage = !keyboardLayoutLoader.item.secondPage testcase.waitForRendering(inputPanel) success = keyActionOnCurrentLayoutCb(key) } else if (keyboardLayoutLoader.item.hasOwnProperty("page") && keyboardLayoutLoader.item.hasOwnProperty("numPages")) { for (var page = 0; !success && page < keyboardLayoutLoader.item.numPages; page++) { keyboardLayoutLoader.item.page = page testcase.waitForRendering(inputPanel) success = keyActionOnCurrentLayoutCb(key) } } else if (typeof key != "number" || key !== Qt.Key_Shift) { // Some layouts (such as Arabic, Hindi) may have a second layout virtualKeyClick(Qt.Key_Shift) InputContext.priv.shiftHandler.clearToggleShiftTimer() testcase.waitForRendering(inputPanel) success = keyActionOnCurrentLayoutCb(key) if (!success) { virtualKeyClick(Qt.Key_Shift) InputContext.priv.shiftHandler.clearToggleShiftTimer() testcase.waitForRendering(inputPanel) } } if (success) break } // Symbol mode not allowed in handwriting mode if (inputPanel.handwritingMode) break // Toggle symbol mode keyboard.symbolMode = !keyboard.symbolMode testcase.waitForRendering(inputPanel) success = keyActionOnCurrentLayoutCb(key) } if (!success) console.warn("Key not found \\u%1".arg(key.charCodeAt(0).toString(16))) return success } function virtualKeyPress(key) { if (!key) return false return multiLayoutKeyActionHelper(key, virtualKeyPressOnCurrentLayout) } function virtualKeyDrag(key) { if (virtualKeyPressPoint !== null) { var keyObj = Utils.findChildByProperty(keyboardLayoutLoader, (typeof key == "number") ? "key" : "text", key, null) if (keyObj !== null) { virtualKeyPressPoint = inputPanel.mapFromItem(keyObj, keyObj.width / 2, keyObj.height / 2) testcase.mouseMove(inputPanel, virtualKeyPressPoint.x, virtualKeyPressPoint.y) testcase.waitForRendering(inputPanel) return true } } return false } function virtualKeyRelease() { if (virtualKeyPressPoint !== null) { testcase.mouseRelease(inputPanel, virtualKeyPressPoint.x, virtualKeyPressPoint.y) virtualKeyPressPoint = null return true } return false } function virtualKeyClick(key) { if (virtualKeyPress(key)) { virtualKeyRelease() testcase.waitForRendering(inputPanel) return true } return false } function emulateNavigationKeyClick(navigationKey) { testcase.keyClick(navigationKey) while (inputPanel.naviationHighlightAnimating) testcase.wait(inputPanel.naviationHighlight.moveDuration / 2) } function navigationHighlightContains(point) { var navigationPoint = inputPanel.mapToItem(inputPanel.naviationHighlight, point.x, point.y) return inputPanel.naviationHighlight.contains(Qt.point(navigationPoint.x, navigationPoint.y)) } function navigateToKeyOnPoint(point) { activateNavigationKeyMode() if (inputPanel.naviationHighlight.visible) { while (true) { var navigationPoint = inputPanel.mapToItem(inputPanel.naviationHighlight, point.x, point.y) if (navigationHighlightContains(point)) return true if (inputPanel.naviationHighlight.y > point.y) emulateNavigationKeyClick(Qt.Key_Up) else if (inputPanel.naviationHighlight.y + inputPanel.naviationHighlight.height < point.y) emulateNavigationKeyClick(Qt.Key_Down) else if (inputPanel.naviationHighlight.x > point.x) emulateNavigationKeyClick(Qt.Key_Left) else if (inputPanel.naviationHighlight.x + inputPanel.naviationHighlight.width < point.x) emulateNavigationKeyClick(Qt.Key_Right) } } return false } function navigateToKeyOnCurrentLayout(key) { var keyObj = findVirtualKey(key) var alternativeKey = false if (!keyObj && typeof key == "string") { keyObj = findVirtualKeyAlternative(key) alternativeKey = keyObj !== null } if (keyObj) { var point = inputPanel.mapFromItem(keyObj, keyObj.width / 2, keyObj.height / 2) if (!navigateToKeyOnPoint(point)) return false if (alternativeKey) { alternativeKeysSpy.clear() testcase.keyPress(Qt.Key_Return) alternativeKeysSpy.wait() testcase.keyRelease(Qt.Key_Return) var keyIndex = keyObj.effectiveAlternativeKeys.indexOf(key) while (inputPanel.alternativeKeys.listView.currentIndex !== keyIndex) { testcase.verify(inputPanel.alternativeKeys.listView.currentIndex !== -1) emulateNavigationKeyClick(inputPanel.alternativeKeys.listView.currentIndex < keyIndex ? Qt.Key_Right : Qt.Key_Left) } } return true } return false } function navigationKeyClickOnCurrentLayout(key) { if (navigateToKeyOnCurrentLayout(key)) { testcase.keyClick(Qt.Key_Return) return true } return false } function navigateToKey(key) { return multiLayoutKeyActionHelper(key, navigateToKeyOnCurrentLayout) } function navigationKeyClick(key) { return multiLayoutKeyActionHelper(key, navigationKeyClickOnCurrentLayout) } function activateNavigationKeyMode() { if (!inputPanel.naviationHighlight.visible) { inputPanel.naviationHighlight.moveDuration = 0 inputPanel.naviationHighlight.resizeDuration = 0 emulateNavigationKeyClick(Qt.Key_Right) if (inputPanel.naviationHighlight.visible) { while (inputPanel.naviationHighlightAnimating) testcase.wait(inputPanel.naviationHighlight.moveDuration / 2) } } return inputPanel.naviationHighlight.visible } function toggleShift() { InputContext.priv.shiftHandler.toggleShift() } function setShiftActive(shiftActive) { InputContext.priv.shiftHandler.shiftActive = shiftActive } function setCapsLockActive(capsLockActive) { InputContext.priv.shiftHandler.capsLockActive = capsLockActive } function style() { return VirtualKeyboardSettings.styleName } function setStyle(style) { VirtualKeyboardSettings.styleName = style } function selectionListSearchSuggestion(suggestion) { if (wordCandidateListVisibleHint === false) return false if (inputPanel.wordCandidateView.count === 0) return false; var suggestionFound = false var origIndex = inputPanel.wordCandidateView.currentIndex if (origIndex === -1) { inputPanel.wordCandidateView.incrementCurrentIndex() origIndex = inputPanel.wordCandidateView.currentIndex } if (origIndex !== -1) { while (true) { if (inputPanel.wordCandidateView.model.dataAt(inputPanel.wordCandidateView.currentIndex) === suggestion) { suggestionFound = true break } if (inputPanel.wordCandidateView.currentIndex === inputPanel.wordCandidateView.count - 1) break inputPanel.wordCandidateView.incrementCurrentIndex() } if (!suggestionFound) { while (inputPanel.wordCandidateView.currentIndex !== origIndex) { inputPanel.wordCandidateView.decrementCurrentIndex() } } testcase.waitForRendering(inputPanel) } return suggestionFound } function selectionListSelectCurrentItem() { if (!inputPanel.wordCandidateView.currentItem) return false testcase.wait(200) testcase.verify(inputPanel.wordCandidateView.currentItem, "Expected wordCandidateView to have a currentItem, but it's null." + " Its property values at the time of failure are:" + " x=" + inputPanel.wordCandidateView.x + " y=" + inputPanel.wordCandidateView.y + " width=" + inputPanel.wordCandidateView.width + " height=" + inputPanel.wordCandidateView.height + " count=" + inputPanel.wordCandidateView.count + " flicking=" + inputPanel.wordCandidateView.flicking + " moving=" + inputPanel.wordCandidateView.moving + " visible=" + inputPanel.wordCandidateView.visible) var itemPos = inputPanel.mapFromItem(inputPanel.wordCandidateView.currentItem, inputPanel.wordCandidateView.currentItem.width / 2, inputPanel.wordCandidateView.currentItem.height / 2) testcase.mouseClick(inputPanel, itemPos.x, itemPos.y, Qt.LeftButton, 0, 20) testcase.waitForRendering(inputPanel) return true } function selectionListCurrentIndex() { return inputPanel.wordCandidateView.currentIndex } function selectionListSuggestionIsFromUserDictionary() { if (!inputPanel.wordCandidateView.currentItem) return false var dictionaryType = inputPanel.wordCandidateView.model.dataAt(inputPanel.wordCandidateView.currentIndex, SelectionListModel.Role.Dictionary) return dictionaryType !== undefined && dictionaryType === SelectionListModel.DictionaryType.User } function openWordCandidateContextMenu() { if (!inputPanel.wordCandidateView.currentItem) return false testcase.wait(200) wordCandidateContextMenuActiveSpy.clear() testcase.mousePress(inputPanel.wordCandidateView.currentItem) wordCandidateContextMenuActiveSpy.wait() testcase.mouseRelease(inputPanel.wordCandidateView.currentItem) return wordCandidateContextMenu.active } function selectItemFromWordCandidateContextMenu(index) { if (!inputPanel.wordCandidateView.currentItem) return false if (!wordCandidateContextMenu.active) return false var wordCandidateContextMenuList = Utils.findChildByProperty(keyboard, "objectName", "wordCandidateContextMenuList", null) if (wordCandidateContextMenuList.currentIndex !== index) { wordCandidateContextMenuList.currentIndex = index testcase.waitForRendering(inputPanel) } if (!wordCandidateContextMenuList.currentItem) return false var itemPos = inputPanel.mapFromItem(wordCandidateContextMenuList.currentItem, wordCandidateContextMenuList.currentItem.width / 2, wordCandidateContextMenuList.currentItem.height / 2) testcase.mouseClick(inputPanel, itemPos.x, itemPos.y, Qt.LeftButton, 0, 20) testcase.waitForRendering(inputPanel) return true } function setHandwritingMode(enabled) { if (inputPanel.keyboard.handwritingMode !== enabled) { if (!enabled || inputPanel.keyboard.isHandwritingAvailable()) inputPanel.keyboard.setHandwritingMode(enabled, true) } return inputPanel.keyboard.handwritingMode === enabled } function emulateHandwriting(ch, instant) { if (!inputPanel.keyboard.handwritingMode) return false var hwrInputArea = Utils.findChildByProperty(keyboard, "objectName", "hwrInputArea", null) inputMethodResultSpy.clear() if (!Handwriting.emulate(testcase, hwrInputArea, ch, instant, VirtualKeyboardSettings.locale)) { if (virtualKeyClick(ch)) return true console.warn("Cannot produce the symbol '%1' in handwriting mode".arg(ch)) return false } if (isSuperimposedHandwriting()) return true inputMethodResultSpy.wait(3000) return inputMethodResultSpy.count > 0 } function isSuperimposedHandwriting() { if (!inputPanel.keyboard.handwritingMode) return false return inputMethod != null && inputMethod.hasOwnProperty("superimposed") && inputMethod.superimposed } }