Reinhard Russinger il y a 8 ans
commit
36db27a8d2

+ 46 - 0
.gitignore

@@ -0,0 +1,46 @@
+# C++ objects and libs
+
+*.slo
+*.lo
+*.o
+*.a
+*.la
+*.lai
+*.so
+*.dll
+*.dylib
+
+# Qt-es
+
+object_script.*.Release
+object_script.*.Debug
+*_plugin_import.cpp
+/.qmake.cache
+/.qmake.stash
+*.pro.user
+*.pro.user.*
+*.qbs.user
+*.qbs.user.*
+*.moc
+moc_*.cpp
+moc_*.h
+qrc_*.cpp
+ui_*.h
+Makefile*
+*build-*
+
+
+# Qt unit tests
+target_wrapper.*
+
+
+# QtCreator
+
+*.autosave
+
+# QtCtreator Qml
+*.qmlproject.user
+*.qmlproject.user.*
+
+# QtCtreator CMake
+CMakeLists.txt.user*

+ 213 - 0
DeclarativeInputEngine.cpp

@@ -0,0 +1,213 @@
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include "DeclarativeInputEngine.h"
+
+#include <QInputMethodEvent>
+#include <QCoreApplication>
+#include <QGuiApplication>
+#include <QDebug>
+#include <QQmlEngine>
+#include <QJSEngine>
+#include <QtQml>
+#include <QTimer>
+
+
+/**
+ * Private data class
+ */
+struct DeclarativeInputEnginePrivate
+{
+    DeclarativeInputEngine* _this;
+    bool Animating;
+    QTimer* AnimatingFinishedTimer;//< triggers position adjustment of focused QML item is covered by keybaord rectangle
+    int InputMode;
+    QRect KeyboardRectangle;
+
+    /**
+     * Private data constructor
+     */
+    DeclarativeInputEnginePrivate(DeclarativeInputEngine* _public);
+}; // struct DeclarativeInputEnginePrivate
+
+
+
+//==============================================================================
+DeclarativeInputEnginePrivate::DeclarativeInputEnginePrivate(DeclarativeInputEngine* _public)
+    : _this(_public),
+      Animating(false),
+      InputMode(DeclarativeInputEngine::Latin)
+{
+
+}
+
+
+//==============================================================================
+DeclarativeInputEngine::DeclarativeInputEngine(QObject *parent) :
+    QObject(parent),
+    d(new DeclarativeInputEnginePrivate(this))
+{
+    d->AnimatingFinishedTimer = new QTimer(this);
+    d->AnimatingFinishedTimer->setSingleShot(true);
+    d->AnimatingFinishedTimer->setInterval(100);
+    connect(d->AnimatingFinishedTimer, SIGNAL(timeout()), this, SLOT(animatingFinished()));
+}
+
+
+//==============================================================================
+DeclarativeInputEngine::~DeclarativeInputEngine()
+{
+    delete d;
+}
+
+
+//==============================================================================
+void DeclarativeInputEngine::virtualKeyCancel()
+{
+
+}
+
+
+//==============================================================================
+bool DeclarativeInputEngine::virtualKeyClick(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers)
+{
+    Q_UNUSED(key)
+    Q_UNUSED(modifiers)
+
+    QInputMethodEvent ev;
+    if (text == QString("\x7F"))
+    {
+        //delete one char
+        ev.setCommitString("",-1,1);
+
+    } else
+    {
+        //add some text
+        ev.setCommitString(text);
+    }
+    QCoreApplication::sendEvent(QGuiApplication::focusObject(),&ev);
+    return true;
+}
+
+
+//==============================================================================
+void DeclarativeInputEngine::sendKeyToFocusItem(const QString& text)
+{
+    qDebug() << "CDeclarativeInputEngine::sendKeyToFocusItem " << text;
+    QInputMethodEvent ev;
+    if (text == QString("\x7F"))
+    {
+        // Backspace
+//        ev.setCommitString("",-1,1);
+        QKeyEvent ev(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
+        QCoreApplication::sendEvent(QGuiApplication::focusObject(),&ev);
+
+    } else if (text == "\n") {
+        // Qt::Key_Enter
+        QKeyEvent evEnterP(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
+        QCoreApplication::sendEvent(QGuiApplication::focusObject(),&evEnterP);
+    } else  if (text == "\uf060") {
+        // move left
+        QKeyEvent ev(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier);
+        QCoreApplication::sendEvent(QGuiApplication::focusObject(),&ev);
+    } else  if (text == "\uf061") {
+        // move right
+        QKeyEvent ev(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier);
+        QCoreApplication::sendEvent(QGuiApplication::focusObject(),&ev);
+    } else {
+
+        //add some text
+        ev.setCommitString(text);
+        QCoreApplication::sendEvent(QGuiApplication::focusObject(),&ev);
+    }
+
+}
+
+
+//==============================================================================
+bool DeclarativeInputEngine::virtualKeyPress(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers, bool repeat)
+{
+    Q_UNUSED(key)
+    Q_UNUSED(text)
+    Q_UNUSED(modifiers)
+    Q_UNUSED(repeat)
+
+    // not implemented yet
+    return true;
+}
+
+
+//==============================================================================
+bool DeclarativeInputEngine::virtualKeyRelease(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers)
+{
+    Q_UNUSED(key)
+    Q_UNUSED(text)
+    Q_UNUSED(modifiers)
+
+    // not implemented yet
+    return true;
+}
+
+
+//==============================================================================
+QRect DeclarativeInputEngine::keyboardRectangle() const
+{
+    return d->KeyboardRectangle;
+}
+
+
+//==============================================================================
+void DeclarativeInputEngine::setKeyboardRectangle(const QRect& Rect)
+{
+    setAnimating(true);
+    d->AnimatingFinishedTimer->start(100);
+    d->KeyboardRectangle = Rect;
+    emit keyboardRectangleChanged();
+}
+
+
+//==============================================================================
+bool DeclarativeInputEngine::isAnimating() const
+{
+    return d->Animating;
+}
+
+
+//==============================================================================
+void DeclarativeInputEngine::setAnimating(bool Animating)
+{
+    if (d->Animating != Animating)
+    {
+        d->Animating = Animating;
+        emit animatingChanged();
+    }
+}
+
+
+//==============================================================================
+void DeclarativeInputEngine::animatingFinished()
+{
+    setAnimating(false);
+}
+
+
+//==============================================================================
+int DeclarativeInputEngine::inputMode() const
+{
+    return d->InputMode;
+}
+
+
+//==============================================================================
+void DeclarativeInputEngine::setInputMode(int Mode)
+{
+    qDebug() << "CDeclarativeInputEngine::setInputMode " << Mode;
+    if (Mode != d->InputMode)
+    {
+        d->InputMode = Mode;
+        emit inputModeChanged();
+    }
+}
+
+//------------------------------------------------------------------------------
+// EOF DeclarativeInputEngine.cpp

+ 141 - 0
DeclarativeInputEngine.h

@@ -0,0 +1,141 @@
+#ifndef DECLARATIVEINPUTENGINE_H
+#define DECLARATIVEINPUTENGINE_H
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include <QObject>
+#include <QRect>
+
+struct DeclarativeInputEnginePrivate;
+
+/**
+ * The input engine provides input context information and is responsible
+ * for routing input events to focused QML items.
+ * The InputEngine can be accessed as singleton instance from QML
+ */
+class DeclarativeInputEngine : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(QRect keyboardRectangle READ keyboardRectangle WRITE setKeyboardRectangle NOTIFY keyboardRectangleChanged FINAL)
+    Q_PROPERTY(bool animating READ isAnimating WRITE setAnimating NOTIFY animatingChanged FINAL)
+    Q_PROPERTY(int inputMode READ inputMode WRITE setInputMode NOTIFY inputModeChanged FINAL)
+    Q_ENUMS(InputMode)
+private:
+    DeclarativeInputEnginePrivate* d;
+    friend class DeclarativeInputEnginePrivate;
+
+private slots:
+    void animatingFinished();
+
+public:
+    /**
+     * The InputMode enum provides a list of valid input modes
+     */
+    enum InputMode {Latin, Numeric, Dialable};
+
+    /**
+     * Creates a dclarative input engine with the given parent
+     */
+    explicit DeclarativeInputEngine(QObject *parent = 0);
+
+    /**
+     * Virtual destructor
+     */
+    virtual ~DeclarativeInputEngine();
+
+    /**
+     * Returns the kesyboard rectangle
+     */
+    QRect keyboardRectangle() const;
+
+    /**
+     * Returns the animating status
+     */
+    bool isAnimating() const;
+
+    /**
+     * Use this property to set the animating status, for example during UI
+     * transitioning states.
+     */
+    void setAnimating(bool Animating);
+
+    /**
+     * Returns the current input mode
+     * \see InputMode for a list of valid input modes
+     */
+    int inputMode() const;
+
+    /**
+     * Use this function to set the current input mode
+     * \see InputMode for a list of valid input modes
+     */
+    void setInputMode(int Mode);
+
+public slots:
+    /**
+     * Reverts the active key state without emitting the key event.
+     * This method is useful when the user discards the current key and the
+     * key state needs to be restored.
+     * \note Not implemented yet and not used yet
+     */
+    void virtualKeyCancel();
+
+    /**
+     * Emits a key click event for the given key, text and modifiers.
+     * Returns true if the key event was accepted by the input engine.
+     * \note Not implemented yet and not used yet
+     */
+    bool virtualKeyClick(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers);
+
+    /**
+     * Called by the keyboard layer to indicate that key was pressed, with the
+     * given text and modifiers.
+     * The key is set as an active key (down key). The actual key event is
+     * triggered when the key is released by the virtualKeyRelease() method.
+     * The key press event can be discarded by calling virtualKeyCancel().
+     * The key press also initiates the key repeat timer if repeat is true.
+     * Returns true if the key was accepted by this input engine.
+     * \note Not implemented yet and not used yet
+     */
+    bool virtualKeyPress(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers, bool repeat);
+
+    /**
+     * Releases the key at key. The method emits a key event for the input
+     * method if the event has not been generated by a repeating timer.
+     * The text and modifiers are passed to the input method.
+     * Returns true if the key was accepted by the input engine
+     * \note Not implemented yet and not used yet
+     */
+    bool virtualKeyRelease(Qt::Key key, const QString & text, Qt::KeyboardModifiers modifiers);
+
+    /**
+     * This function sends the given text to the focused QML item
+     * \note This function will get replaced by virtualKeyClick function later
+     */
+    void sendKeyToFocusItem(const QString &keyText);
+
+    /**
+     * Reports the active keyboard rectangle to the engine
+     */
+    void setKeyboardRectangle(const QRect& Rect);
+
+signals:
+    /**
+     * Notify signal of keyboardRectangle property
+     */
+    void keyboardRectangleChanged();
+
+    /**
+     * Notify signal of animating property
+     */
+    void animatingChanged();
+
+    /**
+     * Notify signal of inputModep property
+     */
+    void inputModeChanged();
+}; // class CDeclarativeInputEngine
+
+
+//---------------------------------------------------------------------------
+#endif // DECLARATIVEINPUTENGINE_H

BIN
FontAwesome.otf


+ 236 - 0
FreeVirtualKeyboardInputContext.cpp

@@ -0,0 +1,236 @@
+//============================================================================
+//                                 INCLUDES
+//============================================================================
+#include "FreeVirtualKeyboardInputContext.h"
+
+#include <QDebug>
+#include <QEvent>
+#include <QGuiApplication>
+#include <QQmlEngine>
+#include <QQmlContext>
+#include <QVariant>
+#include <QQmlEngine>
+#include <QJSEngine>
+#include <QPropertyAnimation>
+
+#include <private/qquickflickable_p.h>
+#include "DeclarativeInputEngine.h"
+
+
+/**
+ * Private data class for FreeVirtualKeyboardInputContext
+ */
+class FreeVirtualKeyboardInputContextPrivate
+{
+public:
+    FreeVirtualKeyboardInputContextPrivate();
+    QQuickFlickable* Flickable;
+    QQuickItem* FocusItem;
+    bool Visible;
+    DeclarativeInputEngine* InputEngine;
+    QPropertyAnimation* FlickableContentScrollAnimation;//< for smooth scrolling of flickable content item
+};
+
+
+//==============================================================================
+FreeVirtualKeyboardInputContextPrivate::FreeVirtualKeyboardInputContextPrivate()
+    : Flickable(0),
+      FocusItem(0),
+      Visible(false),
+      InputEngine(new DeclarativeInputEngine())
+{
+
+}
+
+
+//==============================================================================
+FreeVirtualKeyboardInputContext::FreeVirtualKeyboardInputContext() :
+    QPlatformInputContext(), d(new FreeVirtualKeyboardInputContextPrivate)
+{
+    d->FlickableContentScrollAnimation = new QPropertyAnimation(this);
+    d->FlickableContentScrollAnimation->setPropertyName("contentY");
+    d->FlickableContentScrollAnimation->setDuration(400);
+    d->FlickableContentScrollAnimation->setEasingCurve(QEasingCurve(QEasingCurve::OutBack));
+    qmlRegisterSingletonType<DeclarativeInputEngine>("FreeVirtualKeyboard", 1, 0,
+        "InputEngine", inputEngineProvider);
+    connect(d->InputEngine, SIGNAL(animatingChanged()), this, SLOT(ensureFocusedObjectVisible()));
+}
+
+
+//==============================================================================
+FreeVirtualKeyboardInputContext::~FreeVirtualKeyboardInputContext()
+{
+
+}
+
+
+//==============================================================================
+FreeVirtualKeyboardInputContext* FreeVirtualKeyboardInputContext::instance()
+{
+    static FreeVirtualKeyboardInputContext* InputContextInstance = new FreeVirtualKeyboardInputContext;
+    return InputContextInstance;
+}
+
+
+
+//==============================================================================
+bool FreeVirtualKeyboardInputContext::isValid() const
+{
+    return true;
+}
+
+
+//==============================================================================
+QRectF FreeVirtualKeyboardInputContext::keyboardRect() const
+{
+    return QRectF();
+}
+
+
+//==============================================================================
+void FreeVirtualKeyboardInputContext::showInputPanel()
+{
+    qDebug( "showInputPanel");
+    d->Visible = true;
+    QPlatformInputContext::showInputPanel();
+    emitInputPanelVisibleChanged();
+}
+
+
+//==============================================================================
+void FreeVirtualKeyboardInputContext::hideInputPanel()
+{
+    qDebug( "hideInputPanel");
+    d->Visible = false;
+    QPlatformInputContext::hideInputPanel();
+    emitInputPanelVisibleChanged();
+}
+
+
+//==============================================================================
+bool FreeVirtualKeyboardInputContext::isInputPanelVisible() const
+{
+    return d->Visible;
+}
+
+
+//==============================================================================
+bool FreeVirtualKeyboardInputContext::isAnimating() const
+{
+    return false;
+}
+
+
+//==============================================================================
+void FreeVirtualKeyboardInputContext::setFocusObject(QObject *object)
+{
+    static const int NumericInputHints = Qt::ImhPreferNumbers | Qt::ImhDate
+        | Qt::ImhTime | Qt::ImhDigitsOnly | Qt::ImhFormattedNumbersOnly;
+    static const int DialableInputHints = Qt::ImhDialableCharactersOnly;
+
+
+    qDebug() << "FreeVirtualKeyboardInputContext::setFocusObject";
+    if (!object)
+    {
+        return;
+    }
+
+    // we only support QML at the moment - so if this is not a QML item, then
+    // we leave immediatelly
+    d->FocusItem = dynamic_cast<QQuickItem*>(object);
+    if (!d->FocusItem)
+    {
+        return;
+    }
+
+    // Check if an input control has focus that accepts text input - if not,
+    // then we can leave immediatelly
+    bool AcceptsInput = d->FocusItem->inputMethodQuery(Qt::ImEnabled).toBool();
+    if (!AcceptsInput)
+    {
+        return;
+    }
+
+    // Set input mode depending on input method hints queried from focused
+    // object / item
+    Qt::InputMethodHints InputMethodHints(d->FocusItem->inputMethodQuery(Qt::ImHints).toInt());
+    qDebug() << QString("InputMethodHints: %1").arg(InputMethodHints, 0, 16);
+    if (InputMethodHints & DialableInputHints)
+    {
+        d->InputEngine->setInputMode(DeclarativeInputEngine::Dialable);
+    }
+    else if (InputMethodHints & NumericInputHints)
+    {
+        d->InputEngine->setInputMode(DeclarativeInputEngine::Numeric);
+    }
+    else
+    {
+        d->InputEngine->setInputMode(DeclarativeInputEngine::Latin);
+    }
+
+    // Search for the top most flickable so that we can scroll the control
+    // into the visible area, if the keyboard hides the control
+    QQuickItem* i = d->FocusItem;
+    d->Flickable = 0;
+    while (i)
+    {
+        QQuickFlickable* Flickable = dynamic_cast<QQuickFlickable*>(i);
+        if (Flickable)
+        {
+            d->Flickable = Flickable;
+            qDebug() << "is QQuickFlickable";
+        }
+        i = i->parentItem();
+    }
+
+    ensureFocusedObjectVisible();
+}
+
+
+//==============================================================================
+void FreeVirtualKeyboardInputContext::ensureFocusedObjectVisible()
+{
+    // If the keyboard is hidden, no scrollable element exists or the keyboard
+    // is just animating, then we leave here
+    if (!d->Visible || !d->Flickable || d->InputEngine->isAnimating())
+    {
+        return;
+    }
+
+    qDebug() << "FreeVirtualKeyboardInputContext::ensureFocusedObjectVisible";
+    QRectF FocusItemRect(0, 0, d->FocusItem->width(), d->FocusItem->height());
+    FocusItemRect = d->Flickable->mapRectFromItem(d->FocusItem, FocusItemRect);
+    qDebug() << "FocusItemRect: " << FocusItemRect;
+    qDebug() << "Content origin: " << QPointF(d->Flickable->contentX(),
+        d->Flickable->contentY());
+    qDebug() << "Flickable size: " << QSize(d->Flickable->width(), d->Flickable->height());
+    d->FlickableContentScrollAnimation->setTargetObject(d->Flickable);
+    qreal ContentY = d->Flickable->contentY();
+    if (FocusItemRect.bottom() >= d->Flickable->height())
+    {
+        qDebug() << "Item outside!!!  FocusItemRect.bottom() >= d->Flickable->height()";
+        ContentY = d->Flickable->contentY() + (FocusItemRect.bottom() - d->Flickable->height()) + 20;
+        d->FlickableContentScrollAnimation->setEndValue(ContentY);
+        d->FlickableContentScrollAnimation->start();
+    }
+    else if (FocusItemRect.top() < 0)
+    {
+        qDebug() << "Item outside!!!  d->FocusItem->position().x < 0";
+        ContentY = d->Flickable->contentY() + FocusItemRect.top() - 20;
+        d->FlickableContentScrollAnimation->setEndValue(ContentY);
+        d->FlickableContentScrollAnimation->start();
+    }
+}
+
+
+//==============================================================================
+QObject* FreeVirtualKeyboardInputContext::inputEngineProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
+{
+    Q_UNUSED(engine)
+    Q_UNUSED(scriptEngine)
+    return FreeVirtualKeyboardInputContext::instance()->d->InputEngine;
+}
+
+//------------------------------------------------------------------------------
+// EOF FreeVirtualKeyboardInpitContext.cpp
+

+ 106 - 0
FreeVirtualKeyboardInputContext.h

@@ -0,0 +1,106 @@
+#ifndef FREEVIRTUALKEYBOARDINPUTCONTEXT_H
+#define FREEVIRTUALKEYBOARDINPUTCONTEXT_H
+//============================================================================
+//                                 INCLUDES
+//============================================================================
+#include <QRectF>
+#include <qpa/qplatforminputcontext.h>
+
+
+//============================================================================
+//                             FORWARD DECLARATIONS
+//============================================================================
+class QQmlEngine;
+class QJSEngine;
+class FreeVirtualKeyboardInputContextPrivate;
+
+
+/**
+ * Implementation of QPlatformInputContext
+ */
+class FreeVirtualKeyboardInputContext : public QPlatformInputContext
+{
+    Q_OBJECT
+private:
+    /**
+     * The input contet creates the InputEngine object and provides it
+     * as a singleton to the QML context
+     */
+    static QObject* inputEngineProvider(QQmlEngine *engine, QJSEngine *scriptEngine);
+
+protected:
+    /**
+     * Protected constructor - use instance function to get the one and only
+     * object
+     */
+    FreeVirtualKeyboardInputContext();
+
+public:
+    /**
+     * Virtual destructor
+     */
+    virtual ~FreeVirtualKeyboardInputContext();
+
+    /**
+     * Returns input context validity. Deriving implementations should
+     * return true - so we simply return true
+     */
+    virtual bool isValid() const;
+
+    /**
+     * This function can be reimplemented to return virtual keyboard rectangle
+     * in currently active window coordinates. Default implementation returns
+     * invalid rectangle.
+     */
+    virtual QRectF keyboardRect() const;
+
+    /**
+     * Simply calls the emitInputPanelVisibleChanged() function
+     */
+    virtual void showInputPanel();
+
+    /**
+     * Simply calls the emitInputPanelVisibleChanged() function
+     */
+    virtual void hideInputPanel();
+
+    /**
+     * Returns input panel visibility status.
+     * This value will be available in QGuiApplication::inputMethod()->isVisible()
+     */
+    virtual bool isInputPanelVisible() const;
+
+    /**
+     * This function returns true whenever input method is animating
+     * shown or hidden.
+     */
+    virtual bool isAnimating() const;
+
+    /**
+     * This virtual method gets called to notify updated focus to object.
+     * \warning Input methods must not call this function directly.
+     * This function does the main work. It sets the input mode of the
+     * InputEngine singleton and it ensures that the focused QML object is
+     * visible if it is a child item of a Flickable
+     */
+    virtual void setFocusObject(QObject *object);
+
+    /**
+     * Use this static instance function to access the singleton input context
+     * instance
+     */
+    static FreeVirtualKeyboardInputContext* instance();
+
+private:
+    FreeVirtualKeyboardInputContextPrivate *d;
+
+private slots:
+    /**
+     * This function scrolls the QML item into visible area if the focused
+     * QML item is child of a flickable
+     */
+    void ensureFocusedObjectVisible();
+}; // FreeVirtualKeyboardInputContext
+
+//------------------------------------------------------------------------------
+#endif // FREEVIRTUALKEYBOARDINPUTCONTEXT_H

+ 24 - 0
FreeVirtualKeyboardInputContextPlugin.cpp

@@ -0,0 +1,24 @@
+#include "FreeVirtualKeyboardInputContextPlugin.h"
+#include "FreeVirtualKeyboardInputContext.h"
+//============================================================================
+//                                 INCLUDES
+//============================================================================
+#include <QDebug>
+
+
+//============================================================================
+QPlatformInputContext* FreeVirtualKeyboardInputContextPlugin::create(const QString& system, const QStringList& paramList)
+{
+    Q_UNUSED(paramList);
+
+    qDebug() << "FreeVirtualKeyboardInputContextPlugin::create: " << system;
+    if (system.compare(system, QStringLiteral("qtfreevirtualkeyboard"), Qt::CaseInsensitive) == 0)
+    {
+        return FreeVirtualKeyboardInputContext::instance();
+    }
+    return 0;
+}
+
+
+//------------------------------------------------------------------------------
+// EOF FreeVirtualInputContextPlugin.cpp

+ 22 - 0
FreeVirtualKeyboardInputContextPlugin.h

@@ -0,0 +1,22 @@
+#ifndef FREEVIRTUALKEYBOARDINPUTCONTEXTPLUGIN_H
+#define FREEVIRTUALKEYBOARDINPUTCONTEXTPLUGIN_H
+//============================================================================
+//                                 INCLUDES
+//============================================================================
+#include "freevirtualkeyboard_global.h"
+#include <qpa/qplatforminputcontextplugin_p.h>
+
+/**
+ * Implementation of QPlatformInputContextPlugin
+ */
+class FreeVirtualKeyboardInputContextPlugin : public QPlatformInputContextPlugin
+{
+    Q_OBJECT
+    Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "FreeVirtualKeyboardInputContextPlugin.json")
+
+public:
+    QPlatformInputContext *create(const QString&, const QStringList&);
+};  // class FreeVirtualKeyboardInputContextPlugin
+
+//------------------------------------------------------------------------------
+#endif // FREEVIRTUALKEYBOARDINPUTCONTEXTPLUGIN_H

+ 3 - 0
FreeVirtualKeyboardInputContextPlugin.json

@@ -0,0 +1,3 @@
+{                                                                                                                                                                                             
+    "Keys": [ "qtfreevirtualkeyboard" ]                                                                                                                                                                       
+}

+ 247 - 0
InputPanel.qml

@@ -0,0 +1,247 @@
+import QtQuick 2.0
+import "."
+import FreeVirtualKeyboard 1.0
+
+/**
+ * This is the QML input panel that provides the virtual keyboard UI
+ * The code has been copied from
+ * http://tolszak-dev.blogspot.de/2013/04/qplatforminputcontext-and-virtual.html
+ */
+Item {
+    id:root
+    objectName: "inputPanel"
+    width: parent.width
+    height: width / 4
+    // Report actual keyboard rectangle to input engine
+    onYChanged: InputEngine.setKeyboardRectangle(Qt.rect(x, y, width, height))
+
+    KeyModel {
+        id:keyModel
+    }
+    FontLoader {
+        source: "FontAwesome.otf"
+    }
+    QtObject {
+        id:pimpl
+        property bool shiftModifier: false
+        property bool symbolModifier: false
+        property int verticalSpacing: keyboard.height / 40
+        property int horizontalSpacing: verticalSpacing
+        property int rowHeight: keyboard.height/24*5 - verticalSpacing
+        property int buttonWidth:  (keyboard.width-column.anchors.margins)/12 - horizontalSpacing
+    }
+
+    // The delegate that paints the key buttons
+    Component {
+        id: keyButtonDelegate
+        KeyButton {
+            id: button
+            width: pimpl.buttonWidth
+            height: pimpl.rowHeight
+            text: (pimpl.shiftModifier) ? letter.toUpperCase() : (pimpl.symbolModifier)?firstSymbol : letter
+            inputPanel: root
+        }
+    }
+
+    Component {
+        id: numberButtonDelegate
+        KeyButton {
+            id: button
+            width: pimpl.buttonWidth
+            height: pimpl.rowHeight * 4 / 5
+            text: (pimpl.shiftModifier) ? letter.toUpperCase() : (pimpl.symbolModifier)?firstSymbol : letter
+            inputPanel: root
+            color: "grey"
+        }
+    }
+
+    Connections {
+        target: InputEngine
+        // Switch the keyboard layout to Numeric if the input mode of the InputEngine changes
+        onInputModeChanged: {
+            pimpl.symbolModifier = ((InputEngine.inputMode == InputEngine.Numeric)
+                                 || (InputEngine.inputMode == InputEngine.Dialable))
+            if (pimpl.symbolModifier) {
+                pimpl.shiftModifier = false
+            }
+        }
+    }
+
+    // This function shows the character preview popup for each key button
+    function showKeyPopup(keyButton)
+    {
+        // console.log("showKeyPopup");
+        keyPopup.popup(keyButton, root);
+    }
+
+    // The key popup for character preview
+    KeyPopup {
+        id: keyPopup
+        visible: false
+        z: 100
+    }
+
+
+    Rectangle {
+        id:keyboard
+        color: "black"
+        anchors.fill: parent;
+        MouseArea {
+            anchors.fill: parent
+        }
+
+        Column {
+            id:column
+            anchors.margins: 5
+            anchors.fill: parent
+            spacing: pimpl.verticalSpacing
+            Row {
+                height: pimpl.rowHeight
+                spacing: pimpl.horizontalSpacing
+                anchors.horizontalCenter:parent.horizontalCenter
+                Repeater {
+                    model: keyModel.numbersRowModel
+                    delegate: numberButtonDelegate
+                }
+            }
+
+            Row {
+                height: pimpl.rowHeight
+                spacing: pimpl.horizontalSpacing
+                anchors.horizontalCenter:parent.horizontalCenter
+                Repeater {
+                    model: keyModel.firstRowModel
+                    delegate: keyButtonDelegate
+                }
+            }
+            Row {
+                height: pimpl.rowHeight
+                spacing: pimpl.horizontalSpacing
+                anchors.horizontalCenter:parent.horizontalCenter
+                Repeater {
+                    model: keyModel.secondRowModel
+                    delegate: keyButtonDelegate
+                }
+            }
+            Item {
+                height: pimpl.rowHeight
+                width:parent.width
+                KeyButton {
+                    id: shiftKey
+                    color: (pimpl.shiftModifier)? "#1e6fa7": "#1e1b18"
+                    anchors.left: parent.left
+                    width: 1.25*pimpl.buttonWidth
+                    height: pimpl.rowHeight
+                    font.family: "FontAwesome"
+                    text: "\uf062"
+                    functionKey: true
+                    onClicked: {
+                        if (pimpl.symbolModifier) {
+                            pimpl.symbolModifier = false
+                        }
+                        pimpl.shiftModifier = !pimpl.shiftModifier
+                    }
+                    inputPanel: root
+                }
+                Row {
+                    height: pimpl.rowHeight
+                    spacing: pimpl.horizontalSpacing
+                    anchors.horizontalCenter:parent.horizontalCenter
+                    Repeater {
+                        anchors.horizontalCenter: parent.horizontalCenter
+                        model: keyModel.thirdRowModel
+                        delegate: keyButtonDelegate
+                    }
+                }
+                KeyButton {
+                    id: backspaceKey
+                    font.family: "FontAwesome"
+                    color: "#1e1b18"
+                    anchors.right: parent.right
+                    width: 1.25*pimpl.buttonWidth
+                    height: pimpl.rowHeight
+                    text: "\x7F"
+                    displayText: "\uf177"
+                    inputPanel: root
+                    repeat: true
+                }
+            }
+            Row {
+                height: pimpl.rowHeight
+                spacing: pimpl.horizontalSpacing
+                anchors.horizontalCenter:parent.horizontalCenter
+                KeyButton {
+                    id: hideKey
+                    color: "#1e1b18"
+                    width: 1.25*pimpl.buttonWidth
+                    height: pimpl.rowHeight
+                    font.family: "FontAwesome"
+                    text: "\uf078"
+                    functionKey: true
+                    onClicked: {
+                        Qt.inputMethod.hide()
+                    }
+                    inputPanel: root
+                    showPreview: false
+                }
+                KeyButton {
+                    color: "#1e1b18"
+                    width: 1.25*pimpl.buttonWidth
+                    height: pimpl.rowHeight
+                    text: ""
+                    inputPanel: root
+                    functionKey: true
+                }
+                KeyButton {
+                    color: "#1e1b18"
+                    width: pimpl.buttonWidth
+                    height: pimpl.rowHeight
+                    font.family: "FontAwesome"
+                    text: "\uf060" // arrow left
+                    //onClicked: InputEngine.sendKeyToFocusItem(text)
+                    inputPanel: root
+                }
+                KeyButton {
+                    id: spaceKey
+                    width: 3*pimpl.buttonWidth
+                    height: pimpl.rowHeight
+                    text: " "
+                    inputPanel: root
+                    showPreview: false
+                }
+                KeyButton {
+                    color: "#1e1b18"
+                    width: pimpl.buttonWidth
+                    height: pimpl.rowHeight
+                    font.family: "FontAwesome"
+                    text: "\uf061"  //pimpl.symbolModifier ? ":" :"."
+                    inputPanel: root
+                }
+                KeyButton {
+                    id: symbolKey
+                    color: "#1e1b18"
+                    width: 1.25*pimpl.buttonWidth
+                    height: pimpl.rowHeight
+                    text: (!pimpl.symbolModifier)? "12#" : "ABC"
+                    functionKey: true
+                    onClicked: {
+                        if (pimpl.shiftModifier) {
+                            pimpl.shiftModifier = false
+                        }
+                        pimpl.symbolModifier = !pimpl.symbolModifier
+                    }
+                    inputPanel: root
+                }
+                KeyButton {
+                    id: enterKey
+                    color: "#1e1b18"
+                    width: 1.25*pimpl.buttonWidth
+                    height: pimpl.rowHeight
+                    displayText: "Enter"
+                    text: "\n"
+                    inputPanel: root
+                }
+            }
+        }
+    }
+}

+ 149 - 0
KeyButton.qml

@@ -0,0 +1,149 @@
+import QtQuick 2.0
+import FreeVirtualKeyboard 1.0
+
+/**
+ * This is the type implements one single key button in the InputPanel
+ * The code has been copied from
+ * http://tolszak-dev.blogspot.de/2013/04/qplatforminputcontext-and-virtual.html
+ */
+Item {
+    id:root
+
+    // The background color of this button
+    property color color: "#35322f"
+
+    // The key text to show in this button
+    property string text
+
+    // The font for rendering of text
+    property alias font: txt.font
+
+    // The color of the text in this button
+    property alias textColor: txt.color
+
+    // This property holds the pressed status of the key.
+    property alias isPressed: buttonMouseArea.pressed
+
+    // This property holds a reference to the input panel.
+    // A key can only show the charcter preview popup if this property contains
+    // a valid refernce to the input panel
+    property var inputPanel
+
+    // This property holds the highlighted status of the key
+    // The highlighted status is a little bit different from the pressed status
+    // If the user releases the key, it is not pressed anymore, but it is still
+    // highlighted for some milliseconds
+    property bool isHighlighted: false
+
+    // Sets the show preview attribute for the character preview key popup
+    property bool showPreview: true
+
+    // Sets the key repeat attribute.
+    // If the repeat is enabled, the key will repeat the input events while held down.
+    // The default is false.
+    property bool repeat: false
+
+    // Sets the key code for input method processing.
+    property int key
+
+    // Sets the display text - this string is rendered in the keyboard layout.
+    // The default value is the key text.
+    property alias displayText: txt.text
+
+    // Sets the function key attribute.
+    property bool functionKey: false
+
+    signal clicked()
+    signal pressed()
+    signal released()
+
+    Rectangle {
+        anchors.fill: parent
+        radius: height / 20
+        color: isHighlighted ? Qt.tint(root.color, "#801e6fa7") : root.color
+        Text {
+            id: txt
+            color: "white"
+            anchors.margins: parent.height / 6
+            anchors.fill: parent
+            fontSizeMode: Text.Fit
+            font.pixelSize: height
+            horizontalAlignment: Text.AlignHCenter
+            verticalAlignment: Text.AlignVCenter
+            text: root.text
+        }
+        MouseArea {
+            id: buttonMouseArea
+            anchors.fill: parent
+            onClicked: root.clicked()
+            onPressed: root.pressed()
+            onReleased: root.released()
+        }
+    }
+
+    Timer {
+        id: highlightTimer
+        interval: 100
+        running: !isPressed
+        repeat: false
+
+        onTriggered: {
+            isHighlighted = false;
+        }
+    }
+
+    Timer {
+        id: repeatTimer
+        interval: 500
+        repeat: true
+        running: root.repeat && root.isPressed
+
+        onTriggered: {
+            if (root.state == "")
+            {
+                root.state = "REPEATING"
+                console.log("switching to repeating");
+            }
+            else if (root.state == "REPEATING")
+            {
+                console.log("repeating");
+            }
+
+            if (!functionKey)
+            {
+                InputEngine.sendKeyToFocusItem(text)
+            }
+        }
+    }
+
+    onInputPanelChanged: {
+        console.log("onInputPanelChanged: " + inputPanel.objectName);
+    }
+
+    // If the InputPanel property has a valid InputPanel reference and if
+    // showPreview is true, then this function calls showKeyPopup() to
+    // show the character preview popup.
+    onPressed: {
+        if (inputPanel != null && showPreview)
+        {
+            inputPanel.showKeyPopup(root);
+        }
+        isHighlighted = true;
+    }
+
+    onReleased: {
+        state = ""
+        console.log("onReleased - functionKey = " + functionKey)
+        if (!functionKey)
+        {
+            InputEngine.sendKeyToFocusItem(text)
+        }
+    }
+
+    states: [
+        State {
+            name: "REPEATING"
+            PropertyChanges { target: repeatTimer; interval: 50}
+        }
+    ]
+}

+ 152 - 0
KeyModel.qml

@@ -0,0 +1,152 @@
+import QtQuick 2.0
+
+/**
+ * This is quick and dirty model for the keys of the InputPanel *
+ * The code has been copied from
+ * http://tolszak-dev.blogspot.de/2013/04/qplatforminputcontext-and-virtual.html
+ */
+
+
+/********************************************************
+                English Keyboard Layout
+ ********************************************************/
+
+
+Item {
+    property QtObject firstRowModel: first
+    property QtObject secondRowModel: second
+    property QtObject thirdRowModel: third
+    property QtObject numbersRowModel: numbers
+
+    ListModel {
+        id:numbers
+        ListElement { letter: "1"; firstSymbol: "1"}
+        ListElement { letter: "2"; firstSymbol: "2"}
+        ListElement { letter: "3"; firstSymbol: "3"}
+        ListElement { letter: "4"; firstSymbol: "4"}
+        ListElement { letter: "5"; firstSymbol: "5"}
+        ListElement { letter: "6"; firstSymbol: "6"}
+        ListElement { letter: "7"; firstSymbol: "7"}
+        ListElement { letter: "8"; firstSymbol: "8"}
+        ListElement { letter: "9"; firstSymbol: "9"}
+        ListElement { letter: "0"; firstSymbol: "0"}
+        ListElement { letter: "@"; firstSymbol: "@"}
+        // ListElement { letter: "="; firstSymbol: "+"}
+    }
+
+    ListModel {
+        id:first
+        ListElement { letter: "q"; firstSymbol: "!"}
+        ListElement { letter: "w"; firstSymbol: "°"}
+        ListElement { letter: "e"; firstSymbol: "#"}
+        ListElement { letter: "r"; firstSymbol: "$"}
+        ListElement { letter: "t"; firstSymbol: "%"}
+        ListElement { letter: "y"; firstSymbol: "^"}
+        ListElement { letter: "u"; firstSymbol: "&"}
+        ListElement { letter: "i"; firstSymbol: "+"}
+        ListElement { letter: "o"; firstSymbol: "-"}
+        ListElement { letter: "p"; firstSymbol: "*"}
+        ListElement { letter: "("; firstSymbol: "/"}
+        ListElement { letter: ")"; firstSymbol: "="}
+    }
+    ListModel {
+        id:second
+        ListElement { letter: "a"; firstSymbol: "{"}
+        ListElement { letter: "s"; firstSymbol: "}"}
+        ListElement { letter: "d"; firstSymbol: "["}
+        ListElement { letter: "f"; firstSymbol: "]"}
+        ListElement { letter: "g"; firstSymbol: "("}
+        ListElement { letter: "h"; firstSymbol: ")"}
+        ListElement { letter: "j"; firstSymbol: ":"}
+        ListElement { letter: "k"; firstSymbol: "\""}
+        ListElement { letter: "l"; firstSymbol: "'"}
+        ListElement { letter: "'"; firstSymbol: "|"}
+        ListElement { letter: "/"; firstSymbol: "\\"}
+    }
+    ListModel {
+        id:third
+        ListElement { letter: "z"; firstSymbol: "<"}
+        ListElement { letter: "x"; firstSymbol: ">"}
+        ListElement { letter: "c"; firstSymbol: "€"}
+        ListElement { letter: "v"; firstSymbol: "µ"}
+        ListElement { letter: "b"; firstSymbol: "?"}
+        ListElement { letter: "n"; firstSymbol: ".com"}
+        ListElement { letter: "m"; firstSymbol: ";"}
+        ListElement { letter: ","; firstSymbol: ","}
+        ListElement { letter: "."; firstSymbol: "."}
+    }
+}
+
+
+
+/********************************************************
+                German Keyboard Layout
+ ********************************************************/
+/*
+
+Item {
+    property QtObject firstRowModel: first
+    property QtObject secondRowModel: second
+    property QtObject thirdRowModel: third
+    property QtObject numbersRowModel: numbers
+
+    ListModel {
+        id:numbers
+        ListElement { letter: "1"; firstSymbol: "1"}
+        ListElement { letter: "2"; firstSymbol: "2"}
+        ListElement { letter: "3"; firstSymbol: "3"}
+        ListElement { letter: "4"; firstSymbol: "4"}
+        ListElement { letter: "5"; firstSymbol: "5"}
+        ListElement { letter: "6"; firstSymbol: "6"}
+        ListElement { letter: "7"; firstSymbol: "7"}
+        ListElement { letter: "8"; firstSymbol: "8"}
+        ListElement { letter: "9"; firstSymbol: "9"}
+        ListElement { letter: "0"; firstSymbol: "0"}
+        ListElement { letter: "ß"; firstSymbol: "@"}
+        // ListElement { letter: "="; firstSymbol: "+"}
+    }
+
+    ListModel {
+        id:first
+        ListElement { letter: "q"; firstSymbol: "!"}
+        ListElement { letter: "w"; firstSymbol: "°"}
+        ListElement { letter: "e"; firstSymbol: "#"}
+        ListElement { letter: "r"; firstSymbol: "$"}
+        ListElement { letter: "t"; firstSymbol: "%"}
+        ListElement { letter: "z"; firstSymbol: "^"}
+        ListElement { letter: "u"; firstSymbol: "&"}
+        ListElement { letter: "i"; firstSymbol: "+"}
+        ListElement { letter: "o"; firstSymbol: "-"}
+        ListElement { letter: "p"; firstSymbol: "*"}
+        ListElement { letter: "ü"; firstSymbol: "/"}
+        ListElement { letter: ""; firstSymbol: "="}
+    }
+    ListModel {
+        id:second
+        ListElement { letter: "a"; firstSymbol: "{"}
+        ListElement { letter: "s"; firstSymbol: "}"}
+        ListElement { letter: "d"; firstSymbol: "["}
+        ListElement { letter: "f"; firstSymbol: "]"}
+        ListElement { letter: "g"; firstSymbol: "("}
+        ListElement { letter: "h"; firstSymbol: ")"}
+        ListElement { letter: "j"; firstSymbol: ":"}
+        ListElement { letter: "k"; firstSymbol: "\""}
+        ListElement { letter: "l"; firstSymbol: "'"}
+        ListElement { letter: "ö"; firstSymbol: "|"}
+        ListElement { letter: "ä"; firstSymbol: "\\"}
+    }
+    ListModel {
+        id:third
+        ListElement { letter: "y"; firstSymbol: "<"}
+        ListElement { letter: "x"; firstSymbol: ">"}
+        ListElement { letter: "c"; firstSymbol: "€"}
+        ListElement { letter: "v"; firstSymbol: "µ"}
+        ListElement { letter: "b"; firstSymbol: "?"}
+        ListElement { letter: "n"; firstSymbol: ".de"}
+        ListElement { letter: "m"; firstSymbol: ";"}
+        ListElement { letter: ","; firstSymbol: ","}
+        ListElement { letter: "."; firstSymbol: "."}
+    }
+}
+
+*/

+ 81 - 0
KeyPopup.qml

@@ -0,0 +1,81 @@
+import QtQuick 2.0
+import QtGraphicalEffects 1.0
+
+/**
+ * This is the key popup that shows a character preview above the
+ * pressed key button like it is known from keyboards on phones.
+ */
+
+Item {
+    id: root
+    property alias text: txt.text
+    property alias font: txt.font
+
+    width: 40
+    height: 40
+    visible: false
+
+    Rectangle {
+        id: popup
+        anchors.fill: parent
+        radius: Math.round(height / 30)
+        z: shadow.z + 1
+
+        gradient: Gradient {
+                 GradientStop { position: 0.0; color: Qt.lighter(Qt.lighter("#35322f"))}
+                 GradientStop { position: 1.0; color: Qt.lighter("#35322f")}
+
+        }
+
+        Text {
+            id: txt
+            color: "white"
+            anchors.fill: parent
+            fontSizeMode: Text.Fit
+            font.pixelSize: height
+            horizontalAlignment: Text.AlignHCenter
+            verticalAlignment: Text.AlignVCenter
+        }
+    }
+
+    Rectangle {
+        id: shadow
+        width: root.width
+        height: root.height
+        color: "#3F000000"
+        x: 4
+        y: 4
+    }
+
+    function popup(keybutton, inputPanel) {
+        // console.log("popup: " + inputPanel.objectName);
+        // console.log("keybutton.text: " + keybutton.text);
+        width = keybutton.width * 1.4;
+        height = keybutton.height * 1.4;
+        var KeyButtonGlobalLeft = keybutton.mapToItem(inputPanel, 0, 0).x;
+        var KeyButtonGlobalTop = keybutton.mapToItem(inputPanel, 0, 0).y;
+        var PopupGlobalLeft = KeyButtonGlobalLeft - (width - keybutton.width) / 2;
+        var PopupGlobalTop = KeyButtonGlobalTop - height - pimpl.verticalSpacing * 1.5;
+        // console.log("Popup position left: " + KeyButtonGlobalLeft);
+        var PopupLeft = root.parent.mapFromItem(inputPanel, PopupGlobalLeft, PopupGlobalTop).x;
+        y = root.parent.mapFromItem(inputPanel, PopupGlobalLeft, PopupGlobalTop).y;
+        if (PopupGlobalLeft < 0)
+        {
+            x = 0;
+        }
+        else if ((PopupGlobalLeft + width) > inputPanel.width)
+        {
+            x = PopupLeft - (PopupGlobalLeft + width - inputPanel.width);
+        }
+        else
+        {
+            x = PopupLeft;
+        }
+
+        text = keybutton.displayText;
+        font.family = keybutton.font.family
+        visible = Qt.binding(function() {return keybutton.isHighlighted});
+    }
+}
+
+

+ 8 - 0
LICENSE

@@ -0,0 +1,8 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <olszak.tomasz@gmail.com> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return Tomasz Olszak
+ * ----------------------------------------------------------------------------
+ */

+ 36 - 0
Paths.txt

@@ -0,0 +1,36 @@
+Target:
+/usr/qml/QtQuick/FreeVirtualKeyboard/
+	FontAwesome.otf
+	InputPanel.qml
+	KeyButton.qml
+	KeyModel.qml
+	KeyPopup.qml
+	qmldir
+
+/usr/lib/qt/plugins/platforminputcontexts/libFreeVirtualKeyboard.so
+
+Toolchain:
+/opt/GfA/TC_L4465_C493_QT562/usr/arm-buildroot-linux-gnueabihf/sysroot/usr/qml/QtQuick/FreeVirtualKeyboard
+	FontAwesome.otf
+	InputPanel.qml
+	KeyButton.qml
+	KeyModel.qml
+	KeyPopup.qml
+	qmldir
+
+/opt/GfA/TC_L4465_C493_QT562/usr/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/qt/plugins/platforminputcontexts/libFreeVirtualKeyboard.so
+
+
+==============================================================================
+PC:
+/opt/Qt/5.6.2/5.6/gcc_64/qml/QtQuick/FreeVirtualKeyboard
+	FontAwesome.otf
+	InputPanel.qml
+	KeyButton.qml
+	KeyModel.qml
+	KeyPopup.qml
+	qmldir
+
+/opt/Qt/5.6.2/5.6/gcc_64/plugins/platforminputcontexts/libFreeVirtualKeyboard.so
+
+

+ 24 - 0
README first.txt

@@ -0,0 +1,24 @@
+*******************************************************************************
+* README for qtvirtual Keyboard
+*******************************************************************************
+
+Introduction
+============
+The code for this virtual keyboard is based on code from
+https://github.com/githubuser0xFFFF/QtFreeVirtualKeyboard 
+and
+http://tolszak-dev.blogspot.in/2013/04/qplatforminputcontext-and-virtual.html
+
+It is the implementation of a Qt virtual keyboard plugin for QtQuick-based 
+embedded applications (like phyKitDemo software).
+
+
+Deployment/Installation
+=======================
+The file "libVirtualKeyboard.so" has to be copied into the qt installation plugin directory.
+For standard GfA BSP this will be: /usr/lib/qt/plugins/platforminputcontexts
+
+The files FontAwesome.otf, KeyButton.qml, KeyPopup.qml ,InputPanel.qml, KeyModel.qml, qmldir have to be copied into 
+qml directory (e.g.: /usr/lib/qt/qml/QtQuick/VirtualKeyboard), so that they can be imported from QtQuick 
+
+

+ 12 - 0
README.md

@@ -0,0 +1,12 @@
+# QtFreeVirtualKeyboard
+A QML based on screen virtual keyboard for embedded QML applications.
+
+![Screenshot](doc/VirtualKeyboardScreenshot.png)
+
+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.
+
+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.
+
+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.
+
+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.

+ 21 - 0
deployment.pri

@@ -0,0 +1,21 @@
+linux-buildroot-g++ {
+    message( embedded target-deployment )
+    # deployment
+
+    INSTALLS += target
+
+    deployment.files = $$files(*.qml) FontAwesome.otf qmldir
+
+    linux-buildroot-g++ {
+        deployment.path = /usr/qml/QtQuick/FreeVirtualKeyboard
+        target.path = /usr/lib/qt/plugins/platforminputcontexts
+    } else {
+        deployment.path = $$[QT_INSTALL_QML]/QtQuick/FreeVirtualKeyboard
+        target.path = $$[QT_INSTALL_PLUGINS]/platforminputcontexts
+    }
+
+    INSTALLS += target \
+                deployment
+
+    export(target.path)
+}

+ 37 - 0
freevirtualkeyboard.pro

@@ -0,0 +1,37 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2013-04-04T23:11:38
+#
+#-------------------------------------------------
+
+QT       += qml quick quick-private gui-private
+
+CONFIG += plugin
+
+TARGET = FreeVirtualKeyboard
+TEMPLATE = lib
+
+
+SOURCES += FreeVirtualKeyboardInputContextPlugin.cpp \
+    FreeVirtualKeyboardInputContext.cpp \
+    DeclarativeInputEngine.cpp
+
+HEADERS += FreeVirtualKeyboardInputContextPlugin.h\
+    FreeVirtualKeyboardInputContext.h \
+    DeclarativeInputEngine.h
+
+
+
+OTHER_FILES += \
+    InputPanel.qml \
+    KeyModel.qml \
+    KeyButton.qml \
+    KeyPopup.qml \
+    deployment.pri
+
+RESOURCES += \
+    freevirtualkeyboard.qrc
+
+
+# Default rules for deployment.
+include(deployment.pri)

+ 3 - 0
freevirtualkeyboard.qrc

@@ -0,0 +1,3 @@
+<RCC>
+    <qresource prefix="/"/>
+</RCC>

+ 12 - 0
freevirtualkeyboard_global.h

@@ -0,0 +1,12 @@
+#ifndef MOCKUPFREEVIRTUALKEYBOARD_GLOBAL_H
+#define MOCKUPFREEVIRTUALKEYBOARD_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(MOCKUPFREEVIRTUALKEYBOARD_LIBRARY)
+#  define MOCKUPFREEVIRTUALKEYBOARDSHARED_EXPORT Q_DECL_EXPORT
+#else
+#  define MOCKUPFREEVIRTUALKEYBOARDSHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // MOCKUPFREEVIRTUALKEYBOARD_GLOBAL_H

+ 2 - 0
qmldir

@@ -0,0 +1,2 @@
+module QtQuick.FreeVirtualKeyboard
+InputPanel 1.0 InputPanel.qml

+ 8 - 0
toToolchain.sh

@@ -0,0 +1,8 @@
+#!/bin/sh
+
+QUICKPATH=$SYSROOTARM/usr/qml/QtQuick/FreeVirtualKeyboard
+LIBPATH=$SYSROOTARM/usr/lib/qt/plugins/platforminputcontexts
+mkdir -p $QUICKPATH
+mkdir -p $LIBPATH
+
+#--- quickmodule