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;
};
QskHunspellCompositionModel::QskHunspellCompositionModel( QskInputContext* context ):
Inherited( Words, context ),
QskHunspellCompositionModel::QskHunspellCompositionModel( QObject* object ):
Inherited( Words, object ),
m_data( new PrivateData() )
{
#if 1

View File

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

View File

@ -4,13 +4,10 @@
*****************************************************************************/
#include "QskInputCompositionModel.h"
#include "QskInputContext.h"
#include <QInputMethodQueryEvent>
QskInputCompositionModel::QskInputCompositionModel(
Attributes attributes, QskInputContext* context ):
QObject( context ),
Attributes attributes, QObject* parent ):
QObject( parent ),
m_attributes( attributes )
{
}
@ -19,72 +16,9 @@ QskInputCompositionModel::~QskInputCompositionModel()
{
}
QskInputContext* QskInputCompositionModel::context() const
QskInputCompositionModel::Attributes QskInputCompositionModel::attributes() const
{
return qobject_cast< QskInputContext* >( parent() );
}
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();
return m_attributes;
}
#include "moc_QskInputCompositionModel.cpp"

View File

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

View File

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

View File

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

View File

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

View File

@ -125,7 +125,7 @@ public:
QskLinearBox* layout;
QskTextLabel* prompt;
TextInput* textInput;
TextInput* inputProxy;
QskInputSuggestionBar* suggestionBar;
QskVirtualKeyboard* keyboard;
@ -142,8 +142,8 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
m_data->prompt = new QskTextLabel();
m_data->prompt->setVisible( false );
m_data->textInput = new TextInput();
m_data->textInput->setVisible( m_data->hasInputProxy );
m_data->inputProxy = new TextInput();
m_data->inputProxy->setVisible( m_data->hasInputProxy );
m_data->suggestionBar = new QskInputSuggestionBar();
m_data->suggestionBar->setVisible( false );
@ -153,7 +153,7 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
auto layout = new QskLinearBox( Qt::Vertical, this );
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->addItem( m_data->suggestionBar );
layout->addItem( m_data->keyboard );
@ -199,7 +199,7 @@ qreal QskInputPanel::heightForWidth( qreal width ) const
qreal height = m_data->keyboard->heightForWidth( width );
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 )
{
@ -228,7 +228,7 @@ qreal QskInputPanel::widthForHeight( qreal height ) const
height -= padding.top() + padding.bottom();
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 )
{
@ -278,7 +278,7 @@ void QskInputPanel::setInputProxy( bool on )
return;
m_data->hasInputProxy = on;
m_data->textInput->setVisible( on );
m_data->inputProxy->setVisible( on );
auto prompt = m_data->prompt;
@ -288,6 +288,56 @@ void QskInputPanel::setInputProxy( bool on )
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
{
return m_data->suggestionBar->isVisible();

View File

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