├── .gitignore ├── LICENSE ├── LICENSE.MIT ├── README.md ├── S95application ├── doc └── VirtualKeyboardScreenshot.png ├── examples └── qmlapp │ ├── ButtonFlatStyle.qml │ ├── DejaVuSans.ttf │ ├── FontAwesome.otf │ ├── Main.qml │ ├── MainContainer.qml │ ├── MainDesigner.qml │ ├── MainQuickControls.qml │ ├── ProgressBarFlatStyle.qml │ ├── SliderFlatStyle.qml │ ├── Style.qml │ ├── Syringe.qml │ ├── TextFieldFlatStyle.qml │ ├── content │ ├── ScrollBar.qml │ ├── TextArea.qml │ ├── TextBase.qml │ └── TextField.qml │ ├── main.cpp │ ├── qmlappdemo.pro │ ├── qmlappdemo.qrc │ ├── qmldir │ ├── syringe1.png │ └── syringe2.svg ├── install.sh ├── src ├── DeclarativeInputEngine.cpp ├── DeclarativeInputEngine.h ├── FontAwesome.otf ├── InputPanel.qml ├── KeyButton.qml ├── KeyModel.qml ├── KeyPopup.qml ├── VirtualKeyboardInputContext.cpp ├── VirtualKeyboardInputContext.h ├── VirtualKeyboardInputContextPlugin.cpp ├── VirtualKeyboardInputContextPlugin.h ├── freevirtualkeyboard.json ├── libFreeVirtualKeyboard.so ├── qmldir ├── virtualkeyboard.pro ├── virtualkeyboard.qrc └── virtualkeyboard_global.h └── uEnv.txt /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | /src/virtualkeyboard.pro.user 3 | /examples/qmlapp/qmlappdemo.pro.user.3.3-pre1 4 | /examples/qmlapp/*.exe 5 | /examples/qmlapp/qmlappdemo.pro.user 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------- 3 | * "THE BEER-WARE LICENSE" (Revision 42): 4 | * wrote this file. As long as you retain this notice you 5 | * can do whatever you want with this stuff. If we meet some day, and you think 6 | * this stuff is worth it, you can buy me a beer in return Tomasz Olszak 7 | * ---------------------------------------------------------------------------- 8 | */ -------------------------------------------------------------------------------- /LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Uwe Kindler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QtFreeVirtualKeyboard 2 | A QML based on screen virtual keyboard for embedded QML applications. 3 | 4 | ![Screenshot](doc/VirtualKeyboardScreenshot.png) 5 | 6 | As soon as you implement your first QML application for an embedded touchscreen device, you will notice, that the open source version of Qt lacks a virtual on screen keyboard. I'm an experienced Qt developer, but I'm a complete newbie when it comes to QML programming. I'm a great fan of the [Beaglebone Black](http://beagleboard.org/BLACK) embedded Linux device and I just ordered a [capacitive touchscreen device](https://www.kickstarter.com/projects/1924187374/manga-screen-multi-touch-43-lcd) for my bone. I started learning QML to create an example application for my Beaglebone. I quickly realized that an important essential piece was missing for entering text and values: a virtual on screen keyboard for embedded QML applications - that means for applications without a window manager like X11 or Wayland. 7 | 8 | There is a nice solution for Qt Enterprise version: [Qt Virtual Keyboard](http://doc.qt.io/QtVirtualKeyboard/index.html). The documentation also comes with a nice [technical guide](http://doc.qt.io/QtVirtualKeyboard/technical-guide.html) that shows how they implemented the virtual keyboard. They implemented `QPlatformInputContextPlugin` and `QPlatformInputContext` interfaces. I googled a little bit to find a similar open source solution and found the fantastic blog post from [Tomasz Olszak](http://tolszak-dev.blogspot.de/2013/04/qplatforminputcontext-and-virtual.html). He did a virtual keyboard mockup for Qt applications on systems with a window manager (Windows or Linux Desktop). Interesting for me was the fact, that he also implemented `QPlatformInputContextPlugin` and `QPlatformInputContext` to provide its on screen keyboard. So it seems to be the right way for implementing a virtual keyboard. The UI of Tomasz implementation was completely QML based - so it was perfectly suited for integration into QML applications. 9 | 10 | Long story short, I simply copied his code and modified it, to enable integration into embedded QML applications without window manager. I added a little bit of functionality (i.e. character preview popup, or automatic scrolling of flickable elements if keyboard overlaps focused input element). So I have to say a big thank you to Tomasz Olszak for providing a nice virtual keyboard mockup. The example application in examples/qmlapp has been copied from the [Qt Virtual Keyboard example](http://doc.qt.io/QtVirtualKeyboard/qtvirtualkeyboard-enterprise-virtualkeyboard-virtualkeyboard-example.html). I only did some minor modifications to run the example with my Virtual Keyboard implementation instead of the Qt Enterprise Virtual Keyboard. 11 | 12 | This implementation is far from feature complete. But I think it is a starting point for people that need to implement virtual keyboard support for QML applications. Keep in mind that I'm a QML newbie and that my QML is far from beeing perfect. So if you find something in my QML code that could be done better, then please tell me or send me a pull request. 13 | -------------------------------------------------------------------------------- /S95application: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # mount 3rd partition of SD card into userdata directory and start application 4 | # mount with sync option to disable write cache because user may simply switch 5 | # off the device 6 | #mount -o sync,noatime /dev/mmcblk0p3 /ledarray/userdata 7 | cd /vktest 8 | ./virtualkeyboardqmldemo & 9 | -------------------------------------------------------------------------------- /doc/VirtualKeyboardScreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reHackable/QtFreeVirtualKeyboard/64e6a9434546c69ddcceb6168b9dae0522e8a67f/doc/VirtualKeyboardScreenshot.png -------------------------------------------------------------------------------- /examples/qmlapp/ButtonFlatStyle.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Controls 1.2 3 | import QtQuick.Controls.Styles 1.2 4 | import "." 5 | 6 | ButtonStyle { 7 | id: textfieldstyle 8 | property font font 9 | 10 | background: Rectangle { 11 | id: bg 12 | color: !control.pressed ? "#00FFFFFF" : "#5caa15" 13 | radius: Style.dp(8) 14 | border.color: "#5caa15" 15 | border.width: Style.dp(2) 16 | } 17 | 18 | label: Text { 19 | id: textLabel 20 | renderType: Text.NativeRendering 21 | verticalAlignment: Text.AlignVCenter 22 | horizontalAlignment: Text.AlignHCenter 23 | color: control.pressed ? "white" : "#5caa15" 24 | text: control.text 25 | font: textfieldstyle.font 26 | } 27 | 28 | padding.left: Style.dp(20) 29 | padding.right: Style.dp(20) 30 | padding.top: Style.dp(10) 31 | padding.bottom: Style.dp(10) 32 | } 33 | -------------------------------------------------------------------------------- /examples/qmlapp/DejaVuSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reHackable/QtFreeVirtualKeyboard/64e6a9434546c69ddcceb6168b9dae0522e8a67f/examples/qmlapp/DejaVuSans.ttf -------------------------------------------------------------------------------- /examples/qmlapp/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reHackable/QtFreeVirtualKeyboard/64e6a9434546c69ddcceb6168b9dae0522e8a67f/examples/qmlapp/FontAwesome.otf -------------------------------------------------------------------------------- /examples/qmlapp/Main.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Digia Plc 4 | ** All rights reserved. 5 | ** For any questions to Digia, please use contact form at http://www.qt.io 6 | ** 7 | ** This file is part of the Qt Virtual Keyboard add-on for Qt Enterprise. 8 | ** 9 | ** Licensees holding valid Qt Enterprise licenses may use this file in 10 | ** accordance with the Qt Enterprise License Agreement provided with the 11 | ** Software or, alternatively, in accordance with the terms contained in 12 | ** a written agreement between you and Digia. 13 | ** 14 | ** If you have questions regarding the use of this file, please use 15 | ** contact form at http://www.qt.io 16 | ** 17 | ****************************************************************************/ 18 | 19 | import QtQuick 2.0 20 | import "content" 21 | 22 | Rectangle { 23 | width: parent.width 24 | height: parent.height 25 | color: "#005F3F" 26 | 27 | Flickable { 28 | id: flickable 29 | 30 | property real scrollMarginVertical: 20 31 | 32 | anchors.fill: parent 33 | contentWidth: content.width 34 | contentHeight: content.height 35 | interactive: contentHeight > height 36 | flickableDirection: Flickable.VerticalFlick 37 | children: ScrollBar {} 38 | 39 | MouseArea { 40 | id: content 41 | 42 | width: flickable.width 43 | height: textEditors.height + 24 44 | 45 | onClicked: focus = true 46 | 47 | Column { 48 | id: textEditors 49 | spacing: 15 50 | x: 12; y: 12 51 | width: parent.width - 26 52 | 53 | Text { 54 | color: "#EEEEEE" 55 | text: "Tap fields to enter text" 56 | anchors.horizontalCenter: parent.horizontalCenter 57 | font.pixelSize: 22 58 | } 59 | TextField { 60 | width: parent.width 61 | previewText: "One line field" 62 | //enterKeyAction: EnterKeyAction.Next 63 | onEnterKeyClicked: passwordField.focus = true 64 | objectName: "One line field" 65 | } 66 | TextField { 67 | id: passwordField 68 | 69 | width: parent.width 70 | echoMode: TextInput.Password 71 | previewText: "Password field" 72 | inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhPreferLowercase | Qt.ImhSensitiveData | Qt.ImhNoPredictiveText 73 | //enterKeyAction: EnterKeyAction.Next 74 | onEnterKeyClicked: upperCaseField.focus = true 75 | } 76 | TextField { 77 | id: upperCaseField 78 | 79 | width: parent.width 80 | previewText: "Upper case field" 81 | inputMethodHints: Qt.ImhUppercaseOnly 82 | //enterKeyAction: EnterKeyAction.Next 83 | onEnterKeyClicked: lowerCaseField.focus = true 84 | } 85 | TextField { 86 | id: lowerCaseField 87 | 88 | width: parent.width 89 | previewText: "Lower case field" 90 | inputMethodHints: Qt.ImhLowercaseOnly 91 | //enterKeyAction: EnterKeyAction.Next 92 | onEnterKeyClicked: phoneNumberField.focus = true 93 | } 94 | TextField { 95 | id: phoneNumberField 96 | 97 | validator: RegExpValidator { regExp: /^[0-9\+\-\#\*\ ]{6,}$/ } 98 | width: parent.width 99 | previewText: "Phone number field" 100 | inputMethodHints: Qt.ImhDialableCharactersOnly 101 | //enterKeyAction: EnterKeyAction.Next 102 | onEnterKeyClicked: formattedNumberField.focus = true 103 | } 104 | TextField { 105 | id: formattedNumberField 106 | 107 | width: parent.width 108 | previewText: "Formatted number field" 109 | inputMethodHints: Qt.ImhFormattedNumbersOnly 110 | //enterKeyAction: EnterKeyAction.Next 111 | onEnterKeyClicked: digitsField.focus = true 112 | } 113 | TextField { 114 | id: digitsField 115 | 116 | width: parent.width 117 | previewText: "Digits only field" 118 | inputMethodHints: Qt.ImhDigitsOnly 119 | //enterKeyAction: EnterKeyAction.Next 120 | onEnterKeyClicked: textArea.focus = true 121 | } 122 | TextArea { 123 | id: textArea 124 | 125 | width: parent.width 126 | previewText: "Multiple lines field" 127 | height: Math.max(206, implicitHeight) 128 | } 129 | } 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /examples/qmlapp/MainContainer.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Digia Plc 4 | ** All rights reserved. 5 | ** For any questions to Digia, please use contact form at http://www.qt.io 6 | ** 7 | ** This file is part of the Qt Virtual Keyboard add-on for Qt Enterprise. 8 | ** 9 | ** Licensees holding valid Qt Enterprise licenses may use this file in 10 | ** accordance with the Qt Enterprise License Agreement provided with the 11 | ** Software or, alternatively, in accordance with the terms contained in 12 | ** a written agreement between you and Digia. 13 | ** 14 | ** If you have questions regarding the use of this file, please use 15 | ** contact form at http://www.qt.io 16 | ** 17 | ****************************************************************************/ 18 | 19 | import QtQuick 2.0 20 | import QtQuick.FreeVirtualKeyboard 1.0 21 | import QtQuick.Window 2.0 22 | 23 | 24 | Rectangle { 25 | id: root 26 | color: "black" 27 | implicitWidth: mainQml.implicitWidth 28 | implicitHeight: mainQml.implicitHeight 29 | //onWidthChanged: console.log("3 Root item size: " + height + " " + width) 30 | //onHeightChanged: console.log("3 Root item size: " + height + " " + width) 31 | Item { 32 | clip: true 33 | id: appContainer 34 | width: parent.width - 100 35 | height: parent.height - 100 36 | anchors.centerIn: parent 37 | anchors.horizontalCenterOffset: 5 38 | MainQuickControls { 39 | id: mainQml 40 | anchors.left: parent.left 41 | anchors.top: parent.top 42 | anchors.right: parent.right 43 | anchors.bottom: inputPanel.top 44 | } 45 | InputPanel { 46 | id: inputPanel 47 | z: 99 48 | y: appContainer.height 49 | anchors.left: parent.left 50 | anchors.right: parent.right 51 | states: State { 52 | name: "visible" 53 | when: Qt.inputMethod.visible 54 | PropertyChanges { 55 | target: inputPanel 56 | y: appContainer.height - inputPanel.height 57 | } 58 | } 59 | transitions: Transition { 60 | from: "" 61 | to: "visible" 62 | reversible: true 63 | ParallelAnimation { 64 | NumberAnimation { 65 | properties: "y" 66 | duration: 150 67 | easing.type: Easing.InOutQuad 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /examples/qmlapp/MainDesigner.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 1.2 3 | import QtQuick.Layouts 1.0 4 | 5 | Rectangle { 6 | width: 800 7 | height: 480 8 | 9 | Flickable { 10 | id: flickable1 11 | anchors.fill: parent 12 | flickableDirection: Flickable.VerticalFlick 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/qmlapp/MainQuickControls.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Controls 1.2 3 | import QtQuick.Controls.Styles 1.2 4 | import "." 5 | 6 | Rectangle { 7 | id: root 8 | width: parent.width 9 | height: parent.height 10 | color: "white" 11 | 12 | FontLoader { 13 | source: "FontAwesome.otf" 14 | } 15 | 16 | // this is a standalone animation, it's not running by default 17 | PropertyAnimation { id: syringeLevelAnimation; target: syringe; property: "level"} 18 | 19 | Flickable { 20 | id: flickable 21 | anchors.fill: parent 22 | contentWidth: content.width 23 | contentHeight: content.height 24 | interactive: contentHeight > height 25 | flickableDirection: Flickable.VerticalFlick 26 | 27 | Item { 28 | id: content 29 | x: Style.dp(20) 30 | y: Style.dp(20) 31 | width: flickable.width - Style.dp(42) 32 | //height: syringeRow.implicitHeight + grid.implicitHeight 33 | 34 | Row { 35 | id: syringeRow 36 | anchors.left: content.left 37 | anchors.right: content.right 38 | height: Style.dp(160) 39 | //spacing: 10 40 | Button { 41 | id: emptyButton 42 | text: "\uf049" 43 | width: content.width * 0.15 44 | height: parent.height 45 | style: ButtonFlatStyle { 46 | font.family: "FontAwesome" 47 | font.pixelSize: Style.dp(60) 48 | } 49 | 50 | onPressedChanged: { 51 | syringeLevelAnimation.to = syringe.minimumLevel; 52 | syringeLevelAnimation.duration = syringe.level / syringe.maximumLevel * 5000 * flowSlider.maximumValue / flowSlider.value 53 | syringeLevelAnimation.running = pressed; 54 | } 55 | } 56 | 57 | Syringe { 58 | id: syringe 59 | height: parent.height 60 | width: content.width * 0.7 61 | minimumLevel: 0 62 | maximumLevel: 10 63 | level: maximumLevel / 2 64 | } 65 | 66 | 67 | Button { 68 | id: refillButton 69 | text: "\uf050" 70 | width: content.width * 0.15 71 | height: parent.height 72 | style: ButtonFlatStyle { 73 | font.family: "FontAwesome" 74 | font.pixelSize: Style.dp(60) 75 | } 76 | 77 | onPressedChanged: { 78 | syringeLevelAnimation.to = syringe.maximumLevel 79 | syringeLevelAnimation.duration = (syringe.maximumLevel - syringe.level) / syringe.maximumLevel * 5000 * flowSlider.maximumValue / flowSlider.value 80 | syringeLevelAnimation.running = pressed; 81 | } 82 | } 83 | } 84 | 85 | 86 | Grid { 87 | id: grid 88 | columns: 2 89 | verticalItemAlignment: Grid.AlignVCenter 90 | horizontalItemAlignment: Grid.AlignLeft 91 | columnSpacing: Style.dp(10) 92 | rowSpacing: Style.dp(20) 93 | anchors.left: content.left 94 | anchors.right: content.right 95 | anchors.top: syringeRow.bottom 96 | anchors.topMargin: Style.dp(20) 97 | 98 | // 1st rot ---------------------- 99 | Label { 100 | text: "Level (ml):" 101 | font.pixelSize: levelTextField.font.pixelSize 102 | } 103 | TextField { 104 | id: levelTextField 105 | style: TextFieldFlatStyle {} 106 | width: grid.width - x 107 | //placeholderText: "Level (ml)" 108 | inputMethodHints: Qt.ImhFormattedNumbersOnly 109 | text: syringe.level 110 | validator: DoubleValidator { 111 | bottom: syringe.minimumLevel; 112 | top: syringe.maximumLevel; 113 | notation: DoubleValidator.StandardNotation 114 | decimals: 6 115 | } 116 | } 117 | 118 | // 1st rot ---------------------- 119 | Label { 120 | text: "Volume (ml):" 121 | font.pixelSize: volumeTextField.font.pixelSize 122 | } 123 | TextField { 124 | id: volumeTextField 125 | style: TextFieldFlatStyle {} 126 | width: grid.width - x 127 | //placeholderText: "Volume (ml)" 128 | inputMethodHints: Qt.ImhFormattedNumbersOnly 129 | text: "0" 130 | validator: DoubleValidator { 131 | bottom: 0; 132 | top: 2000; 133 | notation: DoubleValidator.StandardNotation 134 | decimals: 6 135 | } 136 | } 137 | 138 | // 2nd row ---------------------- 139 | Label { 140 | text: "Flow (ml/s):" 141 | font.pixelSize: flowTextField.font.pixelSize 142 | } 143 | TextField { 144 | id: flowTextField 145 | style: TextFieldFlatStyle {} 146 | width: grid.width - x 147 | //placeholderText: "Flow (ml/s)" 148 | inputMethodHints: Qt.ImhFormattedNumbersOnly 149 | validator: DoubleValidator { 150 | bottom: 0; 151 | top: 2000; 152 | notation: DoubleValidator.StandardNotation 153 | decimals: 6 154 | } 155 | } 156 | 157 | // 3rd row ---------------------- 158 | Rectangle { 159 | id: dumy 160 | width: Style.dp(10) 161 | height: Style.dp(10) 162 | } 163 | 164 | Slider { 165 | id: flowSlider 166 | width: grid.width - x 167 | minimumValue: 0 168 | maximumValue: 100 169 | value: 30 170 | style: SliderFlatStyle {} 171 | onValueChanged: { 172 | flowTextField.text = value 173 | } 174 | } 175 | } 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /examples/qmlapp/ProgressBarFlatStyle.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Controls 1.2 3 | import QtQuick.Controls.Styles 1.2 4 | import "." 5 | 6 | 7 | 8 | Component { 9 | id: progressBarFlatStyle 10 | ProgressBarStyle { 11 | background: Rectangle { 12 | radius: Style.dp(8) 13 | color: "#00FFFFFF" 14 | border.color: "#c9c9c9" 15 | border.width: Style.dp(w) 16 | implicitWidth: Style.dp(200) 17 | implicitHeight: Style.dp(24) 18 | } 19 | progress: Rectangle { 20 | color: "#5caa15" 21 | radius: Style.dp(8) 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /examples/qmlapp/SliderFlatStyle.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Controls 1.2 3 | import QtQuick.Controls.Styles 1.2 4 | import "." 5 | 6 | 7 | Component { 8 | id: sliderFlatStyle 9 | SliderStyle { 10 | groove: Rectangle { 11 | color: "#c9c9c9" 12 | radius: Math.round(height / 2) 13 | border.color: "#c9c9c9" 14 | border.width: Style.dp(2) 15 | height: Style.dp(8) 16 | 17 | Rectangle { 18 | color: "#5caa15" 19 | radius: Math.round(height / 2) 20 | anchors.left: parent.left 21 | anchors.top: parent.top 22 | anchors.bottom: parent.bottom 23 | width: parent.width * control.value / (control.maximumValue - control.minimumValue) 24 | } 25 | } 26 | 27 | handle: Item { 28 | implicitWidth: Style.dp(45) 29 | implicitHeight: Style.dp(45) 30 | Rectangle { 31 | id: foreground 32 | color: "white" 33 | radius: Math.round(height / 2) 34 | border.color: !control.pressed ? "#999999" : "#328930" 35 | border.width: Style.dp(2) 36 | anchors.fill: parent 37 | z: 10 38 | } 39 | 40 | Rectangle { 41 | id: shadow 42 | color: "#1F000000" 43 | radius: foreground.radius 44 | border.color: "transparent" 45 | border.width: 0 46 | width: foreground.width 47 | height: foreground.height 48 | x: foreground.x + 2 49 | y: foreground.y + 2 50 | z: 9 51 | } 52 | 53 | Rectangle { 54 | id: glow 55 | width: foreground.width * 1.7 56 | height: foreground.height * 1.7 57 | border.color: "#328930" 58 | border.width: Style.dp(2) 59 | anchors.centerIn: foreground 60 | radius: Math.round(height / 2) 61 | color: "#2F5caa15" 62 | visible: control.pressed 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /examples/qmlapp/Style.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | import QtQuick 2.3 3 | import QtQuick.Window 2.0 4 | 5 | QtObject { 6 | function dp(value) { 7 | var px = Math.round(value * (screenPixelDensity / 160.0)); 8 | if(Qt.platform.os == "windows" || Qt.platform.os == "mac") { 9 | console.log("dp = " + px + " Screen.pixelDensity " + screenPixelDensity); 10 | return px * 2; 11 | } 12 | else { 13 | return px; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/qmlapp/Syringe.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Controls 1.2 3 | import QtQuick.Controls.Styles 1.2 4 | import "." 5 | 6 | Item { 7 | id: root 8 | implicitHeight: syringeImage.height 9 | property alias maximumLevel: progressBar.maximumValue 10 | property alias minimumLevel: progressBar.minimumValue 11 | property alias level: progressBar.value 12 | 13 | Image { 14 | id: syringeImage 15 | source: "syringe2.svg" 16 | fillMode: Image.PreserveAspectFit 17 | anchors.fill: parent 18 | z: 100 19 | } 20 | 21 | ProgressBar { 22 | id: progressBar 23 | anchors.left: parent.left 24 | anchors.leftMargin: Math.round( 25 | (syringeImage.width - syringeImage.paintedWidth) / 2 + syringeImage.paintedWidth * 0.125) 26 | anchors.right: parent.right 27 | anchors.rightMargin: Math.round( 28 | (syringeImage.width - syringeImage.paintedWidth) / 2 + syringeImage.paintedWidth * 0.13) 29 | anchors.verticalCenter: parent.verticalCenter 30 | height: syringeImage.height * 0.65 31 | style: syringeProgressBarStyle 32 | z: 0 33 | } 34 | 35 | Component { 36 | id: syringeProgressBarStyle 37 | ProgressBarStyle { 38 | background: Rectangle { 39 | color: "#00FFFFFF" 40 | border.color: "transparent" 41 | border.width: 0 42 | implicitWidth: 200 43 | implicitHeight: 24 44 | } 45 | progress: Rectangle { 46 | color: "#5caa15" 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/qmlapp/TextFieldFlatStyle.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Controls 1.2 3 | import QtQuick.Controls.Styles 1.2 4 | import "." 5 | 6 | Component { 7 | id: textfieldFlatStyle 8 | 9 | TextFieldStyle { 10 | id: textfieldstyle 11 | textColor: "#333333" 12 | placeholderTextColor: "#c9c9c9" 13 | font.pixelSize: Style.dp(30) 14 | background: Rectangle { 15 | color: "#00FFFFFF" 16 | radius: Style.dp(8) 17 | border.color: "#c9c9c9" 18 | border.width: Style.dp(2) 19 | implicitHeight: textfieldstyle.font.pixelSize * 2.6 20 | } 21 | padding.left: Style.dp(30) 22 | padding.right: Style.dp(30) 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /examples/qmlapp/content/ScrollBar.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Digia Plc 4 | ** All rights reserved. 5 | ** For any questions to Digia, please use contact form at http://www.qt.io 6 | ** 7 | ** This file is part of the Qt Virtual Keyboard add-on for Qt Enterprise. 8 | ** 9 | ** Licensees holding valid Qt Enterprise licenses may use this file in 10 | ** accordance with the Qt Enterprise License Agreement provided with the 11 | ** Software or, alternatively, in accordance with the terms contained in 12 | ** a written agreement between you and Digia. 13 | ** 14 | ** If you have questions regarding the use of this file, please use 15 | ** contact form at http://www.qt.io 16 | ** 17 | ****************************************************************************/ 18 | 19 | import QtQuick 2.0 20 | 21 | Item { 22 | property var scrollArea: parent 23 | 24 | width: 6 25 | opacity: scrollArea && scrollArea.movingVertically ? 1.0 : 0.0 26 | visible: scrollArea && scrollArea.contentHeight >= scrollArea.height 27 | anchors { right: parent.right; top: parent.top; bottom: parent.bottom; margins: 2 } 28 | 29 | Behavior on opacity { NumberAnimation { properties: "opacity"; duration: 600 } } 30 | 31 | function size() { 32 | var nh = scrollArea.visibleArea.heightRatio * height 33 | var ny = scrollArea.visibleArea.yPosition * height 34 | return ny > 3 ? Math.min(nh, Math.ceil(height - 3 - ny)) : nh + ny 35 | } 36 | Rectangle { 37 | x: 1 38 | y: scrollArea ? Math.max(2, scrollArea.visibleArea.yPosition * parent.height) : 0 39 | height: scrollArea ? size() : 0 40 | width: parent.width - 2 41 | color: Qt.rgba(1.0, 1.0, 1.0, 0.5) 42 | radius: 1 43 | } 44 | } -------------------------------------------------------------------------------- /examples/qmlapp/content/TextArea.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Digia Plc 4 | ** All rights reserved. 5 | ** For any questions to Digia, please use contact form at http://www.qt.io 6 | ** 7 | ** This file is part of the Qt Virtual Keyboard add-on for Qt Enterprise. 8 | ** 9 | ** Licensees holding valid Qt Enterprise licenses may use this file in 10 | ** accordance with the Qt Enterprise License Agreement provided with the 11 | ** Software or, alternatively, in accordance with the terms contained in 12 | ** a written agreement between you and Digia. 13 | ** 14 | ** If you have questions regarding the use of this file, please use 15 | ** contact form at http://www.qt.io 16 | ** 17 | ****************************************************************************/ 18 | 19 | import QtQuick 2.0 20 | 21 | TextBase { 22 | id: textArea 23 | 24 | property alias color: textEdit.color 25 | property alias text: textEdit.text 26 | property alias textWidth: textEdit.width 27 | property alias readOnly: textEdit.readOnly 28 | property alias inputMethodHints: textEdit.inputMethodHints 29 | 30 | editor: textEdit 31 | 32 | Repeater { 33 | model: Math.floor((parent.height - 30) / editor.cursorRectangle.height) 34 | Rectangle { 35 | x: 8 36 | y: (index+1)*editor.cursorRectangle.height+6 37 | height: 1; width: textArea.width-24 38 | color: Qt.rgba(1.0, 1.0, 1.0, 0.5) 39 | } 40 | } 41 | TextEdit { 42 | id: textEdit 43 | 44 | /*EnterKeyAction.actionId: textArea.enterKeyAction 45 | EnterKeyAction.label: textArea.enterKeyText 46 | EnterKeyAction.enabled: textArea.enterKeyEnabled*/ 47 | 48 | y: 6 49 | focus: true 50 | color: "#EEEEEE" 51 | wrapMode: TextEdit.Wrap 52 | cursorVisible: activeFocus 53 | height: Math.max(implicitHeight, 60) 54 | font.pixelSize: textArea.fontPixelSize 55 | selectionColor: Qt.rgba(1.0, 1.0, 1.0, 0.5) 56 | selectedTextColor: Qt.rgba(0.0, 0.0, 0.0, 0.8) 57 | anchors { left: parent.left; right: parent.right; margins: 12 } 58 | onActiveFocusChanged: if (!activeFocus) deselect() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/qmlapp/content/TextBase.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Digia Plc 4 | ** All rights reserved. 5 | ** For any questions to Digia, please use contact form at http://www.qt.io 6 | ** 7 | ** This file is part of the Qt Virtual Keyboard add-on for Qt Enterprise. 8 | ** 9 | ** Licensees holding valid Qt Enterprise licenses may use this file in 10 | ** accordance with the Qt Enterprise License Agreement provided with the 11 | ** Software or, alternatively, in accordance with the terms contained in 12 | ** a written agreement between you and Digia. 13 | ** 14 | ** If you have questions regarding the use of this file, please use 15 | ** contact form at http://www.qt.io 16 | ** 17 | ****************************************************************************/ 18 | import QtQuick 2.0 19 | 20 | FocusScope { 21 | id: textBase 22 | 23 | property var editor 24 | property bool previewTextActive: !editor.activeFocus && text.length === 0 25 | property int fontPixelSize: 32 26 | property string previewText 27 | //property int enterKeyAction: EnterKeyAction.None 28 | property int enterKeyAction 29 | property string enterKeyText 30 | //property bool enterKeyEnabled: enterKeyAction === EnterKeyAction.None || editor.text.length > 0 || editor.inputMethodComposing 31 | property bool enterKeyEnabled 32 | property alias mouseParent: mouseArea.parent 33 | 34 | implicitHeight: editor.height + 12 35 | 36 | signal enterKeyClicked 37 | 38 | Keys.onReleased: { 39 | if (event.key === Qt.Key_Return) 40 | enterKeyClicked() 41 | } 42 | 43 | Rectangle { 44 | // background 45 | radius: 5.0 46 | anchors.fill: parent 47 | color: Qt.rgba(1.0, 1.0, 1.0, 0.2) 48 | border { width: editor.activeFocus ? 2 : 0; color: "#CCCCCC" } 49 | } 50 | Text { 51 | id: previewText 52 | 53 | y: 8 54 | color: "#CCCCCC" 55 | visible: previewTextActive 56 | text: textBase.previewText 57 | font.pixelSize: 28 58 | anchors { left: parent.left; right: parent.right; margins: 12 } 59 | 60 | } 61 | MouseArea { 62 | id: mouseArea 63 | 64 | z: 1 65 | parent: textBase 66 | anchors.fill: parent 67 | onClicked: { 68 | if (editor.inputMethodComposing) { 69 | if (!Qt.inputMethod.visible) { 70 | Qt.inputMethod.show() 71 | return 72 | } 73 | Qt.inputMethod.commit() 74 | } 75 | var positionInEditor = mapToItem(editor, mouseX, mouseY) 76 | var cursorPosition = editor.positionAt(positionInEditor.x, positionInEditor.y) 77 | editor.cursorPosition = cursorPosition 78 | editor.forceActiveFocus() 79 | Qt.inputMethod.show() 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /examples/qmlapp/content/TextField.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Digia Plc 4 | ** All rights reserved. 5 | ** For any questions to Digia, please use contact form at http://www.qt.io 6 | ** 7 | ** This file is part of the Qt Virtual Keyboard add-on for Qt Enterprise. 8 | ** 9 | ** Licensees holding valid Qt Enterprise licenses may use this file in 10 | ** accordance with the Qt Enterprise License Agreement provided with the 11 | ** Software or, alternatively, in accordance with the terms contained in 12 | ** a written agreement between you and Digia. 13 | ** 14 | ** If you have questions regarding the use of this file, please use 15 | ** contact form at http://www.qt.io 16 | ** 17 | ****************************************************************************/ 18 | 19 | import QtQuick 2.0 20 | //import "../../../src" 21 | 22 | TextBase { 23 | id: textField 24 | 25 | property alias color: textInput.color 26 | property alias text: textInput.text 27 | property alias textWidth: textInput.width 28 | property alias readOnly: textInput.readOnly 29 | property alias inputMethodHints: textInput.inputMethodHints 30 | property alias validator: textInput.validator 31 | property alias echoMode: textInput.echoMode 32 | property int passwordMaskDelay: 1000 33 | 34 | editor: textInput 35 | mouseParent: flickable 36 | 37 | Flickable { 38 | id: flickable 39 | 40 | x: 12 41 | clip: true 42 | width: parent.width-24 43 | height: parent.height 44 | flickableDirection: Flickable.HorizontalFlick 45 | interactive: contentWidth - 4 > width 46 | 47 | contentWidth: textInput.width+2 48 | contentHeight: textInput.height 49 | TextInput { 50 | id: textInput 51 | 52 | /*EnterKeyAction.actionId: textField.enterKeyAction 53 | EnterKeyAction.label: textField.enterKeyText 54 | EnterKeyAction.enabled: textField.enterKeyEnabled*/ 55 | 56 | y: 6 57 | focus: true 58 | color: "#EEEEEE" 59 | cursorVisible: activeFocus 60 | passwordCharacter: "\u2022" 61 | font.pixelSize: textField.fontPixelSize 62 | selectionColor: Qt.rgba(1.0, 1.0, 1.0, 0.5) 63 | selectedTextColor: Qt.rgba(0.0, 0.0, 0.0, 0.8) 64 | width: Math.max(flickable.width, implicitWidth)-2 65 | onActiveFocusChanged: if (!activeFocus) deselect() 66 | objectName: parent.objectName 67 | 68 | Binding { 69 | target: textInput 70 | property: "passwordMaskDelay" 71 | value: textField.passwordMaskDelay 72 | when: textInput.hasOwnProperty("passwordMaskDelay") 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /examples/qmlapp/main.cpp: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | /// \file main.cpp 3 | /// \author Uwe Kindler 4 | /// \date 08.01.2015 5 | /// \brief main of virtual keyboard example application 6 | //============================================================================ 7 | 8 | //============================================================================ 9 | // INCLUDES 10 | //============================================================================ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | /** 22 | * main entry point for application 23 | */ 24 | int main(int argc, char *argv[]) 25 | { 26 | // Load virtualkeyboard input context plugin 27 | qputenv("QT_IM_MODULE", QByteArray("freevirtualkeyboard")); 28 | 29 | QGuiApplication app(argc, argv); 30 | 31 | // Set standard font so that application looks equal on all platforms 32 | QFontDatabase FontDatabase; 33 | FontDatabase.addApplicationFont(":/DejaVuSans.ttf"); 34 | app.setFont(QFont("DejaVu Sans")); 35 | app.setObjectName("QGuiApplication"); 36 | 37 | QQuickView view; 38 | //view.setSource(QString("qrc:/MainContainer.qml")); 39 | view.engine()->rootContext()->setContextProperty("screenPixelDensity", 40 | QGuiApplication::primaryScreen()->physicalDotsPerInch()); 41 | view.setSource(QString("MainContainer.qml")); 42 | view.setObjectName("QQuickView"); 43 | view.setResizeMode(QQuickView::SizeRootObjectToView); 44 | view.engine()->setObjectName("QQuickEngine"); 45 | view.engine()->addImportPath(qApp->applicationDirPath()); 46 | 47 | // Set size to 800 x 480 WXGA - this is the size of the upcoming Manga 48 | // screen. 49 | view.setWidth(1280); 50 | view.setHeight(800); 51 | 52 | view.show(); 53 | 54 | return app.exec(); 55 | } 56 | -------------------------------------------------------------------------------- /examples/qmlapp/qmlappdemo.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | TARGET = virtualkeyboardqmldemo 3 | QT += qml quick 4 | SOURCES += main.cpp 5 | CONFIG += link_pkgconfig 6 | 7 | 8 | linux-buildroot-g++ { 9 | deployment.files = *.qml *.otf *.ttf *.svg 10 | target.path = /vktest 11 | deployment.path = /vktest 12 | INSTALLS += target deployment 13 | } else { 14 | target.path = $$[QT_INSTALL_EXAMPLES]/freevirtualkeyboard 15 | INSTALLS += target 16 | } 17 | 18 | 19 | RESOURCES += \ 20 | qmlappdemo.qrc 21 | 22 | OTHER_FILES += \ 23 | content/ScrollBar.qml \ 24 | content/TextArea.qml \ 25 | content/TextBase.qml \ 26 | content/TextField.qml \ 27 | Main.qml \ 28 | MainContainer.qml 29 | 30 | DESTDIR = $$PWD 31 | 32 | DISTFILES += \ 33 | StyleHelper.aml \ 34 | Style.qml 35 | -------------------------------------------------------------------------------- /examples/qmlapp/qmlappdemo.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | content/ScrollBar.qml 4 | content/TextArea.qml 5 | content/TextBase.qml 6 | content/TextField.qml 7 | DejaVuSans.ttf 8 | Main.qml 9 | MainContainer.qml 10 | MainQuickControls.qml 11 | MainDesigner.qml 12 | TextFieldFlatStyle.qml 13 | SliderFlatStyle.qml 14 | ProgressBarFlatStyle.qml 15 | Syringe.qml 16 | ButtonFlatStyle.qml 17 | FontAwesome.otf 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/qmlapp/qmldir: -------------------------------------------------------------------------------- 1 | singleton Style Style.qml -------------------------------------------------------------------------------- /examples/qmlapp/syringe1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reHackable/QtFreeVirtualKeyboard/64e6a9434546c69ddcceb6168b9dae0522e8a67f/examples/qmlapp/syringe1.png -------------------------------------------------------------------------------- /examples/qmlapp/syringe2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 23 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 60 | 61 | 62 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 63 | 64 | 65 | 66 | 67 | Remigho – The daisy log 68 | 69 | 70 | 71 | 72 | 74 | 76 | 78 | 80 | 82 | 84 | 86 | 88 | 89 | 90 | 91 | 96 | 103 | 109 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 152 | 157 | 162 | 167 | 172 | 177 | 182 | 185 | 192 | 199 | 206 | 207 | 212 | 217 | 222 | 227 | 232 | 237 | 242 | 247 | 252 | 257 | 262 | 267 | 274 | 281 | 288 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | # some configuration variables - adjust them to your application 5 | export APP_DIR=ledarray 6 | export APP_BINARY=bbb_ledarray 7 | DTB=bbb-ledarray-linux3.12.dtb 8 | 9 | # some variables we need 10 | export PROJECT_DIR=.. 11 | 12 | export BUILDROOT=/home/user/Coding/buildroot_git 13 | export BUILDROOT_STAGING=$BUILDROOT/output/staging 14 | BUILDROOT_IMAGES=$BUILDROOT/output/images 15 | 16 | BOOTDIR=/media/user/BOOT 17 | TFTP_DIR=/home/user/BBB/tftp 18 | BUILDROOT_CETONI=/home/user/Coding/buildroot-cetoni 19 | BBB_DIR=$BUILDROOT_CETONI/board/beaglebone 20 | 21 | 22 | # check if SD card is properly mounted 23 | check_sd_mount() { 24 | if [ "$target" = "n" ] 25 | then 26 | return; 27 | fi 28 | 29 | mountpoint="/media/user" 30 | volume="$mountpoint/BOOT" 31 | if ! mount|grep $volume; then 32 | echo "Volume $volume not mounted" 33 | exit; 34 | fi 35 | 36 | volume="$mountpoint/LINUX" 37 | if ! mount|grep $volume; then 38 | echo "Volume $volume not mounted" 39 | exit; 40 | fi 41 | 42 | volume="$mountpoint/DATA" 43 | if ! mount|grep $volume; then 44 | echo "Volume $volume not mounted" 45 | exit; 46 | fi 47 | } 48 | 49 | 50 | # some functions we need 51 | set_sd_target_vars() { 52 | export ROOTFS_DIR=/media/user/LINUX 53 | export APP_PATH=$ROOTFS_DIR/$APP_DIR 54 | } 55 | 56 | set_nfs_target_vars() { 57 | export ROOTFS_DIR=/home/user/BBB/rootfs 58 | export APP_PATH=$ROOTFS_DIR/$APP_DIR 59 | } 60 | 61 | 62 | #------------------------------------------------------------------------------ 63 | # Install buildroot to SD or NFS 64 | #------------------------------------------------------------------------------ 65 | install_buildroot () { 66 | if [ ! -d "$BOOTDIR" ] && [ "$target" = "s" ] 67 | then 68 | echo "SD card not mounted - canceling buildroot installation" 69 | return; 70 | fi 71 | 72 | # clear rootfs and boot dir 73 | rm -r $ROOTFS_DIR/* 74 | if [ -d "$BOOTDIR" ] 75 | then 76 | rm -r $BOOTDIR/* 77 | fi 78 | 79 | # extract root filesystem to rootfs dir 80 | tar -xf $BUILDROOT_IMAGES/rootfs.tar -C $ROOTFS_DIR 81 | mv $ROOTFS_DIR/boot/$DTB $ROOTFS_DIR/boot/am335x-boneblack.dtb 82 | 83 | if [ -d "$BOOTDIR" ] 84 | then 85 | cp $BUILDROOT_IMAGES/MLO $BOOTDIR 86 | cp $BUILDROOT_IMAGES/u-boot.img $BOOTDIR 87 | cp $BBB_DIR/uEnv_zImage_Debian.txt $BOOTDIR/uEnv.txt 88 | echo "Installing $BBB_DIR/uEnv_zImage_Debian.txt" 89 | fi 90 | 91 | # copy some additional helper scripts 92 | cp $BBB_DIR/etc/wpa_supplicant.conf $ROOTFS_DIR/etc/wpa_supplicant.conf 93 | cp -r -f $BBB_DIR/usr/bin/* $ROOTFS_DIR/usr/bin 94 | cp -vf $BUILDROOT_CETONI/scripts/bbb-SD-eMMC-copy.sh $ROOTFS_DIR/usr/sbin/ 95 | } 96 | 97 | 98 | #------------------------------------------------------------------------------ 99 | # Install cetoni libraries to SD or NFS 100 | #------------------------------------------------------------------------------ 101 | install_cetoni_libs() { 102 | # set write permissions for rootfs /usr/lib and /usr/bin for development 103 | # system 104 | if [ "$target" = "n" ] 105 | then 106 | chmod o+w $ROOTFS_DIR/usr/lib 107 | chmod o+w $ROOTFS_DIR/usr/bin 108 | cp -f -av $BUILDROOT_STAGING/usr/bin/*_test $ROOTFS_DIR/usr/bin 109 | fi 110 | 111 | # copy libraries 112 | cp -f -av $BUILDROOT_STAGING/usr/lib/libusl* $ROOTFS_DIR/usr/lib 113 | cp -f -av $BUILDROOT_STAGING/usr/lib/libcanoo* $ROOTFS_DIR/usr/lib 114 | cp -f -av $BUILDROOT_STAGING/usr/lib/liblabbcan* $ROOTFS_DIR/usr/lib 115 | cp -f -av $BUILDROOT_STAGING/usr/lib/liblabbCAN* $ROOTFS_DIR/usr/lib 116 | cp -f -av $BUILDROOT_STAGING/usr/lib/libcsi* $ROOTFS_DIR/usr/lib 117 | cp -f -av $BUILDROOT_STAGING/usr/lib/libled_array_api* $ROOTFS_DIR/usr/lib 118 | } 119 | 120 | 121 | #------------------------------------------------------------------------------ 122 | # Installs the application to SD or NFS 123 | #------------------------------------------------------------------------------ 124 | install_app() { 125 | echo "APP_PATH = $APP_PATH" 126 | #mkdir -p $APP_PATH/data/embedded_linux 127 | #mkdir -p $APP_PATH/userdata 128 | 129 | # copy application 130 | #cp -f -av $PROJECT_DIR/$APP_BINARY $APP_PATH 131 | #cp -f -av $PROJECT_DIR/data/start_app.sh $APP_PATH 132 | #cp -f -av $PROJECT_DIR/data/embedded_linux/* $APP_PATH/data/embedded_linux 133 | #chmod 777 $APP_PATH/$APP_BINARY 134 | 135 | # copy install script 136 | #if [ "$target" = "s" ] 137 | #then 138 | # cp -f -av S45application $ROOTFS_DIR/etc/init.d/ 139 | #fi 140 | #cp -f -av S30usb $ROOTFS_DIR/etc/init.d/ 141 | #cp -f -av S41usbgadget $ROOTFS_DIR/etc/init.d/ 142 | #cp -f -av interfaces $ROOTFS_DIR/etc/network/ 143 | } 144 | 145 | 146 | 147 | # The script must be run as root to have access to root file system ------------ 148 | if ! id | grep -q root; 149 | then 150 | echo "must be run as root" 151 | exit 152 | fi 153 | 154 | while true; do 155 | echo "What do you want to install? (c=complete | a=app | b=buildroot | l=cetoni libs)" 156 | read -p ": " installtype 157 | case $installtype in 158 | [c]* ) break;; 159 | [a]* ) break;; 160 | [b]* ) break;; 161 | [l]* ) break;; 162 | * ) echo "Please select a valid ID.";; 163 | esac 164 | done 165 | 166 | while true; do 167 | read -p "Where to you want to install? (s=SDCard | n=NFS): " target 168 | case $target in 169 | [s]* ) set_sd_target_vars; break;; 170 | [n]* ) set_nfs_target_vars; break;; 171 | * ) echo "Please select a valid ID.";; 172 | esac 173 | done 174 | 175 | check_sd_mount 176 | 177 | 178 | if [ "$installtype" = "b" ] || [ "$installtype" = "c" ] 179 | then 180 | install_buildroot 181 | fi 182 | 183 | if [ "$installtype" = "l" ] || [ "$installtype" = "c" ] 184 | then 185 | install_cetoni_libs 186 | fi 187 | 188 | if [ "$installtype" = "a" ] || [ "$installtype" = "c" ] 189 | then 190 | install_app 191 | fi 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /src/DeclarativeInputEngine.cpp: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | /// \file DeclarativeInputEngine.cpp 3 | /// \author Uwe Kindler 4 | /// \date 08.01.2015 5 | /// \brief Implementation of CDeclarativeInputEngine 6 | /// 7 | /// Copyright 2015 Uwe Kindler 8 | /// Licensed under MIT see LICENSE.MIT in project root 9 | //============================================================================ 10 | 11 | //============================================================================ 12 | // INCLUDES 13 | //============================================================================ 14 | #include "DeclarativeInputEngine.h" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | /** 27 | * Private data class 28 | */ 29 | struct DeclarativeInputEnginePrivate 30 | { 31 | DeclarativeInputEngine* _this; 32 | bool Animating; 33 | QTimer* AnimatingFinishedTimer;//< triggers position adjustment of focused QML item is covered by keybaord rectangle 34 | int InputMode; 35 | QRect KeyboardRectangle; 36 | 37 | /** 38 | * Private data constructor 39 | */ 40 | DeclarativeInputEnginePrivate(DeclarativeInputEngine* _public); 41 | }; // struct DeclarativeInputEnginePrivate 42 | 43 | 44 | 45 | //============================================================================== 46 | DeclarativeInputEnginePrivate::DeclarativeInputEnginePrivate(DeclarativeInputEngine* _public) 47 | : _this(_public), 48 | Animating(false), 49 | InputMode(DeclarativeInputEngine::Latin) 50 | { 51 | 52 | } 53 | 54 | 55 | //============================================================================== 56 | DeclarativeInputEngine::DeclarativeInputEngine(QObject *parent) : 57 | QObject(parent), 58 | d(new DeclarativeInputEnginePrivate(this)) 59 | { 60 | d->AnimatingFinishedTimer = new QTimer(this); 61 | d->AnimatingFinishedTimer->setSingleShot(true); 62 | d->AnimatingFinishedTimer->setInterval(100); 63 | connect(d->AnimatingFinishedTimer, SIGNAL(timeout()), this, SLOT(animatingFinished())); 64 | } 65 | 66 | 67 | //============================================================================== 68 | DeclarativeInputEngine::~DeclarativeInputEngine() 69 | { 70 | delete d; 71 | } 72 | 73 | 74 | //============================================================================== 75 | void DeclarativeInputEngine::virtualKeyCancel() 76 | { 77 | 78 | } 79 | 80 | 81 | //============================================================================== 82 | bool DeclarativeInputEngine::virtualKeyClick(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers) 83 | { 84 | Q_UNUSED(key) 85 | Q_UNUSED(modifiers) 86 | 87 | QInputMethodEvent ev; 88 | if (text == QString("\x7F")) 89 | { 90 | //delete one char 91 | ev.setCommitString("",-1,1); 92 | 93 | } else 94 | { 95 | //add some text 96 | ev.setCommitString(text); 97 | } 98 | QCoreApplication::sendEvent(QGuiApplication::focusObject(),&ev); 99 | return true; 100 | } 101 | 102 | 103 | //============================================================================== 104 | void DeclarativeInputEngine::sendKeyToFocusItem(const QString& text) 105 | { 106 | qDebug() << "CDeclarativeInputEngine::sendKeyToFocusItem " << text; 107 | QInputMethodEvent ev; 108 | if (text == QString("\x7F")) 109 | { 110 | //delete one char 111 | ev.setCommitString("",-1,1); 112 | 113 | } else 114 | { 115 | //add some text 116 | ev.setCommitString(text); 117 | } 118 | QCoreApplication::sendEvent(QGuiApplication::focusObject(),&ev); 119 | } 120 | 121 | 122 | //============================================================================== 123 | bool DeclarativeInputEngine::virtualKeyPress(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers, bool repeat) 124 | { 125 | Q_UNUSED(key) 126 | Q_UNUSED(text) 127 | Q_UNUSED(modifiers) 128 | Q_UNUSED(repeat) 129 | 130 | // not implemented yet 131 | return true; 132 | } 133 | 134 | 135 | //============================================================================== 136 | bool DeclarativeInputEngine::virtualKeyRelease(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers) 137 | { 138 | Q_UNUSED(key) 139 | Q_UNUSED(text) 140 | Q_UNUSED(modifiers) 141 | 142 | // not implemented yet 143 | return true; 144 | } 145 | 146 | 147 | //============================================================================== 148 | QRect DeclarativeInputEngine::keyboardRectangle() const 149 | { 150 | return d->KeyboardRectangle; 151 | } 152 | 153 | 154 | //============================================================================== 155 | void DeclarativeInputEngine::setKeyboardRectangle(const QRect& Rect) 156 | { 157 | setAnimating(true); 158 | d->AnimatingFinishedTimer->start(100); 159 | d->KeyboardRectangle = Rect; 160 | emit keyboardRectangleChanged(); 161 | } 162 | 163 | 164 | //============================================================================== 165 | bool DeclarativeInputEngine::isAnimating() const 166 | { 167 | return d->Animating; 168 | } 169 | 170 | 171 | //============================================================================== 172 | void DeclarativeInputEngine::setAnimating(bool Animating) 173 | { 174 | if (d->Animating != Animating) 175 | { 176 | d->Animating = Animating; 177 | emit animatingChanged(); 178 | } 179 | } 180 | 181 | 182 | //============================================================================== 183 | void DeclarativeInputEngine::animatingFinished() 184 | { 185 | setAnimating(false); 186 | } 187 | 188 | 189 | //============================================================================== 190 | int DeclarativeInputEngine::inputMode() const 191 | { 192 | return d->InputMode; 193 | } 194 | 195 | 196 | //============================================================================== 197 | void DeclarativeInputEngine::setInputMode(int Mode) 198 | { 199 | qDebug() << "CDeclarativeInputEngine::setInputMode " << Mode; 200 | if (Mode != d->InputMode) 201 | { 202 | d->InputMode = Mode; 203 | emit inputModeChanged(); 204 | } 205 | } 206 | 207 | //------------------------------------------------------------------------------ 208 | // EOF DeclarativeInputEngine.cpp 209 | -------------------------------------------------------------------------------- /src/DeclarativeInputEngine.h: -------------------------------------------------------------------------------- 1 | #ifndef DECLARATIVEINPUTENGINE_H 2 | #define DECLARATIVEINPUTENGINE_H 3 | //============================================================================ 4 | /// \file DeclarativeInputEngine.h 5 | /// \author Uwe Kindler 6 | /// \date 08.01.2015 7 | /// \brief Declaration of CDeclarativeInputEngine 8 | /// 9 | /// Copyright 2015 Uwe Kindler 10 | /// Licensed under MIT see LICENSE.MIT in project root 11 | //============================================================================ 12 | 13 | //============================================================================ 14 | // INCLUDES 15 | //============================================================================ 16 | #include 17 | #include 18 | 19 | struct DeclarativeInputEnginePrivate; 20 | 21 | /** 22 | * The input engine provides input context information and is responsible 23 | * for routing input events to focused QML items. 24 | * The InputEngine can be accessed as singleton instance from QML 25 | */ 26 | class DeclarativeInputEngine : public QObject 27 | { 28 | Q_OBJECT 29 | Q_PROPERTY(QRect keyboardRectangle READ keyboardRectangle WRITE setKeyboardRectangle NOTIFY keyboardRectangleChanged FINAL) 30 | Q_PROPERTY(bool animating READ isAnimating WRITE setAnimating NOTIFY animatingChanged FINAL) 31 | Q_PROPERTY(int inputMode READ inputMode WRITE setInputMode NOTIFY inputModeChanged FINAL) 32 | Q_ENUMS(InputMode) 33 | private: 34 | DeclarativeInputEnginePrivate* d; 35 | friend class DeclarativeInputEnginePrivate; 36 | 37 | private slots: 38 | void animatingFinished(); 39 | 40 | public: 41 | /** 42 | * The InputMode enum provides a list of valid input modes 43 | */ 44 | enum InputMode {Latin, Numeric, Dialable}; 45 | 46 | /** 47 | * Creates a dclarative input engine with the given parent 48 | */ 49 | explicit DeclarativeInputEngine(QObject *parent = 0); 50 | 51 | /** 52 | * Virtual destructor 53 | */ 54 | virtual ~DeclarativeInputEngine(); 55 | 56 | /** 57 | * Returns the kesyboard rectangle 58 | */ 59 | QRect keyboardRectangle() const; 60 | 61 | /** 62 | * Returns the animating status 63 | */ 64 | bool isAnimating() const; 65 | 66 | /** 67 | * Use this property to set the animating status, for example during UI 68 | * transitioning states. 69 | */ 70 | void setAnimating(bool Animating); 71 | 72 | /** 73 | * Returns the current input mode 74 | * \see InputMode for a list of valid input modes 75 | */ 76 | int inputMode() const; 77 | 78 | /** 79 | * Use this function to set the current input mode 80 | * \see InputMode for a list of valid input modes 81 | */ 82 | void setInputMode(int Mode); 83 | 84 | public slots: 85 | /** 86 | * Reverts the active key state without emitting the key event. 87 | * This method is useful when the user discards the current key and the 88 | * key state needs to be restored. 89 | * \note Not implemented yet and not used yet 90 | */ 91 | void virtualKeyCancel(); 92 | 93 | /** 94 | * Emits a key click event for the given key, text and modifiers. 95 | * Returns true if the key event was accepted by the input engine. 96 | * \note Not implemented yet and not used yet 97 | */ 98 | bool virtualKeyClick(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers); 99 | 100 | /** 101 | * Called by the keyboard layer to indicate that key was pressed, with the 102 | * given text and modifiers. 103 | * The key is set as an active key (down key). The actual key event is 104 | * triggered when the key is released by the virtualKeyRelease() method. 105 | * The key press event can be discarded by calling virtualKeyCancel(). 106 | * The key press also initiates the key repeat timer if repeat is true. 107 | * Returns true if the key was accepted by this input engine. 108 | * \note Not implemented yet and not used yet 109 | */ 110 | bool virtualKeyPress(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers, bool repeat); 111 | 112 | /** 113 | * Releases the key at key. The method emits a key event for the input 114 | * method if the event has not been generated by a repeating timer. 115 | * The text and modifiers are passed to the input method. 116 | * Returns true if the key was accepted by the input engine 117 | * \note Not implemented yet and not used yet 118 | */ 119 | bool virtualKeyRelease(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers); 120 | 121 | /** 122 | * This function sends the given text to the focused QML item 123 | * \note This function will get replaced by virtualKeyClick function later 124 | */ 125 | void sendKeyToFocusItem(const QString &keyText); 126 | 127 | /** 128 | * Reports the active keyboard rectangle to the engine 129 | */ 130 | void setKeyboardRectangle(const QRect& Rect); 131 | 132 | signals: 133 | /** 134 | * Notify signal of keyboardRectangle property 135 | */ 136 | void keyboardRectangleChanged(); 137 | 138 | /** 139 | * Notify signal of animating property 140 | */ 141 | void animatingChanged(); 142 | 143 | /** 144 | * Notify signal of inputModep property 145 | */ 146 | void inputModeChanged(); 147 | }; // class CDeclarativeInputEngine 148 | 149 | 150 | //--------------------------------------------------------------------------- 151 | #endif // DECLARATIVEINPUTENGINE_H 152 | -------------------------------------------------------------------------------- /src/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reHackable/QtFreeVirtualKeyboard/64e6a9434546c69ddcceb6168b9dae0522e8a67f/src/FontAwesome.otf -------------------------------------------------------------------------------- /src/InputPanel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import "." 3 | import FreeVirtualKeyboard 1.0 4 | 5 | /** 6 | * This is the QML input panel that provides the virtual keyboard UI 7 | * The code has been derived from 8 | * http://tolszak-dev.blogspot.de/2013/04/qplatforminputcontext-and-virtual.html 9 | * Copyright 2015 Uwe Kindler 10 | * Licensed under MIT see LICENSE.MIT in project root 11 | */ 12 | Item { 13 | id:root 14 | objectName: "inputPanel" 15 | width: parent.width 16 | height: width / 4 17 | // Report actual keyboard rectangle to input engine 18 | onYChanged: InputEngine.setKeyboardRectangle(Qt.rect(x, y, width, height)) 19 | 20 | KeyModel { 21 | id:keyModel 22 | } 23 | FontLoader { 24 | source: "FontAwesome.otf" 25 | } 26 | QtObject { 27 | id:pimpl 28 | property bool shiftModifier: false 29 | property bool symbolModifier: false 30 | property int verticalSpacing: keyboard.height / 40 31 | property int horizontalSpacing: verticalSpacing 32 | property int rowHeight: keyboard.height/4 - verticalSpacing 33 | property int buttonWidth: (keyboard.width-column.anchors.margins)/10 - horizontalSpacing 34 | } 35 | 36 | /** 37 | * The delegate that paints the key buttons 38 | */ 39 | Component { 40 | id: keyButtonDelegate 41 | KeyButton { 42 | id: button 43 | width: pimpl.buttonWidth 44 | height: pimpl.rowHeight 45 | text: (pimpl.shiftModifier) ? letter.toUpperCase() : (pimpl.symbolModifier)?firstSymbol : letter 46 | inputPanel: root 47 | } 48 | } 49 | 50 | Connections { 51 | target: InputEngine 52 | // Switch the keyboard layout to Numeric if the input mode of the InputEngine changes 53 | onInputModeChanged: { 54 | pimpl.symbolModifier = ((InputEngine.inputMode == InputEngine.Numeric) 55 | || (InputEngine.inputMode == InputEngine.Dialable)) 56 | if (pimpl.symbolModifier) { 57 | pimpl.shiftModifier = false 58 | } 59 | } 60 | } 61 | 62 | /** 63 | * This function shows the character preview popup for each key button 64 | */ 65 | function showKeyPopup(keyButton) 66 | { 67 | console.log("showKeyPopup"); 68 | keyPopup.popup(keyButton, root); 69 | } 70 | 71 | /** 72 | * The key popup for character preview 73 | */ 74 | KeyPopup { 75 | id: keyPopup 76 | visible: false 77 | z: 100 78 | } 79 | 80 | 81 | Rectangle { 82 | id:keyboard 83 | color: "black" 84 | anchors.fill: parent; 85 | MouseArea { 86 | anchors.fill: parent 87 | } 88 | 89 | Column { 90 | id:column 91 | anchors.margins: 5 92 | anchors.fill: parent 93 | spacing: pimpl.verticalSpacing 94 | 95 | Row { 96 | height: pimpl.rowHeight 97 | spacing: pimpl.horizontalSpacing 98 | anchors.horizontalCenter:parent.horizontalCenter 99 | Repeater { 100 | model: keyModel.firstRowModel 101 | delegate: keyButtonDelegate 102 | } 103 | } 104 | Row { 105 | height: pimpl.rowHeight 106 | spacing: pimpl.horizontalSpacing 107 | anchors.horizontalCenter:parent.horizontalCenter 108 | Repeater { 109 | model: keyModel.secondRowModel 110 | delegate: keyButtonDelegate 111 | } 112 | } 113 | Item { 114 | height: pimpl.rowHeight 115 | width:parent.width 116 | KeyButton { 117 | id: shiftKey 118 | color: (pimpl.shiftModifier)? "#1e6fa7": "#1e1b18" 119 | anchors.left: parent.left 120 | width: 1.25*pimpl.buttonWidth 121 | height: pimpl.rowHeight 122 | font.family: "FontAwesome" 123 | text: "\uf062" 124 | functionKey: true 125 | onClicked: { 126 | if (pimpl.symbolModifier) { 127 | pimpl.symbolModifier = false 128 | } 129 | pimpl.shiftModifier = !pimpl.shiftModifier 130 | } 131 | inputPanel: root 132 | } 133 | Row { 134 | height: pimpl.rowHeight 135 | spacing: pimpl.horizontalSpacing 136 | anchors.horizontalCenter:parent.horizontalCenter 137 | Repeater { 138 | anchors.horizontalCenter: parent.horizontalCenter 139 | model: keyModel.thirdRowModel 140 | delegate: keyButtonDelegate 141 | } 142 | } 143 | KeyButton { 144 | id: backspaceKey 145 | font.family: "FontAwesome" 146 | color: "#1e1b18" 147 | anchors.right: parent.right 148 | width: 1.25*pimpl.buttonWidth 149 | height: pimpl.rowHeight 150 | text: "\x7F" 151 | displayText: "\uf177" 152 | inputPanel: root 153 | repeat: true 154 | } 155 | } 156 | Row { 157 | height: pimpl.rowHeight 158 | spacing: pimpl.horizontalSpacing 159 | anchors.horizontalCenter:parent.horizontalCenter 160 | KeyButton { 161 | id: hideKey 162 | color: "#1e1b18" 163 | width: 1.25*pimpl.buttonWidth 164 | height: pimpl.rowHeight 165 | font.family: "FontAwesome" 166 | text: "\uf078" 167 | functionKey: true 168 | onClicked: { 169 | Qt.inputMethod.hide() 170 | } 171 | inputPanel: root 172 | showPreview: false 173 | } 174 | KeyButton { 175 | color: "#1e1b18" 176 | width: 1.25*pimpl.buttonWidth 177 | height: pimpl.rowHeight 178 | text: "" 179 | inputPanel: root 180 | functionKey: true 181 | } 182 | KeyButton { 183 | width: pimpl.buttonWidth 184 | height: pimpl.rowHeight 185 | text: "," 186 | inputPanel: root 187 | } 188 | KeyButton { 189 | id: spaceKey 190 | width: 3*pimpl.buttonWidth 191 | height: pimpl.rowHeight 192 | text: " " 193 | inputPanel: root 194 | showPreview: false 195 | } 196 | KeyButton { 197 | width: pimpl.buttonWidth 198 | height: pimpl.rowHeight 199 | text: "." 200 | inputPanel: root 201 | } 202 | KeyButton { 203 | id: symbolKey 204 | color: "#1e1b18" 205 | width: 1.25*pimpl.buttonWidth 206 | height: pimpl.rowHeight 207 | text: (!pimpl.symbolModifier)? "12#" : "ABC" 208 | functionKey: true 209 | onClicked: { 210 | if (pimpl.shiftModifier) { 211 | pimpl.shiftModifier = false 212 | } 213 | pimpl.symbolModifier = !pimpl.symbolModifier 214 | } 215 | inputPanel: root 216 | } 217 | KeyButton { 218 | id: enterKey 219 | color: "#1e1b18" 220 | width: 1.25*pimpl.buttonWidth 221 | height: pimpl.rowHeight 222 | displayText: "Enter" 223 | text: "\n" 224 | inputPanel: root 225 | } 226 | } 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /src/KeyButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import FreeVirtualKeyboard 1.0 3 | 4 | /** 5 | * This is the type implements one single key button in the InputPanel 6 | * The code has been derived from 7 | * http://tolszak-dev.blogspot.de/2013/04/qplatforminputcontext-and-virtual.html 8 | * Copyright 2015 Uwe Kindler 9 | * Licensed under MIT see LICENSE.MIT in project root 10 | */ 11 | Item { 12 | id:root 13 | /** 14 | * The background color of this button 15 | */ 16 | property color color: "#35322f" 17 | 18 | /** 19 | * The key text to show in this button 20 | */ 21 | property string text 22 | 23 | /** 24 | * The font for rendering of text 25 | */ 26 | property alias font: txt.font 27 | 28 | /** 29 | * The color of the text in this button 30 | */ 31 | property alias textColor: txt.color 32 | 33 | /** 34 | * This property holds the pressed status of the key. 35 | */ 36 | property alias isPressed: buttonMouseArea.pressed 37 | 38 | /** 39 | * This property holds a reference to the input panel. 40 | * A key can only show the charcter preview popup if this property contains 41 | * a valid refernce to the input panel 42 | */ 43 | property var inputPanel 44 | 45 | /** 46 | * This property holds the highlighted status of the key 47 | * The highlighted status is a little bit different from the pressed status 48 | * If the user releases the key, it is not pressed anymore, but it is still 49 | * highlighted for some milliseconds 50 | */ 51 | property bool isHighlighted: false 52 | 53 | /** 54 | * Sets the show preview attribute for the character preview key popup 55 | */ 56 | property bool showPreview: true 57 | 58 | /** 59 | * Sets the key repeat attribute. 60 | * If the repeat is enabled, the key will repeat the input events while held down. 61 | * The default is false. 62 | */ 63 | property bool repeat: false 64 | 65 | /** 66 | * Sets the key code for input method processing. 67 | */ 68 | property int key 69 | 70 | /** 71 | * Sets the display text - this string is rendered in the keyboard layout. 72 | * The default value is the key text. 73 | */ 74 | property alias displayText: txt.text 75 | 76 | /** 77 | * Sets the function key attribute. 78 | */ 79 | property bool functionKey: false 80 | 81 | signal clicked() 82 | signal pressed() 83 | signal released() 84 | 85 | Rectangle { 86 | anchors.fill: parent 87 | radius: height / 30 88 | color: isHighlighted ? Qt.tint(root.color, "#801e6fa7") : root.color 89 | Text { 90 | id: txt 91 | color: "white" 92 | anchors.margins: parent.height / 6 93 | anchors.fill: parent 94 | fontSizeMode: Text.Fit 95 | font.pixelSize: height 96 | horizontalAlignment: Text.AlignHCenter 97 | verticalAlignment: Text.AlignVCenter 98 | text: root.text 99 | } 100 | MouseArea { 101 | id: buttonMouseArea 102 | anchors.fill: parent 103 | onClicked: root.clicked() 104 | onPressed: root.pressed() 105 | onReleased: root.released() 106 | } 107 | } 108 | 109 | Timer { 110 | id: highlightTimer 111 | interval: 100 112 | running: !isPressed 113 | repeat: false 114 | 115 | onTriggered: { 116 | isHighlighted = false; 117 | } 118 | } 119 | 120 | Timer { 121 | id: repeatTimer 122 | interval: 500 123 | repeat: true 124 | running: root.repeat && root.isPressed 125 | 126 | onTriggered: { 127 | if (root.state == "") 128 | { 129 | root.state = "REPEATING" 130 | console.log("switching to repeating"); 131 | } 132 | else if (root.state == "REPEATING") 133 | { 134 | console.log("repeating"); 135 | } 136 | 137 | if (!functionKey) 138 | { 139 | InputEngine.sendKeyToFocusItem(text) 140 | } 141 | } 142 | } 143 | 144 | onInputPanelChanged: { 145 | console.log("onInputPanelChanged: " + inputPanel.objectName); 146 | } 147 | 148 | /** 149 | * If the InputPanel property has a valid InputPanel reference and if 150 | * showPreview is true, then this function calls showKeyPopup() to 151 | * show the character preview popup. 152 | */ 153 | onPressed: { 154 | if (inputPanel != null && showPreview) 155 | { 156 | inputPanel.showKeyPopup(root); 157 | } 158 | isHighlighted = true; 159 | } 160 | 161 | onReleased: { 162 | state = "" 163 | console.log("onReleased - functionKey = " + functionKey) 164 | if (!functionKey) 165 | { 166 | InputEngine.sendKeyToFocusItem(text) 167 | } 168 | } 169 | 170 | states: [ 171 | State { 172 | name: "REPEATING" 173 | PropertyChanges { target: repeatTimer; interval: 50} 174 | } 175 | ] 176 | } 177 | -------------------------------------------------------------------------------- /src/KeyModel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | /** 4 | * This is quick and dirty model for the keys of the InputPanel * 5 | * The code has been derived from 6 | * http://tolszak-dev.blogspot.de/2013/04/qplatforminputcontext-and-virtual.html 7 | * Copyright 2015 Uwe Kindler 8 | * Licensed under MIT see LICENSE.MIT in project root 9 | */ 10 | Item { 11 | property QtObject firstRowModel: first 12 | property QtObject secondRowModel: second 13 | property QtObject thirdRowModel: third 14 | 15 | 16 | ListModel { 17 | id:first 18 | ListElement { letter: "q"; firstSymbol: "1"; keycode: Qt.Key_Q} 19 | ListElement { letter: "w"; firstSymbol: "2"; keycode: Qt.Key_W} 20 | ListElement { letter: "e"; firstSymbol: "3"; keycode: Qt.Key_E} 21 | ListElement { letter: "r"; firstSymbol: "4"; keycode: Qt.Key_R} 22 | ListElement { letter: "t"; firstSymbol: "5"; keycode: Qt.Key_T} 23 | ListElement { letter: "y"; firstSymbol: "6"; keycode: Qt.Key_Y} 24 | ListElement { letter: "u"; firstSymbol: "7"; keycode: Qt.Key_U} 25 | ListElement { letter: "i"; firstSymbol: "8"; keycode: Qt.Key_I} 26 | ListElement { letter: "o"; firstSymbol: "9"; keycode: Qt.Key_O} 27 | ListElement { letter: "p"; firstSymbol: "0"; keycode: Qt.Key_E} 28 | } 29 | ListModel { 30 | id:second 31 | ListElement { letter: "a"; firstSymbol: "!"} 32 | ListElement { letter: "s"; firstSymbol: "@"} 33 | ListElement { letter: "d"; firstSymbol: "#"} 34 | ListElement { letter: "f"; firstSymbol: "$"} 35 | ListElement { letter: "g"; firstSymbol: "%"} 36 | ListElement { letter: "h"; firstSymbol: "&"} 37 | ListElement { letter: "j"; firstSymbol: "*"} 38 | ListElement { letter: "k"; firstSymbol: "?"} 39 | ListElement { letter: "l"; firstSymbol: "/"} 40 | } 41 | ListModel { 42 | id:third 43 | ListElement { letter: "z"; firstSymbol: "_"} 44 | ListElement { letter: "x"; firstSymbol: "\""} 45 | ListElement { letter: "c"; firstSymbol: "'"} 46 | ListElement { letter: "v"; firstSymbol: "("} 47 | ListElement { letter: "b"; firstSymbol: ")"} 48 | ListElement { letter: "n"; firstSymbol: "-"} 49 | ListElement { letter: "m"; firstSymbol: "+"} 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/KeyPopup.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtGraphicalEffects 1.0 3 | 4 | /** 5 | * This is the key popup that shows a character preview above the 6 | * pressed key button like it is known from keyboards on phones. 7 | * Copyright 2015 Uwe Kindler 8 | * Licensed under MIT see LICENSE.MIT in project root 9 | */ 10 | /*Item { 11 | id: root 12 | property alias text: txt.text 13 | property alias font: txt.font 14 | 15 | width: 40 16 | height: 40 17 | visible: false 18 | 19 | Item { 20 | id: container 21 | anchors.centerIn: parent 22 | width: rect.width + (2 * rectShadow.radius) 23 | height: rect.height + (2 * rectShadow.radius) 24 | 25 | Rectangle { 26 | id: rect 27 | radius: root.height / 30 28 | width: root.width 29 | height: root.height 30 | antialiasing: true 31 | anchors.centerIn: parent 32 | gradient: Gradient { 33 | GradientStop { position: 0.0; color: Qt.lighter(Qt.lighter("#35322f"))} 34 | GradientStop { position: 1.0; color: Qt.lighter("#35322f")} 35 | 36 | } 37 | 38 | Text { 39 | id: txt 40 | color: "white" 41 | anchors.fill: parent 42 | fontSizeMode: Text.Fit 43 | font.pixelSize: height 44 | horizontalAlignment: Text.AlignHCenter 45 | verticalAlignment: Text.AlignVCenter 46 | } 47 | } 48 | } 49 | DropShadow { 50 | id: rectShadow 51 | anchors.fill: source 52 | cached: true 53 | horizontalOffset: 3 54 | verticalOffset: 3 55 | radius: root.height / 10 56 | samples: 16 57 | color: "#80000000" 58 | smooth: true 59 | source: container 60 | } 61 | 62 | function popup(keybutton, inputPanel) { 63 | console.log("popup: " + inputPanel.objectName); 64 | console.log("keybutton.text: " + keybutton.text); 65 | width = keybutton.width * 1.4; 66 | height = keybutton.height * 1.4; 67 | var KeyButtonGlobalLeft = keybutton.mapToItem(inputPanel, 0, 0).x; 68 | var KeyButtonGlobalTop = keybutton.mapToItem(inputPanel, 0, 0).y; 69 | var PopupGlobalLeft = KeyButtonGlobalLeft - (width - keybutton.width) / 2; 70 | var PopupGlobalTop = KeyButtonGlobalTop - height - pimpl.verticalSpacing * 1.5; 71 | console.log("Popup position left: " + KeyButtonGlobalLeft); 72 | var PopupLeft = root.parent.mapFromItem(inputPanel, PopupGlobalLeft, PopupGlobalTop).x; 73 | y = root.parent.mapFromItem(inputPanel, PopupGlobalLeft, PopupGlobalTop).y; 74 | if (PopupGlobalLeft < 0) 75 | { 76 | x = 0; 77 | } 78 | else if ((PopupGlobalLeft + width) > inputPanel.width) 79 | { 80 | x = PopupLeft - (PopupGlobalLeft + width - inputPanel.width); 81 | } 82 | else 83 | { 84 | x = PopupLeft; 85 | } 86 | 87 | text = keybutton.displayText; 88 | font.family = keybutton.font.family 89 | visible = Qt.binding(function() {return keybutton.isHighlighted}); 90 | } 91 | }*/ 92 | 93 | Item { 94 | id: root 95 | property alias text: txt.text 96 | property alias font: txt.font 97 | 98 | width: 40 99 | height: 40 100 | visible: false 101 | 102 | Rectangle { 103 | id: popup 104 | anchors.fill: parent 105 | radius: Math.round(height / 30) 106 | z: shadow.z + 1 107 | 108 | gradient: Gradient { 109 | GradientStop { position: 0.0; color: Qt.lighter(Qt.lighter("#35322f"))} 110 | GradientStop { position: 1.0; color: Qt.lighter("#35322f")} 111 | 112 | } 113 | 114 | Text { 115 | id: txt 116 | color: "white" 117 | anchors.fill: parent 118 | fontSizeMode: Text.Fit 119 | font.pixelSize: height 120 | horizontalAlignment: Text.AlignHCenter 121 | verticalAlignment: Text.AlignVCenter 122 | } 123 | } 124 | 125 | Rectangle { 126 | id: shadow 127 | width: popup.width 128 | height: popup.height 129 | radius: popup.radius 130 | color: "#3F000000" 131 | x: 4 132 | y: 4 133 | } 134 | 135 | function popup(keybutton, inputPanel) { 136 | console.log("popup: " + inputPanel.objectName); 137 | console.log("keybutton.text: " + keybutton.text); 138 | width = keybutton.width * 1.4; 139 | height = keybutton.height * 1.4; 140 | var KeyButtonGlobalLeft = keybutton.mapToItem(inputPanel, 0, 0).x; 141 | var KeyButtonGlobalTop = keybutton.mapToItem(inputPanel, 0, 0).y; 142 | var PopupGlobalLeft = KeyButtonGlobalLeft - (width - keybutton.width) / 2; 143 | var PopupGlobalTop = KeyButtonGlobalTop - height - pimpl.verticalSpacing * 1.5; 144 | console.log("Popup position left: " + KeyButtonGlobalLeft); 145 | var PopupLeft = root.parent.mapFromItem(inputPanel, PopupGlobalLeft, PopupGlobalTop).x; 146 | y = root.parent.mapFromItem(inputPanel, PopupGlobalLeft, PopupGlobalTop).y; 147 | if (PopupGlobalLeft < 0) 148 | { 149 | x = 0; 150 | } 151 | else if ((PopupGlobalLeft + width) > inputPanel.width) 152 | { 153 | x = PopupLeft - (PopupGlobalLeft + width - inputPanel.width); 154 | } 155 | else 156 | { 157 | x = PopupLeft; 158 | } 159 | 160 | text = keybutton.displayText; 161 | font.family = keybutton.font.family 162 | visible = Qt.binding(function() {return keybutton.isHighlighted}); 163 | } 164 | } 165 | 166 | 167 | -------------------------------------------------------------------------------- /src/VirtualKeyboardInputContext.cpp: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | /// \file VirtualKeyboardInputContext.cpp 3 | /// \author Uwe Kindler 4 | /// \date 08.01.2015 5 | /// \brief Implementation of VirtualKeyboardInputContext 6 | /// 7 | /// Copyright 2015 Uwe Kindler 8 | /// Licensed under MIT see LICENSE.MIT in project root 9 | //============================================================================ 10 | 11 | //============================================================================ 12 | // INCLUDES 13 | //============================================================================ 14 | #include "VirtualKeyboardInputContext.h" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include "DeclarativeInputEngine.h" 28 | 29 | 30 | /** 31 | * Private data class for VirtualKeyboardInputContext 32 | */ 33 | class VirtualKeyboardInputContextPrivate 34 | { 35 | public: 36 | VirtualKeyboardInputContextPrivate(); 37 | QQuickFlickable* Flickable; 38 | QQuickItem* FocusItem; 39 | bool Visible; 40 | DeclarativeInputEngine* InputEngine; 41 | QPropertyAnimation* FlickableContentScrollAnimation;//< for smooth scrolling of flickable content item 42 | }; 43 | 44 | 45 | //============================================================================== 46 | VirtualKeyboardInputContextPrivate::VirtualKeyboardInputContextPrivate() 47 | : Flickable(0), 48 | FocusItem(0), 49 | Visible(false), 50 | InputEngine(new DeclarativeInputEngine()) 51 | { 52 | 53 | } 54 | 55 | 56 | //============================================================================== 57 | VirtualKeyboardInputContext::VirtualKeyboardInputContext() : 58 | QPlatformInputContext(), d(new VirtualKeyboardInputContextPrivate) 59 | { 60 | d->FlickableContentScrollAnimation = new QPropertyAnimation(this); 61 | d->FlickableContentScrollAnimation->setPropertyName("contentY"); 62 | d->FlickableContentScrollAnimation->setDuration(400); 63 | d->FlickableContentScrollAnimation->setEasingCurve(QEasingCurve(QEasingCurve::OutBack)); 64 | qmlRegisterSingletonType("FreeVirtualKeyboard", 1, 0, 65 | "InputEngine", inputEngineProvider); 66 | connect(d->InputEngine, SIGNAL(animatingChanged()), this, SLOT(ensureFocusedObjectVisible())); 67 | } 68 | 69 | 70 | //============================================================================== 71 | VirtualKeyboardInputContext::~VirtualKeyboardInputContext() 72 | { 73 | 74 | } 75 | 76 | 77 | //============================================================================== 78 | VirtualKeyboardInputContext* VirtualKeyboardInputContext::instance() 79 | { 80 | static VirtualKeyboardInputContext* InputContextInstance = new VirtualKeyboardInputContext; 81 | return InputContextInstance; 82 | } 83 | 84 | 85 | 86 | //============================================================================== 87 | bool VirtualKeyboardInputContext::isValid() const 88 | { 89 | return true; 90 | } 91 | 92 | 93 | //============================================================================== 94 | QRectF VirtualKeyboardInputContext::keyboardRect() const 95 | { 96 | return QRectF(); 97 | } 98 | 99 | 100 | //============================================================================== 101 | void VirtualKeyboardInputContext::showInputPanel() 102 | { 103 | d->Visible = true; 104 | QPlatformInputContext::showInputPanel(); 105 | emitInputPanelVisibleChanged(); 106 | } 107 | 108 | 109 | //============================================================================== 110 | void VirtualKeyboardInputContext::hideInputPanel() 111 | { 112 | d->Visible = false; 113 | QPlatformInputContext::hideInputPanel(); 114 | emitInputPanelVisibleChanged(); 115 | } 116 | 117 | 118 | //============================================================================== 119 | bool VirtualKeyboardInputContext::isInputPanelVisible() const 120 | { 121 | return d->Visible; 122 | } 123 | 124 | 125 | //============================================================================== 126 | bool VirtualKeyboardInputContext::isAnimating() const 127 | { 128 | return false; 129 | } 130 | 131 | 132 | //============================================================================== 133 | void VirtualKeyboardInputContext::setFocusObject(QObject *object) 134 | { 135 | static const int NumericInputHints = Qt::ImhPreferNumbers | Qt::ImhDate 136 | | Qt::ImhTime | Qt::ImhDigitsOnly | Qt::ImhFormattedNumbersOnly; 137 | static const int DialableInputHints = Qt::ImhDialableCharactersOnly; 138 | 139 | 140 | qDebug() << "VirtualKeyboardInputContext::setFocusObject"; 141 | if (!object) 142 | { 143 | return; 144 | } 145 | 146 | // we only support QML at the moment - so if this is not a QML item, then 147 | // we leave immediatelly 148 | d->FocusItem = dynamic_cast(object); 149 | if (!d->FocusItem) 150 | { 151 | return; 152 | } 153 | 154 | // Check if an input control has focus that accepts text input - if not, 155 | // then we can leave immediatelly 156 | bool AcceptsInput = d->FocusItem->inputMethodQuery(Qt::ImEnabled).toBool(); 157 | if (!AcceptsInput) 158 | { 159 | return; 160 | } 161 | 162 | // Set input mode depending on input method hints queried from focused 163 | // object / item 164 | Qt::InputMethodHints InputMethodHints(d->FocusItem->inputMethodQuery(Qt::ImHints).toInt()); 165 | qDebug() << QString("InputMethodHints: %1").arg(InputMethodHints, 0, 16); 166 | if (InputMethodHints & DialableInputHints) 167 | { 168 | d->InputEngine->setInputMode(DeclarativeInputEngine::Dialable); 169 | } 170 | else if (InputMethodHints & NumericInputHints) 171 | { 172 | d->InputEngine->setInputMode(DeclarativeInputEngine::Numeric); 173 | } 174 | else 175 | { 176 | d->InputEngine->setInputMode(DeclarativeInputEngine::Latin); 177 | } 178 | 179 | // Search for the top most flickable so that we can scroll the control 180 | // into the visible area, if the keyboard hides the control 181 | QQuickItem* i = d->FocusItem; 182 | d->Flickable = 0; 183 | while (i) 184 | { 185 | QQuickFlickable* Flickable = dynamic_cast(i); 186 | if (Flickable) 187 | { 188 | d->Flickable = Flickable; 189 | qDebug() << "is QQuickFlickable"; 190 | } 191 | i = i->parentItem(); 192 | } 193 | 194 | ensureFocusedObjectVisible(); 195 | } 196 | 197 | 198 | //============================================================================== 199 | void VirtualKeyboardInputContext::ensureFocusedObjectVisible() 200 | { 201 | // If the keyboard is hidden, no scrollable element exists or the keyboard 202 | // is just animating, then we leave here 203 | if (!d->Visible || !d->Flickable || d->InputEngine->isAnimating()) 204 | { 205 | return; 206 | } 207 | 208 | qDebug() << "VirtualKeyboardInputContext::ensureFocusedObjectVisible"; 209 | QRectF FocusItemRect(0, 0, d->FocusItem->width(), d->FocusItem->height()); 210 | FocusItemRect = d->Flickable->mapRectFromItem(d->FocusItem, FocusItemRect); 211 | qDebug() << "FocusItemRect: " << FocusItemRect; 212 | qDebug() << "Content origin: " << QPointF(d->Flickable->contentX(), 213 | d->Flickable->contentY()); 214 | qDebug() << "Flickable size: " << QSize(d->Flickable->width(), d->Flickable->height()); 215 | d->FlickableContentScrollAnimation->setTargetObject(d->Flickable); 216 | qreal ContentY = d->Flickable->contentY(); 217 | if (FocusItemRect.bottom() >= d->Flickable->height()) 218 | { 219 | qDebug() << "Item outside!!! FocusItemRect.bottom() >= d->Flickable->height()"; 220 | ContentY = d->Flickable->contentY() + (FocusItemRect.bottom() - d->Flickable->height()) + 20; 221 | d->FlickableContentScrollAnimation->setEndValue(ContentY); 222 | d->FlickableContentScrollAnimation->start(); 223 | } 224 | else if (FocusItemRect.top() < 0) 225 | { 226 | qDebug() << "Item outside!!! d->FocusItem->position().x < 0"; 227 | ContentY = d->Flickable->contentY() + FocusItemRect.top() - 20; 228 | d->FlickableContentScrollAnimation->setEndValue(ContentY); 229 | d->FlickableContentScrollAnimation->start(); 230 | } 231 | } 232 | 233 | 234 | //============================================================================== 235 | QObject* VirtualKeyboardInputContext::inputEngineProvider(QQmlEngine *engine, QJSEngine *scriptEngine) 236 | { 237 | Q_UNUSED(engine) 238 | Q_UNUSED(scriptEngine) 239 | return VirtualKeyboardInputContext::instance()->d->InputEngine; 240 | } 241 | 242 | //------------------------------------------------------------------------------ 243 | // EOF VirtualKeyboardInpitContext.cpp 244 | 245 | -------------------------------------------------------------------------------- /src/VirtualKeyboardInputContext.h: -------------------------------------------------------------------------------- 1 | #ifndef VIRTUALKEYBOARDINPUTCONTEXT_H 2 | #define VIRTUALKEYBOARDINPUTCONTEXT_H 3 | //============================================================================ 4 | /// \file VirtualKeyboardInputContext.h 5 | /// \author Uwe Kindler 6 | /// \date 08.01.2015 7 | /// \brief Declaration of VirtualKeyboardInputContext 8 | /// 9 | /// Copyright 2015 Uwe Kindler 10 | /// Licensed under MIT see LICENSE.MIT in project root 11 | //============================================================================ 12 | 13 | //============================================================================ 14 | // INCLUDES 15 | //============================================================================ 16 | #include 17 | #include 18 | 19 | 20 | //============================================================================ 21 | // FORWARD DECLARATIONS 22 | //============================================================================ 23 | class QQmlEngine; 24 | class QJSEngine; 25 | class VirtualKeyboardInputContextPrivate; 26 | 27 | 28 | /** 29 | * Implementation of QPlatformInputContext 30 | */ 31 | class VirtualKeyboardInputContext : public QPlatformInputContext 32 | { 33 | Q_OBJECT 34 | private: 35 | /** 36 | * The input contet creates the InputEngine object and provides it 37 | * as a singleton to the QML context 38 | */ 39 | static QObject* inputEngineProvider(QQmlEngine *engine, QJSEngine *scriptEngine); 40 | 41 | protected: 42 | /** 43 | * Protected constructor - use instance function to get the one and only 44 | * object 45 | */ 46 | VirtualKeyboardInputContext(); 47 | 48 | public: 49 | /** 50 | * Virtual destructor 51 | */ 52 | virtual ~VirtualKeyboardInputContext(); 53 | 54 | /** 55 | * Returns input context validity. Deriving implementations should 56 | * return true - so we simply return true 57 | */ 58 | virtual bool isValid() const; 59 | 60 | /** 61 | * This function can be reimplemented to return virtual keyboard rectangle 62 | * in currently active window coordinates. Default implementation returns 63 | * invalid rectangle. 64 | */ 65 | virtual QRectF keyboardRect() const; 66 | 67 | /** 68 | * Simply calls the emitInputPanelVisibleChanged() function 69 | */ 70 | virtual void showInputPanel(); 71 | 72 | /** 73 | * Simply calls the emitInputPanelVisibleChanged() function 74 | */ 75 | virtual void hideInputPanel(); 76 | 77 | /** 78 | * Returns input panel visibility status. 79 | * This value will be available in QGuiApplication::inputMethod()->isVisible() 80 | */ 81 | virtual bool isInputPanelVisible() const; 82 | 83 | /** 84 | * This function returns true whenever input method is animating 85 | * shown or hidden. 86 | */ 87 | virtual bool isAnimating() const; 88 | 89 | /** 90 | * This virtual method gets called to notify updated focus to object. 91 | * \warning Input methods must not call this function directly. 92 | * This function does the main work. It sets the input mode of the 93 | * InputEngine singleton and it ensures that the focused QML object is 94 | * visible if it is a child item of a Flickable 95 | */ 96 | virtual void setFocusObject(QObject *object); 97 | 98 | /** 99 | * Use this static instance function to access the singleton input context 100 | * instance 101 | */ 102 | static VirtualKeyboardInputContext* instance(); 103 | 104 | private: 105 | VirtualKeyboardInputContextPrivate *d; 106 | 107 | private slots: 108 | /** 109 | * This function scrolls the QML item into visible area if the focused 110 | * QML item is child of a flickable 111 | */ 112 | void ensureFocusedObjectVisible(); 113 | }; // VirtualKeyboardInputContext 114 | 115 | //------------------------------------------------------------------------------ 116 | #endif // VIRTUALKEYBOARDINPUTCONTEXT_H 117 | -------------------------------------------------------------------------------- /src/VirtualKeyboardInputContextPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "VirtualKeyboardInputContextPlugin.h" 2 | #include "VirtualKeyboardInputContext.h" 3 | //============================================================================ 4 | /// \file VirtualKeyboardInputContextPlugin.cpp 5 | /// \author Uwe Kindler 6 | /// \date 08.01.2015 7 | /// \brief Implementation of VirtualKeyboardInputContextPlugin 8 | /// 9 | /// Copyright 2015 Uwe Kindler 10 | /// Licensed under MIT see LICENSE.MIT in project root 11 | //============================================================================ 12 | 13 | //============================================================================ 14 | // INCLUDES 15 | //============================================================================ 16 | #include 17 | 18 | 19 | //============================================================================ 20 | QPlatformInputContext* VirtualKeyboardInputContextPlugin::create(const QString& system, const QStringList& paramList) 21 | { 22 | Q_UNUSED(paramList); 23 | 24 | qDebug() << "VirtualKeyboardInputContextPlugin::create: " << system; 25 | if (system.compare(system, QStringLiteral("freevirtualkeyboard"), Qt::CaseInsensitive) == 0) 26 | { 27 | return VirtualKeyboardInputContext::instance(); 28 | } 29 | return 0; 30 | } 31 | 32 | 33 | //------------------------------------------------------------------------------ 34 | // EOF VirtualInputContextPlugin.cpp 35 | -------------------------------------------------------------------------------- /src/VirtualKeyboardInputContextPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef VIRTUALKEYBOARDINPUTCONTEXTPLUGIN_H 2 | #define VIRTUALKEYBOARDINPUTCONTEXTPLUGIN_H 3 | //============================================================================ 4 | /// \file VirtualKeyboardInputContextPlugin.h 5 | /// \author Uwe Kindler 6 | /// \date 08.01.2015 7 | /// \brief Declaration of VirtualKeyboardInputContextPlugin 8 | /// 9 | /// Copyright 2015 Uwe Kindler 10 | /// Licensed under MIT see LICENSE.MIT in project root 11 | //============================================================================ 12 | 13 | //============================================================================ 14 | // INCLUDES 15 | //============================================================================ 16 | #include "virtualkeyboard_global.h" 17 | #include 18 | 19 | /** 20 | * Implementation of QPlatformInputContextPlugin 21 | */ 22 | class VirtualKeyboardInputContextPlugin : public QPlatformInputContextPlugin 23 | { 24 | Q_OBJECT 25 | Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "freevirtualkeyboard.json") 26 | 27 | public: 28 | QPlatformInputContext *create(const QString&, const QStringList&); 29 | }; // class VirtualKeyboardInputContextPlugin 30 | 31 | //------------------------------------------------------------------------------ 32 | #endif // VIRTUALKEYBOARDINPUTCONTEXTPLUGIN_H 33 | -------------------------------------------------------------------------------- /src/freevirtualkeyboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "Keys": ["freevirtualkeyboard"] 3 | } 4 | -------------------------------------------------------------------------------- /src/libFreeVirtualKeyboard.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reHackable/QtFreeVirtualKeyboard/64e6a9434546c69ddcceb6168b9dae0522e8a67f/src/libFreeVirtualKeyboard.so -------------------------------------------------------------------------------- /src/qmldir: -------------------------------------------------------------------------------- 1 | module QtQuick.FreeVirtualKeyboard 2 | InputPanel 1.0 InputPanel.qml 3 | -------------------------------------------------------------------------------- /src/virtualkeyboard.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2013-04-04T23:11:38 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += qml quick quick-private gui-private 8 | 9 | CONFIG += plugin 10 | 11 | TARGET = freevirtualkeyboardplugin 12 | TEMPLATE = lib 13 | 14 | 15 | SOURCES += VirtualKeyboardInputContextPlugin.cpp \ 16 | VirtualKeyboardInputContext.cpp \ 17 | DeclarativeInputEngine.cpp 18 | 19 | HEADERS += VirtualKeyboardInputContextPlugin.h\ 20 | VirtualKeyboardInputContext.h \ 21 | DeclarativeInputEngine.h 22 | 23 | 24 | deployment.files = *.qml FontAwesome.otf qmldir 25 | 26 | linux-buildroot-g++ { 27 | deployment.path = /usr/qml/QtQuick/FreeVirtualKeyboard 28 | target.path = /usr/lib/qt/plugins/platforminputcontexts 29 | } else { 30 | deployment.path = $$[QT_INSTALL_QML]/QtQuick/FreeVirtualKeyboard 31 | target.path = $$[QT_INSTALL_PLUGINS]/platforminputcontexts 32 | } 33 | 34 | 35 | INSTALLS += target \ 36 | deployment 37 | 38 | OTHER_FILES += \ 39 | InputPanel.qml \ 40 | KeyModel.qml \ 41 | KeyButton.qml \ 42 | KeyPopup.qml 43 | 44 | RESOURCES += \ 45 | virtualkeyboard.qrc 46 | -------------------------------------------------------------------------------- /src/virtualkeyboard.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/virtualkeyboard_global.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKUPVIRTUALKEYBOARD_GLOBAL_H 2 | #define MOCKUPVIRTUALKEYBOARD_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(MOCKUPVIRTUALKEYBOARD_LIBRARY) 7 | # define MOCKUPVIRTUALKEYBOARDSHARED_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define MOCKUPVIRTUALKEYBOARDSHARED_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // MOCKUPVIRTUALKEYBOARD_GLOBAL_H 13 | -------------------------------------------------------------------------------- /uEnv.txt: -------------------------------------------------------------------------------- 1 | ##Use this file if you want to boot from SD card on a Debian system 2 | # uncomment the following lines if you need static ip 3 | ethaddr=90:59:AF:82:3A:D1 4 | ipaddr=192.168.81.10 5 | serverip=192.168.81.1 6 | gatewayip=192.168.81.1 7 | netmask=255.255.255.0 8 | hostname=bbb 9 | 10 | optargs=quiet lpj=1818624 drm.debug=7 11 | mmcboot=echo Booting from mmc ... (uk); run mmcargs; bootz ${loadaddr} - ${fdtaddr} 12 | loadzimage=echo Loading zImage ... (uk); load mmc 0:2 ${loadaddr} /boot/zImage 13 | loadfdt=load mmc 0:2 ${fdtaddr} /boot/${fdtfile} 14 | #setbootargs=setenv bootargs console=${console} ${optargs} root=${mmcroot} rootfstype=${mmcrootfstype} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0 15 | mmcargs=setenv bootargs console=${console} ${optargs} ${cape_disable} ${cape_enable} root=${mmcroot} rootfstype=${mmcrootfstype} ${cmdline} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0 16 | uenvcmd=if run loadzimage; then run loadfdt;run mmcboot;fi; 17 | 18 | --------------------------------------------------------------------------------