code moved to QskInputManager

This commit is contained in:
Uwe Rathmann 2018-06-01 17:26:22 +02:00
parent 186b18587b
commit 11dd05ff49
5 changed files with 189 additions and 115 deletions

View File

@ -7,7 +7,65 @@
#include "QskInputPanel.h" #include "QskInputPanel.h"
#include "QskInputEngine.h" #include "QskInputEngine.h"
#include "QskInputContext.h" #include "QskInputContext.h"
#include <QPointer> #include <QPointer>
#include <QTextCharFormat>
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 class QskInputManager::PrivateData
{ {
@ -92,7 +150,18 @@ Qt::Alignment QskInputManager::panelAlignment() const
QskControl* QskInputManager::createPanel() 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() QskInputEngine* QskInputManager::createEngine()
@ -136,3 +205,63 @@ void QskInputManager::updatePredictor()
m_data->engine->setPredictor( context->textPredictor( locale ) ); 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<QString>() )
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"

View File

@ -31,6 +31,9 @@ public:
QskControl* panel( bool doCreate ); QskControl* panel( bool doCreate );
virtual Qt::Alignment panelAlignment() const; virtual Qt::Alignment panelAlignment() const;
virtual QQuickItem* inputProxy() const;
virtual QQuickItem* inputItem() const;
protected: protected:
virtual QskControl* createPanel(); virtual QskControl* createPanel();
virtual QskInputEngine* createEngine(); virtual QskInputEngine* createEngine();
@ -39,6 +42,10 @@ protected:
void updateEngine( const QLocale& ); void updateEngine( const QLocale& );
private: private:
void applyInput( bool success );
void applyText( const QString&, bool isFinal );
void applyKey( int keyCode );
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;
}; };

View File

@ -13,100 +13,8 @@
#include <QString> #include <QString>
#include <QLocale> #include <QLocale>
#include <QGuiApplication>
#include <QPointer> #include <QPointer>
#include <QInputMethodQueryEvent> #include <QInputMethodQueryEvent>
#include <QTextCharFormat>
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 namespace
{ {
@ -117,9 +25,40 @@ namespace
QskTextInput( parentItem ) QskTextInput( parentItem )
{ {
setObjectName( "InputPanelInputProxy" ); setObjectName( "InputPanelInputProxy" );
#if 1
setFocusPolicy( Qt::NoFocus ); 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: protected:
@ -255,7 +194,7 @@ void QskInputPanel::attachInputItem( QQuickItem* item )
QCoreApplication::sendEvent( item, &event ); QCoreApplication::sendEvent( item, &event );
// not all information is available from the input method query // 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; return m_data->inputItem;
} }
QQuickItem* QskInputPanel::inputProxy() const
{
return m_data->inputProxy;
}
void QskInputPanel::updatePrediction() void QskInputPanel::updatePrediction()
{ {
m_data->predictionBar->setPrediction( m_data->predictionBar->setPrediction(
@ -335,7 +279,7 @@ void QskInputPanel::commitPredictiveText( int index )
const QString text = m_data->engine->predictiveText( index ); const QString text = m_data->engine->predictiveText( index );
m_data->engine->reset(); 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: case Qt::Key_Return:
{ {
done( true ); Q_EMIT done( true );
break; break;
} }
case Qt::Key_Escape: case Qt::Key_Escape:
{ {
done( false ); Q_EMIT done( false );
break; break;
} }
default: default:
{ {
qskSendKey( m_data->receiverItem(), result.key ); Q_EMIT keyEntered( result.key );
} }
} }
} }
else if ( !result.text.isEmpty() ) else if ( !result.text.isEmpty() )
{ {
// changing the current text Q_EMIT textEntered( result.text, result.isFinal );
qskSendText( m_data->receiverItem(), 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 ) void QskInputPanel::processInputMethodQueries( Qt::InputMethodQueries queries )
{ {
if ( m_data->inputItem == nullptr ) if ( m_data->inputItem == nullptr )

View File

@ -39,6 +39,8 @@ public:
QskInputEngine* engine(); QskInputEngine* engine();
bool hasInputProxy() const; bool hasInputProxy() const;
QQuickItem* inputProxy() const;
QString inputPrompt() const; QString inputPrompt() const;
virtual QskAspect::Subcontrol effectiveSubcontrol( virtual QskAspect::Subcontrol effectiveSubcontrol(
@ -50,6 +52,10 @@ Q_SIGNALS:
void inputProxyChanged( bool ); void inputProxyChanged( bool );
void inputPromptChanged( const QString& ); void inputPromptChanged( const QString& );
void textEntered( const QString&, bool isFinal );
void keyEntered( int keyCode );
void done( bool success );
public Q_SLOTS: public Q_SLOTS:
void setInputPrompt( const QString& ); void setInputPrompt( const QString& );
void setInputProxy( bool ); void setInputProxy( bool );
@ -62,7 +68,6 @@ protected:
Qt::InputMethodHints, int spaceLeft ); Qt::InputMethodHints, int spaceLeft );
virtual void updatePrediction(); virtual void updatePrediction();
virtual void done( bool success );
private: private:
void commitKey( int key ); void commitKey( int key );

View File

@ -300,6 +300,7 @@ SOURCES += \
SOURCES += \ SOURCES += \
inputpanel/QskTextPredictor.cpp \ inputpanel/QskTextPredictor.cpp \
inputpanel/QskInputContext.cpp \ inputpanel/QskInputContext.cpp \
inputpanel/QskInputManager.cpp \
inputpanel/QskInputEngine.cpp \ inputpanel/QskInputEngine.cpp \
inputpanel/QskInputPanel.cpp \ inputpanel/QskInputPanel.cpp \
inputpanel/QskInputPredictionBar.cpp \ inputpanel/QskInputPredictionBar.cpp \
@ -308,6 +309,7 @@ SOURCES += \
HEADERS += \ HEADERS += \
inputpanel/QskTextPredictor.h \ inputpanel/QskTextPredictor.h \
inputpanel/QskInputContext.h \ inputpanel/QskInputContext.h \
inputpanel/QskInputManager.h \
inputpanel/QskInputEngine.h \ inputpanel/QskInputEngine.h \
inputpanel/QskInputPanel.h \ inputpanel/QskInputPanel.h \
inputpanel/QskInputPredictionBar.h \ inputpanel/QskInputPredictionBar.h \