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 "QskInputEngine.h"
#include "QskInputContext.h"
#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
{
@ -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<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 );
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;
};

View File

@ -13,100 +13,8 @@
#include <QString>
#include <QLocale>
#include <QGuiApplication>
#include <QPointer>
#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
{
@ -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 )

View File

@ -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 );

View File

@ -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 \