key composition moved to QskInputContext

This commit is contained in:
Uwe Rathmann 2018-04-23 14:06:40 +02:00
parent 4ce1780f90
commit dfe2b875fd
9 changed files with 118 additions and 145 deletions

View File

@ -10,8 +10,8 @@ public:
QVector< QString > candidates; QVector< QString > candidates;
}; };
QskHunspellCompositionModel::QskHunspellCompositionModel( QskInputContext* context ): QskHunspellCompositionModel::QskHunspellCompositionModel( QObject* object ):
Inherited( Words, context ), Inherited( Words, object ),
m_data( new PrivateData() ) m_data( new PrivateData() )
{ {
#if 1 #if 1

View File

@ -14,7 +14,7 @@ class QskHunspellCompositionModel : public QskInputCompositionModel
using Inherited = QskInputCompositionModel; using Inherited = QskInputCompositionModel;
public: public:
QskHunspellCompositionModel( QskInputContext* context ); QskHunspellCompositionModel( QObject* );
virtual ~QskHunspellCompositionModel() override; virtual ~QskHunspellCompositionModel() override;
virtual int candidateCount() const override; virtual int candidateCount() const override;

View File

@ -4,13 +4,10 @@
*****************************************************************************/ *****************************************************************************/
#include "QskInputCompositionModel.h" #include "QskInputCompositionModel.h"
#include "QskInputContext.h"
#include <QInputMethodQueryEvent>
QskInputCompositionModel::QskInputCompositionModel( QskInputCompositionModel::QskInputCompositionModel(
Attributes attributes, QskInputContext* context ): Attributes attributes, QObject* parent ):
QObject( context ), QObject( parent ),
m_attributes( attributes ) m_attributes( attributes )
{ {
} }
@ -19,72 +16,9 @@ QskInputCompositionModel::~QskInputCompositionModel()
{ {
} }
QskInputContext* QskInputCompositionModel::context() const QskInputCompositionModel::Attributes QskInputCompositionModel::attributes() const
{ {
return qobject_cast< QskInputContext* >( parent() ); return m_attributes;
}
void QskInputCompositionModel::composeKey( const QString& text, int spaceLeft )
{
if ( candidateCount() > 0 )
{
m_preedit += text;
requestCandidates( m_preedit );
context()->sendText( m_preedit, false );
return;
}
requestCandidates( m_preedit );
QString txt;
if ( candidateCount() == 0 )
{
txt = m_preedit.left( spaceLeft );
spaceLeft -= txt.length();
}
else
{
txt = candidate( 0 );
--spaceLeft;
}
context()->sendText( txt, true );
m_preedit.clear();
resetCandidates();
if ( spaceLeft )
{
m_preedit = text;
requestCandidates( m_preedit );
if ( candidateCount() > 0 )
{
context()->sendText( m_preedit, false );
}
else
{
context()->sendText( m_preedit, true );
m_preedit.clear();
resetCandidates();
}
}
}
void QskInputCompositionModel::setPreeditText( const QString& text )
{
if ( text != m_preedit )
{
m_preedit = text;
requestCandidates( m_preedit );
}
}
void QskInputCompositionModel::reset()
{
m_preedit.clear();
resetCandidates();
} }
#include "moc_QskInputCompositionModel.cpp" #include "moc_QskInputCompositionModel.cpp"

View File

@ -8,8 +8,6 @@
#include <QObject> #include <QObject>
class QskInputContext;
class QskInputCompositionModel : public QObject class QskInputCompositionModel : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -25,43 +23,22 @@ public:
virtual ~QskInputCompositionModel(); virtual ~QskInputCompositionModel();
void composeKey( const QString& text, int spaceLeft ); virtual void requestCandidates( const QString& preedit ) = 0;
virtual void resetCandidates() = 0;
virtual int candidateCount() const = 0; virtual int candidateCount() const = 0;
virtual QString candidate( int ) const = 0; virtual QString candidate( int ) const = 0;
void reset();
QString preeditText() const;
void setPreeditText( const QString& );
Attributes attributes() const; Attributes attributes() const;
protected:
QskInputCompositionModel( Attributes, QskInputContext* );
virtual void requestCandidates( const QString& preedit ) = 0;
virtual void resetCandidates() = 0;
QskInputContext* context() const;
Q_SIGNALS: Q_SIGNALS:
void candidatesChanged(); void candidatesChanged();
protected:
QskInputCompositionModel( Attributes, QObject* );
private: private:
QString m_preedit;
const Attributes m_attributes; const Attributes m_attributes;
}; };
inline QString QskInputCompositionModel::preeditText() const
{
return m_preedit;
}
inline QskInputCompositionModel::Attributes
QskInputCompositionModel::attributes() const
{
return m_attributes;
}
#endif #endif

View File

@ -49,22 +49,6 @@ static inline QString qskKeyString( int keyCode )
return QChar( keyCode ); return QChar( keyCode );
} }
static inline bool qskIsControlKey( int keyCode )
{
switch ( keyCode )
{
case Qt::Key_Backspace:
case Qt::Key_Muhenkan:
case Qt::Key_Return:
case Qt::Key_Left:
case Qt::Key_Right:
case Qt::Key_Escape:
return true;
}
return false;
}
static void qskSetLocale( QQuickItem* inputPanel, const QLocale& locale ) static void qskSetLocale( QQuickItem* inputPanel, const QLocale& locale )
{ {
if ( auto control = qobject_cast< QskControl* >( inputPanel ) ) if ( auto control = qobject_cast< QskControl* >( inputPanel ) )
@ -145,6 +129,8 @@ public:
QHash< uint, QskInputCompositionModel* > compositionModels; QHash< uint, QskInputCompositionModel* > compositionModels;
QString preedit;
// the input panel is embedded in a window // the input panel is embedded in a window
bool ownsInputPanelWindow : 1; bool ownsInputPanelWindow : 1;
}; };
@ -225,7 +211,7 @@ void QskInputContext::update( Qt::InputMethodQueries queries )
ImhPreferNumbers = 0x8, // default to number keyboard ImhPreferNumbers = 0x8, // default to number keyboard
ImhPreferUppercase = 0x10, // start with shift on ImhPreferUppercase = 0x10, // start with shift on
ImhPreferLowercase = 0x20, // start with shift off ImhPreferLowercase = 0x20, // start with shift off
ImhNoPredictiveText = 0x40, // ignored for now ImhNoPredictiveText = 0x40, // not use predictive text
ImhDate = 0x80, // ignored for now (no date keyboard) ImhDate = 0x80, // ignored for now (no date keyboard)
ImhTime = 0x100, // ignored for know (no time keyboard) ImhTime = 0x100, // ignored for know (no time keyboard)
@ -426,6 +412,12 @@ void QskInputContext::showInputPanel()
} }
update( Qt::ImQueryAll ); update( Qt::ImQueryAll );
#if 1
if ( auto panel = qobject_cast< QskInputPanel* >( m_data->inputPanel ) )
panel->updateInputProxy( m_data->inputItem );
#endif
inputPanel->setVisible( true ); inputPanel->setVisible( true );
#if 0 #if 0
@ -482,6 +474,10 @@ void QskInputContext::hideInputPanel()
} }
qGuiApp->removeEventFilter( this ); qGuiApp->removeEventFilter( this );
m_data->preedit.clear();
if ( auto model = compositionModel() )
model->resetCandidates();
} }
bool QskInputContext::isInputPanelVisible() const bool QskInputContext::isInputPanelVisible() const
@ -612,7 +608,8 @@ void QskInputContext::invokeAction( QInputMethod::Action action, int value )
sendText( text, true ); sendText( text, true );
model->reset(); m_data->preedit.clear();
model->resetCandidates();
} }
break; break;
@ -664,6 +661,7 @@ void QskInputContext::processKey( int key )
if ( !( hints & Qt::ImhHiddenText ) ) if ( !( hints & Qt::ImhHiddenText ) )
model = compositionModel(); model = compositionModel();
auto& preedit = m_data->preedit;
/* /*
First we have to handle the control keys First we have to handle the control keys
*/ */
@ -674,13 +672,12 @@ void QskInputContext::processKey( int key )
{ {
if ( model ) if ( model )
{ {
auto preeditText = model->preeditText(); if ( !preedit.isEmpty() )
if ( !preeditText.isEmpty() )
{ {
preeditText.chop( 1 ); preedit.chop( 1 );
sendText( preeditText, false ); sendText( preedit, false );
model->setPreeditText( preeditText ); model->requestCandidates( preedit );
return; return;
} }
} }
@ -692,13 +689,14 @@ void QskInputContext::processKey( int key )
{ {
if ( model ) if ( model )
{ {
const auto preeditText = model->preeditText(); if ( !preedit.isEmpty() )
if ( !preeditText.isEmpty() )
{ {
if ( spaceLeft ) if ( spaceLeft )
sendText( preeditText.left( spaceLeft ), true ); sendText( preedit.left( spaceLeft ), true );
preedit.clear();
model->resetCandidates();
model->reset();
return; return;
} }
} }
@ -715,14 +713,14 @@ void QskInputContext::processKey( int key )
{ {
if ( model ) if ( model )
{ {
auto preeditText = model->preeditText(); if ( !preedit.isEmpty() && spaceLeft)
if ( !preeditText.isEmpty() && spaceLeft)
{ {
preeditText = preeditText.left( spaceLeft ); preedit = preedit.left( spaceLeft );
sendText( preeditText, true ); sendText( preedit, true );
spaceLeft -= preeditText.length(); spaceLeft -= preedit.length();
model->reset(); preedit.clear();
model->resetCandidates();
} }
} }
@ -741,7 +739,19 @@ void QskInputContext::processKey( int key )
if ( model ) if ( model )
{ {
model->composeKey( text, spaceLeft ); preedit += text;
model->requestCandidates( preedit );
if ( model->candidateCount() > 0 )
{
sendText( preedit, false );
}
else
{
sendText( preedit.left( spaceLeft ), true );
preedit.clear();
}
} }
else else
{ {

View File

@ -17,8 +17,8 @@ public:
QStringList candidates; QStringList candidates;
}; };
QskPinyinCompositionModel::QskPinyinCompositionModel( QskInputContext* context ): QskPinyinCompositionModel::QskPinyinCompositionModel( QObject* parent ):
Inherited( Attributes(), context ), Inherited( Attributes(), parent ),
m_data( new PrivateData ) m_data( new PrivateData )
{ {
#if 1 #if 1

View File

@ -14,7 +14,7 @@ class QskPinyinCompositionModel : public QskInputCompositionModel
using Inherited = QskInputCompositionModel; using Inherited = QskInputCompositionModel;
public: public:
QskPinyinCompositionModel( QskInputContext* ); QskPinyinCompositionModel( QObject* );
virtual ~QskPinyinCompositionModel() override; virtual ~QskPinyinCompositionModel() override;
virtual int candidateCount() const override; virtual int candidateCount() const override;

View File

@ -125,7 +125,7 @@ public:
QskLinearBox* layout; QskLinearBox* layout;
QskTextLabel* prompt; QskTextLabel* prompt;
TextInput* textInput; TextInput* inputProxy;
QskInputSuggestionBar* suggestionBar; QskInputSuggestionBar* suggestionBar;
QskVirtualKeyboard* keyboard; QskVirtualKeyboard* keyboard;
@ -142,8 +142,8 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
m_data->prompt = new QskTextLabel(); m_data->prompt = new QskTextLabel();
m_data->prompt->setVisible( false ); m_data->prompt->setVisible( false );
m_data->textInput = new TextInput(); m_data->inputProxy = new TextInput();
m_data->textInput->setVisible( m_data->hasInputProxy ); m_data->inputProxy->setVisible( m_data->hasInputProxy );
m_data->suggestionBar = new QskInputSuggestionBar(); m_data->suggestionBar = new QskInputSuggestionBar();
m_data->suggestionBar->setVisible( false ); m_data->suggestionBar->setVisible( false );
@ -153,7 +153,7 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
auto layout = new QskLinearBox( Qt::Vertical, this ); auto layout = new QskLinearBox( Qt::Vertical, this );
layout->addItem( m_data->prompt, Qt::AlignLeft | Qt::AlignHCenter ); layout->addItem( m_data->prompt, Qt::AlignLeft | Qt::AlignHCenter );
layout->addItem( m_data->textInput, Qt::AlignLeft | Qt::AlignHCenter ); layout->addItem( m_data->inputProxy, Qt::AlignLeft | Qt::AlignHCenter );
layout->addStretch( 10 ); layout->addStretch( 10 );
layout->addItem( m_data->suggestionBar ); layout->addItem( m_data->suggestionBar );
layout->addItem( m_data->keyboard ); layout->addItem( m_data->keyboard );
@ -199,7 +199,7 @@ qreal QskInputPanel::heightForWidth( qreal width ) const
qreal height = m_data->keyboard->heightForWidth( width ); qreal height = m_data->keyboard->heightForWidth( width );
const QskControl* controls[] = const QskControl* controls[] =
{ m_data->prompt, m_data->textInput, m_data->suggestionBar }; { m_data->prompt, m_data->inputProxy, m_data->suggestionBar };
for ( auto control : controls ) for ( auto control : controls )
{ {
@ -228,7 +228,7 @@ qreal QskInputPanel::widthForHeight( qreal height ) const
height -= padding.top() + padding.bottom(); height -= padding.top() + padding.bottom();
const QskControl* controls[] = const QskControl* controls[] =
{ m_data->prompt, m_data->textInput, m_data->suggestionBar }; { m_data->prompt, m_data->inputProxy, m_data->suggestionBar };
for ( auto control : controls ) for ( auto control : controls )
{ {
@ -278,7 +278,7 @@ void QskInputPanel::setInputProxy( bool on )
return; return;
m_data->hasInputProxy = on; m_data->hasInputProxy = on;
m_data->textInput->setVisible( on ); m_data->inputProxy->setVisible( on );
auto prompt = m_data->prompt; auto prompt = m_data->prompt;
@ -288,6 +288,56 @@ void QskInputPanel::setInputProxy( bool on )
prompt->setVisible( false ); prompt->setVisible( false );
} }
void QskInputPanel::updateInputProxy( const QQuickItem* inputItem )
{
if ( inputItem == nullptr )
return;
QInputMethodQueryEvent event( Qt::ImQueryAll );
QCoreApplication::sendEvent( const_cast< QQuickItem* >( inputItem ), &event );
const auto proxy = m_data->inputProxy;
if ( event.queries() & Qt::ImHints )
{
const auto hints = static_cast< Qt::InputMethodHints >(
event.value( Qt::ImHints ).toInt() );
const auto echoMode = ( hints & Qt::ImhHiddenText )
? QskTextInput::PasswordEchoOnEdit : QskTextInput::Normal;
proxy->setEchoMode( echoMode );
}
if ( event.queries() & Qt::ImSurroundingText )
{
const auto text = event.value( Qt::ImSurroundingText ).toString();
proxy->setText( text );
}
if ( event.queries() & Qt::ImCursorPosition )
{
const auto pos = event.value( Qt::ImCursorPosition ).toInt();
proxy->setCursorPosition( pos );
}
#if 0
if ( event.queries() & Qt::ImCurrentSelection )
{
const auto text = event.value( Qt::ImCursorPosition ).toString();
if ( !text.isEmpty() )
{
}
}
#endif
if ( event.queries() & Qt::ImMaximumTextLength )
{
const auto length = event.value( Qt::ImMaximumTextLength ).toInt();
proxy->setMaxLength( length );
}
}
bool QskInputPanel::isCandidatesEnabled() const bool QskInputPanel::isCandidatesEnabled() const
{ {
return m_data->suggestionBar->isVisible(); return m_data->suggestionBar->isVisible();

View File

@ -52,6 +52,8 @@ public:
virtual QskAspect::Subcontrol effectiveSubcontrol( virtual QskAspect::Subcontrol effectiveSubcontrol(
QskAspect::Subcontrol ) const override; QskAspect::Subcontrol ) const override;
void updateInputProxy( const QQuickItem* );
Q_SIGNALS: Q_SIGNALS:
void inputProxyChanged( bool ); void inputProxyChanged( bool );
void inputPromptChanged( const QString& ); void inputPromptChanged( const QString& );