diff options
Diffstat (limited to 'src/imports/virtualkeyboard/Keyboard.qml')
-rw-r--r-- | src/imports/virtualkeyboard/Keyboard.qml | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/src/imports/virtualkeyboard/Keyboard.qml b/src/imports/virtualkeyboard/Keyboard.qml new file mode 100644 index 0000000..c626dbc --- /dev/null +++ b/src/imports/virtualkeyboard/Keyboard.qml @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import "components" +import Boot2Qt.InputContext 1.0 +import Qt.labs.folderlistmodel 2.0 + +Image { + id: keyboard + + property var activeKey: 0 + property int localeIndex: 1 + property string locale: layoutsModel.count > 0 ? layoutsModel.get(localeIndex, "fileBaseName") : "en_GB" + property bool active: Qt.inputMethod.visible + property bool uppercased: uppercaseOnly ? true : (lowercaseOnly ? false : InputContext.shift || InputContext.capsLock) + property bool uppercaseOnly: InputContext.inputMethodHints & Qt.ImhUppercaseOnly + property bool lowercaseOnly: InputContext.inputMethodHints & Qt.ImhLowercaseOnly + property bool numberMode: InputContext.inputMethodHints & (Qt.ImhDialableCharactersOnly | Qt.ImhFormattedNumbersOnly | Qt.ImhDigitsOnly) + property bool symbolMode + + z: 1 + source: "images/keypad.png" + fillMode: Image.Stretch + width: parent.width + height: keyboardLayout.height+10 + y: Qt.inputMethod.visible ? parent.height - height : parent.height + visible: Qt.inputMethod.visible || Qt.inputMethod.animating; + + onLocaleChanged: InputContext.setLocale(locale) + onUppercasedChanged: if (Qt.inputMethod.visible) InputContext.handleUppercasing(uppercased) + + function changeInputLanguage() { + localeIndex = (localeIndex+1) % layoutsModel.count + } + + Behavior on y { + SequentialAnimation { + ScriptAction { + script: { + if (Qt.inputMethod.visible) { + keyboard.symbolMode = false + InputContext.handleUppercasing(uppercased) + } + InputContext.setAnimating(true) + } + } + NumberAnimation { duration: 300; easing.type: Easing.InOutQuad } + ScriptAction { script: InputContext.setAnimating(false) } + } + } + AutoScroller {} + FolderListModel { + id: layoutsModel + folder: "layouts" + nameFilters: ["*_*.qml"] + } + PressedKey {} + InputEngine { id: inputEngine } + AlternativeKeys { id: alternativeKeys } + Timer { id: releaseInaccuracyTimer; interval: 500 } + CharacterPreviewBubble { enabled: keyboardMouse.pressed && !alternativeKeys.active } + Binding { + target: InputContext + property: "keyboardRectangle" + value: Qt.rect(keyboard.x, keyboard.y, keyboard.width, keyboard.height) + } + Column { + id: keyboardLayout + anchors.centerIn: parent + Loader { + active: false + visible: keyboard.symbolMode && !keyboard.numberMode + source: "layouts/symbols.qml" + onVisibleChanged: if (visible) active = true + Component.onCompleted: if (visible) active = true + anchors.horizontalCenter: parent.horizontalCenter + } + Loader { + active: false + visible: keyboard.numberMode + source: "layouts/numbers.qml" + onVisibleChanged: if (visible) active = true + Component.onCompleted: if (visible) active = true + anchors.horizontalCenter: parent.horizontalCenter + } + Loader { + visible: !keyboard.symbolMode && !keyboard.numberMode + source: "layouts/" + keyboard.locale +".qml" + } + } + MouseArea { + id: keyboardMouse + + property var initialKey + property var previousKey + property bool dragSymbolMode + property real pressAndHoldMargin: 6 + property real releaseMargin: 18 + + anchors.fill: keyboardLayout + + function press(key) { + if (key && key.enabled) { + if (key.key != Qt.Key_unknown || key.text.length > 0) + inputEngine.sendKeyPress(key.key, keyboard.uppercased ? key.text.toUpperCase() : key.text, keyboard.uppercased ? Qt.ShiftModifier : 0, key.repeat) + } + } + function release(key) { + if (key && key.enabled) { + if (key.key != Qt.Key_unknown || key.text.length > 0) + inputEngine.sendKeyRelease(key.key, keyboard.uppercased ? key.text.toUpperCase() : key.text, keyboard.uppercased ? Qt.ShiftModifier : 0) + key.clicked() + } else if (initialKey !== undefined) // rollback + InputContext.preeditText = InputContext.preeditText.substr(0, InputContext.preeditText.length-1) + } + function click(key) { + if (key && key.enabled) { + if (key.key != Qt.Key_unknown || key.text.length > 0) + inputEngine.sendKeyClick(key.key, keyboard.uppercased ? key.text.toUpperCase() : key.text, keyboard.uppercased ? Qt.ShiftModifier : 0, key.repeat) + key.clicked() + } + } + function setActiveKey(activeKey) { + if (keyboard.activeKey) + keyboard.activeKey.active = false + keyboard.activeKey = activeKey + if (keyboard.activeKey) + keyboard.activeKey.active = true + } + function keyOnMouse(mx, my) { + var parentItem = keyboardLayout + var child = parentItem.childAt(mx, my) + while (child != null) { + var position = parentItem.mapToItem(child, mx, my) + mx = position.x; my = position.y + parentItem = child + child = parentItem.childAt(mx, my) + if (child && child.key != undefined) + return child + } + return undefined + } + function hitInitialKey(mouseX, mouseY, margin) { + if (!initialKey) + return false + var position = initialKey.mapFromItem(keyboardMouse, mouseX, mouseY) + return (position.x > -margin + && position.y > -margin + && position.x < initialKey.width + margin + && position.y < initialKey.height + margin) + } + function reset() { + alternativeKeys.close() + previousKey = keyboard.activeKey + setActiveKey(0) + if (dragSymbolMode) + keyboard.symbolMode = false + dragSymbolMode = false + } + + onPressed: { + releaseInaccuracyTimer.start() + initialKey = keyOnMouse(mouseX, mouseY) + setActiveKey(initialKey ? initialKey : 0) + press(initialKey) + } + onPositionChanged: { + if (alternativeKeys.active) { + alternativeKeys.move(mouseX) + } else { + var key = keyOnMouse(mouseX, mouseY) + if (key !== keyboard.activeKey) { + setActiveKey(key ? key : 0) + } + } + } + onPressAndHold: { + var key = hitInitialKey(mouseX, mouseY, pressAndHoldMargin) ? initialKey : keyboard.activeKey + if (key != undefined && key == initialKey) { + alternativeKeys.open(key) + if (!alternativeKeys.active && key.key == Qt.Key_Context1) { + dragSymbolMode = true + keyboard.symbolMode = true + } + } + } + onClicked: {} + onReleased: { + var key = keyOnMouse(mouseX, mouseY) + if (alternativeKeys.active) { + alternativeKeys.move(mouseX) + alternativeKeys.clicked() + } else if (dragSymbolMode) { + var key = keyOnMouse(mouseX, mouseY) + release(initialKey) + click(key) + } else { + release(releaseInaccuracyTimer.running && hitInitialKey(mouseX, mouseY, releaseMargin) ? initialKey : keyOnMouse(mouseX, mouseY)) + } + reset() + } + onCanceled: reset() + } +} |