simplifying the inputcontext stuff

This commit is contained in:
Uwe Rathmann 2018-04-02 17:01:04 +02:00
parent d947fb3999
commit 0a0acb5e27
5 changed files with 94 additions and 101 deletions

View File

@ -10,9 +10,7 @@
#include <QTextCharFormat> #include <QTextCharFormat>
#include <QWindow> #include <QWindow>
#include <unordered_map> static inline QString qskKeyString( int code )
static QString qskKeyString( int code )
{ {
// Special case entry codes here, else default to the symbol // Special case entry codes here, else default to the symbol
switch ( code ) switch ( code )
@ -38,6 +36,15 @@ static QString qskKeyString( int code )
return QChar( code ); return QChar( code );
} }
static inline void qskSendKeyEvents( QObject* receiver, int key )
{
QKeyEvent keyPress( QEvent::KeyPress, key, Qt::NoModifier );
QCoreApplication::sendEvent( receiver, &keyPress );
QKeyEvent keyRelease( QEvent::KeyRelease, key, Qt::NoModifier );
QCoreApplication::sendEvent( receiver, &keyRelease );
}
class QskInputCompositionModel::PrivateData class QskInputCompositionModel::PrivateData
{ {
public: public:
@ -55,14 +62,6 @@ public:
int groupIndex; int groupIndex;
}; };
static inline void sendCompositionEvent( QInputMethodEvent* e )
{
if( auto focusObject = QGuiApplication::focusObject() )
{
QCoreApplication::sendEvent( focusObject, e );
}
}
QskInputCompositionModel::QskInputCompositionModel(): QskInputCompositionModel::QskInputCompositionModel():
m_data( new PrivateData ) m_data( new PrivateData )
{ {
@ -148,20 +147,12 @@ void QskInputCompositionModel::composeKey( Qt::Key key )
{ {
commit( qskKeyString( key ) ); commit( qskKeyString( key ) );
} }
#if 0
else else
{ {
auto focusWindow = QGuiApplication::focusWindow(); if( auto focusWindow = QGuiApplication::focusWindow() )
qskSendKeyEvents( focusWindow, Qt::Key_Return );
if( focusWindow )
{
QKeyEvent keyPress( QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier );
QKeyEvent keyRelease( QEvent::KeyRelease, Qt::Key_Return, Qt::NoModifier ); QCoreApplication::sendEvent( focusWindow, &keyPress );
QCoreApplication::sendEvent( focusWindow, &keyRelease );
} }
}
#endif
return; return;
} }
@ -218,8 +209,9 @@ void QskInputCompositionModel::composeKey( Qt::Key key )
} }
m_data->preeditAttributes.first().length = displayPreedit.length(); m_data->preeditAttributes.first().length = displayPreedit.length();
QInputMethodEvent e( displayPreedit, m_data->preeditAttributes );
sendCompositionEvent( &e ); QInputMethodEvent event( displayPreedit, m_data->preeditAttributes );
sendCompositionEvent( &event );
} }
void QskInputCompositionModel::clearPreedit() void QskInputCompositionModel::clearPreedit()
@ -250,9 +242,10 @@ QString QskInputCompositionModel::polishPreedit( const QString& preedit )
void QskInputCompositionModel::commit( const QString& text ) void QskInputCompositionModel::commit( const QString& text )
{ {
QInputMethodEvent e( QString(), { } ); QInputMethodEvent event( QString(), { } );
e.setCommitString( text ); event.setCommitString( text );
sendCompositionEvent( &e ); sendCompositionEvent( &event );
m_data->preedit.clear(); m_data->preedit.clear();
polishPreedit( m_data->preedit ); polishPreedit( m_data->preedit );
} }
@ -264,27 +257,24 @@ void QskInputCompositionModel::commitCandidate( int index )
void QskInputCompositionModel::backspace() void QskInputCompositionModel::backspace()
{ {
if ( !m_data->inputItem ) if ( m_data->inputItem == nullptr )
return; return;
if ( !m_data->preedit.isEmpty() ) if ( !m_data->preedit.isEmpty() )
{ {
m_data->preedit.chop( 1 ); m_data->preedit.chop( 1 );
const QString displayText = polishPreedit( m_data->preedit );
m_data->preeditAttributes.first().length = displayText.length();
QInputMethodEvent event( displayText, m_data->preeditAttributes );
sendCompositionEvent( &event );
} }
else else
{ {
// Backspace one character only if preedit was inactive // Backspace one character only if preedit was inactive
QKeyEvent keyPress( QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier ); qskSendKeyEvents( m_data->inputItem, Qt::Key_Backspace );
QKeyEvent keyRelease( QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier );
QCoreApplication::sendEvent( m_data->inputItem, &keyPress );
QCoreApplication::sendEvent( m_data->inputItem, &keyRelease );
return;
} }
const QString displayText = polishPreedit( m_data->preedit );
m_data->preeditAttributes.first().length = displayText.length();
QInputMethodEvent e( displayText, m_data->preeditAttributes );
sendCompositionEvent( &e );
} }
void QskInputCompositionModel::moveCursor( Qt::Key key ) void QskInputCompositionModel::moveCursor( Qt::Key key )
@ -339,8 +329,9 @@ void QskInputCompositionModel::setGroupIndex( int groupIndex )
m_data->groupIndex = groupIndex; m_data->groupIndex = groupIndex;
const QString displayText = polishPreedit( m_data->preedit ); const QString displayText = polishPreedit( m_data->preedit );
m_data->preeditAttributes.first().length = displayText.length(); m_data->preeditAttributes.first().length = displayText.length();
QInputMethodEvent e( displayText, m_data->preeditAttributes );
sendCompositionEvent( &e ); QInputMethodEvent event( displayText, m_data->preeditAttributes );
sendCompositionEvent( &event );
} }
QVector< Qt::Key > QskInputCompositionModel::groups() const QVector< Qt::Key > QskInputCompositionModel::groups() const

View File

@ -23,7 +23,7 @@ public:
QPointer< QQuickItem > inputItem; QPointer< QQuickItem > inputItem;
QPointer< QskVirtualKeyboard > inputPanel; QPointer< QskVirtualKeyboard > inputPanel;
QskInputCompositionModel* compositionModel; QskInputCompositionModel* compositionModel;
QHash< QLocale, QskInputCompositionModel* > inputModels; QHash< QLocale, QskInputCompositionModel* > compositionModels;
}; };
QskInputContext::QskInputContext() : QskInputContext::QskInputContext() :
@ -31,17 +31,17 @@ QskInputContext::QskInputContext() :
{ {
m_data->compositionModel = new QskInputCompositionModel(); m_data->compositionModel = new QskInputCompositionModel();
connect( m_data->compositionModel, &QskInputCompositionModel::candidatesChanged,
this, &QskInputContext::handleCandidatesChanged );
connect( qskSetup, &QskSetup::inputPanelChanged, connect( qskSetup, &QskSetup::inputPanelChanged,
this, &QskInputContext::setInputPanel ); this, &QskInputContext::setInputPanel );
#if 1
setCompositionModel( QLocale::Chinese, new QskPinyinCompositionModel() );
#endif
setInputPanel( qskSetup->inputPanel() ); setInputPanel( qskSetup->inputPanel() );
QskPinyinCompositionModel* pinyinModel = new QskPinyinCompositionModel;
// see also: QskVirtualKeyboard::registerCompositionModelForLocale()
inputMethodRegistered( QLocale::Chinese, pinyinModel );
// We could connect candidatesChanged() here, but we don't emit
// the signal in the normal composition model anyhow
} }
QskInputContext::~QskInputContext() QskInputContext::~QskInputContext()
@ -49,7 +49,7 @@ QskInputContext::~QskInputContext()
if ( m_data->inputPanel ) if ( m_data->inputPanel )
delete m_data->inputPanel; delete m_data->inputPanel;
qDeleteAll( m_data->inputModels ); qDeleteAll( m_data->compositionModels );
} }
bool QskInputContext::isValid() const bool QskInputContext::isValid() const
@ -249,18 +249,44 @@ void QskInputContext::setFocusObject( QObject* focusObject )
update( Qt::InputMethodQuery( Qt::ImQueryAll & ~Qt::ImEnabled ) ); update( Qt::InputMethodQuery( Qt::ImQueryAll & ~Qt::ImEnabled ) );
} }
void QskInputContext::inputMethodRegistered( void QskInputContext::setCompositionModel(
const QLocale& locale, QskInputCompositionModel* model ) const QLocale& locale, QskInputCompositionModel* model )
{ {
if ( auto oldModel = m_data->inputModels.value( locale, nullptr ) ) auto& models = m_data->compositionModels;
oldModel->deleteLater();
m_data->inputModels.insert( locale, model ); if ( model )
{
const auto it = models.find( locale );
if ( it != models.end() )
{
if ( it.value() == model )
return;
delete it.value();
*it = model;
}
else
{
models.insert( locale, model );
}
connect( model, &QskInputCompositionModel::candidatesChanged,
this, &QskInputContext::handleCandidatesChanged );
}
else
{
const auto it = models.find( locale );
if ( it != models.end() )
{
delete it.value();
models.erase( it );
}
}
} }
QskInputCompositionModel* QskInputContext::compositionModel() const QskInputCompositionModel* QskInputContext::compositionModel() const
{ {
return m_data->inputModels.value( locale(), m_data->compositionModel ); return m_data->compositionModels.value( locale(), m_data->compositionModel );
} }
void QskInputContext::invokeAction( QInputMethod::Action action, int cursorPosition ) void QskInputContext::invokeAction( QInputMethod::Action action, int cursorPosition )
@ -282,6 +308,7 @@ void QskInputContext::invokeAction( QInputMethod::Action action, int cursorPosit
case QskVirtualKeyboard::SelectCandidate: case QskVirtualKeyboard::SelectCandidate:
{ {
model->commitCandidate( cursorPosition ); model->commitCandidate( cursorPosition );
if ( m_data->inputPanel ) if ( m_data->inputPanel )
m_data->inputPanel->setPreeditCandidates( QVector< QString >() ); m_data->inputPanel->setPreeditCandidates( QVector< QString >() );
@ -290,19 +317,19 @@ void QskInputContext::invokeAction( QInputMethod::Action action, int cursorPosit
} }
} }
void QskInputContext::emitAnimatingChanged()
{
QPlatformInputContext::emitAnimatingChanged();
}
void QskInputContext::handleCandidatesChanged() void QskInputContext::handleCandidatesChanged()
{ {
const auto model = compositionModel(); const auto model = compositionModel();
if ( model == nullptr || m_data->inputPanel == nullptr )
return;
QVector< QString > candidates( model->candidateCount() ); const auto count = model->candidateCount();
for( int i = 0; i < candidates.length(); ++i ) QVector< QString > candidates;
candidates[i] = model->candidate( i ); candidates.reserve( count );
for( int i = 0; i < count; i++ )
candidates += model->candidate( i );
m_data->inputPanel->setPreeditCandidates( candidates ); m_data->inputPanel->setPreeditCandidates( candidates );
} }

View File

@ -38,11 +38,11 @@ public:
virtual QLocale locale() const override; virtual QLocale locale() const override;
void setCompositionModel( const QLocale&, QskInputCompositionModel* );
private Q_SLOTS: private Q_SLOTS:
void emitAnimatingChanged();
void handleCandidatesChanged(); void handleCandidatesChanged();
void setInputPanel( QskVirtualKeyboard* ); void setInputPanel( QskVirtualKeyboard* );
void inputMethodRegistered( const QLocale&, QskInputCompositionModel* );
private: private:
QskInputCompositionModel* compositionModel() const; QskInputCompositionModel* compositionModel() const;

View File

@ -174,7 +174,6 @@ QSK_SUBCONTROL( QskVirtualKeyboard, Panel )
QSK_SUBCONTROL( QskVirtualKeyboardButton, Panel ) QSK_SUBCONTROL( QskVirtualKeyboardButton, Panel )
QSK_SUBCONTROL( QskVirtualKeyboardButton, Text ) QSK_SUBCONTROL( QskVirtualKeyboardButton, Text )
QSK_SUBCONTROL( QskVirtualKeyboardButton, TextCancelButton )
QskVirtualKeyboardButton::QskVirtualKeyboardButton( QskVirtualKeyboardButton::QskVirtualKeyboardButton(
int keyIndex, QskVirtualKeyboard* inputPanel, QQuickItem* parent ) : int keyIndex, QskVirtualKeyboard* inputPanel, QQuickItem* parent ) :
@ -214,7 +213,7 @@ QskAspect::Subcontrol QskVirtualKeyboardButton::effectiveSubcontrol(
return QskVirtualKeyboardButton::Panel; return QskVirtualKeyboardButton::Panel;
if( subControl == QskPushButton::Text ) if( subControl == QskPushButton::Text )
return isCancelButton() ? TextCancelButton : Text; return QskVirtualKeyboardButton::Text;
return subControl; return subControl;
} }
@ -239,13 +238,6 @@ void QskVirtualKeyboardButton::updateText()
} }
} }
bool QskVirtualKeyboardButton::isCancelButton() const
{
auto keyData = m_inputPanel->keyDataAt( m_keyIndex );
bool isCancel = ( keyData.key == 0x2716 );
return isCancel;
}
class QskVirtualKeyboard::PrivateData class QskVirtualKeyboard::PrivateData
{ {
public: public:
@ -567,12 +559,6 @@ void QskVirtualKeyboard::setCandidateOffset( int candidateOffset )
} }
} }
void QskVirtualKeyboard::registerCompositionModelForLocale(
const QLocale& locale, QskInputCompositionModel* model )
{
Q_EMIT inputMethodRegistered( locale, model );
}
void QskVirtualKeyboard::geometryChanged( void QskVirtualKeyboard::geometryChanged(
const QRectF& newGeometry, const QRectF& oldGeometry ) const QRectF& newGeometry, const QRectF& oldGeometry )
{ {
@ -685,11 +671,6 @@ void QskVirtualKeyboard::handleKey( int keyIndex )
: SpecialCharacterMode ) ); : SpecialCharacterMode ) );
return; return;
// This is (one of) the cancel symbol, not Qt::Key_Cancel:
case Qt::Key( 10006 ):
Q_EMIT cancelPressed();
return;
default: default:
break; break;
} }

View File

@ -44,11 +44,13 @@ class QSK_EXPORT QskVirtualKeyboardButton : public QskPushButton
using Inherited = QskPushButton; using Inherited = QskPushButton;
public: public:
QSK_SUBCONTROLS( Panel, Text, TextCancelButton ) QSK_SUBCONTROLS( Panel, Text )
QskVirtualKeyboardButton( int keyIndex, QskVirtualKeyboard* inputPanel, QQuickItem* parent = nullptr ); QskVirtualKeyboardButton( int keyIndex,
QskVirtualKeyboard*, QQuickItem* parent = nullptr );
virtual QskAspect::Subcontrol effectiveSubcontrol( QskAspect::Subcontrol subControl ) const override; virtual QskAspect::Subcontrol effectiveSubcontrol(
QskAspect::Subcontrol ) const override;
int keyIndex() const; int keyIndex() const;
@ -56,8 +58,6 @@ public Q_SLOTS:
void updateText(); void updateText();
private: private:
bool isCancelButton() const;
const int m_keyIndex; const int m_keyIndex;
QskVirtualKeyboard* m_inputPanel; QskVirtualKeyboard* m_inputPanel;
}; };
@ -112,11 +112,12 @@ public:
QskVirtualKeyboard( QQuickItem* parent = nullptr ); QskVirtualKeyboard( QQuickItem* parent = nullptr );
virtual ~QskVirtualKeyboard() override; virtual ~QskVirtualKeyboard() override;
virtual QskAspect::Subcontrol effectiveSubcontrol( QskAspect::Subcontrol subControl ) const override; virtual QskAspect::Subcontrol effectiveSubcontrol(
QskAspect::Subcontrol ) const override;
void updateLocale( const QLocale& locale ); void updateLocale( const QLocale& );
void setMode( QskVirtualKeyboard::Mode index ); void setMode( QskVirtualKeyboard::Mode );
Mode mode() const; Mode mode() const;
const KeyDataSet& keyData( QskVirtualKeyboard::Mode = CurrentMode ) const; const KeyDataSet& keyData( QskVirtualKeyboard::Mode = CurrentMode ) const;
@ -124,9 +125,6 @@ public:
QString textForKey( int ) const; QString textForKey( int ) const;
QString displayLanguageName() const; QString displayLanguageName() const;
// takes ownership:
void registerCompositionModelForLocale( const QLocale&, QskInputCompositionModel* );
void handleKey( int keyIndex ); void handleKey( int keyIndex );
KeyData& keyDataAt( int ) const; KeyData& keyDataAt( int ) const;
QString currentTextForKeyIndex( int keyIndex ) const; QString currentTextForKeyIndex( int keyIndex ) const;
@ -156,11 +154,7 @@ private:
Q_SIGNALS: Q_SIGNALS:
void keyboardRectChanged(); void keyboardRectChanged();
void displayLanguageNameChanged(); void displayLanguageNameChanged();
void inputMethodRegistered( const QLocale& locale, QskInputCompositionModel* model ); void modeChanged( QskVirtualKeyboard::Mode );
void inputMethodEventReceived( QInputMethodEvent* inputMethodEvent );
void keyEventReceived( QKeyEvent* keyEvent );
void modeChanged( QskVirtualKeyboard::Mode mode );
void cancelPressed();
private: private:
class PrivateData; class PrivateData;