From 11dd05ff4987768985ceb3733889099e7ed52245 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 1 Jun 2018 17:26:22 +0200 Subject: [PATCH] code moved to QskInputManager --- src/inputpanel/QskInputManager.cpp | 131 +++++++++++++++++++++++- src/inputpanel/QskInputManager.h | 7 ++ src/inputpanel/QskInputPanel.cpp | 157 ++++++++--------------------- src/inputpanel/QskInputPanel.h | 7 +- src/src.pro | 2 + 5 files changed, 189 insertions(+), 115 deletions(-) diff --git a/src/inputpanel/QskInputManager.cpp b/src/inputpanel/QskInputManager.cpp index 72a5fe5f..5b5241eb 100644 --- a/src/inputpanel/QskInputManager.cpp +++ b/src/inputpanel/QskInputManager.cpp @@ -7,7 +7,65 @@ #include "QskInputPanel.h" #include "QskInputEngine.h" #include "QskInputContext.h" + #include +#include + +static inline void qskSendReplaceText( QQuickItem* receiver, const QString& text ) +{ + if ( receiver == nullptr ) + return; + + QInputMethodEvent::Attribute attribute( + QInputMethodEvent::Selection, 0, 32767, QVariant() ); + + QInputMethodEvent event1( QString(), { attribute } ); + QCoreApplication::sendEvent( receiver, &event1 ); + + QInputMethodEvent event2; + event2.setCommitString( text ); + + QCoreApplication::sendEvent( receiver, &event2 ); +} + +static inline void qskSendText( QQuickItem* receiver, + const QString& text, bool isFinal ) +{ + if ( receiver == nullptr ) + return; + + if ( isFinal ) + { + QInputMethodEvent event; + event.setCommitString( text ); + + QCoreApplication::sendEvent( receiver, &event ); + } + else + { + QTextCharFormat format; + format.setFontUnderline( true ); + + const QInputMethodEvent::Attribute attribute( + QInputMethodEvent::TextFormat, 0, text.length(), format ); + + QInputMethodEvent event( text, { attribute } ); + + QCoreApplication::sendEvent( receiver, &event ); + } +} + +static inline void qskSendKey( QQuickItem* receiver, int key ) +{ + if ( receiver == nullptr ) + return; + + QKeyEvent keyPress( QEvent::KeyPress, key, Qt::NoModifier ); + QCoreApplication::sendEvent( receiver, &keyPress ); + + QKeyEvent keyRelease( QEvent::KeyRelease, key, Qt::NoModifier ); + QCoreApplication::sendEvent( receiver, &keyRelease ); +} class QskInputManager::PrivateData { @@ -92,7 +150,18 @@ Qt::Alignment QskInputManager::panelAlignment() const QskControl* QskInputManager::createPanel() { - return new QskInputPanel(); + auto panel = new QskInputPanel(); + + connect( panel, &QskInputPanel::done, + this, &QskInputManager::applyInput, Qt::UniqueConnection ); + + connect( panel, &QskInputPanel::textEntered, + this, &QskInputManager::applyText, Qt::UniqueConnection ); + + connect( panel, &QskInputPanel::keyEntered, + this, &QskInputManager::applyKey, Qt::UniqueConnection ); + + return panel; } QskInputEngine* QskInputManager::createEngine() @@ -136,3 +205,63 @@ void QskInputManager::updatePredictor() m_data->engine->setPredictor( context->textPredictor( locale ) ); } } + +QQuickItem* QskInputManager::inputItem() const +{ + if ( auto panel = qobject_cast< QskInputPanel* >( m_data->panel ) ) + return panel->attachedInputItem(); + + return nullptr; +} + +QQuickItem* QskInputManager::inputProxy() const +{ + if ( auto panel = qobject_cast< QskInputPanel* >( m_data->panel ) ) + { + if ( panel->hasInputProxy() ) + return panel->inputProxy(); + } + + return nullptr; +} + +void QskInputManager::applyInput( bool success ) +{ + auto item = inputItem(); + if ( item == nullptr ) + return; + + if ( success ) + { + if ( auto proxy = inputProxy() ) + { + const auto value = proxy->property( "text" ); + if ( value.canConvert() ) + qskSendReplaceText( item, value.toString() ); + } + } + + qskSendKey( item, success ? Qt::Key_Return : Qt::Key_Escape ); +} + +void QskInputManager::applyText( const QString& text, bool isFinal ) +{ + auto item = inputProxy(); + if ( item == nullptr ) + item = inputItem(); + + qskSendText( item, text, isFinal ); +} + +void QskInputManager::applyKey( int key ) +{ + // control keys like left/right + + auto item = inputProxy(); + if ( item == nullptr ) + item = inputItem(); + + qskSendKey( item, key ); +} + +#include "moc_QskInputManager.cpp" diff --git a/src/inputpanel/QskInputManager.h b/src/inputpanel/QskInputManager.h index fbbcb907..f818eb0d 100644 --- a/src/inputpanel/QskInputManager.h +++ b/src/inputpanel/QskInputManager.h @@ -31,6 +31,9 @@ public: QskControl* panel( bool doCreate ); virtual Qt::Alignment panelAlignment() const; + virtual QQuickItem* inputProxy() const; + virtual QQuickItem* inputItem() const; + protected: virtual QskControl* createPanel(); virtual QskInputEngine* createEngine(); @@ -39,6 +42,10 @@ protected: void updateEngine( const QLocale& ); private: + void applyInput( bool success ); + void applyText( const QString&, bool isFinal ); + void applyKey( int keyCode ); + class PrivateData; std::unique_ptr< PrivateData > m_data; }; diff --git a/src/inputpanel/QskInputPanel.cpp b/src/inputpanel/QskInputPanel.cpp index 70be6fb5..1b6344f2 100644 --- a/src/inputpanel/QskInputPanel.cpp +++ b/src/inputpanel/QskInputPanel.cpp @@ -13,100 +13,8 @@ #include #include -#include #include #include -#include - -static inline void qskSendReplaceText( QQuickItem* receiver, const QString& text ) -{ - if ( receiver == nullptr ) - return; - - QInputMethodEvent::Attribute attribute( - QInputMethodEvent::Selection, 0, 32767, QVariant() ); - - QInputMethodEvent event1( QString(), { attribute } ); - QCoreApplication::sendEvent( receiver, &event1 ); - - QInputMethodEvent event2; - event2.setCommitString( text ); - - QCoreApplication::sendEvent( receiver, &event2 ); -} - -static inline void qskSendText( QQuickItem* receiver, - const QString& text, bool isFinal ) -{ - if ( receiver == nullptr ) - return; - - if ( isFinal ) - { - QInputMethodEvent event; - event.setCommitString( text ); - - QCoreApplication::sendEvent( receiver, &event ); - } - else - { - QTextCharFormat format; - format.setFontUnderline( true ); - - const QInputMethodEvent::Attribute attribute( - QInputMethodEvent::TextFormat, 0, text.length(), format ); - - QInputMethodEvent event( text, { attribute } ); - - QCoreApplication::sendEvent( receiver, &event ); - } -} - -static inline void qskSendKey( QQuickItem* receiver, int key ) -{ - if ( receiver == nullptr ) - return; - - QKeyEvent keyPress( QEvent::KeyPress, key, Qt::NoModifier ); - QCoreApplication::sendEvent( receiver, &keyPress ); - - QKeyEvent keyRelease( QEvent::KeyRelease, key, Qt::NoModifier ); - QCoreApplication::sendEvent( receiver, &keyRelease ); -} - -static inline void qskSyncInputProxy( - QQuickItem* inputItem, QskTextInput* inputProxy ) -{ - int passwordMaskDelay = -1; - QString passwordCharacter; - - if ( auto textInput = qobject_cast< QskTextInput* >( inputItem ) ) - { - passwordMaskDelay = textInput->passwordMaskDelay(); - passwordCharacter = textInput->passwordCharacter(); - - if ( inputProxy->echoMode() == QskTextInput::NoEcho ) - { - /* - Qt::ImhHiddenText does not provide information - to decide between NoEcho/Password - */ - auto mode = textInput->echoMode(); - if ( mode == QskTextInput::Password ) - inputProxy->setEchoMode( mode ); - } - } - - if ( passwordMaskDelay >= 0 ) - inputProxy->setPasswordMaskDelay( passwordMaskDelay ); - else - inputProxy->resetPasswordMaskDelay(); - - if ( !passwordCharacter.isEmpty() ) - inputProxy->setPasswordCharacter( passwordCharacter ); - else - inputProxy->resetPasswordCharacter(); -} namespace { @@ -117,9 +25,40 @@ namespace QskTextInput( parentItem ) { setObjectName( "InputPanelInputProxy" ); -#if 1 setFocusPolicy( Qt::NoFocus ); -#endif + } + + void setup( QQuickItem* inputItem ) + { + int passwordMaskDelay = -1; + QString passwordCharacter; + + if ( auto textInput = qobject_cast< QskTextInput* >( inputItem ) ) + { + passwordMaskDelay = textInput->passwordMaskDelay(); + passwordCharacter = textInput->passwordCharacter(); + + if ( echoMode() == QskTextInput::NoEcho ) + { + /* + Qt::ImhHiddenText does not provide information + to decide between NoEcho/Password + */ + auto mode = textInput->echoMode(); + if ( mode == QskTextInput::Password ) + setEchoMode( mode ); + } + } + + if ( passwordMaskDelay >= 0 ) + setPasswordMaskDelay( passwordMaskDelay ); + else + resetPasswordMaskDelay(); + + if ( !passwordCharacter.isEmpty() ) + setPasswordCharacter( passwordCharacter ); + else + resetPasswordCharacter(); } protected: @@ -255,7 +194,7 @@ void QskInputPanel::attachInputItem( QQuickItem* item ) QCoreApplication::sendEvent( item, &event ); // not all information is available from the input method query - qskSyncInputProxy( item, m_data->inputProxy ); + m_data->inputProxy->setup( item ); } } } @@ -265,6 +204,11 @@ QQuickItem* QskInputPanel::attachedInputItem() const return m_data->inputItem; } +QQuickItem* QskInputPanel::inputProxy() const +{ + return m_data->inputProxy; +} + void QskInputPanel::updatePrediction() { m_data->predictionBar->setPrediction( @@ -335,7 +279,7 @@ void QskInputPanel::commitPredictiveText( int index ) const QString text = m_data->engine->predictiveText( index ); m_data->engine->reset(); - qskSendText( m_data->receiverItem(), text, true ); + Q_EMIT textEntered( text, true ); } } @@ -376,39 +320,26 @@ void QskInputPanel::processKey( int key, { case Qt::Key_Return: { - done( true ); + Q_EMIT done( true ); break; } case Qt::Key_Escape: { - done( false ); + Q_EMIT done( false ); break; } default: { - qskSendKey( m_data->receiverItem(), result.key ); + Q_EMIT keyEntered( result.key ); } } } else if ( !result.text.isEmpty() ) { - // changing the current text - qskSendText( m_data->receiverItem(), result.text, result.isFinal ); + Q_EMIT textEntered( result.text, result.isFinal ); } } -void QskInputPanel::done( bool success ) -{ - if ( success ) - { - if ( m_data->hasInputProxy ) - qskSendReplaceText( m_data->inputItem, m_data->inputProxy->text() ); - } - - qskSendKey( m_data->inputItem, - success ? Qt::Key_Return : Qt::Key_Escape ); -} - void QskInputPanel::processInputMethodQueries( Qt::InputMethodQueries queries ) { if ( m_data->inputItem == nullptr ) diff --git a/src/inputpanel/QskInputPanel.h b/src/inputpanel/QskInputPanel.h index f675aa21..1df81adf 100644 --- a/src/inputpanel/QskInputPanel.h +++ b/src/inputpanel/QskInputPanel.h @@ -39,6 +39,8 @@ public: QskInputEngine* engine(); bool hasInputProxy() const; + QQuickItem* inputProxy() const; + QString inputPrompt() const; virtual QskAspect::Subcontrol effectiveSubcontrol( @@ -50,6 +52,10 @@ Q_SIGNALS: void inputProxyChanged( bool ); void inputPromptChanged( const QString& ); + void textEntered( const QString&, bool isFinal ); + void keyEntered( int keyCode ); + void done( bool success ); + public Q_SLOTS: void setInputPrompt( const QString& ); void setInputProxy( bool ); @@ -62,7 +68,6 @@ protected: Qt::InputMethodHints, int spaceLeft ); virtual void updatePrediction(); - virtual void done( bool success ); private: void commitKey( int key ); diff --git a/src/src.pro b/src/src.pro index 4acd8e6d..c1985fa4 100644 --- a/src/src.pro +++ b/src/src.pro @@ -300,6 +300,7 @@ SOURCES += \ SOURCES += \ inputpanel/QskTextPredictor.cpp \ inputpanel/QskInputContext.cpp \ + inputpanel/QskInputManager.cpp \ inputpanel/QskInputEngine.cpp \ inputpanel/QskInputPanel.cpp \ inputpanel/QskInputPredictionBar.cpp \ @@ -308,6 +309,7 @@ SOURCES += \ HEADERS += \ inputpanel/QskTextPredictor.h \ inputpanel/QskInputContext.h \ + inputpanel/QskInputManager.h \ inputpanel/QskInputEngine.h \ inputpanel/QskInputPanel.h \ inputpanel/QskInputPredictionBar.h \