input panel again

This commit is contained in:
Uwe Rathmann 2018-06-12 08:20:48 +02:00
parent f8982e2177
commit e195614654
11 changed files with 373 additions and 384 deletions

View File

@ -20,10 +20,10 @@
namespace namespace
{ {
class InputContext : public QskInputContext class InputContextFactory : public QskInputContextFactory
{ {
public: public:
virtual QskTextPredictor* textPredictor( const QLocale& locale ) const virtual QskTextPredictor* createPredictor( const QLocale& locale ) const
{ {
#if HUNSPELL #if HUNSPELL
/* /*
@ -34,7 +34,7 @@ namespace
return new QskHunspellTextPredictor(); return new QskHunspellTextPredictor();
#endif #endif
return QskInputContext::textPredictor( locale ); return QskInputContextFactory::createPredictor( locale );
} }
}; };
} }
@ -94,7 +94,9 @@ QskPlatformInputContext::QskPlatformInputContext()
auto context = QskInputContext::instance(); auto context = QskInputContext::instance();
if ( context == nullptr ) if ( context == nullptr )
{ {
context = new InputContext(); context = new QskInputContext();
context->setFactory( new InputContextFactory() );
QskInputContext::setInstance( context ); QskInputContext::setInstance( context );
} }

View File

@ -307,15 +307,17 @@ int main( int argc, char* argv[] )
QskInputContext::setInputEngine( ... ); QskInputContext::setInputEngine( ... );
#endif #endif
Window window; Window window1;
window.setColor( "PapayaWhip" ); window1.setObjectName( "Window 1" );
window.resize( 600, 600 ); window1.setColor( "PapayaWhip" );
window.show(); window1.resize( 600, 600 );
window1.show();
#if 0 #if 0
Window window2; Window window2;
window2.setObjectName( "Window 2" );
window2.setColor( "Pink" ); window2.setColor( "Pink" );
window2.setX( window.x() + 100 ); window2.setX( window1.x() + 100 );
window2.resize( 600, 600 ); window2.resize( 600, 600 );
window2.show(); window2.show();
#endif #endif

View File

@ -8,7 +8,7 @@
#include <QskDialogButtonBox.h> #include <QskDialogButtonBox.h>
#include <QskDialogButton.h> #include <QskDialogButton.h>
#include <QskFocusIndicator.h> #include <QskFocusIndicator.h>
#include <QskInputPanel.h> #include <QskInputPanelBox.h>
#include <QskListView.h> #include <QskListView.h>
#include <QskPageIndicator.h> #include <QskPageIndicator.h>
#include <QskPushButton.h> #include <QskPushButton.h>
@ -547,7 +547,7 @@ void QskMaterialSkin::initTabViewHints()
void QskMaterialSkin::initInputPanelHints() void QskMaterialSkin::initInputPanelHints()
{ {
using namespace QskAspect; using namespace QskAspect;
using Q = QskInputPanel; using Q = QskInputPanelBox;
const ColorPalette& pal = m_data->palette; const ColorPalette& pal = m_data->palette;

View File

@ -17,7 +17,7 @@
#include <QskTabButton.h> #include <QskTabButton.h>
#include <QskTabBar.h> #include <QskTabBar.h>
#include <QskTabView.h> #include <QskTabView.h>
#include <QskInputPanel.h> #include <QskInputPanelBox.h>
#include <QskInputPredictionBar.h> #include <QskInputPredictionBar.h>
#include <QskVirtualKeyboard.h> #include <QskVirtualKeyboard.h>
#include <QskScrollView.h> #include <QskScrollView.h>
@ -618,7 +618,7 @@ void QskSquiekSkin::initTabViewHints()
void QskSquiekSkin::initInputPanelHints() void QskSquiekSkin::initInputPanelHints()
{ {
using namespace QskAspect; using namespace QskAspect;
using Q = QskInputPanel; using Q = QskInputPanelBox;
setMargins( Q::Panel | Padding, 5 ); setMargins( Q::Panel | Padding, 5 );
setPanel( Q::Panel, Raised ); setPanel( Q::Panel, Raised );

View File

@ -4,8 +4,8 @@
*****************************************************************************/ *****************************************************************************/
#include "QskInputContext.h" #include "QskInputContext.h"
#include "QskInputEngine.h"
#include "QskInputPanel.h" #include "QskInputPanel.h"
#include "QskInputPanelBox.h"
#include "QskLinearBox.h" #include "QskLinearBox.h"
#include "QskDialog.h" #include "QskDialog.h"
@ -26,54 +26,51 @@ QSK_QT_PRIVATE_END
namespace namespace
{ {
class InputEngine final : public QskInputEngine class Panel final : public QskInputPanel
{ {
public: public:
virtual void attachToPanel( QQuickItem* item ) override Panel( QQuickItem* parent = nullptr ):
QskInputPanel( parent )
{ {
if ( m_panel ) setAutoLayoutChildren( true );
m_panel->attachInputItem( item );
m_box = new QskInputPanelBox( this );
connect( m_box, &QskInputPanelBox::keySelected,
this, &QskInputPanel::keySelected );
connect( m_box, &QskInputPanelBox::predictiveTextSelected,
this, &QskInputPanel::predictiveTextSelected );
} }
virtual QskControl* createPanel() override virtual void attachItem( QQuickItem* item ) override
{ {
m_panel = new QskInputPanel(); m_box->attachInputItem( item );
connect( m_panel, &QskInputPanel::keySelected,
this, &QskInputEngine::commitKey, Qt::UniqueConnection );
connect( m_panel, &QskInputPanel::predictiveTextSelected,
this, &QskInputEngine::commitPredictiveText, Qt::UniqueConnection );
return m_panel;
} }
virtual QQuickItem* inputProxy() const override virtual QQuickItem* inputProxy() const override
{ {
if ( m_panel ) return m_box->inputProxy();
{
if ( m_panel->panelHints() & QskInputPanel::InputProxy )
return m_panel->inputProxy();
} }
return nullptr; virtual void setPrompt( const QString& prompt ) override
{
m_box->setInputPrompt( prompt );
} }
virtual void setPredictionEnabled( bool on ) override virtual void setPredictionEnabled( bool on ) override
{ {
if ( m_panel ) m_box->setPanelHint( QskInputPanelBox::Prediction, on );
m_panel->setPanelHint( QskInputPanel::Prediction, on );
} }
virtual void showPrediction( const QStringList& prediction ) override virtual void setPrediction( const QStringList& prediction ) override
{ {
if ( m_panel ) m_box->setPrediction( prediction );
m_panel->setPrediction( prediction );
} }
private: private:
QPointer< QskInputPanel > m_panel; QskInputPanelBox* m_box;
}; };
} }
static QPointer< QskInputContext > qskInputContext = nullptr; static QPointer< QskInputContext > qskInputContext = nullptr;
@ -121,56 +118,50 @@ class QskInputContext::PrivateData
public: public:
// item receiving the input // item receiving the input
QPointer< QQuickItem > inputItem; QPointer< QQuickItem > inputItem;
QPointer< QskInputPanel > panel;
// popup or window embedding the panel // popup or window embedding the panel
QskPopup* inputPopup = nullptr; QskPopup* inputPopup = nullptr;
QskWindow* inputWindow = nullptr; QskWindow* inputWindow = nullptr;
QPointer< QskInputEngine > inputEngine; QPointer< QskInputContextFactory > factory;
}; };
QskInputContext::QskInputContext(): QskInputContext::QskInputContext():
m_data( new PrivateData() ) m_data( new PrivateData() )
{ {
setObjectName( "InputContext" ); setObjectName( "InputContext" );
setEngine( new InputEngine() );
} }
QskInputContext::~QskInputContext() QskInputContext::~QskInputContext()
{ {
} }
void QskInputContext::setEngine( QskInputEngine* engine ) void QskInputContext::setFactory( QskInputContextFactory* factory )
{ {
if ( m_data->inputEngine == engine ) if ( m_data->factory == factory )
return; return;
if ( m_data->inputEngine && m_data->inputEngine->parent() == this ) if ( m_data->factory && m_data->factory->parent() == this )
{ delete m_data->factory;
m_data->inputEngine->disconnect( this );
if ( m_data->inputEngine->parent() == this ) m_data->factory = factory;
delete m_data->inputEngine;
if ( factory && factory->parent() == nullptr )
factory->setParent( this );
} }
m_data->inputEngine = engine; QskInputContextFactory* QskInputContext::factory() const
if ( engine )
{ {
if ( engine->parent() == nullptr ) return m_data->factory;
engine->setParent( this );
connect( engine, &QskInputEngine::activeChanged,
this, &QskInputContext::activeChanged );
connect( engine, &QskInputEngine::localeChanged,
this, [] { qskSendToPlatformContext( QEvent::LocaleChange ); } );
}
} }
QskInputEngine* QskInputContext::engine() const QskTextPredictor* QskInputContext::textPredictor( const QLocale& locale )
{ {
return m_data->inputEngine; if ( m_data->factory )
return m_data->factory->createPredictor( locale );
return nullptr;
} }
QQuickItem* QskInputContext::inputItem() const QQuickItem* QskInputContext::inputItem() const
@ -178,19 +169,6 @@ QQuickItem* QskInputContext::inputItem() const
return m_data->inputItem; return m_data->inputItem;
} }
QskControl* QskInputContext::inputPanel() const
{
if ( m_data->inputEngine == nullptr )
return nullptr;
auto panel = m_data->inputEngine->panel( true );
if ( panel && panel->parent() != this )
panel->setParent( const_cast< QskInputContext* >( this ) );
return panel;
}
void QskInputContext::update( Qt::InputMethodQueries queries ) void QskInputContext::update( Qt::InputMethodQueries queries )
{ {
if ( queries & Qt::ImEnabled ) if ( queries & Qt::ImEnabled )
@ -205,8 +183,8 @@ void QskInputContext::update( Qt::InputMethodQueries queries )
} }
} }
if ( m_data->inputEngine ) if ( m_data->panel )
m_data->inputEngine->updateInputPanel( queries ); m_data->panel->updateInputPanel( queries );
} }
QRectF QskInputContext::panelRect() const QRectF QskInputContext::panelRect() const
@ -217,7 +195,7 @@ QRectF QskInputContext::panelRect() const
return QRectF(); return QRectF();
} }
QskPopup* QskInputContext::createEmbeddingPopup( QskControl* panel ) QskPopup* QskInputContext::createEmbeddingPopup( QskInputPanel* panel )
{ {
auto popup = new QskPopup(); auto popup = new QskPopup();
@ -228,10 +206,7 @@ QskPopup* QskInputContext::createEmbeddingPopup( QskControl* panel )
auto box = new QskLinearBox( popup ); auto box = new QskLinearBox( popup );
box->addItem( panel ); box->addItem( panel );
Qt::Alignment alignment = Qt::AlignVCenter; const auto alignment = panel->alignment() & Qt::AlignVertical_Mask;
if ( m_data->inputEngine )
alignment = m_data->inputEngine->panelAlignment() & Qt::AlignVertical_Mask;
popup->setOverlay( alignment == Qt::AlignVCenter ); popup->setOverlay( alignment == Qt::AlignVCenter );
switch( alignment ) switch( alignment )
@ -257,7 +232,7 @@ QskPopup* QskInputContext::createEmbeddingPopup( QskControl* panel )
return popup; return popup;
} }
QskWindow* QskInputContext::createEmbeddingWindow( QskControl* panel ) QskWindow* QskInputContext::createEmbeddingWindow( QskInputPanel* panel )
{ {
auto window = new QskWindow(); auto window = new QskWindow();
@ -273,18 +248,42 @@ QskWindow* QskInputContext::createEmbeddingWindow( QskControl* panel )
return window; return window;
} }
void QskInputContext::ensurePanel()
{
if ( m_data->panel )
return;
QskInputPanel* panel = nullptr;
if ( m_data->factory )
panel = m_data->factory->createPanel();
if ( panel == nullptr )
panel = new Panel();
panel->setParent( const_cast< QskInputContext* >( this ) );
connect( panel, &QskInputPanel::visibleChanged,
this, &QskInputContext::activeChanged,
Qt::UniqueConnection );
connect( panel, &QskInputPanel::localeChanged,
this, [] { qskSendToPlatformContext( QEvent::LocaleChange ); },
Qt::UniqueConnection );
m_data->panel = panel;
}
void QskInputContext::showPanel() void QskInputContext::showPanel()
{ {
auto focusItem = qobject_cast< QQuickItem* >( qGuiApp->focusObject() ); auto focusItem = qobject_cast< QQuickItem* >( qGuiApp->focusObject() );
if ( focusItem == nullptr ) if ( focusItem == nullptr )
return; return;
auto panel = inputPanel(); ensurePanel();
if ( panel == nullptr )
return;
if ( ( focusItem == panel ) if ( ( focusItem == m_data->panel )
|| qskIsAncestorOf( panel, focusItem ) ) || qskIsAncestorOf( m_data->panel, focusItem ) )
{ {
// ignore: usually the input proxy of the panel // ignore: usually the input proxy of the panel
return; return;
@ -300,7 +299,7 @@ void QskInputContext::showPanel()
if ( m_data->inputWindow == nullptr ) if ( m_data->inputWindow == nullptr )
{ {
auto window = createEmbeddingWindow( panel ); auto window = createEmbeddingWindow( m_data->panel );
if ( window ) if ( window )
{ {
@ -329,7 +328,7 @@ void QskInputContext::showPanel()
if ( m_data->inputPopup == nullptr ) if ( m_data->inputPopup == nullptr )
{ {
auto popup = createEmbeddingPopup( panel ); auto popup = createEmbeddingPopup( m_data->panel );
if ( popup ) if ( popup )
{ {
@ -345,8 +344,7 @@ void QskInputContext::showPanel()
} }
} }
if ( m_data->inputEngine ) m_data->panel->attachInputItem( m_data->inputItem );
m_data->inputEngine->attachInputItem( m_data->inputItem );
} }
void QskInputContext::hidePanel() void QskInputContext::hidePanel()
@ -368,12 +366,12 @@ void QskInputContext::hidePanel()
#endif #endif
} }
if ( m_data->inputEngine ) if ( m_data->panel )
{ {
if ( auto panel = m_data->inputEngine->panel( false ) ) m_data->panel->setParentItem( nullptr );
panel->setParentItem( nullptr ); m_data->panel->disconnect( this );
m_data->inputEngine->attachInputItem( nullptr ); m_data->panel->attachInputItem( nullptr );
} }
if ( m_data->inputPopup ) if ( m_data->inputPopup )
@ -410,11 +408,8 @@ bool QskInputContext::isActive() const
QLocale QskInputContext::locale() const QLocale QskInputContext::locale() const
{ {
if ( m_data->inputEngine ) if ( m_data->panel )
{ return m_data->panel->locale();
if ( auto panel = m_data->inputEngine->panel( false ) )
return panel->locale();
}
return QLocale(); return QLocale();
} }
@ -469,11 +464,6 @@ void QskInputContext::setFocusObject( QObject* focusObject )
m_data->inputItem = nullptr; m_data->inputItem = nullptr;
} }
QskTextPredictor* QskInputContext::textPredictor( const QLocale& ) const
{
return nullptr;
}
void QskInputContext::processClickAt( int cursorPosition ) void QskInputContext::processClickAt( int cursorPosition )
{ {
Q_UNUSED( cursorPosition ); Q_UNUSED( cursorPosition );
@ -484,7 +474,7 @@ void QskInputContext::commitPrediction( bool )
/* /*
called, when the input item loses the focus. called, when the input item loses the focus.
As it it should be possible to navigate inside of the As it it should be possible to navigate inside of the
inputPanel what should we do here ? panel what should we do here ?
*/ */
} }
@ -501,8 +491,8 @@ bool QskInputContext::eventFilter( QObject* object, QEvent* event )
} }
case QEvent::Resize: case QEvent::Resize:
{ {
if ( auto panel = inputPanel() ) if ( m_data->panel )
panel->setSize( m_data->inputWindow->size() ); m_data->panel->setSize( m_data->inputWindow->size() );
break; break;
} }
@ -535,4 +525,23 @@ bool QskInputContext::eventFilter( QObject* object, QEvent* event )
return Inherited::eventFilter( object, event ); return Inherited::eventFilter( object, event );
} }
QskInputContextFactory::QskInputContextFactory( QObject* parent ):
QObject( parent )
{
}
QskInputContextFactory::~QskInputContextFactory()
{
}
QskTextPredictor* QskInputContextFactory::createPredictor( const QLocale& ) const
{
return nullptr;
}
QskInputPanel* QskInputContextFactory::createPanel() const
{
return new Panel();
}
#include "moc_QskInputContext.cpp" #include "moc_QskInputContext.cpp"

View File

@ -12,12 +12,24 @@
#include <memory> #include <memory>
class QskTextPredictor; class QskTextPredictor;
class QskControl; class QskInputPanel;
class QskInputEngine; class QskInputEngine;
class QskPopup; class QskPopup;
class QskWindow; class QskWindow;
class QQuickItem; class QQuickItem;
class QSK_EXPORT QskInputContextFactory : public QObject
{
Q_OBJECT
public:
QskInputContextFactory( QObject* parent = nullptr );
virtual ~QskInputContextFactory();
virtual QskTextPredictor* createPredictor( const QLocale& ) const;
virtual QskInputPanel* createPanel() const;
};
class QSK_EXPORT QskInputContext : public QObject class QSK_EXPORT QskInputContext : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -28,8 +40,8 @@ public:
QskInputContext(); QskInputContext();
virtual ~QskInputContext(); virtual ~QskInputContext();
void setEngine( QskInputEngine* ); void setFactory( QskInputContextFactory* );
QskInputEngine* engine() const; QskInputContextFactory* factory() const;
QRectF panelRect() const; QRectF panelRect() const;
@ -43,7 +55,7 @@ public:
static QskInputContext* instance(); static QskInputContext* instance();
static void setInstance( QskInputContext* ); static void setInstance( QskInputContext* );
virtual QskTextPredictor* textPredictor( const QLocale& ) const; QskTextPredictor* textPredictor( const QLocale& locale );
Q_SIGNALS: Q_SIGNALS:
void activeChanged(); void activeChanged();
@ -52,14 +64,12 @@ Q_SIGNALS:
protected: protected:
virtual bool eventFilter( QObject*, QEvent* ) override; virtual bool eventFilter( QObject*, QEvent* ) override;
virtual QskPopup* createEmbeddingPopup( QskControl* ); virtual QskPopup* createEmbeddingPopup( QskInputPanel* );
virtual QskWindow* createEmbeddingWindow( QskControl* ); virtual QskWindow* createEmbeddingWindow( QskInputPanel* );
virtual void showPanel(); virtual void showPanel();
virtual void hidePanel(); virtual void hidePanel();
QskControl* inputPanel() const;
private: private:
friend class QskPlatformInputContext; friend class QskPlatformInputContext;
@ -69,6 +79,8 @@ private:
virtual void processClickAt( int cursorPosition ); virtual void processClickAt( int cursorPosition );
virtual void commitPrediction( bool ); virtual void commitPrediction( bool );
void ensurePanel();
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;
}; };

View File

@ -3,18 +3,27 @@
* This file may be used under the terms of the QSkinny License, Version 1.0 * This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/ *****************************************************************************/
#include "QskInputEngine.h" #include "QskInputPanel.h"
#include "QskInputContext.h" #include "QskInputContext.h"
#include "QskTextPredictor.h" #include "QskTextPredictor.h"
#include "QskControl.h"
#include <QPointer> #include <QPointer>
#include <QTextCharFormat> #include <QTextCharFormat>
static inline QQuickItem* qskReceiverItem( const QskInputEngine* engine ) static inline QQuickItem* qskReceiverItem( const QskInputPanel* panel )
{ {
auto item = engine->inputProxy(); if ( auto item = panel->inputProxy() )
return item ? item : engine->inputItem(); return item;
return panel->inputItem();
}
static inline bool qskUsePrediction( Qt::InputMethodHints hints )
{
constexpr Qt::InputMethodHints mask =
Qt::ImhNoPredictiveText | Qt::ImhExclusiveInputMask | Qt::ImhHiddenText;
return ( hints & mask ) == 0;
} }
static inline void qskSendReplaceText( QQuickItem* receiver, const QString& text ) static inline void qskSendReplaceText( QQuickItem* receiver, const QString& text )
@ -73,55 +82,21 @@ static inline void qskSendKey( QQuickItem* receiver, int key )
QCoreApplication::sendEvent( receiver, &keyRelease ); QCoreApplication::sendEvent( receiver, &keyRelease );
} }
static inline bool qskUsePrediction( Qt::InputMethodHints hints )
{
constexpr Qt::InputMethodHints mask =
Qt::ImhNoPredictiveText | Qt::ImhExclusiveInputMask | Qt::ImhHiddenText;
return ( hints & mask ) == 0;
}
static inline QString qskKeyString( int keyCode )
{
// Special case entry codes here, else default to the symbol
switch ( keyCode )
{
case Qt::Key_Shift:
case Qt::Key_CapsLock:
case Qt::Key_Mode_switch:
case Qt::Key_Backspace:
case Qt::Key_Muhenkan:
return QString();
case Qt::Key_Return:
case Qt::Key_Kanji:
return QChar( QChar::CarriageReturn );
case Qt::Key_Space:
return QChar( QChar::Space );
default:
break;
}
return QChar( keyCode );
}
namespace namespace
{ {
class KeyProcessor class KeyProcessor
{ {
public: public:
class Result struct Result
{ {
public:
int key = 0; int key = 0;
QString text; QString text;
bool isFinal = true; bool isFinal = true;
}; };
Result processKey( int key, Qt::InputMethodHints inputHints, Result processKey(
int key, Qt::InputMethodHints inputHints,
QskTextPredictor* predictor, int spaceLeft ) QskTextPredictor* predictor, int spaceLeft )
{ {
Result result; Result result;
@ -183,7 +158,7 @@ namespace
{ {
if ( !m_preedit.isEmpty() && spaceLeft) if ( !m_preedit.isEmpty() && spaceLeft)
{ {
m_preedit += qskKeyString( key ); m_preedit += keyString( key );
m_preedit = m_preedit.left( spaceLeft ); m_preedit = m_preedit.left( spaceLeft );
result.text = m_preedit; result.text = m_preedit;
@ -206,7 +181,7 @@ namespace
} }
} }
const QString text = qskKeyString( key ); const QString text = keyString( key );
if ( predictor ) if ( predictor )
{ {
@ -242,15 +217,40 @@ namespace
} }
private: private:
inline QString keyString( int keyCode ) const
{
// Special case entry codes here, else default to the symbol
switch ( keyCode )
{
case Qt::Key_Shift:
case Qt::Key_CapsLock:
case Qt::Key_Mode_switch:
case Qt::Key_Backspace:
case Qt::Key_Muhenkan:
return QString();
case Qt::Key_Return:
case Qt::Key_Kanji:
return QChar( QChar::CarriageReturn );
case Qt::Key_Space:
return QChar( QChar::Space );
default:
break;
}
return QChar( keyCode );
}
QString m_preedit; QString m_preedit;
}; };
} }
class QskInputEngine::PrivateData class QskInputPanel::PrivateData
{ {
public: public:
KeyProcessor keyProcessor; KeyProcessor keyProcessor;
QPointer< QskControl > panel;
QPointer< QQuickItem > inputItem; QPointer< QQuickItem > inputItem;
QLocale predictorLocale; QLocale predictorLocale;
@ -260,17 +260,30 @@ public:
bool hasPredictorLocale = false; bool hasPredictorLocale = false;
}; };
QskInputEngine::QskInputEngine( QObject* parent ): QskInputPanel::QskInputPanel( QQuickItem* parent ):
Inherited( parent ), Inherited( parent ),
m_data( new PrivateData() ) m_data( new PrivateData() )
{ {
setAutoLayoutChildren( true );
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Constrained );
connect( this, &QskInputPanel::keySelected,
this, &QskInputPanel::commitKey );
connect( this, &QskInputPanel::predictiveTextSelected,
this, &QskInputPanel::commitPredictiveText );
connect( this, &QskControl::localeChanged,
this, &QskInputPanel::updateLocale );
updateLocale( locale() );
} }
QskInputEngine::~QskInputEngine() QskInputPanel::~QskInputPanel()
{ {
} }
void QskInputEngine::attachInputItem( QQuickItem* item ) void QskInputPanel::attachInputItem( QQuickItem* item )
{ {
if ( item == m_data->inputItem ) if ( item == m_data->inputItem )
return; return;
@ -288,108 +301,65 @@ void QskInputEngine::attachInputItem( QQuickItem* item )
m_data->keyProcessor.reset(); m_data->keyProcessor.reset();
m_data->inputHints = 0; m_data->inputHints = 0;
attachToPanel( item ); attachItem( item );
Qt::InputMethodQueries queries = Qt::ImQueryAll; Qt::InputMethodQueries queries = Qt::ImQueryAll;
queries &= ~Qt::ImEnabled; queries &= ~Qt::ImEnabled;
updateInputPanel( queries ); updateInputPanel( queries );
if ( inputProxy() )
{
// hiding the cursor in item
const QInputMethodEvent::Attribute attribute(
QInputMethodEvent::Cursor, 0, 0, QVariant() );
QInputMethodEvent event( QString(), { attribute } );
QCoreApplication::sendEvent( item, &event );
}
} }
else else
{ {
attachToPanel( nullptr ); attachItem( nullptr );
} }
} }
void QskInputEngine::updateInputPanel( void QskInputPanel::updateInputPanel( Qt::InputMethodQueries queries )
Qt::InputMethodQueries queries )
{ {
auto item = inputItem(); if ( m_data->inputItem == nullptr )
if ( item == nullptr )
return; return;
QInputMethodQueryEvent event( queries ); QInputMethodQueryEvent event( queries );
QCoreApplication::sendEvent( item, &event ); QCoreApplication::sendEvent( m_data->inputItem, &event );
if ( queries & Qt::ImHints ) if ( queries & Qt::ImHints )
{ {
m_data->inputHints = static_cast< Qt::InputMethodHints >( m_data->inputHints = static_cast< Qt::InputMethodHints >(
event.value( Qt::ImHints ).toInt() ); event.value( Qt::ImHints ).toInt() );
updatePanel(); setPredictionEnabled(
m_data->predictor && qskUsePrediction( m_data->inputHints ) );
} }
if ( queries & Qt::ImPreferredLanguage ) if ( queries & Qt::ImPreferredLanguage )
{ {
if ( m_data->panel ) setLocale( event.value( Qt::ImPreferredLanguage ).toLocale() );
{
m_data->panel->setLocale(
event.value( Qt::ImPreferredLanguage ).toLocale() );
}
} }
} }
QskControl* QskInputEngine::panel( bool doCreate ) void QskInputPanel::updateLocale( const QLocale& locale )
{
if ( m_data->panel == nullptr && doCreate )
{
auto panel = createPanel();
connect( panel, &QQuickItem::visibleChanged,
this, &QskInputEngine::activeChanged );
connect( panel, &QskControl::localeChanged,
this, &QskInputEngine::updateLocale );
m_data->panel = panel;
updateLocale( m_data->panel->locale() );
}
return m_data->panel;
}
Qt::Alignment QskInputEngine::panelAlignment() const
{
/*
When we have an input proxy, we don't care if
the input item becomes hidden
*/
return inputProxy() ? Qt::AlignVCenter : Qt::AlignBottom;
}
void QskInputEngine::updateLocale( const QLocale& locale )
{ {
if ( !m_data->hasPredictorLocale || locale != m_data->predictorLocale ) if ( !m_data->hasPredictorLocale || locale != m_data->predictorLocale )
{ {
m_data->hasPredictorLocale = true; m_data->hasPredictorLocale = true;
m_data->predictorLocale = locale; m_data->predictorLocale = locale;
resetPredictor( locale ); resetPredictor( locale );
m_data->keyProcessor.reset(); m_data->keyProcessor.reset();
updatePanel(); }
} }
Q_EMIT localeChanged(); void QskInputPanel::resetPredictor( const QLocale& locale )
}
void QskInputEngine::updatePanel()
{
setPredictionEnabled(
m_data->predictor && qskUsePrediction( m_data->inputHints ) );
}
QQuickItem* QskInputEngine::inputItem() const
{
return m_data->inputItem;
}
QQuickItem* QskInputEngine::inputProxy() const
{
return nullptr;
}
void QskInputEngine::resetPredictor( const QLocale& locale )
{ {
auto predictor = QskInputContext::instance()->textPredictor( locale ); auto predictor = QskInputContext::instance()->textPredictor( locale );
@ -409,49 +379,22 @@ void QskInputEngine::resetPredictor( const QLocale& locale )
} }
} }
m_data->predictor = predictor;
if ( predictor ) if ( predictor )
{ {
if ( predictor->parent() == nullptr ) if ( predictor->parent() == nullptr )
predictor->setParent( this ); predictor->setParent( this );
connect( predictor, &QskTextPredictor::predictionChanged, connect( predictor, &QskTextPredictor::predictionChanged,
this, &QskInputEngine::updatePrediction ); this, &QskInputPanel::updatePrediction );
} }
m_data->predictor = predictor; setPredictionEnabled(
predictor && qskUsePrediction( m_data->inputHints ) );
} }
void QskInputEngine::applyInput( bool success ) void QskInputPanel::commitPredictiveText( int index )
{
auto item = inputItem();
if ( item == nullptr )
return;
if ( success )
{
if ( auto proxy = inputProxy() )
{
const auto value = proxy->property( "text" );
if ( value.canConvert< QString >() )
qskSendReplaceText( item, value.toString() );
}
}
qskSendKey( item, success ? Qt::Key_Return : Qt::Key_Escape );
}
void QskInputEngine::applyText( const QString& text, bool isFinal )
{
qskSendText( qskReceiverItem( this ), text, isFinal );
}
void QskInputEngine::applyKey( int key )
{
// control keys like left/right
qskSendKey( qskReceiverItem( this ), key );
}
void QskInputEngine::commitPredictiveText( int index )
{ {
QString text; QString text;
@ -463,33 +406,57 @@ void QskInputEngine::commitPredictiveText( int index )
m_data->keyProcessor.reset(); m_data->keyProcessor.reset();
showPrediction( QStringList() ); setPrediction( QStringList() );
applyText( text, true );
qskSendText( qskReceiverItem( this ), text, true );
} }
void QskInputEngine::updatePrediction() void QskInputPanel::updatePrediction()
{ {
if ( m_data->predictor ) if ( m_data->predictor )
showPrediction( m_data->predictor->candidates() ); setPrediction( m_data->predictor->candidates() );
} }
void QskInputEngine::setPredictionEnabled( bool on ) QQuickItem* QskInputPanel::inputProxy() const
{ {
Q_UNUSED( on ) return nullptr;
} }
void QskInputEngine::showPrediction( const QStringList& ) QQuickItem* QskInputPanel::inputItem() const
{
return m_data->inputItem;
}
void QskInputPanel::setPrompt( const QString& )
{ {
} }
void QskInputEngine::commitKey( int key ) void QskInputPanel::setPredictionEnabled( bool )
{
}
void QskInputPanel::setPrediction( const QStringList& )
{
}
Qt::Alignment QskInputPanel::alignment() const
{
/*
When we have an input proxy, we don't care if
the input item becomes hidden
*/
return inputProxy() ? Qt::AlignVCenter : Qt::AlignBottom;
}
void QskInputPanel::commitKey( int key )
{ {
int spaceLeft = -1; int spaceLeft = -1;
if ( !( m_data->inputHints & Qt::ImhMultiLine ) ) if ( !( m_data->inputHints & Qt::ImhMultiLine ) )
{ {
QInputMethodQueryEvent event1( Qt::ImMaximumTextLength ); QInputMethodQueryEvent event1( Qt::ImMaximumTextLength );
QCoreApplication::sendEvent( inputItem(), &event1 ); QCoreApplication::sendEvent( m_data->inputItem, &event1 );
const int maxChars = event1.value( Qt::ImMaximumTextLength ).toInt(); const int maxChars = event1.value( Qt::ImMaximumTextLength ).toInt();
if ( maxChars >= 0 ) if ( maxChars >= 0 )
@ -509,30 +476,42 @@ void QskInputEngine::commitKey( int key )
const auto result = m_data->keyProcessor.processKey( const auto result = m_data->keyProcessor.processKey(
key, m_data->inputHints, predictor, spaceLeft ); key, m_data->inputHints, predictor, spaceLeft );
if ( result.key )
{
switch( result.key ) switch( result.key )
{ {
case 0:
{
if ( !result.text.isEmpty() )
{
qskSendText( qskReceiverItem( this ),
result.text, result.isFinal );
}
break;
}
case Qt::Key_Return: case Qt::Key_Return:
{ {
applyInput( true ); if ( auto proxy = inputProxy() )
{
// using input method query instead
const auto value = proxy->property( "text" );
if ( value.canConvert< QString >() )
{
qskSendReplaceText( m_data->inputItem, value.toString() );
}
}
qskSendKey( m_data->inputItem, result.key );
break; break;
} }
case Qt::Key_Escape: case Qt::Key_Escape:
{ {
applyInput( false ); qskSendKey( m_data->inputItem, result.key );
break; break;
} }
default: default:
{ {
applyKey( result.key ); qskSendKey( qskReceiverItem( this ), result.key );
} }
} }
} }
else if ( !result.text.isEmpty() )
{
applyText( result.text, result.isFinal );
}
}
#include "moc_QskInputEngine.cpp" #include "moc_QskInputPanel.cpp"

View File

@ -3,62 +3,55 @@
* This file may be used under the terms of the QSkinny License, Version 1.0 * This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/ *****************************************************************************/
#ifndef QSK_INPUT_ENGINE_H #ifndef QSK_INPUT_PANEL_H
#define QSK_INPUT_ENGINE_H #define QSK_INPUT_PANEL_H
#include "QskGlobal.h" #include "QskGlobal.h"
#include <QObject> #include "QskControl.h"
#include <memory> #include <memory>
class QskTextPredictor; class QskTextPredictor;
class QskControl; class QString;
class QQuickItem; class QStringList;
class QLocale;
class QSK_EXPORT QskInputEngine : public QObject class QSK_EXPORT QskInputPanel : public QskControl
{ {
Q_OBJECT Q_OBJECT
using Inherited = QObject; using Inherited = QskControl;
public: public:
QskInputEngine( QObject* parent = nullptr ); QskInputPanel( QQuickItem* parent = nullptr );
virtual ~QskInputEngine() override; virtual ~QskInputPanel() override;
virtual void attachInputItem( QQuickItem* ); void attachInputItem( QQuickItem* );
virtual void updateInputPanel( Qt::InputMethodQueries ); void updateInputPanel( Qt::InputMethodQueries );
QskControl* panel( bool doCreate );
virtual Qt::Alignment panelAlignment() const;
virtual QQuickItem* inputProxy() const; virtual QQuickItem* inputProxy() const;
virtual QQuickItem* inputItem() const; QQuickItem* inputItem() const;
virtual Qt::Alignment alignment() const;
public Q_SLOTS: public Q_SLOTS:
void commitKey( int keyCode ); void commitKey( int keyCode );
void commitPredictiveText( int index ); void commitPredictiveText( int index );
Q_SIGNALS: Q_SIGNALS:
void activeChanged(); void keySelected( int keyCode );
void localeChanged(); void predictiveTextSelected( int );
public Q_SLOTS:
virtual void setPrompt( const QString& );
virtual void setPrediction( const QStringList& );
virtual void setPredictionEnabled( bool );
protected: protected:
virtual QskControl* createPanel() = 0; virtual void attachItem( QQuickItem* ) = 0;
virtual void attachToPanel( QQuickItem* ) = 0;
virtual void setPredictionEnabled( bool on );
virtual void showPrediction( const QStringList& );
void applyInput( bool success );
void applyText( const QString&, bool isFinal );
void applyKey( int keyCode );
private: private:
void resetPredictor( const QLocale& ); void resetPredictor( const QLocale& );
void updatePrediction(); void updatePrediction();
void updatePanel();
void updateLocale( const QLocale& ); void updateLocale( const QLocale& );
class PrivateData; class PrivateData;

View File

@ -3,7 +3,7 @@
* This file may be used under the terms of the QSkinny License, Version 1.0 * This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/ *****************************************************************************/
#include "QskInputPanel.h" #include "QskInputPanelBox.h"
#include "QskVirtualKeyboard.h" #include "QskVirtualKeyboard.h"
#include "QskInputPredictionBar.h" #include "QskInputPredictionBar.h"
#include "QskTextInput.h" #include "QskTextInput.h"
@ -13,18 +13,17 @@
#include <QString> #include <QString>
#include <QLocale> #include <QLocale>
#include <QPointer> #include <QPointer>
#include <QInputMethodQueryEvent>
namespace namespace
{ {
class TextInputProxy final : public QskTextInput class TextInputProxy final : public QskTextInput
{ {
public: public:
TextInputProxy( QskInputPanel* panel, QQuickItem* parentItem = nullptr ): TextInputProxy( QskInputPanelBox* panelBox, QQuickItem* parentItem = nullptr ):
QskTextInput( parentItem ), QskTextInput( parentItem ),
m_panel( panel ) m_panelBox( panelBox )
{ {
setObjectName( "InputPanelInputProxy" ); setObjectName( "InputBoxProxy" );
setFocusPolicy( Qt::NoFocus ); setFocusPolicy( Qt::NoFocus );
} }
@ -32,10 +31,10 @@ namespace
QskAspect::Subcontrol subControl ) const override QskAspect::Subcontrol subControl ) const override
{ {
if ( subControl == QskTextInput::Panel ) if ( subControl == QskTextInput::Panel )
return m_panel->effectiveSubcontrol( QskInputPanel::ProxyPanel ); return m_panelBox->effectiveSubcontrol( QskInputPanelBox::ProxyPanel );
if ( subControl == QskTextInput::Text ) if ( subControl == QskTextInput::Text )
return m_panel->effectiveSubcontrol( QskInputPanel::ProxyText ); return m_panelBox->effectiveSubcontrol( QskInputPanelBox::ProxyText );
return subControl; return subControl;
} }
@ -50,15 +49,15 @@ namespace
} }
private: private:
QskInputPanel* m_panel; QskInputPanelBox* m_panelBox;
}; };
} }
QSK_SUBCONTROL( QskInputPanel, Panel ) QSK_SUBCONTROL( QskInputPanelBox, Panel )
QSK_SUBCONTROL( QskInputPanel, ProxyPanel ) QSK_SUBCONTROL( QskInputPanelBox, ProxyPanel )
QSK_SUBCONTROL( QskInputPanel, ProxyText ) QSK_SUBCONTROL( QskInputPanelBox, ProxyText )
class QskInputPanel::PrivateData class QskInputPanelBox::PrivateData
{ {
public: public:
QPointer< QQuickItem > inputItem; QPointer< QQuickItem > inputItem;
@ -69,28 +68,25 @@ public:
QskInputPredictionBar* predictionBar; QskInputPredictionBar* predictionBar;
QskVirtualKeyboard* keyboard; QskVirtualKeyboard* keyboard;
int maxChars = -1; QskInputPanelBox::PanelHints panelHints = QskInputPanelBox::InputProxy;
QskInputPanel::PanelHints panelHints = QskInputPanel::InputProxy;
}; };
QskInputPanel::QskInputPanel( QQuickItem* parent ): QskInputPanelBox::QskInputPanelBox( QQuickItem* parent ):
Inherited( parent ), Inherited( parent ),
m_data( new PrivateData() ) m_data( new PrivateData() )
{ {
setAutoLayoutChildren( true ); setAutoLayoutChildren( true );
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Constrained );
m_data->prompt = new QskTextLabel(); m_data->prompt = new QskTextLabel();
m_data->prompt->setVisible( false ); m_data->prompt->setVisible( false );
m_data->inputProxy = new TextInputProxy( this, nullptr ); m_data->inputProxy = new TextInputProxy( this, nullptr );
m_data->inputProxy->setVisible( m_data->inputProxy->setVisible(
m_data->panelHints & QskInputPanel::InputProxy ); m_data->panelHints & QskInputPanelBox::InputProxy );
m_data->predictionBar = new QskInputPredictionBar(); m_data->predictionBar = new QskInputPredictionBar();
m_data->predictionBar->setVisible( m_data->predictionBar->setVisible(
m_data->panelHints & QskInputPanel::Prediction ); m_data->panelHints & QskInputPanelBox::Prediction );
m_data->keyboard = new QskVirtualKeyboard(); m_data->keyboard = new QskVirtualKeyboard();
@ -105,17 +101,17 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
m_data->layout = layout; m_data->layout = layout;
connect( m_data->predictionBar, &QskInputPredictionBar::predictiveTextSelected, connect( m_data->predictionBar, &QskInputPredictionBar::predictiveTextSelected,
this, &QskInputPanel::predictiveTextSelected ); this, &QskInputPanelBox::predictiveTextSelected );
connect( m_data->keyboard, &QskVirtualKeyboard::keySelected, connect( m_data->keyboard, &QskVirtualKeyboard::keySelected,
this, &QskInputPanel::keySelected ); this, &QskInputPanelBox::keySelected );
} }
QskInputPanel::~QskInputPanel() QskInputPanelBox::~QskInputPanelBox()
{ {
} }
void QskInputPanel::setPanelHint( PanelHint hint, bool on ) void QskInputPanelBox::setPanelHint( PanelHint hint, bool on )
{ {
if ( on ) if ( on )
setPanelHints( m_data->panelHints | hint ); setPanelHints( m_data->panelHints | hint );
@ -123,17 +119,17 @@ void QskInputPanel::setPanelHint( PanelHint hint, bool on )
setPanelHints( m_data->panelHints & ~hint ); setPanelHints( m_data->panelHints & ~hint );
} }
void QskInputPanel::setPanelHints( PanelHints hints ) void QskInputPanelBox::setPanelHints( PanelHints hints )
{ {
if ( hints == m_data->panelHints ) if ( hints == m_data->panelHints )
return; return;
m_data->panelHints = hints; m_data->panelHints = hints;
m_data->inputProxy->setVisible( hints & QskInputPanel::InputProxy ); m_data->inputProxy->setVisible( hints & QskInputPanelBox::InputProxy );
m_data->predictionBar->setVisible( hints & QskInputPanel::Prediction ); m_data->predictionBar->setVisible( hints & QskInputPanelBox::Prediction );
const bool showPrompt = ( hints & QskInputPanel::InputProxy ) const bool showPrompt = ( hints & QskInputPanelBox::InputProxy )
&& !m_data->prompt->text().isEmpty(); && !m_data->prompt->text().isEmpty();
m_data->prompt->setVisible( showPrompt ); m_data->prompt->setVisible( showPrompt );
@ -141,12 +137,12 @@ void QskInputPanel::setPanelHints( PanelHints hints )
Q_EMIT panelHintsChanged(); Q_EMIT panelHintsChanged();
} }
QskInputPanel::PanelHints QskInputPanel::panelHints() const QskInputPanelBox::PanelHints QskInputPanelBox::panelHints() const
{ {
return m_data->panelHints; return m_data->panelHints;
} }
void QskInputPanel::attachInputItem( QQuickItem* item ) void QskInputPanelBox::attachInputItem( QQuickItem* item )
{ {
if ( item == m_data->inputItem ) if ( item == m_data->inputItem )
return; return;
@ -155,55 +151,51 @@ void QskInputPanel::attachInputItem( QQuickItem* item )
if ( item ) if ( item )
{ {
if ( m_data->panelHints & QskInputPanel::InputProxy ) if ( m_data->panelHints & QskInputPanelBox::InputProxy )
{ {
m_data->inputProxy->setupFrom( item ); m_data->inputProxy->setupFrom( item );
m_data->inputProxy->setEditing( true ); m_data->inputProxy->setEditing( true );
// hiding the cursor in item
const QInputMethodEvent::Attribute attribute(
QInputMethodEvent::Cursor, 0, 0, QVariant() );
QInputMethodEvent event( QString(), { attribute } );
QCoreApplication::sendEvent( item, &event );
} }
} }
} }
QQuickItem* QskInputPanel::attachedInputItem() const QQuickItem* QskInputPanelBox::attachedInputItem() const
{ {
return m_data->inputItem; return m_data->inputItem;
} }
QQuickItem* QskInputPanel::inputProxy() const QQuickItem* QskInputPanelBox::inputProxy() const
{ {
if ( m_data->panelHints & QskInputPanelBox::InputProxy )
return m_data->inputProxy; return m_data->inputProxy;
return nullptr;
} }
QskAspect::Subcontrol QskInputPanel::effectiveSubcontrol( QskAspect::Subcontrol QskInputPanelBox::effectiveSubcontrol(
QskAspect::Subcontrol subControl ) const QskAspect::Subcontrol subControl ) const
{ {
if( subControl == QskBox::Panel ) if( subControl == QskBox::Panel )
return QskInputPanel::Panel; return QskInputPanelBox::Panel;
#if 1 #if 1
// TODO ... // TODO ...
if( subControl == QskInputPanel::ProxyPanel ) if( subControl == QskInputPanelBox::ProxyPanel )
return QskTextInput::Panel; return QskTextInput::Panel;
if( subControl == QskInputPanel::ProxyText ) if( subControl == QskInputPanelBox::ProxyText )
return QskTextInput::Text; return QskTextInput::Text;
#endif #endif
return subControl; return subControl;
} }
QString QskInputPanel::inputPrompt() const QString QskInputPanelBox::inputPrompt() const
{ {
return m_data->prompt->text(); return m_data->prompt->text();
} }
void QskInputPanel::setInputPrompt( const QString& text ) void QskInputPanelBox::setInputPrompt( const QString& text )
{ {
auto prompt = m_data->prompt; auto prompt = m_data->prompt;
@ -211,19 +203,19 @@ void QskInputPanel::setInputPrompt( const QString& text )
{ {
prompt->setText( text ); prompt->setText( text );
if ( m_data->panelHints & QskInputPanel::InputProxy ) if ( m_data->panelHints & QskInputPanelBox::InputProxy )
prompt->setVisible( !text.isEmpty() ); prompt->setVisible( !text.isEmpty() );
Q_EMIT inputPromptChanged( text ); Q_EMIT inputPromptChanged( text );
} }
} }
void QskInputPanel::setPrediction( const QStringList& prediction ) void QskInputPanelBox::setPrediction( const QStringList& prediction )
{ {
m_data->predictionBar->setPrediction( prediction ); m_data->predictionBar->setPrediction( prediction );
} }
void QskInputPanel::keyPressEvent( QKeyEvent* event ) void QskInputPanelBox::keyPressEvent( QKeyEvent* event )
{ {
int keyCode = -1; int keyCode = -1;
@ -254,4 +246,4 @@ void QskInputPanel::keyPressEvent( QKeyEvent* event )
} }
} }
#include "moc_QskInputPanel.cpp" #include "moc_QskInputPanelBox.cpp"

View File

@ -3,8 +3,8 @@
* This file may be used under the terms of the QSkinny License, Version 1.0 * This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/ *****************************************************************************/
#ifndef QSK_INPUT_PANEL_H #ifndef QSK_INPUT_PANEL_BOX_H
#define QSK_INPUT_PANEL_H #define QSK_INPUT_PANEL_BOX_H
#include "QskGlobal.h" #include "QskGlobal.h"
#include "QskBox.h" #include "QskBox.h"
@ -14,7 +14,7 @@ class QskInputEngine;
class QString; class QString;
class QLocale; class QLocale;
class QSK_EXPORT QskInputPanel : public QskBox class QSK_EXPORT QskInputPanelBox : public QskBox
{ {
Q_OBJECT Q_OBJECT
@ -38,8 +38,8 @@ public:
Q_ENUM( PanelHint ) Q_ENUM( PanelHint )
Q_DECLARE_FLAGS( PanelHints, PanelHint ) Q_DECLARE_FLAGS( PanelHints, PanelHint )
QskInputPanel( QQuickItem* parent = nullptr ); QskInputPanelBox( QQuickItem* parent = nullptr );
virtual ~QskInputPanel() override; virtual ~QskInputPanelBox() override;
void attachInputItem( QQuickItem* ); void attachInputItem( QQuickItem* );
QQuickItem* attachedInputItem() const; QQuickItem* attachedInputItem() const;
@ -75,7 +75,7 @@ private:
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS( QskInputPanel::PanelHints ) Q_DECLARE_OPERATORS_FOR_FLAGS( QskInputPanelBox::PanelHints )
Q_DECLARE_METATYPE( QskInputPanel::PanelHints ) Q_DECLARE_METATYPE( QskInputPanelBox::PanelHints )
#endif #endif

View File

@ -300,15 +300,15 @@ SOURCES += \
SOURCES += \ SOURCES += \
inputpanel/QskTextPredictor.cpp \ inputpanel/QskTextPredictor.cpp \
inputpanel/QskInputContext.cpp \ inputpanel/QskInputContext.cpp \
inputpanel/QskInputEngine.cpp \
inputpanel/QskInputPanel.cpp \ inputpanel/QskInputPanel.cpp \
inputpanel/QskInputPanelBox.cpp \
inputpanel/QskInputPredictionBar.cpp \ inputpanel/QskInputPredictionBar.cpp \
inputpanel/QskVirtualKeyboard.cpp inputpanel/QskVirtualKeyboard.cpp
HEADERS += \ HEADERS += \
inputpanel/QskTextPredictor.h \ inputpanel/QskTextPredictor.h \
inputpanel/QskInputContext.h \ inputpanel/QskInputContext.h \
inputpanel/QskInputEngine.h \
inputpanel/QskInputPanel.h \ inputpanel/QskInputPanel.h \
inputpanel/QskInputPanelBox.h \
inputpanel/QskInputPredictionBar.h \ inputpanel/QskInputPredictionBar.h \
inputpanel/QskVirtualKeyboard.h inputpanel/QskVirtualKeyboard.h